一、摘要
CloudBees Jenkins 2.32.1版本中存在Java反序列化漏洞,最终可导致远程代码执行。
Jenkins是一款持续集成(continuous integration)与持续交付(continuous delivery)系统,可以提高软件研发流程中非人工参与部分的自动化处理效率。作为一个基于服务器的系统,Jenkins运行在servlet容器(如Apache Tomcat)中,支持版本控制工具(包括AccuRev、CVS、Subversion、Git、Mercurial、Perforce、Clearcase以及RTC),能够执行基于Apache Ant、Apache Maven以及sbt的工程,也支持shell脚本和Windows批处理命令。
二、漏洞细节
为了触发Jenkins的Java反序列化漏洞,我们需要向Jenkins发送两个请求。
该漏洞存在于使用HTTP协议的双向通信通道的具体实现代码中,Jenkins利用此通道来接收命令。
我们可以通过第一个请求,建立双向通道的一个会话,从服务器上下载数据。HTTP报文头部中的“Session”字段用来作为通道的识别符,“Side”字段表明传输的方向(下载或上传,download/upload)。
我们可以通过第二个请求向双向通道发送数据。服务器会阻塞第一个请求,直到我们发送第二个请求为止。HTTP报文头部中的“Session”字段是一个UUID,服务器通过该UUID来匹配具体提供服务的双向通道。
所有发往Jenkins CLI的命令中都包含某种格式的前导码(preamble),前导码格式通常如下所示:
rO0ABXNyABpodWRzb24ucmVtb3RpbmcuQ2FwYWJpbGl0eQAAAAAAAAABAgABSgAEbWFza3hwAAAAAAAAAH4=
该前导码包含一个经过base64编码的序列化对象。“Capability”类型的序列化对象的功能是告诉服务器客户端具备哪些具体功能(比如HTTP分块编码功能)。
前导码和其他一些额外字节发送完毕后,Jenkins服务器希望能够收到一个类型为“Command”的序列化对象。由于Jenkins没有验证序列化对象,因此我们可以向其发送任何序列化对象。
反序列化处理代码位于“Command”类的“readFrom”方法中,如下所示:
readFrom方法在“ClassicCommandTransport”类的“read()”方法中被调用:
通过上传通道发送的数据在ReaderThread线程类中进行读取,如下所示:
该线程由“upload”方法触发运行,而“upload”方法在“CliEndpointResponse”类中被调用:
“upload”方法读取HTTP body数据,之后调用“notify”方法通知线程进行处理。
三、PoC
为了利用该漏洞,攻击者需要运行“payload.jar”脚本,创建一个包含待执行命令的序列化载荷。
接下来,攻击者需要修改jenkins_poc1.py脚本:
1、修改URL变量所指向的目标url;
2、在“FILE_SER = open(“jenkins_poc1.ser”, “rb”).read()”那一行,将要打开的文件指向自己的载荷文件。
修改完毕后,你可以在jenkins的日志输出中看到如下信息:
Jan 26, 2017 2:22:41 PM hudson.remoting.SynchronousCommandTransport$ReaderThread run
SEVERE: I/O error in channel HTTP full-duplex channel a403c455-3b83-4890-b304-ec799bffe582
hudson.remoting.DiagnosedStreamCorruptionException
Read back: 0xac 0xed 0x00 0x05 'sr' 0x00 '/org.apache.commons.collections.map.ReferenceMap' 0x15 0x94 0xca 0x03 0x98 'I' 0x08 0xd7 0x03 0x00 0x00 'xpw' 0x11 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x00 '?@' 0x00 0x00 0x00 0x00 0x00 0x10 'sr' 0x00 '(java.util.concurrent.CopyOnWriteArraySetK' 0xbd 0xd0 0x92 0x90 0x15 'i' 0xd7 0x02 0x00 0x01 'L' 0x00 0x02 'alt' 0x00 '+Ljava/util/concurrent/CopyOnWriteArrayList;xpsr' 0x00 ')java.util.concurrent.CopyOnWriteArrayListx]' 0x9f 0xd5 'F' 0xab 0x90 0xc3 0x03 0x00 0x00 'xpw' 0x04 0x00 0x00 0x00 0x02 'sr' 0x00 '*java.util.concurrent.ConcurrentSkipListSet' 0xdd 0x98 'Py' 0xbd 0xcf 0xf1 '[' 0x02 0x00 0x01 'L' 0x00 0x01 'mt' 0x00 '-Ljava/util/concurrent/ConcurrentNavigableMap;xpsr' 0x00 '*java.util.concurrent.ConcurrentSkipListMap' 0x88 'Fu' 0xae 0x06 0x11 'F' 0xa7 0x03 0x00 0x01 'L' 0x00 0x0a
'comparatort' 0x00 0x16 'Ljava/util/Comparator;xppsr' 0x00 0x1a 'java.security.SignedObject' 0x09 0xff 0xbd 'h*
|