跨站脚本攻击

什么是跨站脚本?

跨站脚本(Cross-site scripting,通常简称为XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。 —— 摘自《维基百科》

危害

  • 盗取信息
    • 盗用 cookie,获取敏感信息;
    • 键盘监听
    • 伪造表单
  • 恶意操作
    • 利用可被攻击的域受到其他域信任的特点,以受信任来源的身份请求一些平时不允许的操作,如进行不当的投票活动;
    • 利用 iframe、frame、XMLHttpRequest 或上述 Flash 等方式,以(被攻击)用户的身份执行一些管理动作,或执行一些一般的如发微博、加好友、发私信等操作;
    • 在访问量极大的一些页面上的XSS可以攻击一些小型网站,实现 DDoS 攻击的效果;
  • 越权
    • 利用植入Flash,通过 crossdomain 权限设置进一步获取更高权限;

方式

按照 XSS 来源,可以将 XSS 攻击方式分为三类:

  • Persistent XSS:恶意代码来自数据库
  • Reflected XSS:恶意代码来自受害者请求
  • DOM-based XSS:客户端代码漏洞

可能存在 XSS 的标签或属性

  • script
  • 事件属性
  • 链接 href
  • iframe src
  • image src

防御

防御 XSS 攻击的方法如下:

  • 禁用浏览器脚本;
  • 将重要的 cookie 标记为 http only;
  • 使用 HTTP 头指定类型;
  • 转义
    • PHP:htmlentities(),htmlspecialchars();
    • Python:cgi.escape();
    • ASP:Server.HTMLEncode;
    • ASP.NET:Server.HtmlEncode(),Microsoft Anti-Cross Site Scripting Library;
    • Java:xssprotect (Open Source Library);
    • Node.js:node-validator;
  • 验证
    • 检查用户输入数据类型和规则;
    • 过滤或移除特殊的 HTML 标签;
    • 过滤 JavaScript 事件的标签;

根据XSS 攻击方法的不同,要采用不同的方法防御,具体防御策略如下:

  • 普通文本参数:有业务需要的话,做些正则表达式验证,例如:昵称使用正则表达式验证,只能包含特定字符,并且显示的时候需要转义
  • 多行文本参数:显示时转义
  • 富文本参数:过滤危险标签(使用白名单),显示时转义
  • coolie:http only

备注:显示可能在服务端渲染,也可能在客户端渲染,根据具体程序语言做相应处理。

疑问:存储数据前转义 VS 显示前转义?

存储数据前转义,显示就不需要再转义,但这样数据库的数据不是用户真实输入的数据,不便于移植(例如,将数据导出到 CSV)。并且如果需要重新编辑转义数据的化,还需要反转义。

此外,存储数据前转义只能防御 Persistent XSS 漏洞,要避免 Reflected XSS 和 DOM-based XSS,还是要做显示前转义。

测试

Java

转义

过滤

参考文献

JavaScript/Node.js

TODO

参考文献

TODO