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.2Now 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.githubusercontent.com.127-0-0-1.nip.io/ - Get a domain and put A record directly:
http://raw.githubusercontent.com.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