CSRF简介

CSRF中文名:跨站请求伪造,英文译为:Cross-site request forgery,CSRF攻击就是attacker(攻击者)利用victim(受害者)尚未失效的身份认证信息(cookie、session等),以某种方式诱骗victim点击attacker精心制作的恶意链接或者访问包含恶意攻击代码的页面,当victim触发成功之后,恶意代码会被执行,浏览器默默的向目标service发出请求加载着victim尚未失效的身份认证信息,导致victim替attacker完成了非法操作比如:在某些论坛上发布大量的恶意言论、网站用户密码被恶意篡改、账户金额被盗取、删除网站个人信息~~~~~

漏洞测试

通过DVWA平台,对CSRF漏洞进行测试,让大家走进CSRF的世界

环境:dvwa服务IP      :192.168.43.146

attacker服务IP :192.168.43.150

low level

查看源码:

<?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>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
} ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
} ?>

代码审计之后发现:网站没有对CSRF做出防范,只对网站进行了SQL防御(通过mysqli_real_escape_string()函数的过滤作用,将用户传入的数据中的特殊字符进行转义,有效预防了attacker对网站的SQL注入攻击)

mysqli_real_escape_string()函数详细介绍:

定义和用法
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。 下列字符受影响: \x00
\n
\r
\
'
"
\x1a
如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。 语法
mysql_real_escape_string(string,connection) 参数 描述
string 必需。规定要转义的字符串。
connection 可选。规定 MySQL 连接。如果未规定,则使用上一个连接。 //有效预防了数据库攻击

既然网站没有对CSRF保护那么attacker就可以直接进行攻击

用户正常修改密码:

用户非正常修改密码:

attacker制作含有恶意攻击代码网页

恶意代码:

<iframe hidden src="http://192.168.43.146/dvwa/vulnerabilities/csrf/?password_new=attacker&password_conf=attacker&Change=Change#"></iframe>

attacker将代码嵌入自己的钓鱼网页中,当victim受害者被诱导访问该网页时,恶意代码就会自动被浏览器所执行并携带着victim未失效的身份认证信息向目标服务器发出请求,而victim却毫无察觉,自己的用户密码已经被attacker恶意篡改

victim被attacker诱导浏览自己网站上的图片(恶意代码就隐藏在该网页中)

你会发现该网站一切好像很正常&很美好,但自己却不知道已经被攻击了,网站密码已经被修改为attacker

此时victim再去登陆时会发现自己已经login不上了

medium level

查看源码:

<?php

if( isset( $_GET[ 'Change' ] ) ) {
// Checks to see where the request came from
if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {
// 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>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>";
} ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
} ?>

代码审计发现:该网站进行了referer字段检测,该字段限制了不是同一个域的不能跨域访问,attacker要想进行CSRF攻击只要绕过if条件就可以,接下来分析该if条件

if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false )

$_SERVER[ 'HTTP_REFERER' ] 获取网页请求的来源URL

$_SERVER[ 'SERVER_NAME' ] 获取目标服务器的域名

$_SERVER[ 'HTTP_REFERER' ]和$_SERVER[ 'SERVER_NAME' ]通过stripos()进行匹配,查看$_SERVER[ 'SERVER_NAME' ]字符串是否包含在$_SERVER[ 'HTTP_REFERER' ]中,从而判断用户的服务请求是否是跨域请求,若是跨域请求则会被目标服务器所拒绝访问

attacker可以有两种方法进行绕过:

第一种:将网页的名字改为$_SERVER[ 'SERVER_NAME' ].html
第二种:添加网页父目录包含$_SERVER[ 'SERVER_NAME' ]

在这里使用第一种方法进行绕过:

victim浏览该网页,恶意代码被成功执行,victim的网站密码被恶意篡改

high level

查看源码:

<?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 = ((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>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
} ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
} // Generate Anti-CSRF token
generateSessionToken(); ?>

代码审计发现:该网站进行了user_token的检测

user_token:

当用户每次访问修改用户密码页面时,服务器会先返回一个随机的token,接下来当用户向服务器发起修改密码请求时,需要提交user_token,当请求到达服务器时,服务器会优先检查token,判断客户端的token和服务端的token是否匹配,若不匹配,服务器则会拒绝客户端的请求

在这里attacker是不能伪造token的,因为token是一个很长的随机数,attacker要想CSRF攻击成功,只有通过利用网站的XSS漏洞获取用户的token

XSS利用代码获取user_token:

<iframe src="../csrf" onload=alert(document.getElementsByName('user_token'))></iframe>

有关XSS的利用可以查看笔者的这篇文章(https://www.cnblogs.com/qftm/p/10317166.html)

利用user_token进行CSRF攻击

构造恶意代码:

victim浏览存在恶意攻击的网页

攻击成功

impossible level

查看源码:

<?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 = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_curr ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$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 = ((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 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(); ?>
代码审计发现:用户修改网站密码不仅需要user_token的验证还需要用户输入当前密码进行验证,因此,attacker不能对用户进行CSRF攻击

总结

学过CSRF和XSS之后,你可能会有疑惑,它们两个一样吗,不用多说,相信大家看名字就知道不一样

CSRF攻击是直接利用用户尚未失效的cookie,并伪造特殊的请求对用户造成危害的一种攻击手段

XSS攻击是直接盗取用户的cookie,所造成的一种攻击手段

两者看似相似,当又有一些不一样的地方

CSRF 漏洞测试的更多相关文章

  1. DedeCMS flink_add Getshell漏洞 管理员CSRF漏洞

    DedeCMS flink_add Getshell漏洞 管理员CSRF漏洞 1.漏洞利用 由于tpl.php中的$action,$content,$filename变量没有初始化,从而能操纵这些变量 ...

  2. web端常见安全漏洞测试结果分析-- appscan

    基于appscan测试结果分析: 一.XSS跨站脚本 指的是攻击者往Web页面里插入恶意html代码,通常是JavaScript编写的恶意代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被 ...

  3. 浅谈CSRF漏洞

    前言: 看完小迪老师的CSRF漏洞讲解.感觉不行 就自己百度学习.这是总结出来的.   歌曲:   正文: CSRF与xss和像,但是两个是完全不一样的东西. xss攻击(跨站脚本攻击)储存型的XSS ...

  4. 从Java的角度修复CSRF漏洞

    漏洞挖掘中,说实话挖过最多的漏洞就属CSRF漏洞了,提交CSRF漏洞很多次,绕过CSRF防御进行攻击也有很多次.CSRF漏洞是一个很容易引发的问题,今天我从Java的角度来说下这个安全漏洞的修复方案. ...

  5. 【代码审计】YzmCMS_PHP_v3.6 CSRF漏洞分析

      0x00 环境准备 YzmCMS官网:http://www.yzmcms.com/ 程序源码下载:http://pan.baidu.com/s/1pKA4u99 测试网站首页: 0x01 代码分析 ...

  6. 用代码来细说Csrf漏洞危害以及防御

    开头: 废话不多说,直接进主题. 0x01 CSRF介绍:CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session ...

  7. CSRF漏洞原理说明与利用方法

    翻译者:Fireweed 原文链接:http://seclab.stanford.edu/websec/ 一 .什么是CSRF Cross-Site Request Forgery(CSRF),中文一 ...

  8. csrf漏洞攻击手段和影响详解

    针对web应用安全中csrf漏洞两种典型的攻击方式:即输入和执行,这种简单模式下的攻击手段以及中途包含确认页面的攻击方法. 图解什么是csrf漏洞 我们先进行约束,比如存在csrf漏洞的网站叫webA ...

  9. CSRF漏洞详细说明

    CSRF漏洞详细说明 通常情况下,有三种方法被广泛用来防御CSRF攻击:验证token,验证HTTP请求的Referer,还有验证XMLHttpRequests里的自定义header.鉴于种种原因,这 ...

随机推荐

  1. 2019年3月2日-小雨.md

    2019年3月2日, 星期六 开学已经一周了,时间好像限制了自己进步的脚步,一个人的精力有限,想做好方方面面实在是太难了,有很多事儿最后都没做的完美.相反,自己应该放下繁琐的包袱,简简单单的干一件事儿 ...

  2. Android应用程序如何使用Internet资源?

    思路:连接Internet资源-->分析XML资源-->使用Download Manager下载文件 Android的Internet连接模型和用于分析Internet数据源的Java技术 ...

  3. DW1000 用户手册中文版 附录2 IEEE-802.15.4 MAC层

    由于已经在wode中排版无法直接复制到博客中,故本节博客发布使用了图片. 论坛可下载PDF  http://bphero.com.cn/forum.php?mod=viewthread&tid ...

  4. 解决Idea无法提示代码、不检查语法的方法

    今天打开Idea做项目的时候,java代码图标出现异常(不是以前的C图标),所有java文件都只有两种颜色,百度查了一下,Idea有一个叫power save mode,在file -> Pow ...

  5. vue-These relative modules were not found

    今天在做vue2.0+webpack的项目的时候,本来一切正常,整理了一下文件夹分类,就是把一些基础的组件新建了一个文件夹移进去,然后就报了以下的错误,其他东西都没改 最后网上找了很多资料,有说配置文 ...

  6. idea设置调用方法时提示方法注释

    如图所示:打开file-->setting-->Editor-->General,搜索show,然后勾选上Show quick documentation on mouse move ...

  7. php操作数组函数

    整理了一份PHP开发中数组操作大全,包含有数组操作的基本函数.数组的分段和填充.数组与栈.数组与列队.回调函数.排序.计算.其他的数组函数等. 一.数组操作的基本函数 数组的键名和值 array_va ...

  8. 使用Jacksum对文件夹和文件生成checksum

    Jacksum 是一个java开源工具, 用来 给单个文件生成checksum, 也可以给整个文件中所有文件生成checksum,生产的checksum 可以是MD系列,也可sha. 你可以参考​ 官 ...

  9. spring-cloud-Zuul学习(四)【中级】--自定义zuul Filter详解【重新定义spring cloud实践】

      实现自定义zuul Filter 方法很简单,只要继承ZuulFilter跟加入到spring IOC容器即可,zuulFilter是一个抽象类,里面包含以下方法需要我们实现: String fi ...

  10. CrypMic分析报告

    一.概述 病毒伪装为NirSoft公司的软件NirCmd并加了MPRESS壳,脱壳后是一个混淆过的PE程序,运行时会用到类似PE映像切换的方式来释放出实际的恶意代码,恶意代码主要对文件进行加密. 二. ...