XSS 跨站脚本攻击
XSS和SQL注入其实没什么区别,只是XSS是在网页中进行注入,而SQL注入是对数据库进行注入。
存储型XSS
例如,攻击者在帖子、评论中加入<script>alert("HACK")</script>并提交,网站服务器存储该带恶意代码的内容,当其他用户浏览时,浏览器页面渲染时会执行恶意JS代码导致被攻击。
反射型XSS
例如,攻击者将包含XSS恶意代码的链接发送给用户:
1 | https://www.baidu.com/search?question=<script>alert("HACK")</script> |
当用户点击时,服务器接受该用户的请求并进行处理,然后把带有XSS的代码发送给用户,用户浏览器解析执行代码,触发XSS漏洞。
二者区别
| 对比点 | 存储型XSS | 反射型XSS |
|---|---|---|
| 是否存储 | 存储在服务器 | 不存储 |
| 触发方式 | 页面访问即触发 | 需要点击恶意链接 |
| 危害范围 | 大(影响所有用户) | 小(单个受害者) |
如何预防
XSS的本质是浏览器把用户输入当成代码执行了。因此XSS防御的核心原则是:
- 不要相信用户输入
- 输出时进行编码
输出编码
将要显示的网页中的特殊字符转义编码,如<script>转为<script>。需要针对HTML内容、JS字符串、URL参数做区分处理。
现在的主流框架都有做此处理。
Content-Security-Policy(CSP)
这是浏览器级别的防护,通过配置HTTP响应头Content-Security-Policy告诉浏览器只能加载我允许的脚本。
输入过滤
例如过滤:
1 | <script> |
但难以过滤所有的可能,只能作为辅助手段。
HttpOnly
在Set-Cookie字段中添加HttpOnly:Set-Cookie: sessionId=xxx; HttpOnly。
此举不能防止XSS攻击,但可以使JS无法读取Cookie,防止document.cookie窃取Cookie。
CSRF 跨站请求伪造
什么是CSRF
例如,攻击者构造网站后台某功能接口的请求地址,诱导用户去点击或者用特殊方法让该请求地址自动加载。网站登录状态下,浏览器会自动携带Cookie,该请求被服务端接收后会被误以为是用户合法的操作,导致用户在不知情时执行了请求。
对于GET接口攻击,诱导用户点击请求地址,或用<img>加载指定url进行请求。
对于POST接口攻击,在某页面直接用JS发送POST请求,只要用户打开该页面,浏览器就会执行JS并触发攻击。
如何防御
CSRF通常从第三方网站发起,被攻击的网站无法防止攻击发生,只能通过增强自己网站针对CSRF的防护能力来提升安全性。
CSRF的两个特点:
- 通常发生在第三方域名。
- 攻击者不能获取到Cookie等信息,只是使用。
针对这两点,我们可以专门制定防护策略,如下:
- 提交时要求附加本域才能获取的信息
- CSRF Token
- 双重Cookie验证
- 阻止不明外域的访问
- Samesite Cookie
- 同源检测
CSRF Token
CSRF攻击之所以能够成功,是因为服务器误把攻击者发送的请求当成了用户自己的请求。那么我们可以要求所有的用户请求都携带一个CSRF攻击者无法获取到的CSRF Token。服务器通过校验请求是否携带正确的Token,来把正常的请求和攻击的请求区分开,进而防范CSRF攻击。
具体步骤:
用户打开网站页面时,服务器生成一个CSRF Token,该Token不能放在Cookie中否则又会被攻击者冒用。页面提交的请求都携带这个Token参数,服务器验证Token是否有效,无效则拒绝请求。
SameSite
在Set-Cookie响应头中添加SameSite=Lax,可以限制浏览器在什么情况下会携带Cookie:
1 | Set-Cookie: sessionId=xxx; SameSite=Lax |
SameSite的取值包括:
| 模式 | 说明 |
|---|---|
| Strict | 完全禁止跨站携带 |
| Lax | 部分允许(GET导航允许) |
| None | 必须配合Secure |
注:老浏览器可能不支持
同源检测
在HTTP协议中,每一个异步请求都会携带两个Header,用于标记来源域名:
- Origin Header
- Referer Header
缺点是无法做到万无一失,只能作为辅助手段。