标签归档:java

Java动态调用Groovy

 

package com.neeao.groovy;

import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyShell;
import groovy.util.GroovyScriptEngine;

public class helloGroovy {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		long time = System.currentTimeMillis();
		fun1();
		fun2();
		fun3();
		System.out.print(System.currentTimeMillis() - time);
		System.out.println(" ms");
	}

	private static void fun3() {
		try {
			GroovyScriptEngine engine = new GroovyScriptEngine("");
			Binding binding = new Binding();
			binding.setVariable("language", "Groovy");
			Object value = engine.run("SimpleScript.groovy", binding);
			assert value.equals("The End");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void fun2() {
		Binding binding = new Binding();
		binding.setVariable("x", 10);
		binding.setVariable("language", "Groovy");
		GroovyShell shell = new GroovyShell(binding);
		Object value = shell.evaluate("println \"Welcome to $language\"; y = x * 2; z = x * 3; println x ");
		assert value.equals(10);
		assert binding.getVariable("y").equals(20);
		assert binding.getVariable("z").equals(30);
	}

	private static void fun1() {
		GroovyClassLoader loader = new GroovyClassLoader();
		try {
			String scriptText = "class Foo {\n"
					+ "  int add(int x, int y) { x + y }}";
			Class<?> newClazz = loader.parseClass(scriptText);
			Object obj = newClazz.newInstance();
			Object i = obj.getClass().getMethod("add", int.class, int.class)
					.invoke(obj, 23, 3);
			System.out.println(i);
		} catch (Exception e) {

		}
	}

}

参考:

http://zjx158.iteye.com/blog/770763

http://tglnn.iteye.com/blog/376978

 

Struts2/XWork < 2.2.0远程执行任意代码漏洞分析及修补

1.exploit-db网站在7月14日爆出了一个Struts2的远程执行任意代码的漏洞,此漏洞危害之大,可谓百发百中,直接root,只要采用了Struts2和webwork框架的系统(对于webwork的版本,不太清楚,我这里没环境对其一一测试,这里有两者关系的介绍),基本上无一幸免。

2.昨天在接到朋友的提醒后,迅速将公司的一些使用此框架开发的项目漏洞修补了,我想大部分大公司的也在第一时间修补的差不多了,但是仍有很多公司,没有安全团队的,估计被黑了还被蒙在鼓里,感觉有必要在这里提醒下使用struts开发的朋友们,因为毕竟自己当初也做过java的开发。

3.漏洞成因在漏洞的poc中已经说的很详细了,但是都是英文的,而且对于Java不了解的人,可能会看得一头雾水,这里简单分析下,其实也是将原文粗略的翻译下了,对于其中名词不熟悉的请Google之:

Struts2的核心是使用的webwork框架,而webwork又是使用的XWork来处理action的,并且通过调用底层的getter/setter方法来处理http的参数,它将每个http参数声明为一个ONGL(这里是ONGL的介绍)语句。当我们提交一个http参数:

user.address.city=Bishkek&user['favoriteDrink']=kumys

ONGL将它转换为:

action.getUser().getAddress().setCity("Bishkek")

action.getUser().setFavoriteDrink("kumys")

这是通过ParametersInterceptor(参数过滤器)来执行的,使用用户提供的HTTP参数调用ValueStack.setValue()。

除了支持参数的设置和读取,ONGL支持另外的一些功能:

  • 调用方法:foo()
  • 调用静态方法:@java.lang.System@exit(1)
  • 类的调用:new MyClass()
  • 处理上下文变量:#foo = new MyClass()

由于ONGL的调用可以通过http传参来执行,为了防止攻击者以此来调用任意方法,Xwork设置了两个参数来进行防护:

  • OgnlContext的属性 'xwork.MethodAccessor.denyMethodExecution'(默认为真)
  • SecurityMemberAccess私有字段 'allowStaticMethodAccess'(默认为假)

为方便开发人员经常访问各种对象,XWork定义了很多预定义的上下文变量:

  • #application
  • #session
  • #request
  • #parameters
  • #attr

这些变量代表各种服务器变量。为了防止攻击者篡改服务器端对象,XWork的ParametersInterceptor是不允许参数名称中有#的,大约在一年前,漏洞发现者找到了一种方法来绕过这种保护(XW-641),即通过java的unicode字符串来表示:\u0023。当时感觉通过一种方法(OGNL value stack clearing)来修补是不够的,但是没有更多的时间来研究。

今年早些时候,漏洞发现者又发现了一些Xwork的一些预定义的变量:

  • #context – 这个方法的能否被调用是基于OgnlContext的 'xwork.MethodAccessor.denyMethodExecution' 属性的值
  • #_memberAccess – SecurityMemberAccess的'allowStaticAccess' 字段用来防止静态方法的执行
  • #root
  •  #this
  • #_typeResolver
  • #_classResolver
  •  #_traceEvaluations
  • #_lastEvaluation
  •  #_keepLastEvaluation

使用XW-641所描述的方法,漏洞发现者通过修改一些值能够调用被保护的Java代码,并且执行任意的Java代码:

#_memberAccess['allowStaticMethodAccess'] = true
#foo = new java .lang.Boolean("false")
#context['xwork.MethodAccessor.denyMethodExecution'] = #foo
#rt = @java.lang.Runtime@getRuntime()
#rt.exec('mkdir /tmp/PWNED')

事实证明通过构造http请求能够调用该OGNL的表达式。这个漏洞的PoC于2010年7月12日发布。如果想测试你的应用程序是否有漏洞,可以使用下面的测试代码,将会调用:java.lang.Runtime.getRuntime().exit(1)

http://mydomain/MyStruts.action?('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.den
yMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\u003d@java.lang.Runtime@getRunti
me()))=1

4.如何修补此漏洞:

目前官方已出了补丁:http://svn.apache.org/viewvc?view=revision&revision=956389

5.快写完了,发现绿盟也将这个漏洞中文说明也发出来了,不过标题是:XWork ParameterInterceptor类绕过安全限制漏洞

严格点说,这个应该是XWork的漏洞,谁让Struts2用的是人家的核心呢?:)。

一种被混淆过的Java类的反编译算法

1.想看某个Java开发的程序的源码,下了个jad反编译后,发现代码被混淆过,一些定义的String变量被混淆算法混淆了,无法看到原来的字符串了,jad反编译后的混淆过的代码如下:

static 
	{
		String as[];
		as = new String[3];
		as[0] = "P H\"\003j:Np$`5Gp";
		as[1] = "F&[?\005#&\\>\031j:Np\004`5G";
		as[2] = "P7H>W`;D \033f L";
		z = as;
		break MISSING_BLOCK_LABEL_146;
		local;
		toCharArray();
		JVM INSTR dup ;
		JVM INSTR arraylength .length;
		JVM INSTR swap ;
		int i = 0;
		JVM INSTR swap ;
		JVM INSTR dup_x1 ;
		1;
		JVM INSTR icmpgt 125;
		   goto _L1 _L2
_L1:
		JVM INSTR dup ;
		i;
_L4:
		JVM INSTR dup2 ;
		JVM INSTR caload ;
		byte byte0;
		switch (i % 5)
		{
		case 0: // '\0'
			byte0 = 3;
			break;

		case 1: // '\001'
			byte0 = 84;
			break;

		case 2: // '\002'
			byte0 = 41;
			break;

		case 3: // '\003'
			byte0 = 80;
			break;

		default:
			byte0 = 119;
			break;
		}
		byte0;
		JVM INSTR ixor ;
		(char);
		JVM INSTR castore ;
		i++;
		JVM INSTR swap ;
		JVM INSTR dup_x1 ;
		JVM INSTR ifne 125;
		   goto _L3 _L2
_L3:
		JVM INSTR dup2 ;
		JVM INSTR swap ;
		  goto _L4
_L2:
		JVM INSTR swap ;
		JVM INSTR dup_x1 ;
		i;
		JVM INSTR icmpgt 49;
		   goto _L5 _L1
_L5:
		JVM INSTR new #145 <Class String>;
		JVM INSTR dup_x1 ;
		JVM INSTR swap ;
		String();
		intern();
		JVM INSTR swap ;
		JVM INSTR pop ;
		JVM INSTR ret 0;
	}

2.是些JVM的指令,在Google后,找到了些资料,不过一时半会也难理解这些JVM的指令,好在找到了一篇文章,在这里,里面这位童鞋对代码做了分析,和我这个情况一个样,于是乎直接拿代码来用了,把里面的关键部分提取出来,写了个函数,方便调用。

3.我写的函数及测试代码:

package com.neeao.com;

public class neeao {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String as[];
		as = new String[3];
		String z[];
		as[0] = "P H\"\003j:Np$`5Gp";
		as[1] = "F&[?\005#&\\>\031j:Np\004`5G";
		as[2] = "P7H>W`;D \033f L";
		z = as;
		
		for (int m = 0; m < z.length; m++) {
			z[m] = Decode(z[m]);
		}
		 for (int l = 0; l < z.length; l++) {
			 System.out.println("" + l + ": " + z[l]);
		 }
		//System.out.print(Decode(OPT_QUICK_SCAN));
		System.out.print("test");
	}
	/**
	 * 解码函数
	 * @param string 要解码的字符串
	 * @return
	 */
	public static String Decode(String string)
	{
		byte[] con=new byte[] {3,84,41,80,119};
		char[] ch = string.toCharArray();
		for (int i = 0; i < ch.length; i++) {
			//System.out.print(con[i%5]+"\n");
			ch[i] =(char) (ch[i]^con[i%5]);
		}
		return new String(ch);
	}

}

其中decode就是解码函数了,里面的con数组对应jad反编译后代码中的byte0这个变量的switch的5个值。

4.执行后的输出:

0: Starting Scan
1: Error running scan
2: Scan complete
test