近期對平臺安全滲透??測試中遇到有JAVA+mysql架構的滲透網(wǎng)站,針對此架構我們Sine安全滲透工程師整理了下具(′?_?`)體的漏洞檢??測方法和防護修復方法,很多像執行框架漏洞獲取到系統權限,測試測方以及跨權限寫(xiě)入木馬后門(mén)等等操作,希望大家在滲透測試的對J洞檢道路中發(fā)現更多的知識和經(jīng)驗。
4.2.1. 格式化字符串
在Python中,構網(wǎng)有兩種格式化字符串的站漏方式,在Python2的滲透較低版??本中,格式化字符串的測試測方方式為?? "this is a %s" % "test" ,之后(hou)增加了format的對J洞檢方式, 語(yǔ)法為 "this is 構網(wǎng)a { }".format('tヽ(′▽?zhuān)?ノest') 或者 "this is a { test}".format(test='test')
當格式化字符串由用戶(hù)輸入時(shí),則可能會(huì )造成一些問(wèn)題,站漏下面是滲透一個(gè)最簡(jiǎn)單的例子
>&?gt;> 'class of { 0} is { 0.__class__}'.format(42)
"class of 42 is "
從上面這個(gè)簡(jiǎn)單的例子不難知道,當我們可以控制要format的測試測方字符串時(shí),則可以使用?? __i???ni??t__ / __globals__ 等屬性讀取一些比較敏感的對J洞檢值,甚至任意執行代碼。構網(wǎng)
4.2.2.1. pickle
... a = 1
... b = 2
...?? def __reduce__(self):
... return (subprocess??.Popen,站漏 (('cmd.exe',),))
>>> cPickle.dumps(A())
4.2.2.2. 其他
P??yYAML
marshal
shelve
4.2.3. 沙箱
4.2.3.1. 常用函數
dir / type
globals / locals / vars
getattr / setatヽ(′▽?zhuān)?ノtr
4.2.3.2. 繞過(guò)??
最簡(jiǎn)單的思路是在已有的模塊中impor??t,如果那個(gè)模塊中已經(jīng) import 可以利用的模塊就可以使用了
在父類(lèi)中尋找可用的模塊,最常見(jiàn)payload是 ().__cl??ass__.__bases__[0].__subclasses__() 或者用魔術(shù)方法獲取全局作用域 __init_??_.__func__.__globals__
有些網(wǎng)站沒(méi)有過(guò)濾 pickle 模塊,可以(′?_?`)使用 pickle 實(shí)現任意代碼執行,生成 payload 可以使用
有的沙箱把相關(guān)的模塊代碼都被刪除了,則可以使用libc中的函數,Python 中調用一般可以使用 ctypes 或者 cffi。
"A""B" == "AB"
4.2.???3.3. 防御
Python官方給出了一些防御的建議
使用Jython并嘗試使用Java平臺來(lái)鎖定程序的權限
使用fakeroot來(lái)避免
使用一些rootjail的技術(shù)
4.2.4. 框架
4.2(′?ω?`).4.1. Django
4.2.4.1.??1. 歷史漏洞
CVE-2016-7401 CSRF Bypass
CVE-2017-7233/7234 open='open' red(′▽?zhuān)?)i(′_`)rect vulnerability
CVE-201??7-12794 debug page XSS
4.2.4.1.2. 配置相關(guān)
Nginx 在為 Django 做反向代理時(shí),靜態(tài)文件目錄配置錯誤會(huì )導致源碼泄露。訪(fǎng)問(wèn) /static.. 會(huì ) 301 重定向到 /static../
4.2.4.2. Flask
Fl(′?`)as(°□°)k默認使用(yong)客戶(hù)端session,使得session可以被偽造
4.2.5. 危險函數 / 模塊列表
4.2.5.1. 命令執行
os.popen
os.system
os.??spawn
os.fork
os.exec
popen2
commands
subprocess
exec
eval
timeit.sys
timeit.timeit
platform.os
platform.s(?Д?)ys
platform.
popen
pty.spawn
pty??.os
bdb.os
cgi.sys
…
4.2.5.2. 危險第三方庫
Template
subprocess32
4.2.5.3. 反序列化
marshal
PyYAML
pickle
cPickle
s??h??elve
Pヾ(′?`)?IL
Java
4.3.1??. 基本概念
JVM是Java平臺的核心,以機器代碼來(lái)實(shí)現,為程序執行提供了所需的所有基本功能,例如字節碼解析器、JIT編譯器、垃圾收集器等??。由于它是機器代碼實(shí)現的,其同樣受到二進(jìn)制文件受到的攻擊。
JCL是JVM自帶的一個(gè)標準庫,含有數百個(gè)系統類(lèi)。默認情況下,所有系統類(lèi)都??是可信任的,且擁有所有的特權。
4.3.1.2. JNDI
4.3.1.3. OGNL
OGNL(Object-??Graph Navigation Language,對象導航語(yǔ)言)是一種┐(′д`)┌功能強大(′_ゝ`)的表達式語(yǔ)言,通過(guò)簡(jiǎn)單一致的表達式語(yǔ)法,提供了存取對象的任意屬性、調用對象的方法、遍歷整個(gè)對象的結構圖、實(shí)現字段類(lèi)型轉化等功能。
Struts2中使用了OGNL,提供了一個(gè)Vヽ(′▽?zhuān)?ノalueStack類(lèi)。ValueStack分為root和context兩部分。root中是當前的action對象,conte??xt中是ActionContext里面所有的內容。
4.3.1.4. RMI
RMI(Remote Method Invocation,遠程方法調用)能夠讓在客戶(hù)端Java虛擬機上的對象像調用本地對象一樣調用服務(wù)端java虛擬機中的對象上的方法。
RMI遠程調用步驟:
客戶(hù)調用客戶(hù)端輔助對象stub上的方法
客戶(hù)端輔助對象stub打包調用信息(變量,方法名),通過(guò)網(wǎng)絡(luò )發(fā)送給服務(wù)端輔助對象skeleton
服務(wù)端輔助對象將結果打包,發(fā)送給客戶(hù)端輔助對象(′_ゝ`)stub
客戶(hù)端輔助對象將返回值解包,??返回??給調用者
客戶(hù)獲得返回值
4.3.2. 框架
4.3.2.1. Servl??et
4.3.2.1.1. 簡(jiǎn)介
Servlet(Server Appl??et)是Java?? Se??rvle(′_`)t的簡(jiǎn)稱(chēng),稱(chēng)為小服務(wù)程序或服務(wù)連接器,是用Java編寫(xiě)的服務(wù)器端程序,主要功能在于交互式地瀏覽和修改數據,生成動(dòng)態(tài)Web內容。
狹義的Servl(′;ω;`)et是指Java語(yǔ)言實(shí)現的一個(gè)接口,廣義的Servlet是指任何實(shí)現了這個(gè)Servlet接口的類(lèi),一般情況下,人們將Servlet理解為后者。Servlet運(′?_?`)行于支持Java的應用服務(wù)器中。從原理上講,Servlet可以響應任何類(lèi)型的請求??,但絕大多數情??況下Servlet只用來(lái)擴展基于H??TTP協(xié)議的Web服務(wù)器。
4.3.2.1.2. 生命周期為
客戶(hù)端請求該 Servlet
加(′?`)載 Servlet 類(lèi)到內存??
實(shí)例化并調用init()方法初始化該
Servlet service()(根據請求方法不同調用 doGet() / doPos??t() / &hellip??; / destroy()
4.3.2.1.3. 接口
init()
在 Servlet 的生命期中,僅執行一次 init() 方法,在服務(wù)器┐(′ー`)┌裝入 Servlet 時(shí)執行。
service()
service() 方法是 Servlet 的核心。每當一個(gè)客戶(hù)請求一個(gè)HttpServlet對象,該對象的 serv(╯°□°)╯︵ ┻━┻ice() 方法就要(yao)被調用,而且傳遞給這個(gè)方法一個(gè)”請求”(ServletRequest)對象和一??個(gè)”響應”(ServletResponse)對象作為參數。
4.3.2.2. Struts 2
4ヾ(′?`)?.3.2.2.1. 簡(jiǎn)介
Struts2是一個(gè)基于MVC設計模式的Web應用框架,它本質(zhì)上相當于一個(gè)servlet,在MVC設計模式中,Struts2作為控制器(Controller)來(lái)建立模型與視圖的數據交互。
4.3.2.2.2. 請求流程
客戶(hù)端發(fā)送請求的tomcat服務(wù)器
請??求經(jīng)過(guò)一系列過(guò)濾器
FilterDispatcher調(′ω`)用ActionMapper來(lái)決定這個(gè)請求是否要調用某個(gè)Action
ActionMppaer決定調用某個(gè)ActionFilterDispatcher把請求給ActionProxy
ActionPr(O_O)oxy通過(guò)Configuration Manag(╯‵□′)╯er查看structs.xml,找到對應的Action類(lèi)
ActionProxy創(chuàng )建一個(gè)ActionInvocation對象
ActionInvocation對象回調Action的execute方法
Action執行完畢后,ActionInvocation根據返回的字符串,找到相應的result,通過(guò)HttpServ??letResponse返回給服務(wù)器
4.3.2.2.3. 相關(guān)CVE
CVE-2016-3081 (S2-032)
CVE-2016-4438 (S2-03??7)
CVE-2017-5638
CVE-2017-7672
CVE-2017-9787
CVE-2017-9793
CVE-2017-9804
CVE-2017-9805
CVE-2017-12611
CVE-2017-15707
CVE-2018-11776
4.3.2.(′ω`)3. Spring MVC
用戶(hù)發(fā)送請求(╯‵□′)╯給服務(wù)器
服務(wù)器收到請求,使用Dispat??chServlet處理
Dispaヾ(′▽?zhuān)??tch使用Handle???Mapping檢查url是否有對應的Controller,如果有,執行
如果Controller返回字符串,ViewResoヾ(?■_■)ノlver將字符串轉換成相應的ヾ(′ω`)?視圖對象
DispatchServlet將視圖(tu)對象中的數據,輸出給服務(wù)器 服務(wù)器將
數據輸出給客戶(hù)端
4.3.3. 容器
常見(jiàn)(jian)的Java服務(wù)器有Tomcat、Weblogic、JBoss、GlassFish、Jetty、R┐(′д`)┌esin、IBM Websphere等,這里對部分框架做一個(gè)簡(jiǎn)單的說(shuō)明。
4.3.3.1. Tomcat(′ω`)
Tomcat是一個(gè)輕ヽ(′▽?zhuān)?ノ量級應用服務(wù)器,在中小型系統和并(╯‵□′)╯發(fā)訪(fǎng)問(wèn)用戶(hù)不是很多的場(chǎng)合下被普遍使用,用于開(kāi)發(fā)和調試J(???)SP程序。
在收到請求后,Tomcat的處理流程如下:
客戶(hù)端訪(fǎng)問(wèn)(wen)Web服務(wù)器,發(fā)送HTTP請求
Web服務(wù)器接收┐(′ー`)┌到請求后,傳遞給Servlet容器
Servlet容器加載Servlet,產(chǎn)生Servlet實(shí)例后,向其傳??遞表示請求和響應的(???)對象
Servlet實(shí)例使用請求對??象得到客戶(hù)端的請求信息,然后進(jìn)行相應的處理
Servlet實(shí)例將處理結果通過(guò)響應對象發(fā)送回客戶(hù)端,容器負責確保響應正確送出,同時(shí)將控制返回給(gei)Web服務(wù)器
Tomcat服務(wù)器是由一系列可配置的組件構成的,其中核心組件是Catalina Servlet容器,它(ta)是所有其他To??mcat組件的頂層容器。
4.3.3.1.1. 相關(guān)CVE
CVE-2017-12615
CVE-2013-2067
CVE-2012-4534
CVE-2012-4431
CV??E-2012-3546
CVE-2012-3544
CVE-2012-273??3
CVE-2011-3375
CVE-2011-3190
CVE-2008-2938
4.3.3.2. Weblogic
4.3.3.2.1. 簡(jiǎn)介
WebLogic對業(yè)內多種標準的全面支持,包括EJB、JSP、Servlet、JMS、JDBC等。
4.3.3.2.2. 相關(guān)CVE
CVE-2019-2658
CVE-2019-(′▽?zhuān)?2650
CVE-2019-2649
CVE-2019-2648
CVE-2019-2646
CVE-2019-2645
CVE-2019-2618
CVE-2(????)019-2615
CVE-2019-2568
CVE-2018-3252
CVE-2018-3248
CVE-2018-3245
CVE-2018-3201
CVE-2018-3197
CVE-2018-3191
CVE-2018-1258
CVE-2017-10271
CVE-2017-3248
CVE-2016-3510
4.3.3.3. JBoss
4.3.3.3.1. 簡(jiǎn)介
4.3.3.3.2. 相關(guān)CVE
CVE-2017-(′?_?`)12149
4.3.4.1. 簡(jiǎn)介
4.3.4.2. 相關(guān)CVE
C(′ω`)VE(//ω//)-2012-0507
CVE-2012-4681
CVE-2017-3272
CVE-2017-3289
4.3.5. 反序列化
4.3.5.1.ヾ(′▽?zhuān)?? 簡(jiǎn)介
序列化就是把對象轉換成字節流,便于保存在內存、文件、數據庫中;反序列(???)化即逆過(guò)程,由字節流還原成對象。Java中的 ObjectOutputStream 類(lèi)的 writeObject() 方法可以實(shí)現序列化,類(lèi) ObjectInputStream類(lèi)的readObject() 方法用于反序列化。
如果要實(shí)現類(lèi)的反序列化,則是對其實(shí)現 Serializable 接口。
4.3.5.2. 序列數據結構
0xaced 魔術(shù)頭
ObjectOutputStream實(shí)例初始化時(shí),將魔術(shù)頭和版本號寫(xiě)入bout (BlockDataOutputStr(′_`)eam類(lèi)型) 中
調用ObjectOutputStream.writeObject()開(kāi)始寫(xiě)對象數據
○ObjectStreamClass.lookup()封裝待序列化的類(lèi)描述 (返回ObjectStreamClass類(lèi)型) ,獲取包括類(lèi)名、自定義serialVersionUID、可序列化字段 (返回ObjectStreamField類(lèi)型) 和構造方法(fa),以及writeObject、readObject方法等
○writeOrdina(′ω`*)ryObject()寫(xiě)入對象數據
■寫(xiě)入對象類(lèi)型標識
■writeClassDesc()進(jìn)入分支writeNonProxyDesc()寫(xiě)入類(lèi)描述數據
寫(xiě)入類(lèi)(lei)描述符標識
寫(xiě)入類(lèi)名
寫(xiě)入SUID (當SUID為空時(shí),會(huì )進(jìn)行(′▽?zhuān)?)計算并賦值)
計算并寫(xiě)入序列化屬性標志位
寫(xiě)入字段信息數據
寫(xiě)入Block Data結束(shu)標識
寫(xiě)入父類(lèi)描述數據
若類(lèi)自定義了writeObject(),則調用該方法寫(xiě)對象,否則調用defaultWriteFields()寫(xiě)入對象的字段數據 (若是非原始類(lèi)型,則遞歸處理子對象)
4.3.5.4. 反序列化流程
ObjectInputStream實(shí)例初始化時(shí),讀取魔術(shù)頭和版本號進(jìn)行校驗
調用ObjectInputStream.readObject()開(kāi)始讀對象??數據
○讀取對象類(lèi)型標識
○readOrdinaryObje??ct()讀取數據對象
讀取類(lèi)描述符標識,進(jìn)入分支readNonProxyDe??sc()
讀取類(lèi)名
讀取SUID
讀取并分解序列化屬性標志位
讀取字段信息數據
resolveClass()根據類(lèi)名獲取待反序列化的類(lèi)的Class對象,如果獲取失敗,(⊙_⊙)則拋出ClassNotFoundException
skipCustomData()循環(huán)讀取字節直到Block Data結束標識為止?? 讀取父類(lèi)描述數據
initNonProxy()中判斷對象與本地對象的(′?_?`)SUID(//ω//)和類(lèi)名 (不含包名) 是否相同,若不同,則拋出InvalidClassException
Obj(′?`*)ectStreamCla??ss.newInstance()獲取并調用離對象最近的非■Serializable的父類(lèi)的無(wú)參構造方法 (若不存在,則返回null) 創(chuàng )建對??象實(shí)例
■readヽ(′ー`)ノSerialData()讀取對象的序列化數據
若類(lèi)自定義了readObject(),則調用該方法讀對象,否則調用defaultReadFields()讀取并填充對象的字段數據
4.3.5.5. 相關(guān)函數
ObjectInputStream.readObject
ObjectInputStream.readUnshared
Yaml.load
XStream.fromXML
ObjectMapper.readValue??
JSON.parseObject
4.3.5.6. 主流JSON庫
4.3.5.6.1. GSON
Gson默認只能反序列化基本類(lèi)型,如果(guo)是復雜類(lèi)型,需要程序員實(shí)現反序列化機制,相對比較安全。
4.3.5.6.2. Jackson
除非指明@jsonAutoDetect,Jackson不會(huì )反(fan)序列化非public屬性。在防御時(shí),可以不使用enableDefaultTyp??ing方法。
相關(guān)??CVE有
CVE-2017-7525
CVE-2017-15095
4.3.5.6.3. Fa???stjson
相關(guān)CVE有
CVE-2017-18349
commons-fileupload 1.3.1
commons-io 2.4
commons-collections 3.1
commons-logging 1.2
commons-beanutils 1.9.2
org.slf4j:slf4j-api 1.7.21
com.mchange:mchange-commons-java 0.2.11
org.a??p(′?ω?`)ache.commons:commons-collections 4.0
com.mchange:c3p0 0.9.5.2
org.beanshell:bsh 2.0b5
org.springframework:spring-aop 4.1.4.RELEASE
4.3.5.8. 網(wǎng)站漏┐(′?`)┌洞修復和防護
在使用 readObject() 反序列化時(shí)會(huì )調用 resolveClass 方法讀取反序列化的類(lèi)名,可以通過(guò)hook該方法來(lái)校驗反序列化的類(lèi),一個(gè)Demo如下
以上的Demo就只允許序列化 SerialObject ,通過(guò)這種方式,就可以設置允許序列化的白名單
4.3.5.8.2. ValidatingObjectInputStream
Apache Commons IO Serialization包中的 ValidatingObjectInputStream 類(lèi)提供了 accept 方法,可( ?° ?? ?°)以通過(guò)該方法來(lái)實(shí)現反序列化類(lèi)白/黑ヽ(′ー`)ノ名單控制,一個(gè)demo如下
Java 9提供了支持序列化數據過(guò)濾的新特性,可以繼承 java.io.ObjectInputFilter 類(lèi)重寫(xiě) checkInput方法來(lái)實(shí)(╬?益?)現自(zi)定義的過(guò)濾器,并使用 ObjectInputStream 對象的 setObjectInputFilter 設置過(guò)濾器來(lái)實(shí)現反序列化類(lèi)白/(╯‵□′)╯黑名單控制,對JAVA漏洞滲透測試有想進(jìn)一步了解(jie)的可以咨詢(xún)專(zhuān)業(yè)的網(wǎng)站安全公司,國內推薦Sinesafe,綠盟,啟明星辰等等專(zhuān)ˉ\_(ツ)_/ˉ業(yè)的安全維護公司。
(作者:SEO診斷)