在運行時修補Java

本文將重點介紹如何解決與第三方庫相關的問題
  • 不能被規避
  • 難以排除/繞過/替換
  • 只需不提供錯誤修正

在這種情況下,解決問題仍然是一項艱巨的任務。

作為這種情況的誘因,請考慮對“哈希索引”數據結構的攻擊,例如java.util.Hashtable和java.util.HashMap (對于不熟悉此類攻擊的人,我建議查看以下內容28C3: 對Web應用程序進行拒絕服務攻擊變得容易( )。

長話短說,核心問題是使用非加密哈希函數(在其中查找沖突很容易)。 根本原因隱藏在java.lang.String.hashCode()函數中。 顯而易見的方法是修補java.lang.String類,這很困難,原因有兩個:

  1. 它包含本機代碼
  2. 它屬于Java核心類,這些Java核心類隨Java安裝一起提供,因此不受我們的控制

第一點將迫使我們修補體系結構和特定于OS的庫,我們應該在可能的情況下規避這些庫。 第二點是正確的,但是它會更靈活一些,我們將在下面看到。

好的,讓我們重新考慮:修補本機很臟,我們不急于采用這種方式–我們必須為不愿意修復其代碼的其他人(在本例中為SDK SDK庫)做一些工作。

嘗試:
哈希問題涉及到java.util.Hashtablejava.util.HashMap類,它們不使用任何本機代碼。 修補這些類非常容易,因為足以為所有體系結構和OS提供一個編譯的類。 我們可以使用提供的錯誤解決方案之一,并用固定版本調整(或替換)原始類。 困難在于在不接觸核心庫的情況下修補VM –我想如果用戶必須更改其JVM安裝的一部分,或者更糟糕的是,我們的應用程序在安裝過程中自動執行此操作,用戶將非常失望。 在某些情況下,進一步引入新的自定義類加載器可能會很困難。

我們需要的是一種動態修補我們的單個應用程序的解決方案–替換有問題的類,不要碰其他任何東西。 如果我們透明地執行此操作,則其他軟件部件甚至都不會識別任何更改(在最佳情況下),并保持與類的接口,而無需進行任何修改。

可以通過濫用Java Instrumentation API輕松地完成此操作。 引用JavaDoc

“提供允許Java編程語言代理檢測運行在JVM上的程序的服務。”

這正是我們所需要的!

概念證明
首先,我們需要一個示例應用程序來演示該概念:

public class StringChanger {public static void main(String[] args) {System.out.println(A.shout());}}public class A {public static String shout() {return "A";}
}

運行此類時,它僅輸出:A
應用我們的“補丁”之后,我們希望獲得以下輸出:已補丁

“修補的代碼如下所示:

public class A {public static String shout() {return "Apatched";}
}

進一步,我們需要一個“代理”來管理所使用的類并修補正確的類:

final public class PatchingAgent implements ClassFileTransformer {private static byte[] PATCHED_BYTES;private static final String PATH_TO_FILE = "Apatched.class";private static final String CLASS_TO_PATCH = "stringchanger/A";public PatchingAgent() throws FileNotFoundException, IOException {if (PATCHED_BYTES == null) {PATCHED_BYTES = readPatchedCode(PATH_TO_FILE);}}public static void premain(String agentArgument,final Instrumentation instrumentation) { System.out.println("Initializing hot patcher...");PatchingAgent agent = null;try {agent = new PatchingAgent();} catch(Exception e) {System.out.println("terrible things happened....");}instrumentation.addTransformer(agent);}@Overridepublic byte[] transform(final ClassLoader loader, String className,final Class classBeingRedefined, final ProtectionDomain protectionDomain,final byte[] classfileBuffer) throws IllegalClassFormatException {byte[] result = null;if (className.equals(CLASS_TO_PATCH)) {System.out.println("Patching... " + className);result = PATCHED_BYTES;}return result;}private byte[] readPatchedCode(final String path)throws FileNotFoundException, IOException {...}
}

不用擔心–我不會在實施細節上打擾您,因為這只是PoC代碼,遠非完美,巧妙,快速而簡潔。 除了我因為此時太懶而趕上 Exception以外,我不過濾輸入,構建深拷貝(防御性編程作為流行語),這實際上不應被視為生產代碼。

公共PatchingAgent()
初始化代理(在這種情況下,將獲取修補的A.class文件的字節。修補的類已編譯并存儲在我們可以訪問它的位置。

公共靜態無效premain(…)
在JVM初始化并準備代理后,將調用此方法。

公共字節[]變換(…)
每當定義一個類時(例如,通過ClassLoader.defineClass (…)),該函數都將被調用,并且可以轉換已處理的類字節 []( classfileBuffer )。 可以看出,我們將為stringchanger包中的A類執行此操作。 您不受限制如何轉換類(只要它仍然是有效的Java )–例如,您可以利用字節碼修改框架…–為使事情簡單,我們假設我們將舊字節 []替換為修補的類之一(只需將完整的修補A.class文件緩存到字節 []中)。

這就是修補程序編碼部分的全部內容……最后,我們必須用一個特殊的manifest.mf文件構建一個jar容器,該文件告訴JVM如何調用該代理。

清單版本:1.0
X-COMMENT:Main-Class將通過構建自動添加
Premain-Class:stringchanger.PatchingAgent

構建完這個jar之后,我們可以嘗試PoC應用程序。 首先,我們將在沒有調用代理的必要JVM參數的情況下調用它:

跑:
一個
建立成功(總時間:0秒)

它的行為符合預期,并輸出未修補類定義的輸出。

現在,我們將使用神奇的JVM參數來嘗試調用代理-javaagent:StringChanger.jar:

跑:
初始化熱補丁程序…
讀取修補文件。 修補…換弦器/ A 已分配 建立成功(總時間:0秒)

Voilà,該代碼已成功進行了實時修補!

如我們所見,可以動態地對JVM進行熱補丁而不用觸摸交付的代碼。 必須要做的是開發修補程序和修補的類。 目前,我還不了解性能評估數據。 因此,我不確定該解決方案對生產系統的實用性以及對應用程序性能的影響程度。

明確地說,這不是一個優雅的解決方案–至少它很臟! 最好的方法是修補根本原因,但只要沒有供應商修復程序,開發人員就可以通過熱修補來防止其軟件運行,而無需重寫使用易受攻擊類的每一行。

最后,我希望提出意見,改進或只是更好的解決方案。 非常感謝Juraj Somorovsky與我在這個問題上共同努力。

參考: JCG合作伙伴 在運行時修補Java ? Christopher Meyer討論了Java安全性和相關主題 。


翻譯自: https://www.javacodegeeks.com/2012/02/patching-java-at-runtime.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/373287.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/373287.shtml
英文地址,請注明出處:http://en.pswp.cn/news/373287.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

php return直接輸出,PHP中return用法詳細解讀

原標題:PHP中return用法詳細解讀在大部分編程語言中,return關鍵字可以將函數的執行結果返回,PHP中return的用法也大同小異,對初學者來說,掌握PHP中return的用法也是學習PHP的一個開始。首先,它的意思就是返…

并行執行,沒用到過,寫到這里免得搞忘

/// <summary>/// /// </summary>class Program{static void Main(string[] args){simultaneous();Console.ReadKey();}static void simultaneous(){//盡可能并行執行提供的每個操作Parallel.Invoke(() > ComplexMethod("1"),() > ComplexMethod(&…

UIViewController生命周期

UIViewController生命周期 UIViewController生命周期 posted on 2016-04-07 20:15 相而勿絕 閱讀(...) 評論(...) 編輯 收藏 轉載于:https://www.cnblogs.com/fmdxiangdui/p/5365249.html

Spring的REST分頁

這是有關使用Spring 3.1和Spring Security 3.1和基于Java的配置來建立安全的RESTful Web Service的系列文章的第七篇。 本文將重點介紹RESTful Web服務中的分頁實現 。 REST with Spring系列&#xff1a; 第1部分– 使用Spring 3.1和基于Java的配置引導Web應用程序 第2部分–…

眾籌源碼 php,助創cms眾籌源碼系統v1.0

什么是助創cms眾籌系統?使用“預約團購”的眾籌方式給自己的創意爭取大家的關注和支持&#xff0c;是近年來非常火熱的一種融資模式&#xff0c;助創cms眾籌系統可以10分鐘幫你打造一個和京東眾籌一樣的平臺&#xff0c;包含產品眾籌和公益眾籌兩個部分&#xff0c;可以直接拿…

Linq to SQL 的增刪改查操作

Linq&#xff0c;全稱Language Integrated Query&#xff0c;作為C#3.0新語法&#xff0c;是C#語言的一個擴展&#xff0c;可以將數據查詢直接集成到編程語言本身中。 Linq表達式和SQL語句差不多&#xff0c;說白了就是顛倒sql語法&#xff0c; from where select ...&#xff…

擴展您的JPA POJO

可擴展性是許多體系結構的重要特征。 它衡量是否容易&#xff08;或困難&#xff09; 它是在不影響現有核心系統功能的情況下添加或更改功能。 讓我們舉一個簡單的例子。 假設您的公司擁有一個核心產品來跟蹤體育俱樂部中的所有用戶。 在您的產品體系結構中&#xff0c;您有一個…

web框架--flask

flask介紹Flask是一個基于Python開發并且依賴jinja2模板和Werkzeug WSGI服務的一個微型框架&#xff0c;對于Werkzeug本質是Socket服務端&#xff0c;其用于接收http請求并對請求進行預處理&#xff0c;然后觸發Flask框架&#xff0c;開發人員基于Flask框架提供的功能對請求進行…

php spider shell,ScrapyShell使用

Scrapy ShellScrapy終端是一個交互終端&#xff0c;我們可以在未啟動spider的情況下嘗試及調試代碼&#xff0c;也可以用來測試XPath或CSS表達式&#xff0c;查看他們的工作方式&#xff0c;方便我們爬取的網頁中提取的數據。如果安裝了 IPython &#xff0c;Scrapy終端將使用 …

69 個經典 Spring 面試題和答案

Spring 概述 什么是spring?Spring 是個java企業級應用的開源開發框架。Spring主要用來開發Java應用&#xff0c;但是有些擴展是針對構建J2EE平臺的web應用。Spring 框架目標是簡化Java企業級應用開發&#xff0c;并通過POJO為基礎的編程模型促進良好的編程習慣。使用Spring框架…

高性能MySql

1、索引是對DB優化最有效的方式 varchar(10)定義的是字符的個數&#xff0c;如果是utf-8的話&#xff0c;最大是3X10個字節 二、索引類型 1、MySql的索引是在存儲引擎層實現的&#xff0c;各個存儲引擎的的索引方式也是不同的 2、B-Tree索引 MyISAM索引通過數據的物理位置引用被…

Java Swing井字游戲

大家好&#xff01; 哇&#xff0c;自從我在這里發布了東西以來已經有一段時間了&#xff01; 我必須說我真的很想寫東西&#xff0c;而且我保證我不會再陷入“作家的障礙”。 希望 ..最近兩個月發生了很多事情&#xff0c;我有很多話要說。 但是在這篇文章中&#xff0c;我只是…

Java小青蛙跳臺街,算法-青蛙跳臺階詳解

/*[跳臺階][題目]一只青蛙一次可以跳上1級臺階&#xff0c;也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法。[解析]與斐波那契數列的求解過程類似。典型的動態規劃問題。對于第 n 級臺階&#xff0c;我們可以從第 n-1 級臺階一步到達&#xff0c;也可以從第 n-2 級…

apache服務器配置Net的實踐

前置&#xff1a; 在xp系統中&#xff0c;打補丁之類或啥子操作引起或多或少的問題&#xff0c;最終導致iis不能使用&#xff1b; 不想裝系統...忍著... 最近突發事件導致&#xff0c;需要摸一下apache服務器處理&#xff0c;好吧&#xff0c;那就搜索下吧..... 目標&#xff1…

TestNG或JUnit

多年以來&#xff0c;無論何時使用Java代碼進行單元測試&#xff0c;我始終會回到TestNG。 每當我拿起TestNG時&#xff0c;人們都問我為什么要繼續使用TestNG&#xff0c;尤其是默認開發環境&#xff08;例如Eclipse或Maven&#xff09;提供的JUnit時。 繼續進行同樣的戰斗&am…

event php,PHP event 事件機制

/** PHP 事件機制*/class baseClass{private $_e;public function __set($name,$value){if( strncasecmp($name,"on",2) 0 ){if(!isset($this->_e[$name]))$this->_e[$name] array();return array_push($this->_e[$name] , $value);}}public function __g…

Android JNI編程(五)——C語言的靜態內存分配、動態內存分配、動態創建數組...

版權聲明&#xff1a;本文出自阿鐘的博客&#xff0c;轉載請注明出處:http://blog.csdn.net/a_zhon/。 目錄(?)[] 一&#xff1a;什么是靜態內存什么又是動態內存呢&#xff1f; 靜態內存&#xff1a;是指在程序開始運行時由編譯器分配的內存&#xff0c;它的分配是在程序開始…

Visual Studio-C#-20160411

函數的四個要素包括&#xff1a;名稱&#xff0c;輸入&#xff0c;輸出&#xff0c;加工 注釋的方式&#xff1a;//只注釋一行&#xff1b;/**/注釋一段區域&#xff1b; namespace ConsoleApplication6 ---------//命名空間{ class Program ---------------------------//類…

配置MyBatis 3

MyBatis是一個非常流行且也是最有效的SQL映射框架。 MyBatis可用于Java和.net語言。 MyBatis并不是Hibernate的真正替代品&#xff0c;但是我們可以使用該框架來減少MyBatis提供的高效和高性能的數據庫相關代碼。 本教程將向您展示使用數據庫配置MyBatis 3的步驟。 MyBatis 3支…

php獲取src,PHP讀取文件

本文概述PHP提供了各種功能來從文件讀取數據。有多種功能允許你讀取所有文件數據, 逐行讀取數據以及逐字符讀取數據。下面提供了可用的PHP文件讀取功能。fread()fgets()fgetc()PHP讀取文件-fread()PHP fread()函數用于讀取文件的數據。它需要兩個參數&#xff1a;文件資源和文件…