XSS 安全防范

XSS是跨站脚本攻击,主要特点是开发者之外的人向页面内容注入了脚本执行。
XSS攻击有两个要素,一是来自用户或者三方的内容,二是被当做html或者javascript代码执行。
在面对XSS攻击时,需要牢记的一句话是:一切输入和输出都是敌对的!

XSS 攻击的输入点

开发者之外的人可以通过以下输入点向页面中注入攻击脚本:

  • window.location/document.location/document.referrer
    • 来自url的内容,因为链接可能来自外部页面,所以页面url应当视为外部用户内容。
  • 后端接口返回数据
    • 来自服务端的数据,这些数据可能由其它系统提供,其中可能包含用户的直接输入,所以应该把通过后端接口请求得到的数据视为外部用户产生内容。
  • document.cookie
    • cookie有较多渠道被写入,为安全起见,应当视为用户产生内容。
  • input.value/textarea.value
    • 用户产生内容。

XSS 攻击的输出点

XSS 攻击输出点是开发者在代码中写的语句,这些语句可能会将用户输入的内容作为代码执行,进而发生XSS 攻击。XSS 攻击主要有以下输出点:

  • document.write/document.writeln:直接向文档流写入html内容,不提倡使用.

    • 如果希望用这种方式输出文本,在写入之前,应当使用document.createTextNode+appendChild将之转换成html文本语法。
    • 如果确有特殊设计,希望用这种方式输出html,在写入之前,应当过滤html语法字符。
  • innerHTML/$el.html():直接向文档节点内插入html内容,除使用模板外,不提倡使用。

    • 如果希望用这种方式输出文本,应当使用innerText或者document.createTextNode+appendChild代替。
    • 如果确有特殊设计,希望用这种方式输出html,在写入之前,应当过滤html语法字符。
  • new Function:通过参数字符串创建新函数,除特殊场景外,不提倡使用。如果来自不安全的输入的字符需要拼接成字符串,建议使用JSON.stringify处理。

  • eval:把字符串当做函数执行,除特殊场景外,不提倡使用。如果来自不安全的输入的字符需要拼接成字符串,建议使用JSON.stringify处理。

  • setTimeout/setInterval:时间相关函数,如果第一个参数是字符串,那么效果类似eval,任何场景下,不提倡这样使用,第一个参数应该永远是函数类型。

  • image.src/link.href/a.href:设置url,因为可能是javascript协议,建议使用lib.httpurl解析url的结构和参数,确定域名属于安全域名。

  • window.location:跳转url,因为uri可能是javascript协议,建议使用lib.httpurl解析url的结构和参数,确定域名属于安全域名。

XSS 攻击实例

HTML 攻击

  • 输出点

    • <img src="[代码]">
    • 现在弹个窗:

      <img src="x" onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;">

    • 原code:

      <img src="x" onerror="alert(1)">