
log4j 漏洞一些特殊的利用方式
聲明:該文章來自(安全檔案)版權(quán)由原作者所有,K2OS渲染引擎提供網(wǎng)頁加速服務(wù)。
背景
正愁本周沒主題可寫,結(jié)果兩天前就曝了一個核彈級的漏洞“l(fā)og4j RCE”,這兩天官方的修補(bǔ)方案也逐漸完善。所以本篇就拿 log4j 作為主題講一下我的幾個發(fā)現(xiàn)。
RCE
log4j RCE 原理已經(jīng)有挺多人發(fā)過了,本文不過多贅述。簡單說就是日志在打印時(shí)遇到 ${ 后 Interpolator 類按照 : 分割出第一部分作為 prefix 第二部分作為 key。通過 prefix 去找對應(yīng)的 lookup,再通過對應(yīng)的 lookup 實(shí)例調(diào)用 lookup 方法傳入 key 作為參數(shù)。
log4j-core 自帶的 lookup 有很多實(shí)例,其中就包括了此次存在漏洞的 JndiLookup 實(shí)例。JndiLookup 則是直接把傳進(jìn)來的 key 當(dāng)做 JNDI URL 用 InitialContext.lookup 去訪問,從而造成了 JNDI 代碼執(zhí)行漏洞。
WAF bypass
該漏洞曝光后各安全廠商也紛紛推出了解決方案,WAF、RASP、改源碼、改配置文件、更新到rc2等。
在此次漏洞中最沒有防御效果的就是 WAF 了。有提出?${?、jndi、ldap、rmi?等關(guān)鍵詞規(guī)則的防護(hù)。但研究后發(fā)現(xiàn)都會存在被繞過問題。
首先是 jndi、ldap 簡直太容易被繞過,只要用 lowerCase upperCase 就可以把關(guān)鍵詞分割開。
如果是用了正則的話那還可以使用 upper 把 jnd? 轉(zhuǎn)成 jndi。
注意:這里的??(\u0131)?不是?i(\x69)和I(\x49),經(jīng)過 toUpperCase 就會轉(zhuǎn)變成 I。從而繞過了 jndi 關(guān)鍵詞的攔截。
再就是 ${ 關(guān)鍵詞的攔截了,雖然這個范圍有點(diǎn)大可能會產(chǎn)生一些誤報(bào),但鑒于漏洞的嚴(yán)重性還是有很多人建議攔截 ${
但這樣也未必能夠真正的解決,因?yàn)槁┒吹挠|發(fā)點(diǎn)是在打印日志的時(shí)候把可控內(nèi)容攜帶進(jìn)去了。那么可控內(nèi)容從哪里來?
Header、URL、鍵值對參數(shù)、JSON參數(shù)、XML參數(shù) ...
現(xiàn)在隨著 JSON 數(shù)據(jù)格式的流行,很多系統(tǒng)都在使用 JSON 處理參數(shù),JSON 處理庫用的最多的就數(shù) Jackson和fastjson。
而 Jackson 和 fastjson 又有 unicode 和 hex 的編碼特性。
例如:
{"key":"\u0024\u007b"} {"key":"\x24\u007b"}
這樣就避開了數(shù)據(jù)包中有 ${ 的條件,所以 WAF 的防護(hù)規(guī)則還要多考慮幾種編碼。
信息泄露
sys、env 這兩個 lookup 的 payload 也在討論中被頻繁提起,實(shí)際上他們分別對應(yīng)的是?System.getProperty()?和?System.getenv(),能夠獲取一些環(huán)境變量和系統(tǒng)屬性。部分內(nèi)容是可以被攜帶在 dnslog 傳出去的。
除了 sys、env 以外我還發(fā)現(xiàn) ResourceBundleLookup 也可以獲取敏感信息,但沒有看到有人討論 Bundle,所以重點(diǎn)講一下。
public String lookup(final LogEvent event, final String key) { if (key == null) { return null; } final String[] keys = key.split(":"); final int keyLen = keys.length; if (keyLen != 2) { LOGGER.warn(LOOKUP, "Bad ResourceBundle key format [{}]. Expected format is BundleName:KeyName.", key); return null; } final String bundleName = keys[0]; final String bundleKey = keys[1]; try { // The ResourceBundle class caches bundles, no need to cache here. return ResourceBundle.getBundle(bundleName).getString(bundleKey); } catch (final MissingResourceException e) { LOGGER.warn(LOOKUP, "Error looking up ResourceBundle [{}].", bundleName, e); return null; } }
從代碼上來看就很好理解,把 key 按照 : 分割成兩份,第一個是 bundleName 獲取 ResourceBundle,第二個是 bundleKey 獲取 Properties Value
ResourceBundle 在 Java 應(yīng)用開發(fā)中經(jīng)常被用來做國際化,網(wǎng)站通常會給一段表述的內(nèi)容翻譯成多種語言,比如中文簡體、中文繁體、英文。
那開發(fā)者可能就會使用 ResourceBundle 來分別加載 classpath 下的 zh_CN.properties、en_US.properties。并按照唯一的 key 取出對應(yīng)的那段文字。例如:?zh_CN.properties
LOGIN_SUCCESS=登錄成功
那?ResourceBundle.getBundle("zh_CN").getString("LOGIN_SUCCESS")
?獲取到的就是?登錄成功
如果系統(tǒng)是 springboot 的話,它會有一個 application.properties 配置文件。里面存放著這個系統(tǒng)的各項(xiàng)配置,其中有可能就包含 redis、mysql 的配置項(xiàng)。當(dāng)然也不止 springboot,很多其他類型的系統(tǒng)也會寫一些類似 jdbc.properties 的文件來存放配置。
這些 properties 文件都可以通過 ResourceBundle 來獲取到里面的配置項(xiàng)。所以在 log4j 中 Bundle 是比sys和env更嚴(yán)重的存在。
在不出網(wǎng)的環(huán)境下可以通過 dnslog 的方式來外帶信息。
除了dnslog以外還可以通過這兩種方法來獲取信息。
ldap
dns
修復(fù)方案
log4j 更新到最新版本
[超站]友情鏈接:
四季很好,只要有你,文娛排行榜:https://www.yaopaiming.com/
關(guān)注數(shù)據(jù)與安全,洞悉企業(yè)級服務(wù)市場:https://www.ijiandao.com/
- 1 習(xí)近平接見新疆各族各界代表 7904287
- 2 樺加沙風(fēng)眼內(nèi)部曝光 拍攝部門:震撼 7808790
- 3 飛機(jī)狂風(fēng)中降落 機(jī)翼險(xiǎn)些砸地 7713230
- 4 援疆的山海深情 跨越千里萬里 7617376
- 5 馬克龍被美警察攔下 當(dāng)場打給特朗普 7521425
- 6 臺風(fēng)“樺加沙”影響有多大?解讀來了 7426828
- 7 上海再通報(bào)多校午餐發(fā)臭:涉嫌瞞報(bào) 7329321
- 8 深圳機(jī)場飛機(jī)被“五花大綁”防臺風(fēng) 7232212
- 9 美媒:中國航母能力實(shí)現(xiàn)重大飛躍 7143678
- 10 為避臺風(fēng) 小區(qū)近百輛車停上大橋 7043687