DVWA简介

DVWA(Damn Vulnerable Web Application)是一个用来进行安全脆弱性鉴定的PHP/MySQL Web应用,旨在为安全专业人员测试自己的专业技能和工具提供合法的环境,帮助web开发者更好的理解web应用安全防范的过程。

DVWA共有十个模块,分别是Brute Force(暴力(破解))、Command Injection(命令行注入)、CSRF(跨站请求伪造)、File Inclusion(文件包含)、File Upload(文件上传)、Insecure CAPTCHA(不安全的验证码)、SQL Injection(SQL注入)、SQL Injection(Blind)(SQL盲注)、XSS(Reflected)(反射型跨站脚本)、XSS(Stored)(存储型跨站脚本)。

需要注意的是,DVWA 1.9的代码分为四种安全级别:Low,Medium,High,Impossible。初学者可以通过比较四种级别的代码,接触到一些PHP代码审计的内容。

CSRF(Cross-site request forgery)

CSRF,全称Cross-site request forgery,翻译过来就是跨站请求伪造,是指利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等)。CSRF与XSS最大的区别就在于,CSRF并没有盗取cookie而是直接利用。而最常见的就是QQ空间的登陆。

low级别:

代码:

<?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>密码已更改.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>密码不匹配.</pre>";
} ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
} ?>

可以看到,服务器收到修改密码的请求后,会检查参数password_new与password_conf是否相同,如果相同,就会修改密码,并没有任何的防CSRF机制(当然服务器对请求的发送者是做了身份验证的,是检查的cookie,只是这里的代码没有体现)。

方法一:构造链接:

当我们改密码时:

修改完之后得到链接:http://192.168.5.100/dvwa/vulnerabilities/csrf/?password_new=admin&password_conf=admin&Change=%E6%9B%B4%E6%94%B9#

这个时候只要受害者点击了这个链接,他的密码就会更改为admin。这种方式其实比较直接,链接一看就是修改密码的,而且修改完之后就知道自己的密码被篡改了。

需要注意的是,CSRF最关键的是利用受害者的cookie向服务器发送伪造请求,所以如果受害者之前用Chrome浏览器登录的这个系统,而用搜狗浏览器点击这个链接,攻击是不会触发的,因为搜狗浏览器并不能利用Chrome浏览器的cookie,所以会自动跳转到登录界面。

在大多数时候我们要转换成短链接伪装一下:https://dwz.cn/

比如我之前写过的博客的链接:https://www.cnblogs.com/hzk001/p/12250520.html

缩短链接变成:https://dwz.cn/OWaaAZ86

这样我输入哪个都能进入到博客网址里面,和淘宝口令类似。注意,这里不能用本机的ip地址所以没有把dvwa的地址变成短链接。因为本地搭的环境,服务器域名是ip所以无法生成相应的短链接= =,实际攻击场景下只要目标服务器的域名不是ip,是可以生成相应短链接的。

虽然利用了短链接隐藏url,但受害者最终还是会看到密码修改成功的页面,所以这种攻击方法也并不高明。

现实攻击场景下,这种方法需要事先在公网上传一个攻击页面,诱骗受害者去访问,真正能够在受害者不知情的情况下完成CSRF攻击。这里为了方便演示,就在本地写一个test.html,下面是具体代码。

<img src="http://192.168.5.100/dvwa/vulnerabilities/csrf/?password_new=admin&password_conf=admin&Change=%E6%9B%B4%E6%94%B9#" border="0" style="display:none;"/>

<h1>404<h1>

<h2>file not found.<h2>

当受害者访问时,会误认为这是一个失效的url,但是上已经遭受CRSF攻击,密码已经更改

Medium

代码:

<?php 

if( isset( $_GET[ 'Change' ] ) ) {
// Checks to see where the request came from
if( eregi( $_SERVER[ 'SERVER_NAME' ], $_SERVER[ 'HTTP_REFERER' ] ) ) {
// 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 = mysql_real_escape_string( $pass_new );
$pass_new = md5( $pass_new ); // Update the database
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</pre>' ); // Feedback for the user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
}
}
else {
// Didn't come from a trusted source
echo "<pre>That request didn't look correct.</pre>";
} mysql_close();
} ?>

相关函数说明

int eregi(string pattern, string string)

检查string中是否含有pattern(不区分大小写),如果有返回True,反之False。

可以看到,Medium级别的代码检查了保留变量 HTTP_REFERER(http包头的Referer参数的值,表示来源地址)中是否包含SERVER_NAME(http包头的Host参数,及要访问的主机名,这里是192.168.5.100),希望通过这种机制抵御CSRF攻击。

但是我们可以将攻击页面命名为192.168.5.100.html,(页面被放置在攻击者的服务器里,与其不相同)就可以绕过了,从而修改密码

high

代码:

<?php 

if( isset( $_GET[ 'Change' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // 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 = mysql_real_escape_string( $pass_new );
$pass_new = md5( $pass_new ); // Update the database
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</pre>' ); // Feedback for the user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
} mysql_close();
} // Generate Anti-CSRF token
generateSessionToken(); ?>

可以看到,High级别的代码加入了Anti-CSRF token机制,用户每次访问改密页面时,服务器会返回一个随机的token,向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求。

而要利用这个 漏洞就用到XSS弹出token:

这里相当于XSS和CSRF的组合拳:先用xss弹出token 因为name中有长度限制,所以抓包修改参数绕过限制:

<iframe src="../csrf"onload=alert(frames[0].document.getElementsByName('user_token')[0].value)>

拿到token

最新文章

  1. C# - 多线程 之 锁系统
  2. maven总结5
  3. matlab squeeze函数的用法
  4. java多线程-CountDownLatch
  5. 模拟 2013年山东省赛 J Contest Print Server
  6. 学习笔记:iPhone终极指南、手机端、浏览器各种规范
  7. Bash Shell字符串操作小结
  8. lable自动适配大小
  9. 爱拼图游戏android源码完整版
  10. C语言结构体的引入
  11. 【DP_树形DP专题】题单总结
  12. hdr(host), hdr_beg(host) , path_beg
  13. Swift - 将String类型的数字转换成数字类型
  14. scrollTop doesn&#39;t scroll on Chrome 61
  15. JVMGC机制
  16. 【English】十六、时间相关
  17. location对象的一些属性和方法
  18. 难以接受你的改变:从project.json到.csproj
  19. [转][JSBSim]使用VS2015编译JSBSim
  20. linux-openvpn

热门文章

  1. 2021/2/5 关于new的一个教训
  2. C语言:常量写法
  3. ZooKeeper 分布式锁 Curator 源码 02:可重入锁重复加锁和锁释放
  4. 【剑指offer】42.和为S的两个数字
  5. python之数据驱动Excel+ddt操作(方法二)
  6. linux xsel命令
  7. Appium - adb monkey参数(三)
  8. SpringBoot读取Resource下文件的几种方式(十五)
  9. 第三篇 -- HTML基础
  10. 第四十九篇 -- 添加联系人信息Addcontact