Web前端攻防一些技巧

越来越感觉文章难写了,每次想写点什么东西,找着找着资料就发现早就有前人研究过,站在巨人的肩膀上却没能发现出更好的成果,真是惭愧

link 标签

关于link标签,一个大家非常熟悉的特性就是prefetch,在以前CTF的XSS题目中,prefetch往往是我第一个使用的payload,因为他几乎不被过滤,在Chrome中可以无视CSP策略并且可以第一时间得到管理员的UA和referer等信息,UA和referer的信息收集在前端中是相当重要的,拿渗透的流程类比的话,UA就好比目标站点的http server、CMS类型和版本,referer则类似敏感目录和后台

最开始,Firefox和Chrome对待prefetch的处理方法是不一样的,Firefox的default-src会拦截他,但是Chrome不会,在当时有人甚至将default-src拦截了prefetch作为了一个BUG提交给了mozilla:https://bugzilla.mozilla.org/show_bug.cgi?id=1242902

之后对于CSP是否应该拦截prefetch,这里有过一次讨论:https://github.com/w3c/webappsec-csp/issues/107 从中可以得到的是,未来将引入prefetch-src针对这些预加载进行拦截,而default-src仍然会拦截prefetch请求

在目前的Chrome 66,prefetch已经被Chrome的CSP default-src拦截,如同在Firefox中一样,但是Chrome仍然没有拦截prerender,因为Chrome还没有彻底完成对prefetch-src的实现,但是可以预见的是,在未来通过这类预加载bypass CSP将成为历史

除此之外我还想谈一谈link的import,最开始是在twitter上看到 用link import来bypass浏览器的XSS filter,当然需要一个可控的文件,当时的疑惑是,既然有可控的文件,为什么不直接用script引入文件进行XSS,后来想到,因为JavaScript的严格,如果可控文件内容不是完全可控,那么可能就会污染JavaScript的格式从而无法执行,而如果用link import的话,可以保证script标签内语法不出错,当然,如果仅从CSP的角度来看,link import还是十分鸡肋的,详见我之前的文章

CSP 与 404页面

在 CTF 中的 XSS 题目中,如果整个站点有一处没有设置 CSP 头,那么这个地方往往会成为一个突破口,但实际上这是 Chrome 处理的问题

一个简单的例子:

这段代码在 Chrome 中可以发现成功引入了外部 JS 从而 bypass 了 CSP,但是在 Firefox 中,这个请求被 CSP 拦截了

可以发现,Firefox 在执行 w.document.write() 的时候,打开的目标页的地址栏变成了 opener 的 url,Chrome 维持了目标页的 url,所以显而易见,在用 window.open 打开一个同源页面,并且 opener 对目标页进行 DOM 操作的时候,Firefox 强制转换目标页的 security context 为 opener 的 context,而 Chrome 维持了目标页的 context 原状

从 UXSS 的角度来看,因为场景发生在同源中,所以两种处理方法都没什么大问题,但是从 CSP 的角度来看,Chrome 的处理方法略有不妥
Chrome 对同源用 window.open 打开的页面使用了目标页自身的上下文,导致了他不能有效继承 opener 已经设置正确的 CSP,同时,如果这个页面本身没有正确的 CSP 配置,这将导致 CSP 的全盘崩溃

那么如何保证打开的页面没有正确的设置 CSP 呢? 一般来说,设置 CSP 有两种方法,第一种由页面本身设置,例如 php 的 header(),html 的 meta 标签,第二种则是由 http server 在代理时设置,例如 Nginx 的 add_header,Django 的 middleware

第一种,静态文件不会自己设置 CSP,例如最常见的 robots.txt,以及各种 js 文件,json 文件,css 文件,所以如果一个站点的 CSP 是由文件本身设置的,那么静态文件和目录自然不会有 CSP 设置

第二种,通过 http server 设置,来思考一个问题,对于错误页面或者是 404 页面,http server 会如何处理他的 CSP?

有趣的是,Django 的 middleware 和 Apache 的 mod_headers 正确处理了 404 页面的 CSP 设置,而 Nginx 的 add_header 则默认忽略了 404页面:https://stackoverflow.com/questions/20414669/nginx-add-headers-when-returning-400-codes

对于404页面的 CSP 设置,来看看规范:https://wicg.github.io/origin-policy/#intro.

对错误页面也设置 CSP 是被鼓励的,否则就可能产生安全漏洞,但是 Nginx 的 add_header 默认对404页面无效,这导致在 Chrome 下,几乎总有页面是没有正确配置 CSP 的,同时,因为大多数开发者会把 static 文件单独set header,从而导致忽略了CSP

toSting

Chrome 66以后,toString会打印出comment里的内容,以下这个payload会弹出alert:

iframe

长短短在twitter上提到了一个非常有趣的东西:

object标签的data直接指向一个网页的时候,他的作用和iframe相似,但是在Chrome下,甚至可以直接用contentWindow来获取object指向页面的DOM,Firefox则没有这样的特性(x.contentWindow为null),也就是说,如果iframe被过滤了而object没有被过滤,在Chrome下可以用object来代替iframe完成攻击

发表评论