Skip to content

Latest commit

 

History

History
81 lines (52 loc) · 3.55 KB

XSS.md

File metadata and controls

81 lines (52 loc) · 3.55 KB

XSS

什么是 XSS

XSS(Cross Site Scripting)跨站脚本攻击,更好的叫法是“外部脚本注入攻击”。“外部”的含义是说:用户访问一个网页,触发了一段脚本,而这段脚本,既不是网页开发者加的,也不是自己加的。遇到这种情况,就说明该网站存在 XSS 漏洞且被人利用了

XSS 的概念重点在“脚本”,而非“跨站”。所谓跨站,只是说浏览器默认允许加载任何第三方脚本,因此攻击脚本可以远程加载、注入

一旦 XSS 成立,意味着攻击者可以在用户访问的目标网页中做 js 能做的任何事情

从攻击者的角度看,XSS 的关键,是想办法让目标页面被其他用户访问时,执行一段外部脚本。要实现这个目标,关键是两点:

  • 存在一个输入点可以注入外部脚本
  • 输入后的脚本可以被执行(输出点

那么网页中,哪些地方具备接受输入且输入的内容最终能被执行的可能呢?

最简单的场景:提交数据到服务端,下次请求时接口返回数据,渲染在 dom 中。比如修改自己的昵称为一段 js,或者发一条包含脚本的微博,其他用户只要访问能看到“我”信息的网页,待接口返回数据后,就会触发 XSS。这种叫持久型或存储型 XSS

几个显眼而愚蠢的非持久型 XSS 示例:

// 如果网站中存在类似这样的脚本,等于是招手欢迎 XSS 攻击
eval(location.hash)

// 不光是前端,后端也有类似案例
echo $_GET("name")

非持久型又称反射型,因为不涉及存储,通常提交输入后,立即就能得到输出。不像存储型 XSS,输出点可能在别的地方

非持久型中仅依赖客户端环境的 XSS,又叫 DOM XSS

由此可见,XSS 注入攻击发生的本质原因,就是输入的数据被当成了程序来执行,一旦存在满足这个条件的地方,就意味着存在 XSS

理论上所有的 js 函数,都是潜在的 XSS 输入点,只要该函数满足三个条件:接收参数、该参数可以来自用户输入、该参数有可能被浏览器当作脚本执行

// 可能被浏览器当作脚本执行的地方,一般都和 DOM 有关
document.write()
xxx.innerHTML = 

XSS Worm:利用社交网络中用户的交互行为进行传播的 XSS,可以造成大面积危害

一切输入都是有害的

如何挖掘

基本思路:找到潜在的输入点,拿一批探测样本测试是否存在输入被当作脚本执行的可能。简而言之,先找输入,再找输出

难点一:如何构造探测样本,以提高命中率和效率?

难点二:如果输出点在别处(持久型 XSS),怎么探测?

难点三:找到 XSS 漏洞后,如何构造 payload 以绕过某些限制(比如长度限制)?

如何防御

  • HTTPOnly
  • Content Security Policy
  • 输入检查
    • XXS Filter,通常会检测并过滤一些敏感字符(黑名单)
      • script、javascript
      • 特殊字符:< > ...
    • 问题是有可能把正常的输入也过滤掉了
    • 因此更妥当的办法不是过滤,而是替换,比如将某些半角符号转化为全角
    • 根据场景,还可以采用白名单的思路
  • 输出检查
    • 方式:编码(Encode)或转义(Escape)
      • 输出到 HTML 的地方:HTMLEncode: < => &lt; | \ => &#x2F ...
      • 输出到脚本的地方:JavaScriptEncode
    • 对象
      • 变量
      • 特殊字符

真实案例