复制代码

1.3 DVWA亲测sql注入漏洞

LOW等级
 
我们先输入1

我们加上一个单引号,页面报错

我们看一下源代码:
<?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"]);
}
 
?>
我们看
$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"
$id = $_REQUEST[ 'id' ];
id也没有进行过滤。。。。我们可以尝试闭合单引号 
比如我们输入id=1' or '1'='1
原句就变成:
$query  = "SELECT first_name, last_name FROM users WHERE user_id = '1' or '1'='1';";

 下面是如何来利用sql注入

 

文件读取

写入一句话木马

 

或者用sqlmap自动化注入:
 
sqlmap.py sqlmap -u "http://www.secexercise.tk/vulnerabilities/sqli/?id=1&Submit=Submit#" -p "id" --cookie "uuid=uid15204271354091678690121028269; PHPSESSID=rsv9ga280c8gpn6oheb5vhd8p3; security=low"

sqlmap成功注入

sqlmap获取webshell:
 
 
 

Medium等级
 
我们先尝试来抓包:
然后尝试修改id参数,Go向前观察页面变化
 

后面的利用跟LOW等级一样,这里不再赘述

High等级
我们尝试LOW等级的注入方法,发现一下就成功了
我们使用LOW等级的SQL map自动化攻击,发现失效,应为注入的点与返回的点不在同一个页面上

后面步骤不再展示
impossible等级
我们先来看一下代码:
<?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();
 
?>
重点看以下代码:
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();
这里对接受过的参数id进行判断,is_numeric()函数——》如果id是一个数字,则返回真
然后通过使用预编译语句(prepared statements)和参数化查询(parameterized queries)。这些sql语句从参数,分开的发送到数据库服务端,进行解析。这样黑客不可能插入恶意sql代码。
有两种方式去完成这个:

1.使用PDO对象(对于任何数据库驱动都好用)

$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
 
$stmt->execute(array('name' => $name));
 
foreach ($stmt as $row) {
    // do something with $row
}
2. 使用MySqli
$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);
 
$stmt->execute();
 
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
    // do something with $row
}
如果你链接的数据库不是mysql,你可以参考具体数据库所提供的其他选项,例如(pg_prepare() and pg_execute() for PostgreSQL)
Pdo是一个通用的选项。
 

解释

到底发生了什么呢?你的SQL语句交给prepare 之后被数据库服务器解析和编译了。通过制定参数(不管是?还是命名占位符:name),你都可以告诉数据库引擎哪里你想过滤掉。然后当你执行execute方法时,预处理语句会把你所指定的参数值结合袭来。
这里很重要的就是参数值和编译过的语句绑定在了一起,而不是简简单单的SQL字符串、SQL注入通过骗起脚本加入一些恶意的字符串,在建立sql发送到数据库的时候产生后果。所以,通过分离的从参数中发送真正的sql语句,你控制了风险:在结尾的时候你不打算干的一些事。(译者注:请看开篇的例子)。当你使用预编译的时候,任何参数都会被当作字符串。在这个例子里,如果$name变量包含了’Sarah’; DELETE FROM employees 这个结果只会简单的搜索字符串“‘Sarah’; DELETE FROM employees”,所以你不会得到一张空表。
另外一个使用预编译的好处就是,如果你在同一个会话中执行一个statement多次,只会被解析和编译一次,对速度更友好。
哦,既然你问了增加语句的时候怎么使用,下面给你个例子:
$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');
 
$preparedStatement->execute(array('column' => $unsafeValue));
 
posted @ 2018-04-11 17:57  bmjoker  阅读(970)  评论(0编辑  收藏  举报