05-CSRF
1 CSRF概述
1.1 概述
CSRF (Cross-Site Request Forgery) 跨站请求伪造,也可称为一键式攻击 (one-click-attack),通常缩写为 CSRF 或者 XSRF。
CSRF 攻击是一种挟持用户在当前已登录的浏览器上发送恶意请求的攻击方法。相对于XSS利用用户对指定网站的信任,CSRF则是利用网站对用户网页浏览器的信任
。
攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
例如,攻击者在一个社交媒体网站上发送一个链接,要求受害者点击该链接以查看某张照片。然而,该链接实际上是一个伪装的请求,它会向受害者已登录的银行账户发送一条转账请求,而受害者并不知道自己的账户已经被攻击者攻击。
1.2 原理
前提:
- 用户必须登录站点且保持登录状态
- 伪装链接地址,能诱导用户点击链接
- 找到受攻击的用户群体,并把链接发给他。不管用什么方式 钓鱼 邮件 短信
- 用户必须在同一个浏览器上点击你发的链接地址
原理:
- 攻击者构造出一个后端请求地址,诱导用户点击或者通过某些途径自动发起请求。
- 如果用户是在登录状态下的话,后端就以为是用户在操作,从而进行相应的逻辑。
案例1:登录a网站,可以实现转账功能(get请求),然后在相同浏览器页面上点击b网站,访问了一张图片,图片底层代码有a网站的转账请求,然后就成功了
案例2:登录a网站,可以实现转账功能(post请求),然后在相同浏览器上,访问了网站b,内嵌了一个iframe,post请求的内容是hidden,然后页面只有一个submit,当你点击时,a网站就会转账1000000元。
1.3 类型
1)主动攻击型
- 受害者访问a.com并在自己浏览器留下a.com的登录态(比如cookie)
- 攻击者诱导受害者访问网站b.com
- 网站b.com植有访问a.com接口的恶意代码(删除/增加/修改等),浏览器请求头中会默认携带a.com网站的cookie
- 受害者点击b.com时候,b.com带着a.com的登陆凭证冒充受害用户执行对a.com的恶意操作
2)被动攻击型
- 攻击者在a.com发布带有恶意链接的帖子或者评论(提交对a.com带有增删改的诱导型img/form/a标签)
- 当其他拥有登录态的受害者点击该评论的恶意链接冒用受害者登录凭证发起攻击
- CSRF主要是冒用受害者登录凭证发起恶意的增删改并不会窃取受害者隐私信
2 使用
2.1 get类型
针对客户关系管理系统(网站a),新增用户请求:
http://192.168.190.133/crm/php/add.php?account=test02&password=123456&name=张三
# 或者转账、删除用户、...一些列破坏操作
攻击者服务器网页代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>全国可飞</title>
<style>
a {
text-decoration: none;
}
</style>
</head>
<body>
<a href="http://192.168.190.133/crm/php/add.php?account=test02&password=123456&name=张三">
<img src="https://img1.baidu.com/it/u=342277134,1682059924&fm=253&fmt=auto&app=120&f=JPEG?w=750&h=500">
<p>全国可飞,点我加V</p>
</a>
</body>
</html>
2.2 post类型
特点:
1)攻击一般发起在第三方网站,而不是被攻击的网站(被攻击的网站无法防止攻击发生)
2)攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作,而不是只窃取数据。
3)整个攻击过程攻击者并不能获取受害者的登录凭证,而只是冒用
4)夸张那请求可以用各种方式:图片url、超链接、CORS、form等等,部分请求可以直接嵌入在第三方论坛、文章中,难以进行跟踪
1)修改add功能为post请求
<?php
// 文件包含
include "dbUtil.php";
// 接收表单数据
$account = $_POST["account"];
$password = $_POST["password"];
$name = $_POST["name"];
// 账号不能重复
$sql = "select * from userinfo where account='$account';";
$arr = queryOne($sql);
if(count($arr)){
echo "账号已存在,新增失败";
}else{
$sql = "insert into userinfo(account,password,na