一、摘要
CloudBees Jenkins 2.32.1版本中存在Java反序列化漏洞,最終可導致遠程代碼執(zhí)行。
Jenkins是一款持續(xù)集成(continuous integration)與持續(xù)交付(continuous delivery)系統(tǒng),可以提高軟件研發(fā)流程中非人工參與部分的自動化處理效率。作為一個基于服務器的系統(tǒng),Jenkins運行在servlet容器(如Apache Tomcat)中,支持版本控制工具(包括AccuRev、CVS、Subversion、Git、Mercurial、Perforce、Clearcase以及RTC),能夠執(zhí)行基于Apache Ant、Apache Maven以及sbt的工程,也支持shell腳本和Windows批處理命令。
二、漏洞細節(jié)
為了觸發(fā)Jenkins的Java反序列化漏洞,我們需要向Jenkins發(fā)送兩個請求。
該漏洞存在于使用HTTP協(xié)議的雙向通信通道的具體實現(xiàn)代碼中,Jenkins利用此通道來接收命令。
我們可以通過第一個請求,建立雙向通道的一個會話,從服務器上下載數(shù)據(jù)。HTTP報文頭部中的“Session”字段用來作為通道的識別符,“Side”字段表明傳輸?shù)姆较颍ㄏ螺d或上傳,download/upload)。

我們可以通過第二個請求向雙向通道發(fā)送數(shù)據(jù)。服務器會阻塞第一個請求,直到我們發(fā)送第二個請求為止。HTTP報文頭部中的“Session”字段是一個UUID,服務器通過該UUID來匹配具體提供服務的雙向通道。

所有發(fā)往Jenkins CLI的命令中都包含某種格式的前導碼(preamble),前導碼格式通常如下所示:
rO0ABXNyABpodWRzb24ucmVtb3RpbmcuQ2FwYWJpbGl0eQAAAAAAAAABAgABSgAEbWFza3hwAAAAAAAAAH4=
該前導碼包含一個經過base64編碼的序列化對象。“Capability”類型的序列化對象的功能是告訴服務器客戶端具備哪些具體功能(比如HTTP分塊編碼功能)。
前導碼和其他一些額外字節(jié)發(fā)送完畢后,Jenkins服務器希望能夠收到一個類型為“Command”的序列化對象。由于Jenkins沒有驗證序列化對象,因此我們可以向其發(fā)送任何序列化對象。
反序列化處理代碼位于“Command”類的“readFrom”方法中,如下所示:

readFrom方法在“ClassicCommandTransport”類的“read()”方法中被調用:

通過上傳通道發(fā)送的數(shù)據(jù)在ReaderThread線程類中進行讀取,如下所示:

該線程由“upload”方法觸發(fā)運行,而“upload”方法在“CliEndpointResponse”類中被調用:

“upload”方法讀取HTTP body數(shù)據(jù),之后調用“notify”方法通知線程進行處理。

三、PoC
為了利用該漏洞,攻擊者需要運行“payload.jar”腳本,創(chuàng)建一個包含待執(zhí)行命令的序列化載荷。
接下來,攻擊者需要修改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*
|