漏洞分析|死磕Jenkins漏洞回显与利用效果_jenkins 漏洞


该方法中功能包含一个`Command`类的`readFrom()`方法,会对传入的字节流进行`readObject()`操作,从而导致了反序列化代码执行。



public final Command read() throws IOException, ClassNotFoundException {
try {
Command cmd = Command.readFrom(channel, ois);
if (rawIn!=null)
rawIn.clear();
return cmd;
} catch (RuntimeException e) {// see JENKINS-19046
throw diagnoseStreamCorruption(e);
} catch (StreamCorruptedException e) {
throw diagnoseStreamCorruption(e);
}
}



static Command readFrom(Channel channel, ObjectInputStream ois) throws IOException, ClassNotFoundException {
Channel old = Channel.setCurrent(channel);
try {
return (Command)ois.readObject();
} finally {
Channel.setCurrent(old);
}
}


## 0x03 漏洞利用


在分析完漏洞原因后,我们需要思考如何构造Payload利用漏洞。由于Jenkins中包含了`org.apache.commons.collections`依赖项目,我们则就可以尝试用CC链进行反序列化攻击,但在Jenkins的黑名单中禁止了CC链的直接反序列化,则就需要找到一条链绕过黑名单的限制。


### 3.1 序列化黑名单


在漏洞分析章节中提到,`Channel()`方法会经过一系列的this调用,该过程中调用了`ChannelBuilder`类的`negotiate()`方法,该方法在return时调用了中的`makeTransport()`方法,返回了一个`ClassicCommandTransport`对象,在创建该对象过程中,会创建一个`ObjectInputStreamEx`对象并在传参过程中调用该类的`getClassFilter()`方法,`getClassFilter()`方法返回了一个`ClassFilter.DEFAULT`,`ClassFilter.DEFAULT`最终会返回了一个定义好的黑名单类列表,其中就包含了CC链中的相关类。



private static final String[] DEFAULT_PATTERNS = {
“^bsh[.].*”,
“^com[.]google[.]inject[.].*”,
“^com[.]mchange[.]v2[.]c3p0[.].*”,
“^com[.]sun[.]jndi[.].*”,
“^com[.]sun[.]corba[.].*”,
“^com[.]sun[.]javafx[.].*”,
“^com[.]sun[.]org[.]apache[.]regex[.]internal[.].*”,
“^java[.]awt[.].*”,
“^java[.]rmi[.].*”,
“^javax[.]management[.].*”,
“^javax[.]naming[.].*”,
“^javax[.]script[.].*”,
“^javax[.]swing[.].*”,
“^org[.]apache[.]commons[.]beanutils[.].*”,
“^org[.]apache[.]commons[.]collections[.]functors[.].*”,
“^org[.]apache[.]myfaces[.].*”,
“^org[.]apache[.]wicket[.].*”,
“.*org[.]apache[.]xalan.*”,
“^org[.]codehaus[.]groovy[.]runtime[.].*”,
“^org[.]hibernate[.].*”,
“^org[.]python[.].*”,
“^org[.]springframework..*”,
“^sun[.]rmi[.].*”,
“^javax[.]imageio[.].*”,
“^java[.]util[.]ServiceLoader " , " j a v a [ . ] n e t [ . ] U R L C l a s s L o a d e r ", "^java[.]net[.]URLClassLoader ","java[.]net[.]URLClassLoader
};


### 3.2 黑名单绕过


`jenkins`的黑名单限制了CC链利用的相关类,但`SignedObject`类没有在黑名单中,`SignedObject`类在创建对象时可以传入一个序列化类型的对象,并且`SignedObject`类的`getObject()`方法中会对传入的序列化对象进行反序列化操作,即调用`readObject()`方法,这里的`readObject()`方法并没有对限制CC类的使用,从而可以传入构造的序列化对象进行反序列化恶意执行代码。因此,需要构造一个调用链去调用`SignedObject`类的`getObject()`方法的利用链,从而绕过CC链的黑名单的限制,进行反序列化攻击。


### 3.3 CC利用链绕过的流程


![在这里插入图片描述](https://img-blog.csdnimg.cn/864e68bfc6a54d5c9d0a4b7e0fc35d2f.png#pic_center)


### 3.4 Payload分析


在对`ReferenceMap`类进行反序列化时,会默认调用其`readObject`方法。


![在这里插入图片描述](https://img-blog.csdnimg.cn/ebe2bacf1ce94e61839fd4f0101215b3.png#pic_center)


doReadObject方法对序列化流进行读取,分别复制给key和value,并调用put方法,将其放到一个map中


![在这里插入图片描述](https://img-blog.csdnimg.cn/c39354495c464f4182e77afe9255e45b.png#pic_center)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/f3007717c7ab4d3ab7d900a1e3459a04.png#pic_center)


在put方法中,调用了`isEqualKey`方法对传入的两个key做比较


![在这里插入图片描述](https://img-blog.csdnimg.cn/a42ad6638e754a30bec29998593a1373.png#pic_center)


由于传入的key是`CopyOnWriteArraySet`对象因此会调用该对象的`equals`方法


![在这里插入图片描述](https://img-blog.csdnimg.cn/8ffa3b878a884492b90782d3aa8703e8.png#pic_center)


在`CopyOnWriteArraySet.equals()`方法中调用了 `eq()`方法判断传入的两个对象是否相等。


![在这里插入图片描述](https://img-blog.csdnimg.cn/ffff5070248f4ae3a2de7168f226db63.png#pic_center)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/e1e5c1da03e14d42959f5eb949354ac9.png#pic_center)


由于在处理`CopyOnWriteArraySet`的`equals`方法中传入的对象是`CopyOnWriteArraySet`包装的`ConcurrentSkipListSet`对象和`ListOrderedSet`对象,因此会调用`ConcurrentSkipListSet`对象的`equals`对象将`ListOrderedSet`对象传入进去。


![在这里插入图片描述](https://img-blog.csdnimg.cn/1eb94f5a47604d63833fcff3268047ce.png#pic_center)


在Payload中,由于将`ListOrderedSet`对象的`collection`替换成了`JSONArray`对象。因此在调用`containsAll`方法中,会调用`JSONArray`类的`containsAll`方法对传入的 `ConcurrentSkipListSet`对象进行处理。


![在这里插入图片描述](https://img-blog.csdnimg.cn/4cca1476c2a94dc69a53b45b523a17c4.png#pic_center)


再经过`JSONArray`类内部的方法遍历元素,当传入的元素是一个对象时,则就是将其转换成JSON对象并使用`PropertyUtils.getProperty()`方法获取其中的属性值,在获取属性值的过程中通过反射机制调用了该`SignedObject`对象的`getObject()`,完成了CC链的入口点。


![在这里插入图片描述](https://img-blog.csdnimg.cn/2fb272b9f9864323a4e95d351b6a4a96.png#pic_center)



  • JSONArray.containsAll() ->
  • JSONArray.containsAll() ->
  • JSONArray.fromObject() ->
    
  •  JSONArray._fromCollection() ->
    
  •   JSONArray.addValue() ->
    
  •    JSONArray.processValue() ->
    
  •     JSONArray._processValue() ->
    
  •      AbstractJSON._processValue() ->
    
  •       JSONObject.fromObject() ->
    
  •        JSONObject._fromBean() ->
    
  •         JSONObject.defaultBeanProcessing() ->
    
  •          PropertyUtils.getProperty() ->
    
  •           PropertyUtilsBean.getProperty() ->
    
  •            PropertyUtilsBean.getNestedProperty() ->
    
  •             PropertyUtilsBean.getSimpleProperty() ->
    
  •              PropertyUtilsBean.invokeMethod() ->
    
  •               SignedObject.getObject() ->
    

### 3.5 SignedObject类


在`SignedObject`类的构造方法中传入了一个Serializable类型对象,并将其序列化并保存到了`content`属性中,在`SignedObject`的`getObject()`方法中对`content`进行了反序列化操作。


![在这里插入图片描述](https://img-blog.csdnimg.cn/02dc0ea7ef6f4bddbb3e3dfbab9fc974.png#pic_center)  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/9d8d46b0d641452fb05ad26ba0847b0b.png#pic_center)


### 3.6 漏洞修复


官方的修复方式是将`SingedObejct`类加入了黑名单。


![在这里插入图片描述](https://img-blog.csdnimg.cn/36853786cd2347ca9323ffdcd134903b.png#pic_center)


## 0x04 回显利用


上面我们已经绕过了CC链的黑名单限制,这时,我们就需要思考如何进行漏洞的利用效果,市面上的主流工具如vulhub给出的利用方式是通过jar包生成执行系统命令的序列化对象,但利用过程比较繁琐,无法便捷有效的展示漏洞利用效果。


针对jenkins的http请求和servlet的处理是基于jetty服务器实现的,在jetty服务器的回显马 [jetty789Echo.jsp]( ) 中给出了jetty的两种回显方式。由于CVE-2017-1000353漏洞在利用过程中创建了channel的特性,并将漏洞的download和upload类型的http请求传入了进去。这时我们就可以通过反射获取这个channel中的http属性,并通过传入http消息头中的某些字段进行读取传入的命令内容将其执行,并将执行结果在写入到响应包中,这样就完成了整个回显过程。


反射获取`channel`对象中的`underlyingOutput`属性



Field underlyingOutputField = channel.getClass().getDeclaredField(“underlyingOutput”);
underlyingOutputField.setAccessible(true);
Object underlyingOutput = underlyingOutputField.get(channel);
Object httpConnection;


在`underlyingOutput`属性的`_channel`和`this$0`的属性中保存了http请求响应的相关信息,通过反射获取`_channel`和`this$0`的属性并赋值给`httpConnection`对象



try{
Field _channelField = underlyingOutput.getClass().getDeclaredField(“_channel”);
_channelField.setAccessible(true);
httpConnection = _channelField.get(underlyingOutput);
}catch (Exception e){
Field connectionField = underlyingOutput.getClass().getDeclaredField(“this$0”);
connectionField.setAccessible(true);
httpConnection = connectionField.get(underlyingOutput);
}


获取到http信息后,再通过反射获取请求头中的命令执行cmd字段的值,并将其执行,写入到响应中。



Object request = httpConnection.getClass().getMethod(“getRequest”).invoke(httpConnection);
Object response = httpConnection.getClass().getMethod(“getResponse”).invoke(httpConnection);
String cmd = (String) request.getClass().getMethod(“getHeader”, String.class).invoke(request, “cmd”);
OutputStream outputStream = (OutputStream)response.getClass().getMethod(“getOutputStream”).invoke(response);
String result = “\n”+exec(cmd);
outputStream.write(result.getBytes());
outputStream.flush();


![在这里插入图片描述](https://img-blog.csdnimg.cn/fafd8103b7c84fa1aae13866a62e6193.png#pic_center)


这些技术都集成在了Goby上,在Goby上就可以体验到CVE-2017-1000353漏洞一键命令执行、反弹shell的功能。








## 0x05 效果对比




| 工具/效果 | Goby | CVE-2017-1000353-SNAPSHOT-all.jar |
| --- | --- | --- |
| 执行命令 | 支持 | 支持 |
| 命令回显 | 支持 | 不支持 |
| 利用过程 | 一键命令执行 | 手工生成序列化数据包,执行脚本发送payload |
| 依赖环境 | 无需 | java、python |
| 便捷性 | 操作简单 | 操作繁琐 |


最后感谢 @irelia 师傅的漏洞问题反馈,已奖励红队版15天。我们期待更多师傅真诚反馈产品问题,这对 Goby 的进步至关重要。可加入微信群:公众号发暗号“加群”。


## 0x06 参考


<https://github.com/vulhub/CVE-2017-1000353>




本人从事网路安全工作12年,曾在2个大厂工作过,安全服务、售后服务、售前、攻防比赛、安全讲师、销售经理等职位都做过,对这个行业了解比较全面。


最近遍览了各种网络安全类的文章,内容参差不齐,其中不伐有大佬倾力教学,也有各种不良机构浑水摸鱼,在收到几条私信,发现大家对一套完整的系统的网络安全从学习路线到学习资料,甚至是工具有着不小的需求。


最后,我将这部分内容融会贯通成了一套282G的网络安全资料包,所有类目条理清晰,知识点层层递进,需要的小伙伴可以点击下方小卡片领取哦!下面就开始进入正题,如何从一个萌新一步一步进入网络安全行业。


![](https://img-blog.csdnimg.cn/img_convert/311903982dea1d8a5d2c98fc271b5b41.jpeg)



### 学习路线图


 其中最为瞩目也是最为基础的就是网络安全学习路线图,这里我给大家分享一份打磨了3个月,已经更新到4.0版本的网络安全学习路线图。


相比起繁琐的文字,还是生动的视频教程更加适合零基础的同学们学习,这里也是整理了一份与上述学习路线一一对应的网络安全视频教程。


![](https://img-blog.csdnimg.cn/img_convert/1ddfaf7dc5879b1120e31fafa1ad4dc7.jpeg)


#### 网络安全工具箱


当然,当你入门之后,仅仅是视频教程已经不能满足你的需求了,你肯定需要学习各种工具的使用以及大量的实战项目,这里也分享一份**我自己整理的网络安全入门工具以及使用教程和实战。**


![](https://img-blog.csdnimg.cn/img_convert/bcd1787ce996787388468bb227d8f959.jpeg)


#### 项目实战


最后就是项目实战,这里带来的是**SRC资料&HW资料**,毕竟实战是检验真理的唯一标准嘛~


![](https://img-blog.csdnimg.cn/img_convert/35fc46df24091ce3c9a5032a9919b755.jpeg)


#### 面试题


归根结底,我们的最终目的都是为了就业,所以这份结合了多位朋友的亲身经验打磨的面试题合集你绝对不能错过!

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/topics/618540462)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 30
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值