[代码审计]DVWA代码审计档案

文章来自掣雷小组&&零釼实验室成员

JohnnySuen

文章共7190字28图

预计阅读时间20分钟

第一关暴力破解漏洞

漏洞详情:暴力破解漏洞即我们平时所说的口令爆破(或跑字典),是采用大量的密 码进行批量猜解密码的一种恶意登录方式

我们这里使用 burp 进行爆破

首先抓取登录请求包*

将数据包发送到 intruder 模块中载入相关密码字典点击 start attack 找到返回数据度不同的数据包发现密码是admin

由于我们在验证过程中发现输入#等特殊字符会报错所以我们对源码进行一下审计

代码审计

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

?> 
当前代码将用户输入数据直接带入数据库进行查询所以同样也存在 SQL 注入漏洞,所
以我们同样可以在用户名处输入 admin' or 'a'='a 来进行登录此时输入任何密码都可以登录

成功。细节我们在后面的 SQL 注入一关处进行讲解。

$query  = "SELECT * FROM `users` WHERE user = ' admin'or '1'='' AND password = '$pass';"; 

Num2:Command Execution

漏洞详情:命令执行漏洞是在程序中使用可调用系统命令的函数时未对用户输入数据进行完

全过滤导致程序执行用户输入的数据而产生的。 这个程序的正常功能是 ping 用户所输入的 IP 并返回数据包

此时我们采用多命令执行的格式输入192.168.0.104&&ipconfig 即可触发漏洞

代码审计

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

这里程序接收用户传来的参数使用 shell_exec 执行命令,

没有过滤用户所输入的参数

(* shell_exec将所有输出流作为字符串返回)

所以最终程序所执行的命令便成了

ping 192.168.0.104&&ipconfig

导致命令执行漏洞的产生。

Num3:CSRF (跨站请求伪造

漏洞详情:CSRF 漏洞是在用户未验证身份的情况下对其他用户进行攻击的

一种漏洞

这里程序使用 get 方式对用户密码进行了修改,所以在某些方面来讲这里泄露了程序的执行过程。所以我们现在伪造一个连接来进行 CSRF 的利用

其连接为

http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=admin&password_conf=admin&Change=Change#

代码审计

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

Num4:File inclusion( 文件包含漏洞)

漏洞详情:文件包含是指,程序对用户输入参数过滤不当或程序配置不当,导致的使程序包含用户恶意提交的页面文件

这里在连接中使用 page 参数引用当前页面,这里我们对他进行修改

即可引用其他文件到当前页面

代码审计:

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

这里调用两个页面对传入的 page 参数进行包含,忽略了过滤所以导致文件包含漏洞

故障排查

The PHP function allow_url_include is not enabled.

打开配置文件php.ini更改allow_url_include = OFF为

allow_url_include = On

再更改dvwa里的config文件

config\config.inc.php

查找

$_DVWA[ 'recaptcha_public_key' ] = '';

$_DVWA[ 'recaptcha_private_key' ] = '';

更改为

$_DVWA[ 'recaptcha_public_key' ]  = '6LdK7xITAAzzAAJQTfL7fu6I-0aPl8KHHieAT_yJg';
$_DVWA[ 'recaptcha_private_key' ] = '6LdK7xITAzzAAL_uw9YXVUOPoIHPZLfw2K1n5NVQ';

Num5 :SQL Injection (sql 注入)

漏洞详情:SQL 注入是指程序对用户输入参数过滤不严而使用户执行恶意操作的漏洞

当提交正常数据 a 的时候链接为

http://127.0.0.1/dvwa/vulnerabilities/sqli/?id=a&Submit=Submit#

当提交了 a’页面则发生了报错

http://localhost/dvwa/vulnerabilities/sqli/?id=a%27&Submit=Submit#

提交 a and 1=2 页面却没有任何的变化

http://localhost/dvwa/vulnerabilities/sqli/id=a%20and%201=2&Submit=Submit#

说明程序把我们所输入的内容当做字符串来进行查询所以我们这里需要对引号进行闭合,所以我们输入 ‘and 1=1 # 与 ‘and 2=1 #

都没有变化

到这里很多人都会发现个异常,那就是页面没有报错

这个疑问一开始我也有,但是!让我们执行一下一下语句

'order by 1 #

‘order by 5 #

说明 SQL 注入存在而且闭合成功接下来就是其他的一些顺理成章的东西了

代码审计部分

 <?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"]);
}
?>
程序将用户输入的参数带入查询语句没有对其进行过滤所以产生了 SQL 注入
我们现在来分析一下我们所提交的数据
 'and 1=1 #

最 终 的 执 行 语 句 为

SELECT first_name,last_name FROM users WHEREuser_id=’’and 1=1 #’ 

在 mysql 当中#符代表注释符也就是说#后面的引号会

被注释所以导致数据库执行了我们所提交的语句,第一个暴力破解漏洞中的万能密码也是运
用了此原理

Low6:SQLInjection(Blind)(盲注)

Num6:SQLInjection(Blind)(盲注)

漏洞详情: 盲注与普通 SQL 注入大同小异,只不过盲注在返回结果上比较难以发现,可能页面跟正常页面类似或者没有变化,关于具体信息请在后面的源码审计中查看 用 这里使用 SQLMAP 对其进行检测 `

sqlmap.py -u "http://localhost/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#"     -p "id" --cookie     "security=low;PHPSESSID=4e4mefe0ju8k8la9k68qrga7n5"

`

因为DVWA只有登陆后才能使用程序,所以我们这里使用 cookie选项添加我们当前 的cookie,取获取 cookie值只需要使用 burp抓取当前的请求包复制数据包中的cookie参数一栏即可。如果 cookie数据过长可以去掉多余部分,只保留账户密码部分即可。

代码审计

看起来程序跟普通的 SQL 注入程序没有什么区别,但是请注意箭头所指向的@符,PHP
中@用来屏蔽 SQL 语句报出的错误,当前程序使用$num 获取 mysql 的查询结果集,如果

查询的结果不存在就会返回 0 程序也将会停止,但同样因为没有合理过滤用户输入的数据导致盲注漏洞的产生

Num7:File Upload(文件上传漏洞)

漏洞详情 :文件上传漏洞是由于对于用户上传文件后缀名没有合理过滤控制而造成的

这里我们上传一个 php 文件即可上传成功

代码审计

当前程序将用户上传的文件直接以当前文件名保存,对于后缀名没有任何控制导致了上 传漏洞的产生。

Num8:Reflected Cross SiteScripting (反射跨站脚本(xss))

漏洞详情:反射型跨站脚本是由于对于用户输入过滤不严导致的一次性的脚本,攻击输入

<script>alert(/xss/)</script>

由于浏览器的安全设置所以我这里没有弹窗,但是 HELLO 后面所跟随的信息没有显示

表示脚本插入成功,我们再看一下网页代码

代码审计

程序将用户输入信息直接输出,未进行过滤导致反射型 xss 的产生

Num9:Stored Cross SiteScripting(存储跨站脚本)

漏洞详情:存储性跨站脚本是由于对于用户输入过滤不严导致数据存储在文件中的可多触发型的脚本攻击,危害性大于反射型 xss

<script>alert(/xss/)</script>
 <?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // 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)) ? "" : ""));

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

同样将数据插入到页面当中访问即可触发 xss 未弹窗原因同上,此时我们刷新页面即可再次触发 xss

代码审计:

程序将用户输入的数据插入到了数据库中,这期间未对用户输入字符进行过滤导致了存储型 xss 的产生

Middle1:Command Execution

这里我们依旧提交 127.0.0.1 && net user 发现无法执行

这里我们再来尝试一下 127.0.0.1 | net user 成功执行了我们的语句

代码审计

只是简单过滤了&& ;这样的字符,没有完全过滤所以导致了命令执行漏洞的产生

原文发布于微信公众号 - 渗透云笔记(shentouyun)

原文发表时间:2019-08-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券