一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情。
什么是XSS攻击
跨网站指令码(英语:
Cross-site scripting
,通常简称为:XSS
)是一种网站应用程式的安全漏洞攻击,是代码注入的一种。它允许恶意使用者将程式码注入到网页上,其他使用者在观看网页时就会受到影响。这类攻击通常包含了HTML
以及使用者端脚本语言。
XSS
简单点来说,就是攻击者想尽一切办法将可以执行的代码注入到网页中。
总的来说XSS
可以分为两类:持久型和非持久型。也分为三种:存储型、反射型和 DOM-based
。下面来具体看一下:
1. 存储型
- 存储型的XSS攻击也是持久型的。也就是攻击的代码被服务端写入进数据库中。
- 具体操作:攻击者事先将恶意代码上传或者储存到漏洞服务器中,只要受害者浏览包含此恶意代码的页面就会执行恶意代码。
- 出现场景:一般出现在网站留言、评论、博客日志等交互处,可以将恶意脚本存储到客户端或者服务端的数据库中。
- 危害性:很大,访问了这个页面的访客,都有可能会执行这段恶意脚本。当网站访问量很大的话,就会导致大量正常访问页面的用户都受到攻击。
示例:比如在评论中注入代码
非持久型相比于前者危害就小的多了,一般通过修改 URL
参数的方式加入攻击代码,诱导用户访问链接从而进行攻击。
2. 反射性
- 又称非持久型XSS,这种攻击方式往往具有一次性,只在用户单击时触发。跨站代码一般存在链接中,当受害者请求这样的链接时,跨站代码经过服务端反射回来,这类跨站的代码通常不存储服务端。
- 具体操作:1. 反射型XSS攻击一般是攻击者通过特定手法,诱使用户去访问一个包含恶意代码的URL。2. 用户点击了该链接的时候,3. 服务器返回HTML文档,此时该文档已经包含了那个恶意字符串, 4. 客户端就会执行了植入的恶意脚本,XSS攻击就发生
- 出现场景:网站的搜索栏、用户登录口等地方,常用来窃取客户端Cookies或进行钓鱼欺骗。
3. DOM-based型
- 客户端的脚本程序可以动态地检查和修改页面内容,而不依赖于服务器端的数据。DOM型xss和别的xss最大的区别就是它不经过服务器,仅仅是通过网页本身的JavaScript进行渲染触发的。
- 具体操作:例如客户端如从URL中提取数据并在本地执行,如果用户在客户端输入的数据包含了恶意的JavaScript脚本,而这些脚本没有经过适当的过滤或者消毒,那么应用程序就可能受到DOM-based型XSS攻击。
- 出现场景:DOM中使用了用户输入源document.URL、location.hash、location.search、document.referrer等
示例:dom中动态加载url上的参数
<!-- http://www.domain.com?name=<script>alert(1)</script> -->
<div>{{name}}</div>
对于这种攻击方式来说,如果用户使用 Chrome
这类浏览器的话,浏览器就能自动帮助用户防御攻击。但是我们不能因此就不防御此类攻击了,因为我不能确保用户都使用了该类浏览器。
两者的攻击方式没有什么不同,都是通过电子邮件等方式发送这个含有我们构造的payload的URL给目标用户,当目标用户访可该链接时,服务器接收该目标用户的请求并进行处理,然后服务器把带有XSS代码的数据发送给目标用户的测览器,浏览器解析这段帯有XSS代码的恶意脚本后,就会触发XSS漏洞,一般用于获取对方cookies值
如何防范
1. 字符转义
最普遍的做法是转义输入输出的内容,对于引号,尖括号,斜杠进行转义
function escape(str) {
str = str.replace(/&/g, "&");
str = str.replace(/</g, "<");
str = str.replace(/>/g, ">");
str = str.replace(/"/g, "&quto;");
str = str.replace(/'/g, "&##39;");
str = str.replace(/`/g, "&##96;");
str = str.replace(///g, "&##x2F;");
return str
}
通过转义可以将攻击代码 <script>alert(1)</script>
变成
// -> <script>alert(1)<&##x2F;script>
escape('<script>alert(1)</script>')
对于显示富文本来说,不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。这种情况通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式
var xss = require("xss");
var 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
标签
2. CSP
CSP
本质上就是建立白名单,开发者明确告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截是由浏览器自己实现的。我们可以通过这种方式来尽量减少 XSS
攻击。
通常可以通过两种方式来开启 CSP:
- 设置
HTTP Header
中的Content-Security-Policy
- 设置
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
的兼容性也不错。
3. cookie 如何防范 XSS 攻击
XSS(跨站脚本攻击)是指攻击者在返回的 HTML 中嵌入 javascript 脚本,为了减轻这些 攻击,需要在 HTTP 头部配上,set-cookie
httpOnly
这个属性可以防止 XSS,它会禁止 javascript 脚本来访问cookie
secure
- 这个属性告诉浏览器仅在请求为https
的时候发送cookie