全網連夜修復的Log4j漏洞,如何做到一行代碼都不改?

GitHub 21.5k Star 的Java工程師成神之路,不來了解一下嗎!

GitHub 21.5k Star 的Java工程師成神之路,真的不來了解一下嗎!

Apache Log4j2 遠程代碼執行漏洞的問題最近鬧得沸沸揚揚的,很多人都被大半夜叫起來緊急修復這跟問題。

有很多人在微信上問我:這種漏洞還能怎麼修?下次有問題還要再升級版本嗎?有沒有啥一勞永逸的辦法?就沒啥辦法避免嗎?

其實,是有的。有一種技術,可以針對這類漏洞做定向攔截。可以讓開發者不用急急忙忙修這個漏洞,甚至你如果完全不想修都可以。

這就是RASP技術。

其實這個技術已經誕生很久了,在安全圈也應用很廣泛。應用範圍也很廣泛了。

RASP

RASP 是 Runtime Application Self-Protection 的縮寫,這是一種應用安全保護技術。他的原理是將保護程序注入到應用程序中,與應用程序融爲一體,能夠起到實時監測、阻斷攻擊的作用,使程序自身擁有自保護的能力。

聽起來是不是很高大上?

其實,RASP就是攔截從應用程序到系統的所有調用,確保它們是安全的,並直接在應用程序內驗證數據請求。Web和非Web應用程序都可以通過RASP進行保護。該技術不會影響應用程序的設計,因爲RASP的檢測和保護功能是在應用程序運行的系統上運行的。

RASP 技術非常是和對於0Day 漏洞的防護,如反序列化漏洞、JNDI 注入漏洞、表達式注入漏洞、SQL 諸如漏洞、遠程代碼執行漏洞等。

WAF 和 RASP

在安全防護上,很多人都知道WAF(Web Application Firewall),俗稱防火牆,那麼,和防火牆相比,RASP 技術其實有着很多的優點。

傳統的 WAF 主要通過分析流量中的特徵過濾攻擊請求,並攔截攜帶有攻擊特徵的請求。但是因爲 WAF 是隻能基於流量規則進行防禦,無法根據應用上下文進行檢測,所以存在誤報率高、容易繞過等問題。

但是,RASP 則不同,他就像疫苗會注入到人體一樣,RASP 是運行在應用之中的,與應用融爲一體,可以獲取到應用運行時的上下文,根據請求上下文進行攔截可以對攻擊進行精準的識別和攔截

防火牆就像爲簇擁在大人物周圍的保鏢,大人物去哪裏都帶着保鏢,看起來防禦力爆棚,但是大人物本人肌肉不發達也沒有武功,一旦保鏢被突破或者保鏢被調虎離山,那麼這個大人物就沒有任何保護了,就非常危險了。而RASP 則是讓沒有武功的人在很短的時間並且付出的代價不高的情況下擁有很高的自我保護能力。

RASP 具有以下優點:

  • 1.誤報率低。

  • 2.可以防護0Day級別的漏洞攻擊。

同時也並不是完全沒有缺點,主要的問題就是可能帶來一定的性能損耗。還有就是開發難度比較高,需要對 JVM 字節碼、ASM 工具、漏洞觸發原理以及各類Java 應用容器都有所瞭解。

RASP技術目前已經非常成熟,在PHP、Java、.NET等多種語言中都有實現方案。

實現原理

不同於基於流量特徵的檢測,RASP 主要關注應用自身的行爲,而非流量本身。

當 RASP 發現一個應用,做了它不應該做的事情時,大概率意味着當前應用已經被攻擊者利用漏洞攻陷並做了一些高危操作。

以這次 Log4j的漏洞來看,RASP 並不關注請求中的流量是否包含了惡意的 payload,而是去關注 Log4j2 究竟使用 JNDI 功能去做了什麼。如果進行正常的 JNDI 查詢,就沒有問題;但如果企圖使用 JNDI 功能進行命令執行,就是一個顯而易見的危險行爲。

RASP 要將自己注入到被保護的應用中,基本思路類似於 Java 中的 AOP 技術,將 RASP 的Hook代碼注入到需要進行檢測的地方,根據上下文和關鍵函數的參數等信息判斷請求是否爲惡意請求,並終止或繼續執行。

想要實現RASP,在 Java中逃不開 Agent 技術,Agent是一個運行在目標JVM的特定程序,它的職責是負責從目標JVM中獲取數據,然後將數據傳遞給外部進程。

在Java SE 5之前,要實現一個Agent只能通過編寫Native代碼來實現。從Java SE 5開始,可以使用Java的Instrumentation接口(java.lang.instrument)來編寫Agent。

使⽤ Instrumentation,開發者可以構建⼀個獨⽴於應⽤程序的代理程序(Agent),⽤來監測和協助運⾏在 JVM 上的程序,甚⾄能夠替換和修改某些類的定義。

Java Agent支持目標JVM啓動時加載,也支持在目標JVM運行時加載,這兩種不同的加載模式會使用不同的入口函數,如果需要在目標JVM啓動的同時加載Agent,那麼可以選擇實現下面的方法:

public static void premain(String agentArgs, Instrumentation inst);
public static void premain(String agentArgs);

在premain函數中,我們可以對字節碼進⾏操作,織⼊Rasp的安全探針。

public static void premain(String agentArgs, Instrumentation inst)
        throws ClassNotFoundException, UnmodifiableClassException {
    inst.addTransformer(new ClassTransformer());
}

藉助ClassFileTransformer接口,實現對字節碼的修改,定義一個類,實現ClassFileTransformer接口,並重寫transform方法,在這個方法中,通過 ASM 技術修改字節碼。

public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
                        ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
    byte[] transformeredByteCode = classfileBuffer;

    if (Config.moudleMap.containsKey(className)) {
        try {
            ClassReader reader = new ClassReader(classfileBuffer);
            ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
            ClassVisitor visitor = Reflections.createVisitorIns((String) Config.moudleMap.get(className).get("loadClass"), writer, className);
            reader.accept(visitor, ClassReader.EXPAND_FRAMES);
            transformeredByteCode = writer.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return transformeredByteCode;
}

簡單的原理就是這樣的,因爲篇幅優先就不在這裏展開太多了,大家如果感興趣的話,可以看一下 (https://github.com/xbeark/javaopenrasp )這個開源項目,這是我的一個阿里同事搞的一個簡單的 RASP Demo,裏面包含了一些REC、SQL 注入等的防護:

-w687

使用 Java實現的,代碼不多,很容易理解。

開源工具

RASP作爲一個相對成熟的技術,現在已經有很多開源的產品了,國內外都有很多。如國外的Micro Focus、Prevoty、OWASP AppSensor、Shadowd等等。

國內也有很多廠商也有類似的工具。如:

以上,我們給大家介紹了 RASP 技術,以及他的簡單原理,並給大家提供了一個簡單的 Demo 應用,可以方便大家深入學習,如果想要使用一些開原產品的話,也給大家推薦了幾個,可以選擇性的瞭解一下。

參考資料:

https://segmentfault.com/a/1190000041132495

https://www.freebuf.com/articles/web/197823.html

https://github.com/xbeark/javaopenrasp

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章