绕过vm中的无限debugger

什么叫做“阎王好过,小鬼难缠”呀!这两天我正在兴致勃勃地看油猴中文网的教程,一开始进行得尚算顺利。可是当我进行到去除网页广告的这个章节时,随手打开教学网站(没错,就是那个马甲众多的樱花动漫),按下F12后,我傻眼了,这个小破站竟然部署了无限debugger循环。好了,事已至此,那教程先搁一边,先来个js逆向吧。

目标网站

一、情况分析

无限debugger我早有耳闻,但今天是第一次见。不过第一次就第一次,没什么大不了的,关关难过关关过。先来看一下开发者工具里的状况:

可以看到这个debugger出现在vm(虚拟机)里,那么常见的条件断点或是never pause here不起作用。

那我们看一下堆栈信息,看是哪个地方调用了debugger:

逆流而上,溯源至前一个函数N中一看究竟:

好家伙,不看不知道,一看吓一跳,这张图里出现了堆栈里的两个函数N和d,而且函数d里套着函数N。再分析一下这个d函数,几乎是在无限循环N函数,N函数无限循环debugger!罪魁祸首就是函数d了。页面显示运行到这里进入了debugger:

[b('19')](b('1d') + b('1e'))[b('1f')](b('20')));

很明显这里调用了名为b的函数,拼凑出了可以调用debugger的方法。在控制台依次打印b函数,并将上述几个值传给b函数,得到

可以看到b函数在列表a中定位值,拼凑出了constructor,debu, gger,apply, stateObject等字段,连在一起看就是:

原代码:[b('19')](b('1d') + b('1e'))[b('1f')](b('20')));

还原后:constructor('debugger').apply('stateObject')

截止目前,这个debugger的生成方式和调用关系已经全部清楚了。接下来开始把它,解决掉。

二、绕过实战

1、置空法

因为它的这个循环写得有点恶心,函数d在6个地方调用了函数N,函数d之外还有2个地方调用了函数d,几乎可以说是无限循环。

1.1 overrides 本地替换置空

那就本地置空吧!这个时候,开发者工具中的overrides派上用场了。在本地找一个文件夹,sources面板中打开overrides把函数b的内容全部注释掉,使其成为空函数,Ctrl+s保存,刷新页面即可。如下图:

这样操作相当于用本地修改的js文件覆盖了服务器端的,刷新页面,跳转次级页面都不会受影响。

1.2 置空constructor

这个方式是我在博客园里看见的。既然已经弄明白这个debugger是通过constructor创建的,为何不直接置空constructor呢?

Function.prototype.constructor = function(){}

1.3 简单置空

我已经知道函数d就是罪魁祸首了,那么在函数d处打上断点,并在控制台内写上:

d = function(){};

这样就赶在d执行之前把它置空了。

不过一旦刷新页面,1.2和1.3的方法会失效。

2、简单粗暴禁用断点法

不过这样一来啥也看不到了,那跟我们打开开发者工具的初衷相去甚远,因此这是下策中的下策。

三、总结

网站的安全策略我林林总总也接触过一些,有一个感触就是,越大型的网站越稳定。这个稳定不是指网站服务方面的稳定性,而是网站结构、功能、API之类。就以我见过的几个例子来说吧,一个中小型论坛,安全策略一年内起码变化6~7次,中型视频网站某个接口可能两年内变化3次左右,某大型视频网站,接口已经3年不变了。像是这次遇到的无限debugger骚操作,我还没在大中型网站上见过。我估计一是大型站点背后往往是大公司,大公司操作的灵活性比较有限,中小站点站长一个人、几个人管理的,基本上想到什么做什么,也比较容易玩一些奇技淫巧,二是大公司安全策略自研为主,中小型网站用专业安全厂商的服务比较多。这下子可真的是庙小妖风大了。

发布者

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注