# 什么是 XSS 攻击?
XSS 全称是 Cross Site Scripting(即跨站脚本),为了和 CSS 区分,故叫它XSS。XSS 攻击是指浏览器中执行恶意脚本(无论是跨域还是同域),从而拿到用户的信息并进行操作。
这些操作一般可以完成下面这些事情:
- 窃取
Cookie。 - 监听用户行为,比如输入账号密码后直接发送到黑客服务器。
- 修改 DOM 伪造登录表单。
- 在页面中生成浮窗广告。
通常情况,XSS 攻击的实现有三种方式——存储型、反射型和文档型。原理都比较简单,先来一一介绍一下。
# 存储型
存储型,顾名思义就是将恶意脚本存储了起来,确实,存储型的 XSS 将脚本存储到了服务端的数据库,然后在客户端执行这些脚本,从而达到攻击的效果。
常见的场景是留言评论区提交一段脚本代码,如果前后端没有做好转义的工作,那评论内容存到了数据库,在页面渲染过程中直接执行, 相当于执行一段未知逻辑的 JS 代码,是非常恐怖的。这就是存储型的 XSS 攻击。
# 反射型
反射型XSS指的是恶意脚本作为网络请求的一部分。
比如我输入:
http://sanyuan.com?q=<script>alert("你完蛋了")</script>
这样,在服务器端会拿到q参数,然后将内容返回给浏览器端,浏览器将这些内容作为HTML的一部分解析,发现是一个脚本,直接执行,这样就被攻击了。
之所以叫它反射型, 是因为恶意脚本是通过作为网络请求的参数,经过服务器,然后再反射到HTML文档中,执行解析。和存储型不一样的是,服务器并不会存储这些恶意脚本。
# 文档型
文档型的 XSS 攻击并不会经过服务端,而是作为中间人的角色,在数据传输过程劫持到网络数据包,然后修改里面的 html 文档!
这样的劫持方式包括WIFI路由器劫持或者本地恶意软件等。
# 防范措施
明白了三种XSS攻击的原理,我们能发现一个共同点: 都是让恶意脚本直接能在浏览器中执行。
那么要防范它,就是要避免这些脚本代码的执行。
为了完成这一点,必须做到一个信念,两个利用。
# 一个信念
千万不要相信任何用户的输入!
无论是在前端和服务端,都要对用户的输入进行转码或者过滤。
如:
<script>alert('你完蛋了')</script>
转码后变为:
<script>alert('你完蛋了')</script>
这样的代码在 html 解析的过程中是无法执行的。
当然也可以利用关键词过滤的方式,将 script 标签给删除。那么现在的内容只剩下:
什么也没有了:)
# 利用 CSP
CSP,即浏览器中的内容安全策略,它的核心思想就是服务器决定浏览器加载哪些资源,具体来说可以完成以下功能:
- 限制其他域下的资源加载。
- 禁止向其它域提交数据。
- 提供上报机制,能帮助我们及时发现 XSS 攻击。
# 利用 HttpOnly
很多 XSS 攻击脚本都是用来窃取Cookie, 而设置 Cookie 的 HttpOnly 属性后,JavaScript 便无法读取 Cookie 的值。这样也能很好的防范 XSS 攻击。
# XSS总结
XSS 攻击是指浏览器中执行恶意脚本, 然后拿到用户的信息进行操作。主要分为存储型、反射型和文档型。防范的措施包括:
- 一个信念: 不要相信用户的输入,对输入内容转码或者过滤,让其不可执行。
- 两个利用: 利用 CSP,利用 Cookie 的 HttpOnly 属性。
# 什么是CSRF攻击?
CSRF(Cross-site request forgery), 即跨站请求伪造,指的是黑客诱导用户点击链接,打开黑客的网站,然后黑客利用用户目前的登录状态发起跨站请求。
举个例子, 你在某个论坛点击了黑客精心挑选的小姐姐图片,你点击后,进入了一个新的页面。
那么恭喜你,被攻击了:)
你可能会比较好奇,怎么突然就被攻击了呢?接下来我们就来拆解一下当你点击了链接之后,黑客在背后做了哪些事情。
可能会做三样事情。列举如下:
# 1. 自动发 GET 请求
黑客网页里面可能有一段这样的代码:
<img src="https://xxx.com/info?user=hhh&count=100"></img>
进入页面后自动发送 get 请求,值得注意的是,这个请求会自动带上关于 xxx.com 的 cookie 信息(这里是假定你已经在 xxx.com 中登录过)。
假如服务器端没有相应的验证机制,它可能认为发请求的是一个正常的用户,因为携带了相应的 cookie,然后进行相应的各种操作,可以是转账汇款以及其他的恶意操作。
# 2. 自动发 POST 请求
黑客可能自己填了一个表单,写了一段自动提交的脚本。
<form id='hacker-form' action="https://xxx.com/info" method="POST">
<input type="hidden" name="user" value="hhh" />
<input type="hidden" name="count" value="100" />
</form>
<script>document.getElementById('hacker-form').submit();</script>
2
3
4
5
同样也会携带相应的用户 cookie 信息,让服务器误以为是一个正常的用户在操作,让各种恶意的操作变为可能。
# 3. 诱导点击发送 GET 请求
在黑客的网站上,可能会放上一个链接,驱使你来点击:
<a href="https://xxx/info?user=hhh&count=100" taget="_blank">点击进入修仙世界</a>
点击后,自动发送 get 请求,接下来和自动发 GET 请求部分同理。
这就是CSRF攻击的原理。和XSS攻击对比,CSRF 攻击并不需要将恶意代码注入用户当前页面的html文档中,而是跳转到新的页面,利用服务器的验证漏洞和用户之前的登录状态来模拟用户进行操作。
# 防范措施
# 1. 利用Cookie的SameSite属性
CSRF攻击中重要的一环就是自动发送目标站点下的 Cookie,然后就是这一份 Cookie 模拟了用户的身份。因此在Cookie上面下文章是防范的不二之选。
恰好,在 Cookie 当中有一个关键的字段,可以对请求中 Cookie 的携带作一些限制,这个字段就是SameSite。
SameSite可以设置为三个值,Strict、Lax和None。
a. 在Strict模式下,浏览器完全禁止第三方请求携带Cookie。比如请求sanyuan.com网站只能在sanyuan.com域名当中请求才能携带 Cookie,在其他网站请求都不能。
b. 在Lax模式,就宽松一点了,但是只能在 get 方法提交表单况或者a 标签发送 get 请求的情况下可以携带 Cookie,其他情况均不能。
c. 在None模式下,也就是默认模式,请求会自动携带上 Cookie。
# 2. 验证来源站点
这就需要要用到请求头中的两个字段: Origin和Referer。
其中,Origin只包含域名信息,而Referer包含了具体的 URL 路径。
当然,这两者都是可以伪造的,通过 Ajax 中自定义请求头即可,安全性略差。
# 3. CSRF Token
Django作为 Python 的一门后端框架,用它开发过的同学就知道,在它的模板(template)中, 开发表单时,经常会附上这样一行代码:
{% csrf_token %}
这就是CSRF Token的典型应用。那它的原理是怎样的呢?
首先,浏览器向服务器发送请求时,服务器生成一个字符串,将其植入到返回的页面中。
然后浏览器如果要发送请求,就必须带上这个字符串,然后服务器来验证是否合法,如果不合法则不予响应。这个字符串也就是CSRF Token,通常第三方站点无法拿到这个 token, 因此也就是被服务器给拒绝。
# CSRF总结
CSRF(Cross-site request forgery), 即跨站请求伪造,指的是黑客诱导用户点击链接,打开黑客的网站,然后黑客利用用户目前的登录状态发起跨站请求。
CSRF攻击一般会有三种方式:
- 自动 GET 请求
- 自动 POST 请求
- 诱导点击发送 GET 请求。
防范措施: 利用 Cookie 的 SameSite 属性、验证来源站点和CSRF Token。