[Web] CSAW - orange v3


orange v3

I wrote a little proxy program in NodeJS for my poems folder but I’m bad at programming so I had to rewrite it. Again.

I changed up flag.txt too but everyone still wants to read it…

http://web.chal.csaw.io:7312/?path=orange.txt

Keep in mind I didn’t solve this challenge during the CTF but I was pretty close, the way to do this was to use unicode characters, I gave up in mid way after trying alot of characters and gave up and started thinking there was another way of bypassing the new filters! but It didn’t, the reason why I’m doing the writeup is to explain why some approaches don’t work and others do, this write up is based after reading dcua writeup , so all the credits go to them!

Analysis

Same problem as orange v1 after testing a bunch of characters and see which ones were giving a 404 error BANNED and now our string must have “.txt“ at the end of the string so we are “stuck” into a one extension:

1
r".|#|%" # --> if the path GET parameter has any of this characters will return a 404

Note that even null bytes don’t work here because the string must always end with “.txt“.

Double url encoding approach

Double url encoding no longer works and why? because the character “%“ is banned, so imagine that we try to inject this %202e the nodejs UrlParse function will decode it first into “%2e“ and the black list filter will block it because it contains a “%2e“!

Why are they banning # character

Remember the code from orange v1?

1
2
var path = url.parse(req.url, true).query;
path = path['path'];

They are using url.parse! url parse in nodejs works the same way that php one works, here what happens when you add # character in php for example:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ php -r "var_dump(parse_url('web.chal.csaw.io:7312/?path=hi#.txt'));"
array(5) {
["host"]=>
string(16) "web.chal.csaw.io"
["port"]=>
int(7312)
["path"]=>
string(1) "/"
["query"]=>
string(10) "path=hello"
["fragment"]=>
string(4) ".txt"
}

You can see the trick? yes if the programmer uses the query parameter he’s fucked! everything after the ‘#’ will go to the field “fragment“! And the string won’t have the “.txt“ in the end of the string!

Same thing in nodejs:

1
2
3
var url = require('url');
console.log(url.parse('web.chal.csaw.io:7312/?path=hi#.txt', true).query);
// { path: 'hi' }

Bypassing the extension filter

Well if “#” removes everything after it how do we bypass the extension? well lets do the obvious lets encode “#”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ curl 'web.chal.csaw.io:7312/?path=%23.txt'
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /poems/</title>
<body>
<h2>Directory listing for /poems/</h2>
<hr>
<ul>
<li><a href="burger.txt">burger.txt</a>
<li><a href="haiku.txt">haiku.txt</a>
<li><a href="orange.txt">orange.txt</a>
<li><a href="ppp.txt">ppp.txt</a>
<li><a href="the_red_wheelbarrow.txt">the_red_wheelbarrow.txt</a>
</ul>
<hr>
</body>
</html>

It works! url.parse won’t remove the #, and after this nodejs will make a request at an url, and a GET request ignores everything after a #.
Now I will teach another way to bypass this but with another character “?“ or its url encoded version “%3F“:

url.parse will do this:

1
2
3
var url = require('url');
console.log(url.parse('web.chal.csaw.io:7312/?path=hi?.txt', true).query);
// { path: 'hi?.txt' }

WTH? if it isn’t the url parse what is happening here?

1
2
3
4
5
6
7
8
9
10
var callback = function(response){
var str = '';
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
res.end(str);
});
};
http.get(base + path, callback).end();

Yap it’s the http.get function, yes a GET request will ignore everything that is after a ? and this works because this isn’t Local File Inclusion function like include in php but a HTTP REQUEST! amazing isn’t it?

Bypassing the “.“ filter

Everything else is blocked so the only thing that is left is unicode! You could find all UTF-16 characters at here and the character was this one http://www.fileformat.info/info/unicode/char/012e/index.htm

It works! now getting the flag!