Web安全漏洞

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>转为&lt;script&gt;。需要针对HTML内容、JS字符串、URL参数做区分处理。

现在的主流框架都有做此处理。

Content-Security-Policy(CSP)

这是浏览器级别的防护,通过配置HTTP响应头Content-Security-Policy告诉浏览器只能加载我允许的脚本。

输入过滤

例如过滤:

1
2
3
4
<script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<a href="javascript:alert(1)">

但难以过滤所有的可能,只能作为辅助手段。

HttpOnly

Set-Cookie字段中添加HttpOnlySet-Cookie: sessionId=xxx; HttpOnly

此举不能防止XSS攻击,但可以使JS无法读取Cookie,防止document.cookie窃取Cookie。

CSRF 跨站请求伪造

什么是CSRF

CSRF是什么

例如,攻击者构造网站后台某功能接口的请求地址,诱导用户去点击或者用特殊方法让该请求地址自动加载。网站登录状态下,浏览器会自动携带Cookie,该请求被服务端接收后会被误以为是用户合法的操作,导致用户在不知情时执行了请求。

对于GET接口攻击,诱导用户点击请求地址,或用<img>加载指定url进行请求。

对于POST接口攻击,在某页面直接用JS发送POST请求,只要用户打开该页面,浏览器就会执行JS并触发攻击。

如何防御

CSRF防御之token认证

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

缺点是无法做到万无一失,只能作为辅助手段。

验证码