查漏补缺-前端安全之XSS与CSRF

XSS

XSS(Cross Site Scripting)跨站脚本攻击

简称本应为css,但是为了防止与CSS(Cascading Style Sheets,层叠样式表)搞混,就取为xss

跨站脚本攻击就是用 JS 脚本攻击,案例如下:

情景模拟

假设有一个前后端不分离的网站,后端用express搭建,文件 app.js 内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const express = require('express') // npm i express
const path = require('path')
const app = express()
const ejs = require('ejs'); // npm i ejs

app.set('views', path.join(__dirname, 'views')); // views的文件都会被当作模板被读到
app.engine('html', ejs.__express);
app.set('view engine', 'html'); // 让模板引擎生效

app.get('/', function (req, res) { // 定义一个跟路径
res.render('index', {title:'express', xss: req.query.xss}) // res.render向前端输出
})

app.listen(3000, () => {
console.log('listening on 3000');
})

而其返回的 HTML 页面 index.html 内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %></title>
</head>
<body>
<h1><%= title %></h1>
<p>hello <%= title %></p>
<div>
<%- xss %>
</div>
</body>
</html>

现在在浏览器中输入URL:http://localhost:3000/?xss=123 ,title已经被默认赋值为 expressxss则被赋值为 123,可以得到如下页面

1.png

如果这时,我们把参数换成一个script标签,并且在script里面写个alert,用来模拟脚本攻击,具体URL为:

1
http://localhost:3000/?xss=<script>alert('你被攻击了')</script>

1.gif

URL里可以设置任何类型的参数,所以理论上可以写一个输入框,这样用户可能在访问网址时弹出输入框,并误以为这是银行网站自己弹出的内容,从而在输入框中输入如密码等重要信息,而黑客已经在后台获取了这些资料

XSS的危害

  1. 窃取cookie信息:黑客可以在其他电脑上模拟登录状态
  2. 可以监听用户行为:可以监听用户点击键盘的行为,得到用户信息
  3. 伪造登录窗口
  4. 在你的页面生成浮窗广告

浮窗广告例子:在body中添加一个 div

1
http://localhost:3000/?xss=<script>let div = document.createElement('div');document.body.appendChild(div);div.style.width = '300px';div.style.height = '200px';div.style.border = '1px solid black';div.style.position = 'fixed';div.style.top = '300px';div.style.left = '300px';</script>

2.gif

如何注入?

那么问题来了,XSS是在URL中写入参数,用户又不会自己入侵自己,如何将脚本放到别人的客户端上运行呢?

  1. 反射型攻击:在url中写入参数,也就是上面的例子,比如攻击者发送的钓鱼短信等等,如果受害者点击并且执行,就会执行恶意脚本

img

  1. 存储型攻击:这种情况更加复杂一些,比如某网站存在一个评论区,我在评论区输入脚本,那么连带脚本的这部分内容就会被存入到数据库中,其他受害者点击这些评论时(可能模拟为某些按钮或文本),就有可能触发这类内容

img

  1. DOM型攻击:一种基于 HTML 解析 DOM 过程中的安全漏洞进行的跨站攻击,攻击的过程与反射型XSS攻击极其类似,差异在于反射型XSS会把攻击脚本传递给服务器,而DOM型XSS不需要,从而可以绕过WAF、躲避服务端的检测。

    DOM型XSS攻击通常也是攻击者诱导用户访问一个恶意网站,用户在输入数据后,js脚本将这些内容组合成被篡改的DOM片段,并在其中注入恶意脚本,而浏览器只要解析这些DOM片段,就会执行这些恶意脚本,从而窃取用户信息。

如何防范XSS

  1. 对输入参数进行强校验,把不安全字符(如 <, >, / 等) 过滤,从而避免浏览器执行这些内容
  2. 将用户输入的内容返回到页面上时,同样进行校验,防止被解析为HTML标签
  3. 使用 HTTPOnly cookie,这样 js 脚本不能读取到 cookie 信息
  4. 使用如验证码等安全控件来应对一些特殊页面(登录、支付页面)
  5. 设置 CSPContent Security Policy),通过白名单和黑名单限制加载的资源类型和来源,从而防止恶意脚本的加载和执行
  6. 使用 innerTexttextContent 等更安全的 API 取代 innerHTML
  7. 限制用户输入
  8. 提示用户小心恶意链接

CSRF

CSRF (Cross Site Request Forgery) 跨站请求伪造

是指指恶意攻击者利用用户已经登录其他网站的“身份”伪造用户的请求

img

受害者正常访问 aa.com ,其登录状态保存在浏览器中

而如果其访问 bb.com(恶意网站),网站会利用同一个浏览器中 aa.com 的登录状态,直接向 aa.com 发送其他恶意请求

如何防范

  1. 利用好CookieSameSite属性,防止跨站点使用 cookie
  2. 服务端验证请求来源,比如Origin字段记录了请求来源地址,杜绝第三方站点请求源
  3. 在用户进行敏感操作前进行用户身份验证
  4. 使用 CSRF Token,在提交请求时一并提交,由服务端进行验证
  5. 设置 CSPContent Security Policy),通过白名单和黑名单限制加载的资源类型和来源,从而防止恶意脚本的加载和执行

查漏补缺-前端安全之XSS与CSRF
https://username.github.io/2024/09/06/查漏补缺-前端安全之XSS与CSRF/
作者
ZhuoRan-Takuzen
发布于
2024年9月6日
许可协议