當(dāng)前位置:首頁 >  站長 >  建站經(jīng)驗(yàn) >  正文

滲透測試對Java架構(gòu)網(wǎng)站漏洞檢測方法

 2019-10-24 11:12  來源: A5用戶投稿   我來投稿 撤稿糾錯(cuò)

  域名預(yù)訂/競價(jià),好“米”不錯(cuò)過

近期對平臺(tái)安全滲透測試中遇到有JAVA+mysql架構(gòu)的網(wǎng)站,針對此架構(gòu)我們Sine安全滲透工程師整理了下具體的漏洞檢測方法和防護(hù)修復(fù)方法,很多像執(zhí)行框架漏洞獲取到系統(tǒng)權(quán)限,以及跨權(quán)限寫入木馬后門等等操作,希望大家在滲透測試的道路中發(fā)現(xiàn)更多的知識(shí)和經(jīng)驗(yàn)。

4.2.1. 格式化字符串

在Python中,有兩種格式化字符串的方式,在Python2的較低版本中,格式化字符串的方式為 "this is a %s" % "test" ,之后增加了format的方式, 語法為 "this is a {}".format('test') 或者 "this is a {test}".format(test='test')

當(dāng)格式化字符串由用戶輸入時(shí),則可能會(huì)造成一些問題,下面是一個(gè)最簡單的例子

>>> 'class of {0} is {0.__class__}'.format(42)

"class of 42 is "

從上面這個(gè)簡單的例子不難知道,當(dāng)我們可以控制要format的字符串時(shí),則可以使用 __init__ / __globals__ 等屬性讀取一些比較敏感的值,甚至任意執(zhí)行代碼。

4.2.2. 反序列化

4.2.2.1. pickle

>>> class A(object):

... a = 1

... b = 2

... def __reduce__(self):

... return (subprocess.Popen, (('cmd.exe',),))

>>> cPickle.dumps(A())

"csubprocess\nPopen\np1\n((S'cmd.exe'\np2\ntp3\ntp4\nRp5\n."

4.2.2.2. 其他

PyYAML

marshal

shelve

4.2.3. 沙箱

4.2.3.1. 常用函數(shù)

eval / exec / compile

dir / type

globals / locals / vars

getattr / setattr

4.2.3.2. 繞過

最簡單的思路是在已有的模塊中import,如果那個(gè)模塊中已經(jīng) import 可以利用的模塊就可以使用了

在父類中尋找可用的模塊,最常見payload是 ().__class__.__bases__[0].__subclasses__() 或者用魔術(shù)方法獲取全局作用域 __init__.__func__.__globals__

有些網(wǎng)站沒有過濾 pickle 模塊,可以使用 pickle 實(shí)現(xiàn)任意代碼執(zhí)行,生成 payload 可以使用

有的沙箱把相關(guān)的模塊代碼都被刪除了,則可以使用libc中的函數(shù),Python 中調(diào)用一般可以使用 ctypes 或者 cffi。

"A""B" == "AB"

4.2.3.3. 防御

Python官方給出了一些防御的建議

使用Jython并嘗試使用Java平臺(tái)來鎖定程序的權(quán)限

使用fakeroot來避免

使用一些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 redirect vulnerability

CVE-2017-12794 debug page XSS

4.2.4.1.2. 配置相關(guān)

Nginx 在為 Django 做反向代理時(shí),靜態(tài)文件目錄配置錯(cuò)誤會(huì)導(dǎo)致源碼泄露。訪問 /static.. 會(huì) 301 重定向到 /static../

4.2.4.2. Flask

Flask默認(rèn)使用客戶端session,使得session可以被偽造

4.2.5. 危險(xiǎn)函數(shù) / 模塊列表

4.2.5.1. 命令執(zhí)行

os.popen

os.system

os.spawn

os.fork

os.exec

popen2

commands

subprocess

exec

execfile

eval

timeit.sys

timeit.timeit

platform.os

platform.sys

platform.

popen

pty.spawn

pty.os

bdb.os

cgi.sys

4.2.5.2. 危險(xiǎn)第三方庫

Template

subprocess32

4.2.5.3. 反序列化

marshal

PyYAML

pickle

cPickle

shelve

PIL

Java

4.3.1. 基本概念

JVM是Java平臺(tái)的核心,以機(jī)器代碼來實(shí)現(xiàn),為程序執(zhí)行提供了所需的所有基本功能,例如字節(jié)碼解析器、JIT編譯器、垃圾收集器等。由于它是機(jī)器代碼實(shí)現(xiàn)的,其同樣受到二進(jìn)制文件受到的攻擊。

JCL是JVM自帶的一個(gè)標(biāo)準(zhǔn)庫,含有數(shù)百個(gè)系統(tǒng)類。默認(rèn)情況下,所有系統(tǒng)類都是可信任的,且擁有所有的特權(quán)。

4.3.1.2. JNDI

JNDI(Java Naming and Directory Interface,JAVA命名和目錄接口)是為JAVA應(yīng)用程序提供命名和目錄訪問服務(wù)的API(Application Programing Interface,應(yīng)用程序編程接口)。

4.3.1.3. OGNL

OGNL(Object-Graph Navigation Language,對象導(dǎo)航語言)是一種功能強(qiáng)大的表達(dá)式語言,通過簡單一致的表達(dá)式語法,提供了存取對象的任意屬性、調(diào)用對象的方法、遍歷整個(gè)對象的結(jié)構(gòu)圖、實(shí)現(xiàn)字段類型轉(zhuǎn)化等功能。

Struts2中使用了OGNL,提供了一個(gè)ValueStack類。ValueStack分為root和context兩部分。root中是當(dāng)前的action對象,context中是ActionContext里面所有的內(nèi)容。

4.3.1.4. RMI

RMI(Remote Method Invocation,遠(yuǎn)程方法調(diào)用)能夠讓在客戶端Java虛擬機(jī)上的對象像調(diào)用本地對象一樣調(diào)用服務(wù)端java虛擬機(jī)中的對象上的方法。

RMI遠(yuǎn)程調(diào)用步驟:

客戶調(diào)用客戶端輔助對象stub上的方法

客戶端輔助對象stub打包調(diào)用信息(變量,方法名),通過網(wǎng)絡(luò)發(fā)送給服務(wù)端輔助對象skeleton

服務(wù)端輔助對象skeleton將客戶端輔助對象發(fā)送來的信息解包,找出真正被調(diào)用的方法以及該方法所在對象

調(diào)用真正服務(wù)對象上的真正方法,并將結(jié)果返回給服務(wù)端輔助對象skeleton

服務(wù)端輔助對象將結(jié)果打包,發(fā)送給客戶端輔助對象stub

客戶端輔助對象將返回值解包,返回給調(diào)用者

客戶獲得返回值

4.3.2. 框架

4.3.2.1. Servlet

4.3.2.1.1. 簡介

Servlet(Server Applet)是Java Servlet的簡稱,稱為小服務(wù)程序或服務(wù)連接器,是用Java編寫的服務(wù)器端程序,主要功能在于交互式地瀏覽和修改數(shù)據(jù),生成動(dòng)態(tài)Web內(nèi)容。

狹義的Servlet是指Java語言實(shí)現(xiàn)的一個(gè)接口,廣義的Servlet是指任何實(shí)現(xiàn)了這個(gè)Servlet接口的類,一般情況下,人們將Servlet理解為后者。Servlet運(yùn)行于支持Java的應(yīng)用服務(wù)器中。從原理上講,Servlet可以響應(yīng)任何類型的請求,但絕大多數(shù)情況下Servlet只用來擴(kuò)展基于HTTP協(xié)議的Web服務(wù)器。

4.3.2.1.2. 生命周期為

客戶端請求該 Servlet

加載 Servlet 類到內(nèi)存

實(shí)例化并調(diào)用init()方法初始化該

Servlet service()(根據(jù)請求方法不同調(diào)用 doGet() / doPost() / … / destroy()

4.3.2.1.3. 接口

init()

在 Servlet 的生命期中,僅執(zhí)行一次 init() 方法,在服務(wù)器裝入 Servlet 時(shí)執(zhí)行。

service()

service() 方法是 Servlet 的核心。每當(dāng)一個(gè)客戶請求一個(gè)HttpServlet對象,該對象的 service() 方法就要被調(diào)用,而且傳遞給這個(gè)方法一個(gè)”請求”(ServletRequest)對象和一個(gè)”響應(yīng)”(ServletResponse)對象作為參數(shù)。

4.3.2.2. Struts 2

4.3.2.2.1. 簡介

Struts2是一個(gè)基于MVC設(shè)計(jì)模式的Web應(yīng)用框架,它本質(zhì)上相當(dāng)于一個(gè)servlet,在MVC設(shè)計(jì)模式中,Struts2作為控制器(Controller)來建立模型與視圖的數(shù)據(jù)交互。

4.3.2.2.2. 請求流程

客戶端發(fā)送請求的tomcat服務(wù)器

請求經(jīng)過一系列過濾器

FilterDispatcher調(diào)用ActionMapper來決定這個(gè)請求是否要調(diào)用某個(gè)Action

ActionMppaer決定調(diào)用某個(gè)ActionFilterDispatcher把請求給ActionProxy

ActionProxy通過Configuration Manager查看structs.xml,找到對應(yīng)的Action類

ActionProxy創(chuàng)建一個(gè)ActionInvocation對象

ActionInvocation對象回調(diào)Action的execute方法

Action執(zhí)行完畢后,ActionInvocation根據(jù)返回的字符串,找到相應(yīng)的result,通過HttpServletResponse返回給服務(wù)器

4.3.2.2.3. 相關(guān)CVE

CVE-2016-3081 (S2-032)

CVE-2016-3687 (S2-033)

CVE-2016-4438 (S2-037)

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-1327

CVE-2018-11776

4.3.2.3. Spring MVC

4.3.2.3.1. 請求流程

用戶發(fā)送請求給服務(wù)器

服務(wù)器收到請求,使用DispatchServlet處理

Dispatch使用HandleMapping檢查url是否有對應(yīng)的Controller,如果有,執(zhí)行

如果Controller返回字符串,ViewResolver將字符串轉(zhuǎn)換成相應(yīng)的視圖對象

DispatchServlet將視圖對象中的數(shù)據(jù),輸出給服務(wù)器 服務(wù)器將

數(shù)據(jù)輸出給客戶端

4.3.3. 容器

常見的Java服務(wù)器有Tomcat、Weblogic、JBoss、GlassFish、Jetty、Resin、IBM Websphere等,這里對部分框架做一個(gè)簡單的說明。

4.3.3.1. Tomcat

Tomcat是一個(gè)輕量級(jí)應(yīng)用服務(wù)器,在中小型系統(tǒng)和并發(fā)訪問用戶不是很多的場合下被普遍使用,用于開發(fā)和調(diào)試JSP程序。

在收到請求后,Tomcat的處理流程如下:

客戶端訪問Web服務(wù)器,發(fā)送HTTP請求

Web服務(wù)器接收到請求后,傳遞給Servlet容器

Servlet容器加載Servlet,產(chǎn)生Servlet實(shí)例后,向其傳遞表示請求和響應(yīng)的對象

Servlet實(shí)例使用請求對象得到客戶端的請求信息,然后進(jìn)行相應(yīng)的處理

Servlet實(shí)例將處理結(jié)果通過響應(yīng)對象發(fā)送回客戶端,容器負(fù)責(zé)確保響應(yīng)正確送出,同時(shí)將控制返回給Web服務(wù)器

Tomcat服務(wù)器是由一系列可配置的組件構(gòu)成的,其中核心組件是Catalina Servlet容器,它是所有其他Tomcat組件的頂層容器。

4.3.3.1.1. 相關(guān)CVE

CVE-2019-0232

CVE-2017-12615

CVE-2013-2067

CVE-2012-4534

CVE-2012-4431

CVE-2012-3546

CVE-2012-3544

CVE-2012-2733

CVE-2011-3375

CVE-2011-3190

CVE-2008-2938

4.3.3.2. Weblogic

4.3.3.2.1. 簡介

WebLogic是美國Oracle公司出品的一個(gè)Application Server,是一個(gè)基于Java EE架構(gòu)的中間件,WebLogic是用于開發(fā)、集成、部署和管理大型分布式Web應(yīng)用、網(wǎng)絡(luò)應(yīng)用和數(shù)據(jù)庫應(yīng)用的Java應(yīng)用服務(wù)器。其將Java的動(dòng)態(tài)功能和Java Enterprise標(biāo)準(zhǔn)的安全性引入大型網(wǎng)絡(luò)應(yīng)用的開發(fā)、集成、部署和管理之中。

WebLogic對業(yè)內(nèi)多種標(biāo)準(zhǔn)的全面支持,包括EJB、JSP、Servlet、JMS、JDBC等。

4.3.3.2.2. 相關(guān)CVE

CVE-2019-2658

CVE-2019-2650

CVE-2019-2649

CVE-2019-2648

CVE-2019-2647

CVE-2019-2646

CVE-2019-2645

CVE-2019-2618

CVE-2019-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

CVE-2015-4852

4.3.3.3. JBoss

4.3.3.3.1. 簡介

JBoss是一個(gè)基于J2EE的管理EJB的容器和服務(wù)器,但JBoss核心服務(wù)不包括支持servlet/JSP的WEB容器,一般與Tomcat或Jetty綁定使用。

4.3.3.3.2. 相關(guān)CVE

CVE-2017-12149

4.3.4. 沙箱

4.3.4.1. 簡介

Java實(shí)現(xiàn)了一套沙箱環(huán)境,使遠(yuǎn)程的非可信代碼只能在受限的環(huán)境下執(zhí)行。

4.3.4.2. 相關(guān)CVE

CVE-2012-0507

CVE-2012-4681

CVE-2017-3272

CVE-2017-3289

4.3.5. 反序列化

4.3.5.1. 簡介

序列化就是把對象轉(zhuǎn)換成字節(jié)流,便于保存在內(nèi)存、文件、數(shù)據(jù)庫中;反序列化即逆過程,由字節(jié)流還原成對象。Java中的 ObjectOutputStream 類的 writeObject() 方法可以實(shí)現(xiàn)序列化,類 ObjectInputStream類的readObject() 方法用于反序列化。

如果要實(shí)現(xiàn)類的反序列化,則是對其實(shí)現(xiàn) Serializable 接口。

4.3.5.2. 序列數(shù)據(jù)結(jié)構(gòu)

0xaced 魔術(shù)頭

4.3.5.3. 序列化流程

ObjectOutputStream實(shí)例初始化時(shí),將魔術(shù)頭和版本號(hào)寫入bout (BlockDataOutputStream類型) 中

調(diào)用ObjectOutputStream.writeObject()開始寫對象數(shù)據(jù)

○ObjectStreamClass.lookup()封裝待序列化的類描述 (返回ObjectStreamClass類型) ,獲取包括類名、自定義serialVersionUID、可序列化字段 (返回ObjectStreamField類型) 和構(gòu)造方法,以及writeObject、readObject方法等

○writeOrdinaryObject()寫入對象數(shù)據(jù)

■寫入對象類型標(biāo)識(shí)

■writeClassDesc()進(jìn)入分支writeNonProxyDesc()寫入類描述數(shù)據(jù)

寫入類描述符標(biāo)識(shí)

寫入類名

寫入SUID (當(dāng)SUID為空時(shí),會(huì)進(jìn)行計(jì)算并賦值)

計(jì)算并寫入序列化屬性標(biāo)志位

寫入字段信息數(shù)據(jù)

寫入Block Data結(jié)束標(biāo)識(shí)

寫入父類描述數(shù)據(jù)

■writeSerialData()寫入對象的序列化數(shù)據(jù)

若類自定義了writeObject(),則調(diào)用該方法寫對象,否則調(diào)用defaultWriteFields()寫入對象的字段數(shù)據(jù) (若是非原始類型,則遞歸處理子對象)

4.3.5.4. 反序列化流程

ObjectInputStream實(shí)例初始化時(shí),讀取魔術(shù)頭和版本號(hào)進(jìn)行校驗(yàn)

調(diào)用ObjectInputStream.readObject()開始讀對象數(shù)據(jù)

○讀取對象類型標(biāo)識(shí)

○readOrdinaryObject()讀取數(shù)據(jù)對象

■readClassDesc()讀取類描述數(shù)據(jù)

讀取類描述符標(biāo)識(shí),進(jìn)入分支readNonProxyDesc()

讀取類名

讀取SUID

讀取并分解序列化屬性標(biāo)志位

讀取字段信息數(shù)據(jù)

resolveClass()根據(jù)類名獲取待反序列化的類的Class對象,如果獲取失敗,則拋出ClassNotFoundException

skipCustomData()循環(huán)讀取字節(jié)直到Block Data結(jié)束標(biāo)識(shí)為止 讀取父類描述數(shù)據(jù)

initNonProxy()中判斷對象與本地對象的SUID和類名 (不含包名) 是否相同,若不同,則拋出InvalidClassException

ObjectStreamClass.newInstance()獲取并調(diào)用離對象最近的非■Serializable的父類的無參構(gòu)造方法 (若不存在,則返回null) 創(chuàng)建對象實(shí)例

■readSerialData()讀取對象的序列化數(shù)據(jù)

若類自定義了readObject(),則調(diào)用該方法讀對象,否則調(diào)用defaultReadFields()讀取并填充對象的字段數(shù)據(jù)

4.3.5.5. 相關(guān)函數(shù)

ObjectInputStream.readObject

ObjectInputStream.readUnshared

XMLDecoder.readObject

Yaml.load

XStream.fromXML

ObjectMapper.readValue

JSON.parseObject

4.3.5.6. 主流JSON庫

4.3.5.6.1. GSON

Gson默認(rèn)只能反序列化基本類型,如果是復(fù)雜類型,需要程序員實(shí)現(xiàn)反序列化機(jī)制,相對比較安全。

4.3.5.6.2. Jackson

除非指明@jsonAutoDetect,Jackson不會(huì)反序列化非public屬性。在防御時(shí),可以不使用enableDefaultTyping方法。

相關(guān)CVE有

CVE-2017-7525

CVE-2017-15095

4.3.5.6.3. Fastjson

相關(guān)CVE有

CVE-2017-18349

4.3.5.7. 存在危險(xiǎn)的基礎(chǔ)庫

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.apache.commons:commons-collections 4.0

com.mchange:c3p0 0.9.5.2

org.beanshell:bsh 2.0b5

org.codehaus.groovy:groovy 2.3.9

org.springframework:spring-aop 4.1.4.RELEASE

4.3.5.8. 網(wǎng)站漏洞修復(fù)和防護(hù)

4.3.5.8.1. Hook resolveClass

在使用 readObject() 反序列化時(shí)會(huì)調(diào)用 resolveClass 方法讀取反序列化的類名,可以通過hook該方法來校驗(yàn)反序列化的類,一個(gè)Demo如下

以上的Demo就只允許序列化 SerialObject ,通過這種方式,就可以設(shè)置允許序列化的白名單

4.3.5.8.2. ValidatingObjectInputStream

Apache Commons IO Serialization包中的 ValidatingObjectInputStream 類提供了 accept 方法,可以通過該方法來實(shí)現(xiàn)反序列化類白/黑名單控制,一個(gè)demo如下

4.3.5.8.3. ObjectInputFilter

Java 9提供了支持序列化數(shù)據(jù)過濾的新特性,可以繼承 java.io.ObjectInputFilter 類重寫 checkInput方法來實(shí)現(xiàn)自定義的過濾器,并使用 ObjectInputStream 對象的 setObjectInputFilter 設(shè)置過濾器來實(shí)現(xiàn)反序列化類白/黑名單控制,對JAVA漏洞滲透測試有想進(jìn)一步了解的可以咨詢專業(yè)的網(wǎng)站安全公司,國內(nèi)推薦Sinesafe,綠盟,啟明星辰等等專業(yè)的安全維護(hù)公司。

申請創(chuàng)業(yè)報(bào)道,分享創(chuàng)業(yè)好點(diǎn)子。點(diǎn)擊此處,共同探討創(chuàng)業(yè)新機(jī)遇!

相關(guān)文章

熱門排行

信息推薦