DVWA通关笔记​

2025-05-30 09:39:38

DVWA通关笔记 ​DVWA 是一个入门的 Web 安全学习靶场,结合源码去学习的话,是个入门安全的好靶场,这个靶场是我刚入行的时候练习的,当时还没有记录的习惯,所以这里只提供部分题解,等以后有时间了再慢慢补上吧!

环境配置 ​DVWA、kali2020.4、火狐浏览器、中国蚁剑

firefox渗透浏览器下载: 链接:https://pan.baidu.com/s/1zBSl8CyJN6HHbsYC1JpOlQ 提取码:zj13

环境的搭建毫无意义,应该注重漏洞本身,这边建议直接docker拉一个镜像

dockerfile# 拉取镜像

docker pull sqreen/dvwa

# 部署安装

docker run -d -t -p 8888:80 sqreen/dvwaBrute Force 暴力破解 ​在 Web 安全领域暴力破解是一个基础技能,不仅需要好的字典,还需要具有灵活编写脚本的能力。

Low ​暴力破解一般就是加线程,然后就是看字典大不大、好不好。写的话有点浪费时间。这里提供思路吧

查看源码

phpif( isset( $_GET[ 'Login' ] ) ) {

# 获取用户名和密码

$user = $_GET[ 'username' ];

$pass = $_GET[ 'password' ];

$pass = md5( $pass );

# 查询验证用户名和密码

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

$result = mysql_query( $query ) or die( '

' . mysql_error() . '
' );

if( $result && mysql_num_rows( $result ) == 1 ) {

# 输出头像和用户名

$avatar = mysql_result( $result, 0, "avatar" );

echo "

Welcome to the password protected area {$user}

";

}

else {

登录失败

}

mysql_close();

}源码审计,发现用户名和密码都没有进行过滤,直接单线程字典跑一下即可

Medium ​查看源码

php// 对用户名和密码进行了过滤

$user = $_GET[ 'username' ];

$user = mysql_real_escape_string( $user );

$pass = $_GET[ 'password' ];

$pass = mysql_real_escape_string( $pass );

$pass = md5( $pass );

// 验证用户名和密码

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

if( $result && mysql_num_rows( $result ) == 1 ) {

登录成功

}

else {

sleep( 2 );

登录失败

}代码审计发现这里做了一点小改动,登录失败的时候会延时 2 秒,这样爆破的速度会慢一些,爆破问题不大

High ​查看源码

php// 检测用户的 token

checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

// 过滤用户名和密码

$user = $checkToken_GET[ 'username' ];

$user = stripslashes( $user );

$user = mysql_real_escape_string( $user );

$pass = $_GET[ 'password' ];

$pass = stripslashes( $pass );

$pass = mysql_real_escape_string( $pass );

$pass = md5( $pass );

// 数据匹配

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

$result = mysql_query( $query ) or die( '

' . mysql_error() . '
' );

if( $result && mysql_num_rows( $result ) == 1 ) {

登录成功

}

else {

sleep( rand( 0, 3 ) );

登录失败

}这一关增加了 token 的检测,下面简单介绍下bp爆破过程

bp拦截包,选择Pitchfork模式,并且给要破解的项带上美元符号

给第一个项加playload

给第二个项加playload

匹配的值是需要我们去抓到的

首先将线程的值改为1

然后到options中Grep-Extract中添加匹配规则

选中并复制

粘贴到这里

找到Redirections模块设置允许重定向,选择always

爆破准备环节完成,开始爆破。

爆破成功

Command Injection ​用户可以执行恶意代码语句,在实战中危害比较高,也称作命令执行,一般属于高危漏洞。

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 "

{$cmd}
";

}

?>注意到这里有两个函数,stristr和php_uname

stristr函数搜索字符串在另一字符串中的第一次出现,返回字符串的剩余部分(从匹配点),如果未找到所搜索的字符串,则返回 FALSE。参数string规定被搜索的字符串,参数search规定要搜索的字符串(如果该参数是数字,则搜索匹配该数字对应的 ASCII 值的字符),可选参数before_true为布尔型,默认为"false" ,如果设置为 "true",函数将返回 search 参数第一次出现之前的字符串部分。

php_uname(mode)这个函数会返回运行php的操作系统的相关描述,参数mode可取值”a” (此为默认,包含序列”s n r v m”里的所有模式),”s ”(返回操作系统名称),”n”(返回主机名),” r”(返回版本名称),”v”(返回版本信息), ”m”(返回机器类型)。

这里通过判断操作系统执行不同ping命令,但是对ip参数并未做任何的过滤,导致任意命令注入。

结果验证

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 "

{$cmd}
";

}

?>相比Low级别的代码,这里对ip参数做了一定过滤,str_replace把&& 、;替换为空字符,因为被过滤的只有&&与;,所以可以使用&绕过。由于使用的是str_replace把”&&” 、”;”替换为空字符,因此可以采用以下方式绕过:127.0.0.1&;&ipconfig

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 "

{$cmd}
";

}

?>这里进一步完善了黑名单,把”| ”(注意这里|后有一个空格)替换为空字符,于是 可以用”|”绕过。

CSRF 跨站请求伪造 ​Medium ​首先尝试低级别的payload

http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=2&password_conf=2&Change=Change#失败了,抓包看看正常修改密码和利用csrf修改密码的包有什么不一样 正常修改密码 csrf修改 发现利用csrf构造的包差一个referer头,查看源代码可知,中级确实对referer做出了认证, 所以只需要将正常修改密码的referer信息添加到包里面就好 修改成功

High ​正常修改密码的样子

可以看到高级增加了token验证,并且每次都会改变,所以这里使用XSS漏洞先获取token值切换到存储型XSS,payload:

点击进入首页