web: temporary writeup
There are two instances namely public
and internal
.
We can get the address of public
by leaking $_SERVER['REMOTE_ADDR"]
in phpinfo.php?phpinfo
$_SERVER['SERVER_NAME'] _
$_SERVER['SERVER_PORT'] 80
$_SERVER['SERVER_ADDR'] 172.21.0.2
Now let's take a look at image.php
.
// Allow GitHub contents only.
if(!preg_match("/^http(s?):\/\/raw.githubusercontent.com/im", $url)) die;
As you see in this code, the server checks for http://raw.githubusercontent.com
or https://raw.githubusercontent.com
without a trailing slash
From here, you can bypass the domain check by any of the following:
- Use a ip-to-domain service such as
nip.io
:http://raw.521000.best.127-0-0-1.nip.io/
- Get a domain and put A record directly:
http://raw.521000.best.test.harold.kim/
Since we have the A,B,C class of the internal network (172.21.0.2
), we can easily see that the internal IP is 172.21.0.3
(because 172.21.0.1
should be the host domain)
The last thing to do is to load the internal index.php
that contains the flag.
Let's get back to the image.php
file.
if(substr_compare($url, ".jpg", -strlen(".jpg"))) die;
foreach($filter as $_filter){
if(stripos($url, $_filter) !== false) die;
}
Since we have the .jpg
file extension check, the only file we can get from the internal server is supposed to be disaster.jpg
only.
But the internal server is running on CMD [ "php", "-S", "0.0.0.0:80" ]
command.
Have a look the documentation of the command line PHP webserver. https://www.php.net/manual/en/features.commandline.webserver.php
The guideline clearly says:
If neither file exists, the lookup for index.php and index.html will be continued in the parent directory and so on until one is found or the document root has been reached.
If an index.php or index.html is found, it is returned and $_SERVER['PATH_INFO'] is set to the trailing part of the URI.
This means that accessing index.php/filename.jpg
will just execute index.php
with a PATH_INFO of filename.jpg
.
We just kept the disaster.jpg
for the sake of the hint 😄
Exploit