# XSS (跨站脚本攻击)
有用户输入的地方就有可能发生XSS攻击。
# XSS分类
- 反射型。通过URL参数直接注入。
- 存储型。存储到DB后读取时注入。
# 反射型
对于反射型的XSS,通常通过短网址类来传播。
例如带有script的url: http://abc.com?from=<script>alert(1)</script>
生成短网址后可能为 https://4m.cn/c69o6
生成短网址网站有 https://4m.cn/
# 存储型
存储型的xss危害更大,因为传播时不用改变url。 通过评论啊,留言啊之类的写入数据库。
# XSS 攻击注入点
- HTML节点内容
- HTML属性
- JavaScript代码
- 富文本
# HTML节点内容注入
<div>
#{content}
</div>
如果content的值是 <script>alert(1)</script> 则在页面上显示
<div>
<script>alert(1)</script>
</div>
# HTML属性注入
<img scr="#{image}"/>
如果 image的值是 "1 onerror="alert(1) 则在页面上显示
<img scr="1" onerror="alert(1)"/>
# JavaScript代码注入
<script>
var data = "#{data}";
<script/>
如果 data 的值是 hello";alert(1);" 则在页面上显示
<script>
var data = "hello";alert(1);"";
<script/>
# 富文本注入
由于富文本就是带有格式的HTML,因此风险更高。
# XSS防御
- 浏览器自带防御
- 代码中防御
- CSP 内容安全策略
# 浏览器自带防御
一些浏览器可以防御反射型并通过HTML内容和属性注入的脚本.
# 代码中防御
对于HTML节点内容注入,HTML属性注入,JavaScript代码注入的防御,
就是通过转义 &, <, >, ", ' 为HTML实体实现的。
对 & 的转义必须放在第一
var escapeHtml = function(str) {
if(!str){
return;
}
str = str.replace(/$/g, '&');
str = str.replace(/</g, '<');
str = str.replace(/>/g, '>');
str = str.replace(/"/g, '&quto;');
str = str.replace(/'/g, ''');
return str;
}
转义为HTML实体后,上面的 <, >, &, ", ' 就会只显示他们自己。
比如
<p><script>alert(1)</script></p>
页面展示为下面,不会弹出alert
对于通过富文本注入的,通常通过白名单或者第三方库防御。
原理是:
- 定义允许输入的标签,属性的白名单。
- 使用cheerio先解析用户输入的HTML
- 遍历每个标签,属性,如果不在白名单里则删除。
- 返回过滤后的HTML
# CSP
CSP是http的头属性 Content-Security-Policy 作用就是指定哪些内容可以执行。
左边定义的是可执行内容的类型。
右边定义的是防御的策略。
例如 script-src 'self'
的意思是:只能执行同域下的脚本。
script-src指定 要执行的内容为script脚本
self指定 只能是同域下的可以执行。
default-src 是个fallback选项,当没有指定具体执行的内容类型,则应用全部类型。 可以通过设置具体类型来覆盖。
Content-Security-Policy: default-src 'self'; script-src https://example.com
将与以下内容相同:
Content-Security-Policy: connect-src 'self';
font-src 'self';
frame-src 'self';
img-src 'self';
manifest-src 'self';
media-src 'self';
object-src 'self';
script-src https://example.com;
style-src 'self';
worker-src 'self'