准备
编译Gondvv.java,生成在Gondvv.class,在同目录下新建test.htm,内容如下
<APPLET CODE="Gondvv.class" WIDTH=200 HEIGHT=100> </APPLET>
粗略观察一下java代码,应该是绕过了Java Sandbox,而并非是JVM中溢出等漏洞,所以可以直接调试java代码。
setSecurityManager
首先需要简单了解setSecurityManager()函数。setSecurityManager()用于设置一个SystemSecurity。如果已经设置过securityManager,调用setSecurityManager时则会调用checkPermission检查权限是否正确。同样可以通过调用setSecurityManager来替换掉一个现有的securityManager。所以绕过SandBox的方法一般为禁用掉SecurityManager,调用setSecurityManager()函数,并传入null参数。如下图
首先对setSecurityManager()下断点,检查函数调用链,看是在何处修改security manager。
中断在setSecurityManager(),观察函数调用链
可以在调用链中观察到Gondvv中的代码,调用了Gondvv.disableSecurity()函数。并且观察一下setSecurityManager()的参数,为null,这是一个取消security manager的操作,若执行成功,则可以绕过其权限检查,从而任意执行命令。链中出现Gondvv的代码,为非信任代码,却仍成功关闭SecurityManager,猜测可能是权限被修改。
代码分析
下面开始分析Gondvv.java中的disableSecurity()函数。
首 先 创 建 表 达 式 , 用 于 执 行setSecurityManager()。但是,若直接执行则会触发setSecurityManager()中checkPermission()的检查,导致失败
所以在Gondvv.java中,首先修改上下文为AllPermission,以保证以AllPermission权限调用
setSecurityManager(),绕过检查。下图为准备设置的新权限。
接着调用关键函数,在此函数内,完成权限的更改。
创建一个表达式,用来获取到SunToolkit,在java6中是获取不到的,java7中的ClassFinder
可以获取到SunToolkit
查看GetClass的实现,是表达式调用Class.forName(“sun.awt.SunToolkit”),用来获取SunToolkit
接着会在Expression.invoke()调用到ClassFinder.findClass(),如下图
此时可以观察ClassFinder.findClass()的参数,正是“sun.awt.SunToolkit”,通过ClassFinder类成功的获取到了我们想要的信息
其中”acc”为Statement中的私有成员,用于控制当前Statement上下文的访问权限
getField()为sun.awt.SunToolkit中的一个公有方法,并返回一个对象的引用(Field类型),并且
该方法可以获取到私有成员,如下图
以下表达式实际为SunToolkit.getField(Statement.class, “acc”),即执行该表达式后,即可返
回”acc”的引用
此时已成功获取acc对象,可直接修改其权限。
调用Field类的set方法,成功的将传入的localStatement上下文设置为AllPermission,localStatement上下文权限已被修改,执行该Statement将可通过setSecurityManager()中的权限检查,将SecurityManager置为null
执行Statement,即可执行任意命令。
Exploit中弹出calc
漏洞成因
sun.awt.SunToolkit本身就是安全机制实现的一部分,按照SandBox的机制,是不应该让不信任的代码直接获取到该类库的,而ClassFinder.findClass()却没有考虑这一点,致使攻击者可以获取到SunToolkit,修改自身权限,进而关闭SecurityManager.