代码审计-DVWA-SQL注入

新手入门篇,不是很深入。

DVWA代码审计-SQL注入

low

<?php
if( isset( $_REQUEST[ 'Submit' ] ) ) {
    // Get input
    $id = $_REQUEST[ 'id' ];
    // Check database
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Get values
        $first = $row["first_name"];
        $last  = $row["last_name"];
        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }
    mysqli_close($GLOBALS["___mysqli_ston"]);
}
?> 

1、接收从表单中传来的数据,并将name为id的值赋给变量id。
2、query变量是处理sql语句的方式,可以看到没有进行任何过滤,直接将用户输入的拼接到sql语句中,通过单引号闭合,那么便存在字符型注入。
3、mysqli_query()函数执行某个针对数据库的查询。$_GLOBALS["__mysqli_ston"]是规定使用的MySQL连接,$query就是查询语句。mysqli_query()针对成功的SELECT、SHOW、DESCRIBE、EXPLAIN查询,将返回一个mysqli_result对象,针对其他成功的查询返回true,失败返回false。or die()即如果前面的返回result对象失败,那么执行后面的die()语句,后面是两个三目运算符的嵌套,现在读起来比价困难
4、从mysqli_query()中返回的result中,使用mysqli_fetch_assoc()函数从结果集中取得一行作为关联数组。
5、使用while循环遍历并输出。
6、mysqli_close()函数关闭先前打开的数据库连接。

medium

<?php
if( isset( $_POST[ 'Submit' ] ) ) {
    // Get input
    $id = $_POST[ 'id' ];
    $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' );
    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Display values
        $first = $row["first_name"];
        $last  = $row["last_name"];
        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }
}
// This is used later on in the index.php page
// Setting it here so we can close the database connection in here like in the rest of the source scripts
$query  = "SELECT COUNT(*) FROM users;";
$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
$number_of_rows = mysqli_fetch_row( $result )[0];
mysqli_close($GLOBALS["___mysqli_ston"]);
?> 

1、从mysqli_real_escape_string()函数开始,$GLOBALS["___mysqli_ston"]是必选项,规定使用的MySQL连接(这个地方菜鸟教程和w3cschool冲突了,菜鸟是必选;w3c是可选,如果未规定,则使用上一个连接);$id同样是必选项,它是要转义的字符串,编码的字符是NUL(ASCII 0)、 、 、、'、"和Contol-Z。如果成功,该函数返回被转义的字符串,失败返回false,也就是说这个地方能够过滤单双引号。
2、但是从下面的sql语句中可以看到,它也是直接拼接在sql语句中,且没有单双引号包裹,虽然上面有转义,但是没什么意义,因为这边是数字型注入。且注意是POST方式传入数据。
3、后面就不写了,太菜了,读起来太困难了,算是先埋坑吧。

high

<?php
if( isset( $_SESSION [ 'id' ] ) ) {
    // Get input
    $id = $_SESSION[ 'id' ];
    // Check database
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' );
    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Get values
        $first = $row["first_name"];
        $last  = $row["last_name"];
        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);        
}
?> 

1、额,这个的话就是从session中取得用户参数,可能考验的是注入点的位置。像注入点的话凡是直接与数据库交互的话就可能存在。

imposeable

<?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();
        $row = $data->fetch();
        // Make sure only 1 result is returned
        if( $data->rowCount() == 1 ) {
            // Get values
            $first = $row[ 'first_name' ];
            $last  = $row[ 'last_name' ];
            // Feedback for end user
            echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
        }
    }
}
// Generate Anti-CSRF token
generateSessionToken();
?> 

1、前面的checkToken()检查token就不说了。
2、在处理用户输入的时候,首先是判断用户输入的是不是数字类型,is_nummic()函数判断id是否是数字,是返回true,否则返回false。emmm、、这、、效率也太高了,通过这个判断可以将特殊字符或or、xor等都过滤掉,因为限制只能是纯数字。当然,这是因为该功能点只要输入数字,像其他输入字符串的肯定没有这么容易。
3、再看里面操作,使用的是MySQL预处理语句,参考链接至于这个预处理绑定这个语句,着实不会,不敢乱描述,先这样。


如果大家发现有什么错误请联系QQ:472668561

原文地址:https://www.cnblogs.com/ahtoh/p/12096548.html