长亭百川云 - 文章详情

强防御下的XSS绕过思路(四) 逻辑判断

不忘初心px1624

51

2024-07-13

前言

本来该系列只有三篇,而且本篇的一半内容是在《强防御下的XSS绕过思路(三)限制长度》这篇文章里面写的,但是由于设计的题目别人给出了多个我没想到的解法思路,导致最终文章内容的变化,以及文章篇幅等问题,所以就暂且作罢了,相关解析后面就单独写了这篇《强防御下的XSS绕过思路(四)逻辑判断》文章来分享了。

三道题的题目地址如下:

http://px1624.sinaapp.com/test/shortxss.php

http://px1624.sinaapp.com/test/shortxss1.php

http://px1624.sinaapp.com/test/shortxss2.php

其中前两题主要是以长度限制的绕过思路为主进行设计的,第三题的主要难点,是绕过if这个逻辑判断,也是这篇文章讲述的重点。

正 文

1、第一题

http://px1624.sinaapp.com/test/shortxss.php

这个题目其实很简单,根据提示先传个px参数进去

发现会直接把参数内容输出在script里面

 

那么貌似就很容易了,直接px=alert(2020)应该就可以了。但是仔细去数一数,alert(2020)这是11个字符,上面说限制长度10个字符,所以还是不行。

不死心,去试试,果然没这么简单。

到这里,很多人就不知道怎么弄了。

然后可能就放弃了,其实这些知识,之前在《强防御下的XSS绕过思路(三)限制长度》里面有讲到过,具体方法很简单,就是该文章中提到的“借刀杀人”,利用eval(name)即可。

 

2、第二题

http://px1624.sinaapp.com/test/shortxss1.php

根据提示把3个参数传进去。

可以看到,分别输出在了img的alt属性以及js代码里面。测试后就会发现,属性里面的参数也都限制了20个字符。所以如果要弹出12345,直接去"onload="alert(12345)是肯定不行的,因为这样会多一个字符出来,长度超过限制。那么直接在js中构造 ';alert(12345);' 这样行不行呢?理论上来说也是不行的,因为看到上面有写,除了双引号基本特殊字符都过滤掉了。

当然我设计这个案例的时候是有一个自己的标准答案的,但是大家的思路往往各式各样,所以我给ID:gainover发过去,看他有没有其他不一样思路,仅仅1分钟后就有了答案,而且和我预想的不太一样。

http://px1624.sinaapp.com/test/shortxss1.php?px=alert(12345)&px1=%22onload=%22w=eval&px2=%22onload=%22w(px202012)

他的思路是把eval进行重新定义,然后再巧妙的利用js中的可控变量,从而成功执行脚本代码。

不过这个方法有个缺点,因为markdown-img标签加载成功触发onload的先后顺序,并不一定是按照该标签写入页面的前后顺序执行的,所以会导致这个payload不会100%的触发漏洞。

不过也算是一种别的思路的解法。

然后后面又有人直接给出一个让我惊奇的答案。ID:啦啦

http://px1624.sinaapp.com/test/shortxss1.php?px=';alert(12345);'&px1=1&px2=2

我一看,奇怪?这怎么可以直接用单引号了,我记得我单引号是过滤了啊。打开php源码一看,明明我过滤了啊,但是别人的的确确是用单引号直接突破的。

排查下问题在哪,才发现,原来是strpos这个函数的坑,这个函数在匹配的时候返回的下标是从0开始的,然后匹配不到就直接返回false,然后在代码判断的时候,又存在0==false,所以就尴尬了。只要别人把相关字符放在第一个位置,那么返回的就是0,这个字符就直接默认成白名单可以用的了,所以就直接绕过了。

百度搜了下发现,原来这种坑点,踩的人也蛮多的。

比如这里这个案例 https://xz.aliyun.com/t/2467

然后出现这个问题后,及时改了下代码,将弱判断改成了强判断。

其实很多时候,某些逻辑漏洞的出现,往往就是由于这种弱判断的代码逻辑导致的。

改了代码后,ID:啦啦给出了和ID:gainover一样思路的答案,随后ID: Huuuuu又给出了一个不一样的答案。

http://px1624.sinaapp.com/test/shortxss1.php?px=1&px1=12345%22id=&px2=%22onload=%22alert(alt)

这个思路等于是把2个标签给合并成一个标签了,看到这个答案,我内心有点小郁闷。因为其实这个案例,我是想模拟那些富文本环境或者表单提交环境的XSS组合利用。这种场景下,这些属性基本都是dom写入的,所以肯定不会出现标签被直接穿越的情况。不过由于模拟环境出题的不严谨,等于又被(偷鸡)给出了一个其他思路的解法。所以说,出题貌似比解题感觉要难的多啊。

最后我给出我设计的题目的解法吧。

http://px1624.sinaapp.com/test/shortxss1.php?px=alert(12345)&px1=eval(px202012)%22id=%22t&px2=%22onload=%22eval(t.alt)

为什么要这么设计呢?

其实这个思路在《强防御下的XSS绕过思路(三)限制长度》里面也有讲过,就是该文章中提到的“借尸还魂”的方法。

因为在实际情况中,上面ID:Huuuuu的穿越标签的方法肯定是不行的。然后如果想100%触发漏洞,就得这么去构造。利用两次eval,将js变量中的可控参数进行利用,从而最终XSS。

图片img加载,执行onload,然后执行其中的t.alt 这个对应过去就是上面的img里面的eval(px202012) 然后px202012这个变量就是'alert(12345)' 所以等于最终就执行了 eval('alert(12345)') 这个代码。

这里可能有人说为啥不直接eval(px202012)呢?主要还是因为长度问题。这个点也是模拟实战环境,因为实际环境中,网页的可控变量的名字往往会特别长,如果能塞进去当然可以直接eval,如果塞不进去的话,那就需要这样再去中转下了。

本来shortxss就设计了2道题,也是在写《强防御下的XSS绕过思路(三)限制长度》这篇文章的时候,临时写的demo小题作为案例使用的,也是打算直接写入那篇文章的。所以代码写的也比较随意,这也是导致这个第二题,被大家给出了多种不同的答案的原因之一,其实我本意是没有留这些问题BUG点的。

第二题中,因为t.alt这种 id.属性的写法技巧,我灵机一动,又去设计了第三个shortxss小题。这个题目我故意留了些坑(误导解题人思路的),而且也反复验证了下题目设计的严谨性,避免再次被人偷鸡(打脸)。

3、第三题

http://px1624.sinaapp.com/test/shortxss2.php

还是老步骤,第一步看下页面源码。

根据提示把px1和px2两个参数传进去。

发现px1有两处输出,一处在img的alt属性里,一处在js代码的if判断里。px2有一处输出,在js代码的else判断里。

长度都限制在了21个字符,而且过滤了除了双引号的几乎所有特殊字符。如果直接在alt位置构造的话,那么"onload="alert`2012.12.25`这个26个字节,长度是肯定超了的。

那么想着在if位置构造,结果会发现单引号根本就突破不了。

咦?下面有个动态写src的,那我在这里尝试下?

然后测试了就会发现,不管怎么构造,始终都是突破不了src的双引号。这也就是我前面在第二题,穿越标签闭合双引号的那个解法中,提到的实际环境中的属性,基本都是这么写进去的。这种方法去写标签属性,如果你写双引号进去,就会自动被编码掉。

那么上面的位置都不行,难道要在else这位置去入手?

没错,这个题真正考验的就是要突破if判断,执行else这里的代码。其他的输出点有的是辅助点,有的是故意设置的干扰。如果可以执行else代码的话,那么直接 ";alert`2012.12.25`;" 即可。

那么要如何执行这个else呢?从题目判断,只要 document.getElementById("px") 这个不是true,就会执行else的内容。但是明明document.getElementById("px")就是true啊,那么这题岂不是无解?

这里往往思路就陷入到了一个死循环了,可能也有想到这里,但是又会很快的否决掉自己的这个想法。其实方法很简单,要让document.getElementById("px")不是true 那么最直接的方法就是要么px这个id不存在,要么压根连 document.getElementById("px")这个都不存在。

所以也就是覆盖变量、函数的问题了,覆盖px这个id的话,如果说alt属性在id属性之前,那么是可以很容易就做到的,直接 alt=""id="px" 这样就行了。但是这个思路我在设计题目的时候已经注意到了,所以我故意把id这个属性放在了img标签的最前面。那么这个思路不行的话,就只能是去覆盖document.getElementById("px") 这个了。这要怎么搞?其实方法很简单,我先直接给出答案。

http://px1624.sinaapp.com/test/shortxss2.php?px1=%22name=%22getElementById&px2=%22;alert\`2012.12.25\`;%22

为什么就可以了呢?去控制台看看吧。

可以看到,控制台报错document.getElementById不是个函数,那么它现在到底是什么呢?通过控制台去调试,我们发现它现在就是这个name为getElementById的img标签了。

前面第二题里提到了 id.属性的写法,其实有的标签也是可以写成name.属性的,像这里的img就可以。

为什么会这样呢?这是由于非标准化的 DOM 行为,浏览器有时可能会向各种 DOM 元素添加 name 和 id 属性,作为对文档或全局对象的属性引用。但是,这会导致覆盖掉 document原有的属性或全局变量,或者劫持一些变量的内容。

利用这个特性,往往可以绕过一些判断造成XSS,现在这个方法已经有了一个比较专业的名字,叫Dom Clobbering具体的原理和细节,我这里就不在细述了,可以参考这篇文章,写的蛮详细的。

使用 Dom Clobbering 扩展 XSS   https://xz.aliyun.com/t/7329

总 结

通过三道比较简单的shortxss小题的思路解析分享,可以看到,这三个题看似简单,但其实都是要求解题者要有着比较扎实的基础,以及需要不断的去变换思路才能搞定的。

后 记

本来这个文章的名字叫《三道shaortxss题目解析和延伸》,但是后面我发现这个标题貌似太普通和随意了,而且这篇文章主要分析的其实是第三题的思路,而且也是在比较强防御下的一种逻辑判断的绕过,所以我就修改了前言内容,并更改了一些其他内容和标题。

第三题的构造,由于必须绕过那个if的逻辑判断,执行else里面的代码,所以如果这点突破不了的话,这个题应该是解不出来的。结果就是截至目前,还没有人成功给出答案。

然后在发稿前,我在思考会不会还有其他我不知道的思路的解法,所以我把该题目发给了ID:gainover让他试试。一分钟后他给出了答案,payload有些不同,但是解法和我设计的答案的思路是一样的,都是覆盖getElementById变量。区别就是他并没有直接写入alert而是用name进行了中转,这样的处理其实更加的合理,因为这样name位置就完全不受长度的限制了。

给出的payload如下:

或者

如果其他人有不同的方法,可以将答案发到我的邮箱:px1624@qq.com,说不定下篇你的思路就会被收录了呢。

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2