成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

如何分析JavaWeb安全中的代碼審計(jì)

這篇文章將為大家詳細(xì)講解有關(guān)如何分析Java Web安全中的代碼審計(jì),文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

調(diào)兵山網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)建站!從網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營維護(hù)。創(chuàng)新互聯(lián)建站從2013年創(chuàng)立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)建站。

一、JavaWeb 安全基礎(chǔ)

1. 何為代碼審計(jì)?

通俗的說Java代碼審計(jì)就是通過審計(jì)Java代碼來發(fā)現(xiàn)Java應(yīng)用程序自身中存在的安全問題,由于Java本身是編譯型語言,所以即便只有class文件的情況下我們依然可以對Java代碼進(jìn)行審計(jì)。對于未編譯的Java源代碼文件我們可以直接閱讀其源碼,而對于已編譯的class或者jar文件我們就需要進(jìn)行反編譯了。

Java代碼審計(jì)其本身并無多大難度,只要熟練掌握審計(jì)流程和常見的漏洞審計(jì)技巧就可比較輕松的完成代碼審計(jì)工作了。但是Java代碼審計(jì)的方式絕不僅僅是使用某款審計(jì)工具掃描一下整個(gè)Java項(xiàng)目代碼就可以完事了,一些業(yè)務(wù)邏輯和程序架構(gòu)復(fù)雜的系統(tǒng)代碼審計(jì)就非常需要審計(jì)者掌握一定的Java基礎(chǔ)并具有具有一定的審計(jì)經(jīng)驗(yàn)、技巧甚至是對Java架構(gòu)有較深入的理解和實(shí)踐才能更加深入的發(fā)現(xiàn)安全問題。

本文將分為多章節(jié)來講述Java代碼審計(jì)需要掌握的前置知識以及Java代碼審計(jì)的流程、技巧。

2. 準(zhǔn)備環(huán)境和輔助工具

在開始Java代碼審計(jì)前請自行安裝好Java開發(fā)環(huán)境,建議使用MacOS、Ubuntu操作系統(tǒng)。

所謂“工欲善其事,必先利其器”,合理的使用一些輔助工具可以極大的提供我們的代碼審計(jì)的效率和質(zhì)量!

強(qiáng)烈推薦下列輔助工具:

1.Jetbrains IDEA(IDE)

2.Sublime text(文本編輯器)

3.JD-GUI(反編譯)

4.Fernflower(反編譯)

5.Bytecode-Viewer

6.Eclipse(IDE)

7.NetBeans(IDE)

如何分析Java Web安全中的代碼審計(jì)

二、反編譯技巧

在滲透測試的時(shí)候需要審計(jì)的代碼通常是class文件或者jar包,那么我們應(yīng)該如何審計(jì)呢?讓我們先來學(xué)習(xí)一下什么是Java源碼和字節(jié)碼。

1. Java類編譯與反編譯基礎(chǔ)

簡單的說Java源碼就是未經(jīng)編譯的.java文件,我們可以很輕松的閱讀其中的代碼邏輯,而字節(jié)碼.class文件則是.java文件經(jīng)過編譯之后產(chǎn)生的字節(jié)碼文件,因?yàn)?class文件是編譯后的二進(jìn)制文件所以我們是無法直接閱讀的,只能通過反編譯工具將二進(jìn)制文件轉(zhuǎn)換成java代碼或者ASM代碼。

示例代碼Test.java:

/**
 * @author yz
 */
public class Test {

	public static void hello() {
		System.out.println("Hello~");
	}

	public void world() {
		System.out.println("World!");
	}

	public static void main(String[] args) {
		hello();
	}

}

Test.java編譯執(zhí)行流程:

如何分析Java Web安全中的代碼審計(jì)Test.java 源碼、字節(jié)碼

如何分析Java Web安全中的代碼審計(jì)

由于class文件的可讀性較差,通常我們需要使用Java反編譯工具來反編譯代碼。我們通常會使用到JD-GUI、IDEA Fernflower插件、Bytecode-Viewer、Fernflower、JAD、JBE、JEB 等工具來反編譯class。

其中JD-GUI可能是目前反編譯中使用的最多的工具了,但是個(gè)人覺得JD-GUI的反編譯能力遠(yuǎn)不如經(jīng)過IDEA(IDEA應(yīng)該是使用的改版后的Fernflower),因?yàn)镮DEA默認(rèn)支持對jar和class的反編譯,所以我個(gè)人強(qiáng)烈推薦使用IDEA來反編譯class代碼。

當(dāng)然,反編譯工具很多時(shí)候也不是萬能的,JD-GUI經(jīng)常遇到無法反編譯或反編譯過程中程序直接崩潰的情況,遇到這類情況我們通??梢允褂肐DEA反編譯試試,如果IDEA也無法反編譯可以使用JBE來加載class文件讀取程序的字節(jié)碼,如果JBE仍無法讀取類信息還可以使用JDK自帶的javap命令來讀取class類字節(jié)碼,如果上訴所有的方法都無法反編譯,那么恐怕是這個(gè)類本身就存在無法編譯問題要么可能就是類文件被加密處理過??赡苣銜fjava編譯的class不是說不可以加密嗎?沒錯(cuò),這里所說的加密其實(shí)是為了保護(hù)編譯后的class代碼不可反編譯,通過實(shí)現(xiàn)自定義ClassLoader來loadClass加密后的類方式而已,這種加密方式曾在實(shí)戰(zhàn)中也有遇到。

2. 反編譯整個(gè)Jar技巧

通常我們在某些特殊的場景下拿到的只是jar文件,那么我們應(yīng)該如何反編譯整個(gè)jar包的class文件呢?

2.1. Fernflower

Fernflower可以很輕松的實(shí)現(xiàn)jar的完整反編譯,執(zhí)行如下命令即可: java -jar fernflower.jar jarToDecompile.jar decomp/ 其中jarToDecompile.jar是需要反編譯的jar文件,decomp是反編譯后的class文件所存放的目錄。需要注意的是Fernflower如遇無法反編譯的情況可能會生成空的java文件!

2.2. JD-GUI

JD-GUI是一個(gè)帶GUI的反編譯工具,在JD-GUI的菜單中點(diǎn)擊File-->Save All Sources即可反編譯jar。

2.3. IDEA

IDEA默認(rèn)就支持jar包反編譯,同時(shí)還支持class文件名(??F)、類方法名稱(??O)搜索。

2.4. Bytecode-Viewer

FernFlower提供了GUI版本Bytecode-Viewer,Bytecode-Viewer提供了直接反編譯的class、jar、zip、apk、dex功能,直接拖拽jar就可以直接對整個(gè)jar進(jìn)行反編譯了。

如何分析Java Web安全中的代碼審計(jì)

2.5. Find命令

find命令并不能支持Java反編譯,但是find命令可以非常方便的搜索經(jīng)過編譯后的二進(jìn)制文件中的內(nèi)容,所以有的時(shí)候使用find命令通常是最簡單實(shí)用的,直接解壓jar包然后使用find命令搜索: find ./ -type f -name “*.class” |xargs grep XXXX 即可搞定。

2.6 使用Find命令和Fernflower實(shí)現(xiàn)批量反編譯jar

當(dāng)我們只有項(xiàng)目war包且源碼經(jīng)過打包后發(fā)布到WEB-INF/lib的情況下,我們不得不去找出待審計(jì)源碼的具體jar文件并反編譯。遇到這種情況我們可以巧妙的使用find命令來反編譯所有目標(biāo)的jar包。

這里以jcms的一個(gè)非常老版本為例,jcms最終給客戶部署的war包中源碼并不是在WEB-INF/classes目錄下,而是將整個(gè)jcms系統(tǒng)按模塊打包成了多個(gè)jar包放在了WEB-INF/lib目錄下。我們可以通過搜索com.hanweb包名稱來找出所有jar中包含了jcms的文件并通過Fernflower來反編譯。

java -jar /Users/yz/Desktop/javaweb-decomplier/javaweb-decomplier.jar -dgs=1 $(find /Users/yz/Desktop/jcms/WEB-INF/lib/ -type f -name "*.jar" |xargs grep "com.hanweb" |awk '{print $3}') /Users/yz/jcms-decomplier

依賴的jar: javaweb-decomplier、Intellij java-decompiler。

執(zhí)行上面的命令后會在jcms-decomplier目錄下看到所有的jar已經(jīng)被Fernflower反編譯了。

如何分析Java Web安全中的代碼審計(jì)

3. IntelliJ IDEA 推薦

IntelliJ IDEA是Jetbrains出品的一款非常強(qiáng)大的Java IDE,IDEA提供了強(qiáng)大的代碼搜索、近乎完美的反編譯、動(dòng)態(tài)調(diào)試等功能可以最大程度的輔助我們代碼審計(jì)。

不可以否認(rèn),與IDEA相比雖然Eclipse和Netbeans也有與之類似的功能,但是在真正的實(shí)戰(zhàn)體驗(yàn)中個(gè)人更傾向于使用IDEA,雖然曾經(jīng)的我也是一個(gè)重度Eclipse開發(fā)者。

三、IDEA代碼搜索技巧

IDEA的搜索快捷鍵是:??F,使用IDEA提供的搜索功能可以非常快速的定位漏洞點(diǎn)信息。

如何分析Java Web安全中的代碼審計(jì)

IDEA可以通過自定義搜索范圍來精確查找我們需要審計(jì)的代碼。默認(rèn)搜索的是所有的位置,不過我們可以點(diǎn)擊紅色箭頭指向的...按鈕來細(xì)化我們的搜索范圍。

1. 自定義范圍搜索

如何分析Java Web安全中的代碼審計(jì)

自定義搜索范圍示例:

如何分析Java Web安全中的代碼審計(jì)自定義搜索范圍后就可以在搜索時(shí)使用自定義的配置進(jìn)行范圍搜索了,有助于我們在挖漏洞的時(shí)候縮小代碼定位范圍。

如何分析Java Web安全中的代碼審計(jì)

2. 標(biāo)記搜索

搜索快捷鍵: ?O,標(biāo)記搜索支持類名、方法名搜索(包括class或jar文件中的方法也支持搜索)。

如何分析Java Web安全中的代碼審計(jì)

3. Java調(diào)用鏈搜索

當(dāng)我們審計(jì)代碼的時(shí)候發(fā)現(xiàn)某個(gè)方法或類有漏洞時(shí)我們需要定位到漏洞的請求地址(觸發(fā)點(diǎn)),復(fù)雜業(yè)務(wù)系統(tǒng)往往會讓我們很難定位到漏洞的觸發(fā)點(diǎn)。借助IDEA的方法調(diào)用鏈搜索功能就可以很輕松的找出方法的調(diào)用鏈和觸發(fā)點(diǎn)。

選擇類或者方法名-->右鍵-->Find Useages或者使用快捷鍵?F7

如何分析Java Web安全中的代碼審計(jì)

四、Java Web基礎(chǔ)

1. Java分層思想

為了更好的管理項(xiàng)目我們通常會采用分層架構(gòu)的方式來開發(fā)Java Web項(xiàng)目,分層設(shè)計(jì)的好處在于可以非常方便的分清楚包之間的業(yè)務(wù)邏輯關(guān)系。

常見的JavaWeb項(xiàng)目分層:

視圖層(View 視圖)

控制層(Controller、Action 控制層)

服務(wù)層(Service)

業(yè)務(wù)邏輯層BO(business object)  

實(shí)體層(entity 實(shí)體對象、VO(value object) 值對象 、模型層(bean)。

持久層(dao- Data Access Object 數(shù)據(jù)訪問層、PO(persistant object) 持久對象)

基于Java分層架構(gòu)的示例項(xiàng)目:

如何分析Java Web安全中的代碼審計(jì)

2. Java模塊化開發(fā)

如今的較為大型的Java Web項(xiàng)目通常都采用了模塊化方式開發(fā),借助于Maven、Gradle依賴管理工具,Java可以非常輕松的完成模塊化開發(fā)。除此之外使用OSGi(Open Service Gateway Initiative 可實(shí)現(xiàn)模塊熱部署)技術(shù)開發(fā)來Java動(dòng)態(tài)模塊化系統(tǒng)也是較為常見的。

采用模塊化開發(fā)也會給我們做代碼審計(jì)帶來一定的難度,因?yàn)樾枰诟嗟囊蕾噹熘腥ふ倚枰覀儗徲?jì)的代碼。

使用Maven開發(fā)的JavaWeb項(xiàng)目示例:

如何分析Java Web安全中的代碼審計(jì)如何分析Java Web安全中的代碼審計(jì)

3. 什么是Servlet?

Servlet是在Java Web容器上運(yùn)行的小程序,通常我們用Servlet來處理一些較為復(fù)雜的服務(wù)器端的業(yè)務(wù)邏輯。值得注意的是在Servlet3.0之后(Tomcat7+)可以使用注解方式配置Servlet了。

基于注解的Servlet

如何分析Java Web安全中的代碼審計(jì)

Servlet3.0之前的版本都需要在web.xml中配置,Servlet是兩對標(biāo)簽,由<servlet>和<servlet-mapping>組成,Spring MVC框架就是基于Servlet技術(shù)實(shí)現(xiàn)的。

基于配置實(shí)現(xiàn)的Servlet

如何分析Java Web安全中的代碼審計(jì)

HttpServlet類

如何分析Java Web安全中的代碼審計(jì)

實(shí)現(xiàn)一個(gè)Servlet很簡單,只需要繼承javax.servlet.http.HttpServlet類并重寫doXXX方法或者service方法就可以了,其中需要注意的是重寫HttpServlet類的service方法可以獲取到上述七種Http請求方法的請求。

4. JSP、Servlet之間的關(guān)系

JSP、JSPX文件是可以直接被Java容器直接解析的動(dòng)態(tài)腳本,jsp和其他腳本語言無異,不但可以用于頁面數(shù)據(jù)展示,也可以用來處理后端業(yè)務(wù)邏輯。

從本質(zhì)上說JSP就是一個(gè)Servlet,因?yàn)閖sp文件最終會被編譯成class文件,而這個(gè)Class文件實(shí)際上就是一個(gè)特殊的Servlet。

JSP文件會被編譯成一個(gè)java類文件,如index.jsp在Tomcat中Jasper編譯后會生成index_jsp.java和index_jsp.class兩個(gè)文件。而index_jsp.java 繼承于HttpJspBase類,HttpJspBase是一個(gè)實(shí)現(xiàn)了HttpJspPage接口并繼承了HttpServlet的標(biāo)準(zhǔn)的Servlet,__jspService方法其實(shí)是HttpJspPage接口方法,類似于Servlet中的service方法,這里的__jspService方法其實(shí)就是HttpJspBase的service方法調(diào)用。

如何分析Java Web安全中的代碼審計(jì)

5. 什么是Filter

Filter是JavaWeb中的過濾器,用于過濾URL請求。通過Filter我們可以實(shí)現(xiàn)URL請求資源權(quán)限驗(yàn)證、用戶登陸檢測等功能。Filter是一個(gè)接口,實(shí)現(xiàn)一個(gè)Filter只需要重寫init、doFilter、destroy方法即可,其中過濾邏輯都在doFilter方法中實(shí)現(xiàn)。

Filter和Servlet一樣是Java Web中最為核心的部分,使用Servlet和Filter可以實(shí)現(xiàn)后端接口開發(fā)和權(quán)限控制,當(dāng)然使用Filter機(jī)制也可以實(shí)現(xiàn)MVC框架,Struts2實(shí)現(xiàn)機(jī)制就是使用的Filter。

Filter的配置類似于Servlet,由<filter>和<filter-mapping>兩組標(biāo)簽組成,如果Servlet版本大于3.0同樣可以使用注解的方式配置Filter。

如何分析Java Web安全中的代碼審計(jì)

6. Filter和Servlet的總結(jié)

對于基于Filter和Servlet實(shí)現(xiàn)的簡單架構(gòu)項(xiàng)目,代碼審計(jì)的重心集中于找出所有的Filter分析其過濾規(guī)則,找出是否有做全局的安全過濾、敏感的URL地址是否有做權(quán)限校驗(yàn)并嘗試?yán)@過Filter過濾。第二點(diǎn)則是找出所有的Servlet,分析Servlet的業(yè)務(wù)是否存在安全問題,如果存在安全問題是否可以利用?是否有權(quán)限訪問?利用時(shí)是否被Filter過濾等問題,切勿看到Servlet、JSP中的漏洞點(diǎn)就妄下定論,不要忘了Servlet前面很有可能存在一個(gè)全局安全過濾的Filter。

Filter和Servlet都是Java Web提供的API,簡單的總結(jié)了下有如下共同點(diǎn)。

  1.Filter和Servlet都需要在web.xml或注解(@WebFilter、@WebServlet)中配置,而且配置方式是非常的相似的;

  2.Filter和Servlet都可以處理來自Http請求的請求,兩者都有request、response對象;

  3.Filter和Servlet基礎(chǔ)概念不一樣,Servlet定義是容器端小程序,用于直接處理后端業(yè)務(wù)邏輯,而Filter的思想則是實(shí)現(xiàn)對Java Web請求資源的攔截過濾;

  4.Filter和Servlet雖然概念上不太一樣,但都可以處理Http請求,都可以用來實(shí)現(xiàn)MVC控制器(Struts2和Spring框架分別基于Filter和Servlet技術(shù)實(shí)現(xiàn)的);

  5.一般來說Filter通常配置在MVC、Servlet和JSP請求前面,常用于后端權(quán)限控制、統(tǒng)一的Http請求參數(shù)過濾(統(tǒng)一的XSS、SQL注入、Struts2命令執(zhí)行等攻擊檢測處理)處理,其核心主要體現(xiàn)在請求過濾上,而Servlet更多的是用來處理后端業(yè)務(wù)請求上

7. 初識JavaWeb MVC框架

傳統(tǒng)的開發(fā)存在結(jié)構(gòu)混亂易用性差耦合度高可維護(hù)性差等多種問題,為了解決這些毛病分層思想和MVC框架就出現(xiàn)了。MVC即模型(Model)、視圖(View)、控制器(Controller), MVC模式的目的就是實(shí)現(xiàn)Web系統(tǒng)的職能分工。

截至2018年底,絕大多數(shù)的新項(xiàng)目都已然改為了基于Spring Boot的Spring MVC實(shí)現(xiàn),也就是說曾經(jīng)站在JavaWeb MVC最巔峰的Struts2框架已經(jīng)逐漸隕落。

7.1 Spring MVC 控制器

在Spring進(jìn)入了3.0時(shí)代,使用Java注解的方式也逐漸的流行了起來,曾經(jīng)寫一個(gè)Spring的控制器我們通常要在xml中聲明Spring bean并配置處理的URL,而在新時(shí)代的Spring項(xiàng)目中我們通常用Spring MVC注解就可以輕松完成Spring MVC的配置了。

一個(gè)基于Spring 注解配置的控制器:

package org.javaweb.codereview.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class IndexController {
@RequestMapping("/index.php")
public String index() {
return "/index.html";
}
}

Spring Controller注解:

@Controller

@RestController

@RepositoryRestController

Spring MVC請求配置注解:

@RequestMapping

@GetMapping

@PostMapping

@PutMapping

@DeleteMapping

@PatchMapping

Spring MVC除了上述6種Http請求處理注解以外還有Spring Data JPA Rest提供的特殊的@RepositoryRestResource注解,@RepositoryRestResource是基于Spring Data JPA REST庫實(shí)現(xiàn)的,Spring Data JPA REST提供的API可支持通過JPA查詢數(shù)據(jù)并處理Http請求服務(wù)。

基于XML配置的Spring MVC

對于一些老舊的項(xiàng)目可能還保留了一些基于xml配置的方式Spring MVC項(xiàng)目,這里只簡單的介紹下如何配置不做過多的描述?;谂渲梅绞降目刂破饕话闶窃贑ontroller類中實(shí)現(xiàn)了Spring的org.springframework.web.servlet.mvc.Controller接口的handleRequest方法(當(dāng)然還有其他途徑,如:AbstractCommandController和SimpleFormController但都已經(jīng)過時(shí)了)。

TestController.java示例代碼:

package org.javaweb.codereview.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @author yz
 */
public class TestController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView();
mv.setViewName("index");
return mv;
}
}

XML配置具體的bean

<bean name="/test.do" class="org.javaweb.codereview.controller.TestController"/>

7.2 Struts2控制器

Struts2主要的開發(fā)模式是基于xml配置,在struts.xml中配置Action地址和對應(yīng)的處理類。

如何分析Java Web安全中的代碼審計(jì)

不過Struts2(2.1.6版本開始)也可以使用struts2-convention-plugin插件來實(shí)現(xiàn)基于注解方式的配置。

如何分析Java Web安全中的代碼審計(jì)

需要注意的是Struts2的參數(shù)是可以通過get/set方法傳入的,如上圖TestActionAnnotation類的username變量是可以直接在Http請求中的URL傳入的。

7.3 快速找出Http請求請求URL

代碼審計(jì)中我們可以選擇優(yōu)先從Controller、Servlet和JSP中入手,也可以選擇從漏洞點(diǎn)反向推出Http請求的入口地址,這里將講解下如何快速找到這些請求入口,因?yàn)镾truts2和Spring MVC的原理比較接近,所以本節(jié)只以Spring MVC為例。

7.3.1 查找Spring MVC所有的控制器

如果有源碼的情況下可以使用find命令或者IDEA的全局搜索功能即可快速搜索到所有的控制器,如果只有class文件的情況下可以使用find命令:

find ~/cms/ -type f -name "*.class" |xargs grep -E "Controller|@RestController|RepositoryRestController"

7.3.2 查找所有的請求處理URL

查找請求處理URL的方式同理,使用如下find命令查找所有class中的請求處理注解:

find ~/cms/ -type f -name "*.class" |xargs grep -E "RequestMapping|GetMapping|PostMapping|PutMapping|DeleteMapping|PatchMapping|RepositoryRestResource"

7.4 Spring MVC和Struts2控制器小結(jié)

這一小節(jié)我們只是簡單的介紹下Spring MVC和Struts2的控制器,在后面的框架服務(wù)章節(jié)將會詳細(xì)介紹。至于如何去快速定位Struts2的action請自行參考Spring MVC的Controller查找方式這里不再講解。

五、Java語言的動(dòng)態(tài)性

Java語言動(dòng)態(tài)性一直以來都比較差,并不像PHP那樣靈活。在Java中的動(dòng)態(tài)性往往需要使用一些曲折的方式來實(shí)現(xiàn).這里簡單列舉了Java十余種動(dòng)態(tài)性相關(guān)技術(shù)并總結(jié)部分技術(shù)實(shí)現(xiàn)安全問題。

1.Java反射機(jī)制

2.MethodHandle

3.JDK動(dòng)態(tài)代理

4.使用JVM上的動(dòng)態(tài)語言(如:Groovy、JRuby、Jython)

5.表達(dá)式庫(如:OGNL、MVEL、SpEL、EL)

6.JSP、JSPX、Quercus(Resin容器提供了PHP5支持)

7.字節(jié)碼庫(如:Asm、Javassist、Cglib、BCEL)

8.ScriptEngineManager(腳本引擎)。

9.動(dòng)態(tài)編譯(如:JDT、JavaCompiler)

10.ClassLoader、URLClassLoader

11.模版引擎(如:Freemarker、Velocity)

12.序列化、反序列化(包含Java 對象序列化、XML、JSON等)

13.JNI、JNA(Java調(diào)用C/C++)

14.OSGi(Open Service Gateway Initiative)

15.RMI(Java遠(yuǎn)程方法調(diào)用,基于對象序列化機(jī)制實(shí)現(xiàn))

16.WebService

17.JDWP(Java Platform Debugger Architecture Java調(diào)試協(xié)議)

18.JMX(Java Management Extensions)

1. Java反射機(jī)制特性

Java反射機(jī)制可以無視類方法、變量訪問權(quán)限修飾符,可以調(diào)用任何類的任意方法、訪問并修改成員變量值。也就是說只要發(fā)現(xiàn)一處Java反射調(diào)用漏洞幾乎就可以為所欲為了。當(dāng)然前提可能需要你能控制反射的類名、方法名和參數(shù)。

一行代碼即可實(shí)現(xiàn)反射調(diào)用Runtime執(zhí)行本地命令:

Runtime.class.getMethod("exec", String.class).invoke(Runtime.class.getMethod("getRuntime").invoke(null), "whoami")

獲取一個(gè)類的對象(如Runtime類)我們一般會采用如下幾種方式:

  1.Class.forName("java.lang.Runtime")、"".getClass().forName("java.lang.Runtime")

  2.Runtime.class

  3.ClassLoader.getSystemClassLoader().loadClass("java.lang.Runtime")

Java反射獲取類方法有兩種方式:

  1.getMethod(xxx),getMethods()

  2.getDeclaredMethod(xxx)、getDeclaredMethods()。

區(qū)別在于getMethod會返回當(dāng)前類和父類的所有public方法,而getDeclaredMethod返回的是當(dāng)前的所有方法。

Java反射獲取類成員變量有兩種方式:

  1.getField(xxx)、getFields()

  2.getDeclaredField(xxx)、getDeclaredFields()

getField和getDeclaredField區(qū)別同上,如果想要調(diào)用private修飾的Field或者M(jìn)ethod只需要設(shè)置下setAccessible為true就可以了,如:xxxMethod.setAccessible(true)。

Java的大部分框架都是采用了反射機(jī)制來實(shí)現(xiàn)的(如:Spring MVC、ORM框架等),所以我們不得不掌握J(rèn)ava反射機(jī)制來提升我們的代碼審計(jì)能力。

Java反射機(jī)制實(shí)現(xiàn)無關(guān)鍵字執(zhí)行命令

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Scanner;
/**
 * @author yz
 */
public class ReflectionTest {
public static void exec() {
try {
System.out.println(Runtime.class.getMethod("exec", String.class).invoke(Runtime.class.getMethod("getRuntime").invoke(null), "curl -i localhost:8000"));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
String str = "whoami";
// java.lang.Runtime
String runtime = new String(new byte[]{106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101});
// Runtime.class
Class<?> c = Class.forName(runtime);
// 獲取getRuntime方法,Runtime.getRuntime()
Method m1 = c.getMethod(new String(new byte[]{103, 101, 116, 82, 117, 110, 116, 105, 109, 101}));
// 獲取Runtime的exec方法,rt.exec(xxx)
Method m2 = c.getMethod(new String(new byte[]{101, 120, 101, 99}), String.class);
// Runtime.getRuntime().exec(str)
Object obj2 = m2.invoke(m1.invoke(null), str);
// 獲取命令執(zhí)行結(jié)果Process類的getInputStream()方法
Method m = obj2.getClass().getMethod(new String(new byte[]{103, 101, 116, 73, 110, 112, 117, 116, 83, 116, 114, 101, 97, 109}));
m.setAccessible(true);
// process.getInputStream()
InputStream in = (InputStream) m.invoke(obj2, new Object[]{});
// 輸出InputStream內(nèi)容到
Scanner scanner = new Scanner(in).useDelimiter("\\A");
System.out.println(scanner.hasNext() ? scanner.next() : "");
} catch (Throwable t) {
t.printStackTrace();
}
}
}

2. JDK7+ MethodHandle

JDK7開始Java提供了MethodHandle可以非常方便的訪問和調(diào)用類方法,MethodHandle的能力和Java反射機(jī)制相似,但效率卻遠(yuǎn)高出Java反射機(jī)制,但MethodHandle也并不是那么完美的,缺點(diǎn)是MethodHandle必須要求JDK版本大于等于1.7,MethodHandle也無法像反射那樣調(diào)用私有方法和變量。

參考:通過代碼簡單介紹JDK 7的MethodHandle,并與.NET的委托對比。

基于MethodHandle實(shí)現(xiàn)的調(diào)用Runtime執(zhí)行系統(tǒng)命令

import java.io.InputStream;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Scanner;
/**
 * @author yz
 */
public class MethodHandlesTest {
public static void main(String[] args) {
try {
String               str          = "ping p2j.cn -c 1";
Class                runtimeClass = Runtime.class;
MethodHandles.Lookup lookup       = MethodHandles.lookup();
// Runtime rt = Runtime.getRuntime()
MethodHandle methodHandle = lookup.findStatic(
runtimeClass, "getRuntime", MethodType.methodType(runtimeClass)
);
// 獲取Runtime的exec方法
MethodHandle execMethod = lookup.findVirtual(
runtimeClass, "exec", MethodType.methodType(Process.class, new Class[]{
String.class
})
);
// 獲取Process的getInputStream方法
MethodHandle inputStreamMethod = lookup.findVirtual(
Process.class, "getInputStream", MethodType.methodType(InputStream.class)
);
// 調(diào)用Runtime.getRuntime().exec(xxx).getInputStream()
InputStream in = (InputStream) inputStreamMethod.invoke(
execMethod.invoke(methodHandle.invoke(), str)
);
// 輸出InputStream內(nèi)容到
Scanner scanner = new Scanner(in).useDelimiter("\\A");
System.out.println(scanner.hasNext() ? scanner.next() : "");
} catch (Throwable t) {
t.printStackTrace();
}
}
}

六、Java代碼審計(jì)-Checklist

通常我喜歡把代碼審計(jì)的方向分為業(yè)務(wù)層安全問題、代碼實(shí)現(xiàn)和服務(wù)架構(gòu)安全問題,。

1. 業(yè)務(wù)層安全常見問題

業(yè)務(wù)層的安全問題集中在業(yè)務(wù)邏輯和越權(quán)問題上,我們在代碼審計(jì)的過程中盡可能的去理解系統(tǒng)的業(yè)務(wù)流程以便于發(fā)現(xiàn)隱藏在業(yè)務(wù)中的安全問題。

1.1 業(yè)務(wù)層中常見的安全問題Checklist

1.用戶登陸、用戶注冊、找回密碼等功能中密碼信息未采用加密算法。

2.用戶登陸、用戶注冊、找回密碼等功能中未采用驗(yàn)證碼或驗(yàn)證碼未做安全刷新(未刷新Session中驗(yàn)證碼的值)導(dǎo)致的撞庫、密碼爆破漏洞。

3.找回密碼邏輯問題(如:可直接跳過驗(yàn)證邏輯直接發(fā)包修改)。

4.手機(jī)、郵箱驗(yàn)證、找回密碼等涉及到動(dòng)態(tài)驗(yàn)證碼等功能未限制驗(yàn)證碼失敗次數(shù)、驗(yàn)證碼有效期、驗(yàn)證碼長度過短導(dǎo)致的驗(yàn)證碼爆破問題。

5.充值、付款等功能調(diào)用了第三方支付系統(tǒng)未正確校驗(yàn)接口(如:1分錢買IPhone X)。

6.后端采用了ORM框架更新操作時(shí)因處理不當(dāng)導(dǎo)致可以更新用戶表任意字段(如:用戶注冊、用戶個(gè)人資料修改時(shí)可以直接創(chuàng)建管理員賬號或其他越權(quán)修改操作)。

7.后端采用了ORM框架查詢數(shù)據(jù)時(shí)因處理不當(dāng)導(dǎo)致可以接收任何參數(shù)導(dǎo)致的越權(quán)查詢、敏感信息查詢等安全問題。

8.用戶中心轉(zhuǎn)賬、修改個(gè)人資料、密碼、退出登陸等功能未采用驗(yàn)證碼或Token機(jī)制導(dǎo)致存在CSRF漏洞。

9.后端服務(wù)過于信任前端,重要的參數(shù)和業(yè)務(wù)邏輯只做了前端驗(yàn)證(如:文件上傳功能的文件類型只在JS中驗(yàn)證、后端不從Session中獲取用戶ID、用戶名而是直接接收客戶端請求的參數(shù)導(dǎo)致的越權(quán)問題)。

10.用戶身份信息認(rèn)證邏輯問題(如:后臺系統(tǒng)自動(dòng)登陸時(shí)直接讀取Cookie中的用戶名、用戶權(quán)限不做驗(yàn)證)。

11.重要接口采用ID自增、ID可預(yù)測并且云端未驗(yàn)證參數(shù)有效性導(dǎo)致的越權(quán)訪問、信息泄漏問題(如:任意用戶訂單越權(quán)訪問)。

12.條件競爭問題,某些關(guān)鍵業(yè)務(wù)(如:用戶轉(zhuǎn)賬)不支持并發(fā)、分布式部署時(shí)不支持鎖的操作等。

13.重要接口未限制請求頻率,導(dǎo)致短信、郵件、電話、私信等信息轟炸。

14.敏感信息未保護(hù),如Cookie中直接存儲用戶密碼等重要信息。

15.弱加密算法、弱密鑰,如勿把Base64當(dāng)成數(shù)據(jù)加密方式、重要算法密鑰采用弱口令如123456。

16.后端無異常處理機(jī)制、未自定義50X錯(cuò)誤頁面,服務(wù)器異常導(dǎo)致敏感信息泄漏(如:數(shù)據(jù)庫信息、網(wǎng)站絕對路徑等)。

17.使用DWR框架開發(fā)時(shí)前后端不分漏洞(如:DWR直接調(diào)用數(shù)據(jù)庫信息把用戶登陸邏輯直接放到了前端來做)。

2. 代碼實(shí)現(xiàn)常見問題

代碼審計(jì)的核心是尋找代碼中程序?qū)崿F(xiàn)的安全問題,通常我們會把代碼審計(jì)的重心放在SQL注入、文件上傳、命令執(zhí)行、任意文件讀寫等直接威脅到服務(wù)器安全的漏洞上,因?yàn)檫@一類的漏洞殺傷力極大也是最為致命的。

###2.1 代碼實(shí)現(xiàn)中常見的安全問題Checklist

  1.任意文件讀寫(文件上傳、文件下載)、文件遍歷、文件刪除、文件重命名等漏洞

  2.SQL注入漏洞

  3.XXE(XML實(shí)體注入攻擊)

  4.表達(dá)式執(zhí)行(SpEL、OGNL、MVEL2、EL等)

  5.系統(tǒng)命令執(zhí)行漏洞(ProcessBuilder)

  6.反序列化攻擊(ObjectInputStream、JSON、XML等)

  7.Java反射攻擊

  8.SSRF攻擊

2.1.1 Java 文件名空字節(jié)截?cái)嗦┒?%00 Null Bytes)

空字節(jié)截?cái)嗦┒绰┒丛谥T多編程語言中都存在,究其根本是Java在調(diào)用文件系統(tǒng)(C實(shí)現(xiàn))讀寫文件時(shí)導(dǎo)致的漏洞,并不是Java本身的安全問題。不過好在高版本的JDK在處理文件時(shí)已經(jīng)把空字節(jié)文件名進(jìn)行了安全檢測處理。

2013年9月10日發(fā)布的Java SE 7 Update 40修復(fù)了空字節(jié)截?cái)噙@個(gè)歷史遺留問題。此次更新在java.io.File類中添加了一個(gè)isInvalid方法,專門檢測文件名中是否包含了空字節(jié)。

如何分析Java Web安全中的代碼審計(jì)

修復(fù)的JDK版本所有跟文件名相關(guān)的操作都調(diào)用了isInvalid方法檢測,防止空字節(jié)截?cái)唷?/p>

如何分析Java Web安全中的代碼審計(jì)

修復(fù)前(Java SE 7 Update 25)和修復(fù)后(Java SE 7 Update 40)的對比會發(fā)現(xiàn)Java SE 7 Update 25中的java.io.File類中并未添加\u0000的檢測。

如何分析Java Web安全中的代碼審計(jì)

受空字節(jié)截?cái)嘤绊懙腏DK版本范圍:JDK<1.7.40,單是JDK7于2011年07月28日發(fā)布至2013年09月10日發(fā)表Java SE 7 Update 40這兩年多期間受影響的就有16個(gè)版本,值得注意的是JDK1.6雖然JDK7修復(fù)之后發(fā)布了數(shù)十個(gè)版本,但是并沒有任何一個(gè)版本修復(fù)過這個(gè)問題,而JDK8發(fā)布時(shí)間在JDK7修復(fù)以后所以并不受此漏洞影響。

參考:

JDK-8014846 : File and other classes in java.io do not handle embedded nulls properly。

維基百科-Java版本歷史

Oracle Java 歷史版本下載

2.1.2 測試Java寫文件截?cái)鄿y試

測試類FileNullBytes.java:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
 * @author yz
 */
public class FileNullBytes {
public static void main(String[] args) {
try {
String fileName = "/tmp/null-bytes.txt\u0000.jpg";
FileOutputStream fos = new FileOutputStream(new File(fileName));
fos.write("Test".getBytes());
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

使用JDK1.7.0.25測試成功截?cái)辔募?/p>

如何分析Java Web安全中的代碼審計(jì)

使用JDK1.7.0.80測試寫文件截?cái)鄷r(shí)拋出java.io.FileNotFoundException: Invalid file path異常:

如何分析Java Web安全中的代碼審計(jì)

空字節(jié)截?cái)嗬脠鼍?/strong>

Java空字節(jié)截?cái)嗬脠鼍白畛R姷睦脠鼍熬褪俏募蟼鲿r(shí)后端使用了endWith、正則使用如:.(jpg|png|gif)$驗(yàn)證文件名后綴且文件名最終原樣保存,同理文件刪除(delete)、獲取文件路徑(getCanonicalPath)、創(chuàng)建文件(createNewFile)、文件重命名(renameTo)等方法也可適用。

空字節(jié)截?cái)嘈迯?fù)方案

最簡單直接的方式就是升級JDK,如果擔(dān)心升級JDK出現(xiàn)兼容性問題可在文件操作時(shí)檢測下文件名中是否包含空字節(jié),如JDK的修復(fù)方式:fileName.indexOf('\u0000')即可。

2.1.2 任意文件讀取漏洞

任意文件讀取漏洞即因?yàn)闆]有驗(yàn)證請求的資源文件是否合法導(dǎo)致的,此類漏洞在Java中有著較高的幾率出現(xiàn),任意文件讀取漏洞看似很簡單,但是在這個(gè)問題上翻車的有不乏一些知名的中間件:Weblogic、Tomcat、Resin又或者是主流MVC框架:Spring MVC、Struts2。所以在審計(jì)文件讀取功能的時(shí)候要非常仔細(xì),或許很容易就會有意想不到的收獲!

任意文件讀取示例代碼file-read.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.io.ByteArrayOutputStream" %>
<%@ page import="java.io.File" %>
<%@ page import="java.io.FileInputStream" %>
<%
    File file = new File(request.getParameter("path"));
    FileInputStream fis = new FileInputStream(file);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] b = new byte[1024];
    int a = -1;
    while ((a = fis.read(b)) != -1) {
        baos.write(b, 0, a);
    }
    out.write("<pre>" + new String(baos.toByteArray()) + "</pre>");
    fis.close();
%>

訪問file-read.jsp文件即可讀取任意文件:http://localhost:8080/file/file-read.jsp?path=/etc/passwd

如何分析Java Web安全中的代碼審計(jì)

快速發(fā)現(xiàn)這類漏洞得方式其實(shí)也是非常簡單的,在IDEA中的項(xiàng)目中重點(diǎn)搜下如下文件讀取的類。

  1.JDK原始的java.io.FileInputStream類

  2.JDK原始的java.io.RandomAccessFile類

  3.Apache Commons IO提供的org.apache.commons.io.FileUtils類

  4.JDK1.7新增的基于NIO非阻塞異步讀取文件的java.nio.channels.AsynchronousFileChannel類。

  5.JDK1.7新增的基于NIO讀取文件的java.nio.file.Files類。常用方法如:Files.readAllBytes、Files.readAllLines

如果仍沒有什么發(fā)現(xiàn)可以搜索一下FileUtil很有可能用戶會封裝文件操作的工具類。

Java WebSevice

Web Service是一種基于SOAP協(xié)議實(shí)現(xiàn)的跨語言Web服務(wù)調(diào)用,在Java中Web Service有如下技術(shù)實(shí)現(xiàn):Oracle JWS、Apache Axis1、2、XFire、Apache CXF、JBossWS。

Axis1.4 配置

web.xml配置Axis1.4

如何分析Java Web安全中的代碼審計(jì)

配置server-config.wsdd文件注冊Web Service服務(wù)類和方法:

如何分析Java Web安全中的代碼審計(jì)

FileService類,提供了文件讀寫接口:

如何分析Java Web安全中的代碼審計(jì)

使用IDEA創(chuàng)建Web Service項(xiàng)目默認(rèn)會創(chuàng)建管理Web Service的API:/servlet/AxisServlet、/services、SOAPMonitor、/servlet/AdminServlet,*.jws以及用監(jiān)控Web Service的端口5001或5101。

如何分析Java Web安全中的代碼審計(jì)

訪問Web Service的FileService服務(wù)加上?wsdl參數(shù)可以看到FileService提供的服務(wù)方法和具體的參數(shù)信息。

如何分析Java Web安全中的代碼審計(jì)

使用SOAP-UI調(diào)用Web Service接口示例:

如何分析Java Web安全中的代碼審計(jì)

需要注意的是Web Service也是可以設(shè)置授權(quán)認(rèn)證的,如實(shí)現(xiàn)了WS-Security的WSS4J。

如何分析Java Web安全中的代碼審計(jì)

使用IDEA根據(jù)wsdl生成Web Service客戶端代碼:

如何分析Java Web安全中的代碼審計(jì)

設(shè)置wsdl地址、包名:

如何分析Java Web安全中的代碼審計(jì)

新建FileServiceTest類測試接口調(diào)用:

package org.javaweb.codereview.axis.client;
import java.net.URL;
/**
 * 文件Web Service服務(wù)測試
 *
 * @author yz
 */
public class FileServiceTest {
public static void main(String[] args) {
try {
FileServiceService         fileService   = new FileServiceServiceLocator();
URL                        webServiceUrl = new URL("http://localhost:8080/services/FileService");
FileServiceSoapBindingStub soapService   = new FileServiceSoapBindingStub(webServiceUrl, fileService);
String content = soapService.readFile("/etc/passwd");
System.out.println(content);
} catch (Exception e) {
e.printStackTrace();
}
}
}

關(guān)于如何分析Java Web安全中的代碼審計(jì)就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

分享文章:如何分析JavaWeb安全中的代碼審計(jì)
標(biāo)題路徑:http://jinyejixie.com/article28/gpgejp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)、網(wǎng)站收錄、標(biāo)簽優(yōu)化App開發(fā)、App設(shè)計(jì)、移動(dòng)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

同仁县| 西充县| 邮箱| 灵璧县| 桐城市| 临清市| 新巴尔虎右旗| 华容县| 长垣县| 普兰店市| 宾阳县| 巴马| 武隆县| 顺平县| 阿拉善盟| 慈溪市| 翁牛特旗| 阜南县| 沧州市| 祥云县| 苍溪县| 仙居县| 怀仁县| 三都| 吉首市| 奈曼旗| 类乌齐县| 宁陵县| 肥乡县| 沙洋县| 乌鲁木齐市| 新源县| 平南县| 大兴区| 耒阳市| 河源市| 黎平县| 大埔区| 赫章县| 沽源县| 抚宁县|