Nytro Posted July 29, 2014 Report Posted July 29, 2014 Writing your own blind SQLi scriptWe all know that sqlmap is a really great tool which has a lot of options that you can tweak and adjust to exploit the SQLi vuln you just found (or that sqlmap found for you). On rare occasions however you might want to just have a small and simple script or you just want to learn how to do it yourself. So let’s see how you could write your own script to exploit a blind SQLi vulnerability. Just to make sure we are all on the same page, here is the blind SQLi definition from OWASP:Blind SQL (Structured Query Language) injection is a type of SQL Injection attack that asks the database true or false questions and determines the answer based on the applications response.You can also roughly divide the exploiting techniques in two categories (like owasp does) namely:content basedThe page output tells you if the query was successful or not [*]time basedBased on a time delay you can determine if your query was successful or not Of course you have dozens of variations on the above two techniques, I wrote about one such variation a while ago. For this script we are going to just focus on the basics of the mentioned techniques, if you are more interested in knowing how to find SQLi vulnerabilities you could read my article on Solving RogueCoder’s SQLi challenge. Since we are only focusing on automating a blind sql injection, we will not be building functionality to find SQL injections. Before we even think about sending SQL queries to the servers, let’s first setup the vulnerable environment and try to be a bit realistic about it. Normally this means that you at least have to login, keep your session and then inject. In some cases you might even have to take into account CSRF tokens which depending on the implementation, means you have to parse some HTML before you can send the request. This will however be out of scope for this blog entry. If you want to know how you could parse HTML with python you could take a look at my credential scavenger entry. If you just want the scripts you can find them in the example_bsqli_scripts repository on my github, since this is an entry on how you could write your own scripts all the values are hard coded in the script. The vulnerable environment Since we are doing this for learning purposes anyways, let’s create almost everything from scratch:sudo apt-get install mysql-server mysql-client sudo apt-get install php5-mysql sudo apt-get install apache2 libapache2-mod-php5 Now let’s write some vulnerable code and abuse the mysql database and it’s tables for our vulnerable script, which saves us the trouble of creating a test database. pwnme-plain.php<?php$username = "root";$password = "root";$link = mysql_connect('localhost',$username,$password);if(!$link){ die(mysql_error());}if(!mysql_select_db("mysql",$link)){ die(mysql_error());}$result = mysql_query("select user,host from user where user='" . $_GET['name'] . "'",$link);echo "<html><body>";if(mysql_num_rows($result) > 0){ echo "User exists<br/>";}else{ echo "User does not exist<br/>";}if($_GET['debug'] === "1"){ while ($row = mysql_fetch_assoc($result)){ echo $row['user'] . ":" . $row['host'] . "<br/>"; }}echo "</html></body>";mysql_free_result($result);mysql_close($link);?>Like you can see if you give it a valid username it will say the user exists and if you don’t give it a valid username it will tell you the user doesn’t exist. If you need more information you can append a debug flag to get actual output. You probably also spotted the SQL injection which you can for example exploit like this: http://localhost/pwnme-plain.php?name=x' union select 1,2--+ Which results in the output: User exists and if you mess up the query or the query doesn’t return any row it will result in: User does not exist Sending and receiving data We are going to use the python package requests for this. If you haven’t heard it yet, it makes working with http stuff even easier than urllib2. If you happen to encounter weird errors with the requests library you might want to install the library yourself instead of using the one provided by your distro. To make a request using GET and getting the page content you’d use: print requests.get("http://localhost/pwnme-plain.php").text If you want to pass in parameters you’d do it like: urlparams = {'name':'root'} print requests.get("http://localhost/pwnme-plain.php",parameters=urlparams).text Which ensures that the parameters are automatically encoded. To make a request using POST you’d use: postdata = {'user':'webuser','pass':'webpass'} print requests.post("http://localhost/pwnme-login.php",data=postdata).text That’s all you need to start sending your SQLi payload and receiving the response. Content based automation For content based automation you basically need a query which will change the content based on the output of the query. You can do this in a lot of ways, here are two example:display or don’t display contentid=1 and 1=if(substring((select @@version),1,1)=5,1,2) [*]display content based on the query outputid=1 + substring((select @@version),1,1) For our automation script we will choose the first way of automating it, since it depends less on the available content. The first thing you need is a “universal” query which you use as the base to execute all your other queries. In our case this could be: root’ and 1=if(({PLACEHOLDER})=PLACEHOLDERVAR,1,2)–+ With the above query we can decide what we want to display. If you want display the wrong content we have to replace the PLACEHOLDER text and PLACEHOLDERVAR with something that will make the ‘if clause’ to choose ‘2’, for example: root’ and 1=if(substring((select @@version),1,1)=20,1,2)–+Since there is no mysql version 20 this will lead to a query that ends up being evaluated as: root’ and 1=2 Which results in a False result, thus displaying the wrong content, in our case ‘User does not exist’. If on the other hand we want the query to display the good content we can just change it to: root’ and 1=if(substring((select @@version),1,1)=5,1,2)–+ Which of course will end up as: root’ and 1=1Articol complet: Writing your own blind SQLi script | DiabloHorn Quote