zoukankan      html  css  js  c++  java
  • 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));
     
  • 相关阅读:
    ./configure时候遇到的问题 Cannot find install-sh, install.sh, or shtool in ac-aux
    携程ELK
    操作系统日志分析中常见的搜索条目 20160715
    日志分析方法
    通过UUID方式在fstab中挂载分区
    Linux上查看造成IO高负载的进程
    Logstash 最佳实践
    使用sqlplus执行sql时,发现有中文有乱码解决方法
    Nginx模块GeoIP匹配处理IP所在国家、城市
    《iOS Human Interface Guidelines》——Segmented Control
  • 原文地址:https://www.cnblogs.com/bmjoker/p/8797378.html
Copyright © 2011-2022 走看看