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

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

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

  域名預訂/競價,好“米”不錯過

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

4.2.1. 格式化字符串

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

當格式化字符串由用戶輸入時,則可能會造成一些問題,下面是一個最簡單的例子

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

"class of 42 is "

從上面這個簡單的例子不難知道,當我們可以控制要format的字符串時,則可以使用 __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,如果那個模塊中已經(jīng) import 可以利用的模塊就可以使用了

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

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

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

"A""B" == "AB"

4.2.3.3. 防御

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

使用Jython并嘗試使用Java平臺來鎖定程序的權(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 做反向代理時,靜態(tài)文件目錄配置錯誤會導致源碼泄露。訪問 /static.. 會 301 重定向到 /static../

4.2.4.2. Flask

Flask默認使用客戶端session,使得session可以被偽造

4.2.5. 危險函數(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. 危險第三方庫

Template

subprocess32

4.2.5.3. 反序列化

marshal

PyYAML

pickle

cPickle

shelve

PIL

Java

4.3.1. 基本概念

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

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

4.3.1.2. JNDI

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

4.3.1.3. OGNL

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

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

4.3.1.4. RMI

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

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

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

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

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

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

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

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

客戶獲得返回值

4.3.2. 框架

4.3.2.1. Servlet

4.3.2.1.1. 簡介

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

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

4.3.2.1.2. 生命周期為

客戶端請求該 Servlet

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

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

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

4.3.2.1.3. 接口

init()

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

service()

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

4.3.2.2. Struts 2

4.3.2.2.1. 簡介

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

4.3.2.2.2. 請求流程

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

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

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

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

ActionProxy通過Configuration Manager查看structs.xml,找到對應的Action類

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

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

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

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ā)送請求給服務器

服務器收到請求,使用DispatchServlet處理

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

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

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

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

4.3.3. 容器

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

4.3.3.1. Tomcat

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

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

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

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

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

Servlet實例使用請求對象得到客戶端的請求信息,然后進行相應的處理

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

Tomcat服務器是由一系列可配置的組件構(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公司出品的一個Application Server,是一個基于Java EE架構(gòu)的中間件,WebLogic是用于開發(fā)、集成、部署和管理大型分布式Web應用、網(wǎng)絡應用和數(shù)據(jù)庫應用的Java應用服務器。其將Java的動態(tài)功能和Java Enterprise標準的安全性引入大型網(wǎng)絡應用的開發(fā)、集成、部署和管理之中。

WebLogic對業(yè)內(nèi)多種標準的全面支持,包括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是一個基于J2EE的管理EJB的容器和服務器,但JBoss核心服務不包括支持servlet/JSP的WEB容器,一般與Tomcat或Jetty綁定使用。

4.3.3.3.2. 相關(guān)CVE

CVE-2017-12149

4.3.4. 沙箱

4.3.4.1. 簡介

Java實現(xiàn)了一套沙箱環(huá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() 方法可以實現(xiàn)序列化,類 ObjectInputStream類的readObject() 方法用于反序列化。

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

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

0xaced 魔術(shù)頭

4.3.5.3. 序列化流程

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

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

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

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

■寫入對象類型標識

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

寫入類描述符標識

寫入類名

寫入SUID (當SUID為空時,會進行計算并賦值)

計算并寫入序列化屬性標志位

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

寫入Block Data結(jié)束標識

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

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

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

4.3.5.4. 反序列化流程

ObjectInputStream實例初始化時,讀取魔術(shù)頭和版本號進行校驗

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

○讀取對象類型標識

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

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

讀取類描述符標識,進入分支readNonProxyDesc()

讀取類名

讀取SUID

讀取并分解序列化屬性標志位

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

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

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

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

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

■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默認只能反序列化基本類型,如果是復雜類型,需要程序員實現(xiàn)反序列化機制,相對比較安全。

4.3.5.6.2. Jackson

除非指明@jsonAutoDetect,Jackson不會反序列化非public屬性。在防御時,可以不使用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. 存在危險的基礎庫

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)站漏洞修復和防護

4.3.5.8.1. Hook resolveClass

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

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

4.3.5.8.2. ValidatingObjectInputStream

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

4.3.5.8.3. ObjectInputFilter

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

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

相關(guān)文章

熱門排行

信息推薦