"When a well-packaged web of lies has been sold gradually to the masses over generations, the truth will seem utterly preposterous and its speaker a raving lunatic." --Dresden James
This article originated from someone on the forums asking, in short, how to set up Apache, MySQL and PHP on his localhost in order to test SQL injections. He was asking how to do this on a Mac. I've never used a Mac, but I assumed it was similar to the process on Linux, so I wrote this. This is a slightly tidier version and it assumes you're using Linux (Linux + Apache + MySQL + PHP => LAMP).
I plan on updating this article to always use the latest stable versions of the packages, or other non-stable versions if I feel they offer some benefit worth having. Since phpMyAdmin is released very frequently I will most likely not update this article when new versions of that are out.
I run Fedora Linux, but I've used this exact technique on CentOS, Ubuntu and Debian too. In fact, since I'm working off source code it should work on every Linux distro out there. One thing to note is that it's very likely you're missing some dependencies, these will create errors down the line. Let this happen, when you get the error, then simply install the missing dependency via your distribution's package manager and retry the command that created the error again. Also make sure that your OS doesn't already have a web server or a mysql server installed. To see if one is running, do the following:
nmap -A -p 80 127.0.0.1 | grep 80
nmap -A -p 3306 127.0.0.1 | grep 3306
If nmap says those ports are closed, then that's good, means you're currently not running those servers (at least not on their default ports).
There's more than one way to install LAMP, but I much prefer doing things manually; it gives you a much greater understanding of how things work and interact. It also makes it easy to then later change just one component. I will later create more articles which may for instance tell you how to install SSL into Apache. Because of this modular approach to installing LAMP you'll be able to easily install SSL later, without having to touch MySQL or PHP.
There will be five stages to this install.
1. Installing and configuring Apache
2. Installing and configuring MySQL
3. Installing and configuring PHP
4. Installing the required extensions for PHP
5. Setting up some content for you to play with (remember this article started off as someone wanting to play with SQL injections)
Note that this entire process can take a while as I'm compiling each from their source code. MySQL is probably the slowest of each of the steps, but I remember installing PHP on an old 233MHz machine and it'd take close to an hour just to make the damn thing. Very annoying when I then realised I'd forgotten to patch in suhosin. Also a lot of this is done from memory and only slight amounts of double checking. Because of how I install these things (using the prefix on the ./configure line) it's always a piece of cake to remove everything to do with the specific package.
I will not cover how to start each of these as a service because I don't know how that's done on each of the various distributions. You can probably find that information in the various README files that you get with each download.
The places I download files from are simply mirrors that were given to me as I wrote this, you may want to choose different mirrors for your downloads.
Apache
We're going to use the latest version, why not. This will all be done as the root user, simply so I don't have to say what should be done as root and what not. I've written most of the code in a way that lets you easily copy paste them. But I still suggest you try to understand what each line does. If not, just ask
CODE :
wget http://apache.mirrors.webazilla.nl/httpd/httpd-2.2.8.tar.bz2 #or go to httpd.apache.org to use another mirror or to check for later versions
tar xjf httpd-2.2.8.tar.bz2
cd http-2.2.8
# Now we need to configure our installation. type "./configure --help" minus the quotes to see all the options.
# I like installing Apache to /usr/local/apache and we need --enable-so for PHP later
./configure --enable-so --prefix=/usr/local/apache
make
make install
Now that it's installed we need to configure it. I like my web documents located at /var/www/<site_name>, or if it's a localhost for only testing purposes then we can just use /var/www. Also since it's only for testing purposes by yourself there's no point in making Apache listen to requests from the public. Instead we'll only make it listen on 127.0.0.1.
Open /usr/local/apache2/conf/httpd.conf in your favourite text editor.
That's Apache installed and configured. Before we start Apache though, let's create some files for it to serve.
CODE :
mkdir -vp /var/www
echo "Yawn!!" > /var/www/index.html
chown -R user:group /var/www # Change the user and group to your username and your group to give yourself access to the web folder.
Now let's start Apache
CODE :
/usr/bin/apache/bin/apachectl -k start
It should be obvious how to stop it
Now browse over to 127.0.0.1 and see if Apache yawned at you.
MySQL
Let's get ourselves the latest version from dev.mysql.com. Oh. what's this? There's (currently) loads of versions? Well... There's the latest stable version, then there's the latest 5.X development version (currently a release candidate) and there's the alpha for version 6. I personally use 5.1.22-rc. I use this because it supports event scheduling and this works well for me, so I'll walk you through using it.
CODE :
wget http://dev.mysql.com/get/Downloads/MySQL-5.1/mysql-5.1.22-rc.tar.gz/from/http://www.mirrorservice.org/sites/ftp.mysql.com/ # Or go to dev.mysql.com to get it from another mirror or check for newer versions
tar xzf mysql-5.1.22-rc.tar.gz
cd mysql-5.1.22-rc
# I don't much fiddle with the ./configure line here
./configure --prefix=/usr/local/mysql/
make
make install
Now we need to create the user and the group to run mysql as, usually both are called mysql.
CODE :
groupadd mysql
useradd -M -s /usr/sbin/nologin -g mysql mysql
Before we rush ahead and configure the thing, let's add the binaries to decent paths so we don't need to remember the full path
Now we need to configure the thing. The configuration file is located at /etc/my.cnf, so open that up in your favourite editor. Here's my my.cnf:
CODE :
# Example MySQL config file for medium systems.
# The following options will be passed to all MySQL clients
[client]
#password = your_password
port = 3306
socket = /tmp/mysql.sock
It hasn't been changed much. I've changed the default user to our mysql user. I've disabled binary-logging because I had issues with that and some MySQL function of mine. I also enabled the event scheduler, the whole point of me using this release candidate version of MySQL. I've also removed a lot of the stuff that's normally commented out, purely for brevity.
CODE :
cd /usr/local/mysql
chown -R mysql .
chgrp -R mysql .
bin/mysql_install_db --user=mysql
chown -R root .
chown -R mysql var
bin/mysqld_safe --user=mysql &
This is where you'd want to change the default root user's password (for mysql, not your system). I'll leave it to you to find out how to do this, but I'll give you that it involves the command mysqladmin.
Now MySQL is installed and configured, finally we move on towards PHP.
PHP
This time we use the latest stable version, currently 5.2.5. Now I don't use vanilla PHP. I usually patch in suhosin (plus I use its extension). This may get in the way for you doing SQL injection testing, so I will include the steps for suhosin, but they will be separate from the rest.
If you do not want suhosin patched into PHP. Again I like putting PHP in a very separate folder; /usr/local/php5. I also like having the configuration file in what I feel is a sensible location; /usr/local/php5/etc
CODE :
wget http://uk.php.net/distributions/php-5.2.5.tar.bz2 # Or go to php.net to get it from another mirror or check for newer versions
tar xjf php-5.2.5.tar.bz2
cd php-5.2.5.tar.bz2
./configure --prefix=/usr/local/php5 --with-apxs2=/usr/local/apache2/bin/apxs --with-config-file-path=/usr/local/php5/etc
make
make install
If do do want sohusin patched into PHP
CODE :
wget http://uk.php.net/distributions/php-5.2.5.tar.bz2 # Or go to php.net to get it from another mirror or check for newer versions
wget http://www.hardened-php.net/suhosin/_media/suhosin-patch-5.2.5-0.9.6.2.patch.gz
gunzip suhosin-patch-5.2.5-0.9.6.2.patch.gz
tar xjf php-5.2.5.tar.bz2
cd php-5.2.5.tar.bz2
patch -p1 < ../suhosin-patch-5.2.5-0.9.6.2.patch
./configure --prefix=/usr/local/php5 --with-apxs2=/usr/local/apache2/bin/apxs --with-config-file-path=/usr/local/php5/etc
make
make install
Make sure the version of suhosin you patch in matches the version of PHP you are installing or else you could end up with a corrupt set of files.
Finally that's PHP installed. We still have a bit of work to do configuring it though. Before we do that though, let's shove it into our paths (like we did with MySQL).
# Then let's just update PEAR, because we like being up to date
pear upgrade-all # Who uses PEAR anyway?
Now finally we can configure PHP. Open /usr/local/php5/etc/php.ini in your favourite text editor. If it doesn't exist, then copy php.ini-recommended from the directory that was creating when you extracted the .tar.bz2 to /usr/local/php5/etc/php.ini, then open it up in your favourite text editor.
Change short_open_tag = Off on line 131 to short_open_tag = On. This is a personal choice, but I think <? looks ugly and prefer <?php.
Change extension_dir = "./" on line 536 to extension_dir = "/usr/local/php5/ext"
Change enable_dl = On on line 541 to enable_dl = Off You may want to leave this on for pentesting a web application that uses it, but generally it should be off.
See the extensions list starting at line 655? We'll be adding to that list later, so keep this in mind (you can easily find the list by hitting ctrl-f and searching for ;extension=).
CODE :
mkdir -v /usr/local/php5/ext
Should be obvious why we did that given the above change we made regarding that folder.
Now cd back to the extracted php-5.2.5 folder. We need to start installing some extensions. This is by no means all of them, but it should be enough for you to stand learning about SQL injection.
CODE :
cd ext
cd mysql
phpize
./configure --with-mysql=/usr/local/mysql
make
cp modules/mysql.so /usr/local/php5/ext/
cd ../mysqli
phpize
./configure --with-mysqli=/usr/local/mysql/bin/mysql_config
make
cp modules/mysqli.so /usr/local/php5/ext/
cd ../gd
phpize
./configure --enable-gd-native-ttf --enable-gd-jis-conv --with-gd --with-jpeg-dir
make
cp modules/gd.so /usr/local/php5/ext/
cd ../mbstring
phpize
./configure --enable-mbstring
make
cp modules/mbstring.so /usr/local/php5/ext/
I won't go on any more, but you should be able to install other extensions you may want including sockets, pcntl and curl. If you previously installed the suhosin patch into PHP, then at this point you'd want to do the following:
CODE :
wget http://www.hardened-php.net/suhosin/_media/suhosin-0.9.22.tgz
tar xzf suhosin-0.9.22.tgz
cd suhosin-0.9.22
phpize
./configure --enable-suhosin
make
cp modules/suhosin.so /usr/local/php5/ext/
Now we need to add these extensions into our php.ini so they get loaded. Again open /usr/local/php5/etc/php.ini in your favourite text editor and find that list of extensions. Add this to that list:
CODE :
extension=mysql.so
extension=mysqli.so
extension=gd.so
extension=mbstring.so
# If you installed the suhosin.so mod, then activate it here
Now before we restart Apache with PHP support we want to do a thing or two. These should not be done as root
CODE :
echo "<?php phpinfo(); ?>" > /var/www/info.php
rm /var/www/index.html # We don't want that old file any more
Now we shut down Apache and re-start it and it should have PHP installed, again, as root:
Now browse over to 127.0.0.1 and see if info.php loads fine.
Setting up the vulnerable web application
OK. Finally we're done installing the programs, now we need to set up the vulnerable pages for you to play around with. Before we do that we're going to install phpMyAdmin though. You may be asking what this is, it's an easy to use, and damn useful, MySQL administration tool. MySQL themselves to provide their own, but I prefer this one.
From now nothing is done as root, instead it's done as you, earlier we did give you access to /var/www
CODE :
cd /var/www
wget http://puzzle.dl.sourceforge.net/sourceforge/phpmyadmin/phpMyAdmin-2.11.4-all-languages-utf-8-only.tar.bz2 # Or go to phpmyadmin.net for newer versions
tar xjf phpMyAdmin-2.11.4-all-languages-utf-8-only.tar.bz2
mv phpMyAdmin-2.11.4-all-languages-utf-8-only phpMyAdmin
Now we're going to do something odd. I've had weird bugs in phpMyAdmin earlier where it'd just load blank pages, we'll do this even if this odd fix is no longer needed. We'll do it because I'm not in the mood to check. Open /var/www/phpMyAdmin/libraries/config.default.php in a text editor.
Change
CODE :
$cfg['Servers']['host'] = 'localhost';
on line 80 to CODE :
$cfg['Servers'][$i]['host'] = '127.0.0.1';
(yes that has made a difference for me)
Change
CODE :
$cfg['Servers'][$i]['extension'] = 'mysql';
on line 115 to CODE :
$cfg['Servers'][$i]['extension'] = 'mysqli';
Change
CODE :
$cfg['Servers'][$i]['auth_type'] = 'config';
on line 144 to CODE :
$cfg['Servers'][$i]['auth_type'] = 'http';
Now you can browse to /var/www/phpMyAdmin/, log in and play around with your database(s).
Now then. Let's create a vulnerable web application. I'm getting a little tired of writing, so this part will be quick.
Log into the phpMyAdmin you just set up. Create a new database called sqli. Run the following SQL on it:
CODE :
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` tinytext NOT NULL,
`password` tinytext NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Now create a file called /var/www/sql_injection.php and put the following in it:
CODE :
<?php
// Connect to our database
$link = mysql_connect('127.0.01', 'root', 'mysql-user-password');
if (!$link)
{
die('Could not connect: ' . mysql_error());
}
$db = mysql_select_db('sqli', $link);
// If something was submitted, then search for it
if (isset($_GET['id']))
{
$result = mysql_query("SELECT * FROM `users` WHERE `id`=".$_GET['id']);
if (!$result)
{
echo "There was an error as follows: ". mysql_error();
}
else
{
$result = mysql_result($result, 0, 1);
echo "Database returned the following: ". $result;
}
}
?>
<form method="get">
Enter an ID and hit submit to see the users username (1 or 2 are valid IDs unless you tampered with the DB)<br />
<input type="text" name="id" style="width: 80%" />
</form>
Finally, to test that you really are vulnerable to SQL injection go here: http://127.0.0.1/sql_injection.php?id=2%20and%201=2%20union%20select%20password,password,password%20from%20users
How would you read the password of the second user in the table? I'll leave that as an exercise to the reader.
Cast your vote on this article 10 - Highest, 1 - Lowest
Comments: Published: 4 comments.
HackThisSite is the collective work of the HackThisSite staff, licensed under a CC BY-NC license.
We ask that you inform us upon sharing or distributing.