20201209学习日记---Csrf

早几年了解过HTTP请求,今天从CTF的角度上去看了一下请求中存在的漏洞。

HTTP请求

HTTP其实很多学问,包括请求头(header),代理(agent)等等,在这里先再了解一下几个常用的HTTP请求。最常用的应该是get和post了,而除此之外还有put delete 等等。
表单提交中get和post方式的区别有5点

  1. get是从服务器上获取数据,post是向服务器传送数据。
  2. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTPpost机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。
  3. 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。
  4. get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。(这里有看到其他文章介绍get和post的传送数据大小跟各个浏览器、操作系统以及服务器的限制有关)
  5. get安全性非常低,post安全性较高。
    根据以往的经验来看,大多数api的请求都要求使用post方式。而一般流量一般的网页则用get方式。而put和delete很少用,且很多都能够用post代替。

CSRF跨站请求伪造

钓鱼网站,界面操作和真是的页面一模一样,当用户操作转账功能的时候,转账数据也会发送到真实的后台,但是其中用户输入的信息中对端账户可能会被修改掉,导致用户确实转账了,但是钱却转给了别人

以下内容摘自ctfwiki

CSRF 类型

按请求类型,可分为 GET 型和 POST 型。

按攻击方式,可分为 HTML CSRF、JSON HiJacking、Flash CSRF 等。

HTML CSRF

利用 HTML 元素发出 CSRF 请求,这是最常见的 CSRF 攻击。

HTML 中能设置 src/href 等链接地址的标签都可以发起一个 GET 请求,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<link href="">
<img src="">
<img lowsrc="">
<img dynsrc="">
<meta http-equiv="refresh" content="0; url=">
<iframe src="">
<frame src="">
<script src=""></script>
<bgsound src=""></bgsound>
<embed src=""></bgsound>
<video src=""></video>
<audio src=""></audio>
<a href=""></a>
<table background=""></table>
......

还有 CSS 样式中的:

1
2
3
@import ""
background:url("")
......

也可使用表单来对 POST 型的请求进行伪造。

1
2
3
4
5
6
7
8
9
10
<form action="http://www.a.com/register" id="register" method="post">
<input type=text name="username" value="" />
<input type=password name="password" value="" />
</form>
<script>
var f = document.getElementById("register");
f.inputs[0].value = "test";
f.inputs[1].value = "passwd";
f.submit();
</script>

Flash CSRF

Flash 也有各种方式可以发起网络请求,包括 POST。

1
2
3
4
5
6
7
8
9
import flash.net.URLRequest;
import flash.system.Security;
var url = new URLRequest("http://target/page");
var param = new URLVariables();
param = "test=123";
url.method = "POST";
url.data = param;
sendToURL(url);
stop();

Flash 中还可以使用 getURLloadVars 等方式发起请求。

1
2
3
req = new LoadVars();
req.addRequestHeader("foo", "bar");
req.send("http://target/page?v1=123&v2=222", "_blank", "GET");

CSRF实例

直接通过引文中的内容来实例化,进行CSRF攻击需要有两样东西

  • cookie
  • 仿造表单

    用户正常登录

  1. 用户在正常访问目标网站的时候登录账户,产生相应的cookie,成功变成登录状态。
  2. 用户在不知情的情况下进入受到篡改的网页。

跨站请求伪造

这时候需要伪造一个网页,表单值账户填写自己的账户即可,示例代码

1
2
3
4
5
<form action="http://127.0.0.1/" id="register" method="post">
<input type="hidden" name="to_account" value="admin" /></br>
<input type="hidden" name="money" value="9999" /></br>
<input type="submit" value="点击领取优惠卷" />
</form>

示例图:
rCRf54.png

模拟表单向目标服务器发送请求

通过模拟表单 向已经登录的网站发送请求 即可完成csrf攻击。

CSRF防御

常见的csrf防御其实经常可以见到。

验证码

验证码强制用户必须与应用进行交互,才能完成最终请求。
所以这样为什么那么多网站需要设置验证码,当然验证码的作用还不知这些,比方说还有防爬等作用。

验证Referer

检查请求是否来自合法的源。但服务器并非什么时候都能取得 Referer

Token

CSRF 能够攻击成功的本质原因是重要操作的所有参数都可以被攻击者猜测得到。
token验证(应该也是最常用的验证方式),在许多api的开发文档当中都会涉及到验证token的环节。
Token must be random enough. In addition, the purpose of Token is not to prevent duplicate submissions, so for the convenience of use, it is allowed to use the same Token in the lifetime of a user before the Token is consumed, but if the user has already submitted the form, the Token has Consumed, the token should be regenerated.
Token should also pay attention to its confidentiality. If the Token appears in the URL, it may be leaked through the Referer. Try to put the Token in the form, change the sensitive operation from GET to POST, submit it as a form or AJAX, avoid Token. Give way.

写在后面

这样的攻击(我甚至觉得这不应该称为攻击)常常出现在我们周边,当然真正的攻击远不止那么简单,需要用到多方面的漏洞,当然对于攻击的防御现在运用到哈希散列等等的知识。