Skip to Content
全部文章前端大杂烩面试常考-现代前端项目如何防范XSS攻击

面试宝典-前端项目如何防范CSRF攻击

前端面试中,经常会被问到的知识点之一,什么是XSS攻击?

XSS攻击比起CSRF攻击更加需要前端开发者关注,尤其是在一些富文本输入及处理的情况之下。

什么是XSS攻击?

表现

首先什么是xss攻击,官方化的解释是: XSS 攻击,即跨站脚本攻击(Cross-Site Scripting) ,是一种常见的 Web 应用安全漏洞。由于其缩写 CSS 容易与层叠样式表(Cascading Style Sheets)的缩写混淆,所以通常简称为 XSS。

通俗的讲就是,一些别有用心的人,搞了一段不是你项目中的可执行的js代码插入到你的页面里面,并且被成功执行了,这个危害就取决于他这段代码做了些什么事情了。

举个例子: 现有服务端代码:

const express = require('express'); const app = express(); // 处理搜索请求 app.get('/search', (req, res) => { const keyword = req.query.keyword || ''; // 未对用户输入进行过滤,直接嵌入到 HTML 中 const html = `<h1>你搜索的关键词是: ${keyword}</h1>`; res.send(html); }); const port = 3000; app.listen(port, () => { console.log(`服务器运行在 http://localhost:${port}`); });

然后前端请求的地址是:

http://localhost:3000/search?keyword=<script>alert('你被 XSS 攻击了!')</script>

当个地址被加载之后,你的页面就会弹出一个窗口,也就是参数里面的script标签被执行了。

简单来说,就是你的页面被注入了一段可执行的js代码,称之为xss攻击。

另外xss攻击又被细分为3种:

  • 持久型
  • 非持久型
  • dom型

不论类型是什么,xss攻击的核心都在于:一段非法js代码在你页面插入内容时,里面的script标签被执行了。

危害

从上面的例子可以看出,一旦被xss攻击注入代码,基本上比csrf攻击还要可怕,因为这个时候页面上的恶意代码触发一些接口的调用,甚至都可以拿到csrf令牌来伪造请求, 危害性可见非常大,而且现代前端项目中,像富文本处理非常普遍,这大大提高了攻击的可能性。

防范手段有哪些

CSRF攻击原理

我们可以看出来,攻击的主要目的就是让我们的页面执行一些不可信的js脚本,利用一些动态显示内容的地方来执行js代码。

防范手段

当我们知道攻击原理之后,防范主要就是一点:

  • 前端对于动态插入内容的地方对内容进行检查、过滤(最常见的就时对富文本内容的展示之处)

对动态插入的内容也要做一些xss的攻击检查,检查的关键词包括:

  • <script>
  • <iframe>
  • <img>
  • eval()

在js中,用于过滤xss攻击除了自己处理这些数据以外,还可以借助三方包来处理,用的比较多的有:

推荐前端项目中使用DOMPurify,因为他的更新维护比较及时。

安装DOMPurify

npm install dompurify # 或者 yarn add dompurify

在react中使用DOMPurify处理插入内容

import React from 'react'; import DOMPurify from 'dompurify'; const App = () => { const userInput = '<script>alert("XSS")</script>'; const filteredInput = DOMPurify.sanitize(userInput); return ( <div> {/* 使用dangerouslySetInnerHTML插入过滤后的内容 */} <div dangerouslySetInnerHTML={{ __html: filteredInput }} /> </div> ); }; export default App;

在vue中使用DOMPurify

<template> <div> <!-- 不推荐直接使用v-html插入用户输入 --> <div v-html="filteredInput"></div> </div> </template> <script> import DOMPurify from 'dompurify'; export default { data() { return { userInput: '<script>alert("XSS")</script>' }; }, computed: { filteredInput() { // 使用DOMPurify过滤用户输入 return DOMPurify.sanitize(this.userInput); } } }; </script>

效果

示例1
// 包含恶意脚本的输入 const maliciousInput = '<script>alert("XSS Attack!")</script><p>Hello, World!</p>'; // 使用 DOMPurify 进行净化 const cleanOutput = DOMPurify.sanitize(maliciousInput); console.log('原始输入:', maliciousInput); console.log('净化后的输出:', cleanOutput);

输出

  • 原始输入:<script>alert(“XSS Attack!”)</script><p>Hello, World!</p>
  • 净化后的输出:<p>Hello, World!</p>
示例2
// 包含危险属性的输入 const inputWithDangerousAttr = '<img src="javascript:alert(\'XSS\')" alt="Test">'; // 使用 DOMPurify 进行净化 const cleanOutputWithAttr = DOMPurify.sanitize(inputWithDangerousAttr); console.log('原始输入:', inputWithDangerousAttr); console.log('净化后的输出:', cleanOutputWithAttr);

输出

  • 原始输入:<img src=“javascript:alert(‘XSS’)” alt=“Test”>
  • 净化后的输出:<img alt=“Test”>
示例3
const input = '<p style="color: red;">Some text</p><span>Extra text</span><a href="javascript:alert(\'XSS\')">Link</a>'; const config = { ALLOWED_TAGS: ['p', 'span'], ALLOWED_ATTR: ['style'] }; const cleanOutputCustom = DOMPurify.sanitize(input, config); console.log('原始输入:', input); console.log('净化后的输出:', cleanOutputCustom);

输出

  • 原始输入:<p style=“color: red;“>Some text</p><span>Extra text</span><a href=“javascript:alert(‘XSS’)“>Link</a>
  • 净化后的输出:<p><span>Extra style=“color: red;“>Some text</p><span>Extra text</span>

服务端最好也不要大意

可以看到要防止xss攻击,只需要在前端代码动态插入内容的地方严防死守就可以了,但事实上,我更推荐大家在http请求提交到服务器的数据都要做好安全过滤,避免被注入一下非法代码被服务器执行, 同样也可以避免被注入的代码被其他用户请求到前端被执行(持久型xss攻击)。

在服务端对提交的数据也可以使用JSDOM, 同时需要借助jsdom包。

import { JSDOM } from 'jsdom'; import DOMPurify from 'dompurify'; const window = new JSDOM('').window; const purify = DOMPurify(window); const clean = purify.sanitize('<b>hello there</b>');

最后

尽量保证所有的依赖包都保持最新,因为依赖包都有可能爆出一些漏洞,如果你小众网站可能侥幸没人来搞你,但是最好时不抱有侥幸心理。 可以在这里查看一些公开的漏洞数据 https://github.com/advisories

最后编辑于

hi