【技術分享】Jenkins Nested View插件XXE漏洞(CVE-2021-21680)分析
0×1 前言
逆推這個漏洞本身不難,主要記錄下思路。
先看下漏洞描述:
該插件 1.20 及更早版本未配置其 XML 轉換器以防止 XML 外部實體 (XXE) 攻擊。這使攻擊者能夠配置視圖,讓 Jenkins 解析精心設計的視圖 XML 定義,該定義使用外部實體從 Jenkins 控制器或服務器端請求偽造中提取秘密。
該插件 1.21 禁用了其 XML 轉換器的外部實體解析。
根據漏洞描述可以提取關鍵信息:
- XXE漏洞
- 漏洞出現在配置視圖處
0×2 分析
Jenkins在github提交了修復代碼,修復后的版本和1.19.1對比如下圖。定位代碼修改處,主要是updateByXml方法添加限制對指外部DTD的訪問來進行修復。

updateByXml方法在doConfigDotXml中被調用。當請求方法時GET時會將NestedView作為XML數據返回,當請求方法是POST時,執行updateByXml((Source)new StreamSource(req.getReader()))將請求數據作為Source進行XML解析。那么我們只需要請求的時候設置HTTP method為POST,就可以對NestedView進行更新,然后用GET方法來讀取。

入口具體的api在哪里?在這個鏈接找到了-/user/view/viewname/config.xml。現在我們只要更新config.xml文件就能調用doConfigDotXml方法,那么xml文件的內容就能夠傳入到請求流從而進行解析。

現在的問題是怎么構造xml文件?既然能通過GET獲取XML數據,我們可以在頁面創建一個nested view,通過查看歷史創建的nested view的config.xml文件就能夠來構造我們想要的XML。

現在只要在nested view的config.xml文件中插入dtd,就可以達到我們的目的:
]>
另外需要注意,Jenkins配置了crumb來防御CSRF攻擊,所以請求的時候在url后面加上Jenkins-Crumb,Jenkins-Crumb的值可以通過api/crumbIssuer/api/json獲取。

0×3 總結
此次漏洞主要通過補丁對比反推漏洞,漏洞本身不復雜。首先根據描述提取關鍵信息比如什么漏洞類型、大致的漏洞位置,根據補丁修復代碼,反推出漏洞。該漏洞是一個典型XXE漏洞,通過TransformerFactory使用了默認的解析方法,沒有對dtd禁止。
StreamSource source = new StreamSource(req.getReader());Transformer t = TransformerFactory.newInstance().newTransformer();t.transform(source, new StreamResult(out));
下面是TransformerFactory解析xml防御XXE漏洞的典型方法,禁止外部DTD。
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
除了TransformerFactory,在Java中還有許多XML解析工具,如果需要防御XXE漏洞,基本都是通過禁用DTD及外部實體來解決的。
DocumentBuilderXMLStreamReaderSAXBuilderSAXParserSAXReaderXMLReaderSAXSourceSAXTransformerFactory......