了解Rasp - RASP VS WAF & 簡單分析

0x01 引言


RASP(Runtime application self-protection)運行時應(yīng)用自我保護,是一種植入到應(yīng)用程序內(nèi)部或其運行時環(huán)境的安全技術(shù)。RASP可將自身注入到應(yīng)用程序中,與應(yīng)用程序融為一體,實時監(jiān)測、阻斷攻擊,使程序自身擁有自保護的能力。

實時監(jiān)測、阻斷攻擊這兩個詞看好像與waf(Web Application Firewall,web應(yīng)用防護系統(tǒng))很像,那它們有什么不同之處呢?RASP到底是做什么的?實現(xiàn)原理是什么?一場”修行”又開始了。

0x02 RASP vs WAF


1、簡介

  • WAF

    Web應(yīng)用防火墻是通過執(zhí)行一系列針對HTTP/HTTPS的安全策略來專門為Web應(yīng)用提供保護的一款產(chǎn)品。

    聊點陽間的東西,waf就好像“WEB應(yīng)用小區(qū)”的門衛(wèi),門衛(wèi)手里有個小冊子(俗稱特征庫:存放以往來小區(qū)做壞事的壞蛋特征如壞蛋總是戴頭套)。當小區(qū)外邊人要進小區(qū)串門的時候,它就會攔下來問:來者何人?并根據(jù)這個人的特征和手里的小冊子核對,如果沒有“在案”的壞蛋特征,就一律放行。

    從壞人的角度看,似乎這樣的門衛(wèi)并非無懈可擊,壞人可以換裝、整容等等手段去騙過門衛(wèi)。

  • RASP

    RASP(Runtime application self-protection)運行時應(yīng)用自我保護,是一種植入到應(yīng)用程序內(nèi)部或其運行時環(huán)境的安全技術(shù)。RASP可將自身注入到應(yīng)用程序中,與應(yīng)用程序融為一體,實時監(jiān)測、阻斷攻擊,使程序自身擁有自保護的能力。

    聊點陽間的東西,相當于在小區(qū)里每家每戶都安排了一位管家,無事不登三寶殿,壞人進入小區(qū)肯定是要干壞事的,所以RASP思路就是:你戴不戴頭套我不管,就看你做不做出格(攻擊動作)的事。

    就好像,越獄的方法千萬種,總要離開牢房;撩妹的手段永遠在變花樣,但目標都是...

2、部署&產(chǎn)品特性

  • WAF

    • 外部邊界入口統(tǒng)一部署

    • 支持串聯(lián)、旁路、反向代理三種方式部署

    • 容易形成單點故障,影響面大

    簡單說就是,如果小區(qū)門口門衛(wèi)今天喝多了,可能在門口睡著了導(dǎo)致小區(qū)的人不管好的壞的都進不去。

  • RASP

    • 服務(wù)器上單獨部署,嵌入在應(yīng)用程序內(nèi)部,應(yīng)用代碼無感知

    • 與開發(fā)語言強相關(guān),但防護插件可共用

產(chǎn)品特性對比如下:

a57a6de47b9031c1d923bf55d700505e.png

3、性能&檢測能力

  • WAF

    • 規(guī)則越多,匹配時對性能消耗就越大

    • 和硬件配置相關(guān)

    • 對服務(wù)器CPU無影響

    • 業(yè)務(wù)報文多一次轉(zhuǎn)發(fā),延遲變大

  • RASP

    • 只在關(guān)鍵點檢測,不是所有請求都匹配所有規(guī)則

    • 對服務(wù)器CPU性能有消耗

    • 非防護狀態(tài)延遲增大3-5%,防護狀態(tài)延遲增大4.6 – 8.9%

檢測能力對比如下:

e2e2cd15-d1bc-4b24-bd97-bbdf2b83a7a9.png

百度Openrasp 官方檢測能力說明:https://rasp.baidu.com/doc/usage/web.html

4、優(yōu)劣分析

接著聊小區(qū)門衛(wèi)與管家的事兒,列舉幾個關(guān)鍵點:

1)門衛(wèi)手里有個小冊子(俗稱特征庫:存放以往來小區(qū)做壞事的壞蛋特征如壞蛋總是戴頭套)

Waf誤報多,壞蛋總是戴頭套,但不一定戴頭套的全是壞人。

Waf維護成本高,小冊子需要不斷更新添加新的特征。

Waf漏報多容易被繞過,小冊子要在發(fā)生偷盜事件后再去更新特征比較被動,而且壞人騙過門衛(wèi)的手段太多了,換衣服、化妝、整容等等。

2)RASP 相當于在小區(qū)里每家每戶都安排了一位管家&你戴不戴頭套我不管,就看你做不做出格(攻擊動作)的事

Rasp檢測更全面精準,每家每戶都安排一位管家肯定比小區(qū)門口的門衛(wèi)更了解每家每戶的情況。

Rasp漏洞響應(yīng)更快可預(yù)防未知漏洞,不過多新的偷盜方法肯定要有把錢裝到口袋的動作,不管是0day還是Nday都要獲取權(quán)限執(zhí)行命令。

Rasp消耗服務(wù)器資源多,Waf是一個門衛(wèi)放小區(qū)門口就行,Rasp可能需要N多個管家安排到每家每戶。

Rasp技術(shù)棧太多時使用不方便,需要根據(jù)業(yè)務(wù)不同開發(fā)語言、開發(fā)不同語言的探針。

0x03 以O(shè)penRasp為例了解實現(xiàn)原理


經(jīng)過簡單的對比我們已經(jīng)對RASP有了一定了解,那它是怎么實現(xiàn)的呢?下面以百度的OpenRasp 為例看看它的實現(xiàn)原理。

閱讀官方文檔,發(fā)現(xiàn)啟動方式為:

java -javaagent:/opt/spring-boot/rasp/rasp.jar -jar XXX.jar

java -h
     -javaagent:<jar 路徑>[=<選項>]
                  加載 Java 編程語言代理, 請參閱 java.lang.instrument

發(fā)現(xiàn)是用到了探針技術(shù),原理見:

了解完Java 探針的原理后我們來簡單看下OpenRasp的實現(xiàn)原理,可以發(fā)現(xiàn)其入口同樣是premainagentmain方法,并且都會在pox.xml中標注:

<!--pom.xml-->

    <manifestEntries>
      <Premain-Class>com.baidu.openrasp.Agent</Premain-Class>
      <Agent-Class>com.baidu.openrasp.Agent</Agent-Class>
      <Main-Class>com.baidu.openrasp.Agent</Main-Class>
      <Can-Redefine-Classes>true</Can-Redefine-Classes>
      <Can-Retransform-Classes>true</Can-Retransform-Classes>
  </manifestEntries>

// 所以入口就是 com.baidu.openrasp.Agent

        /**
     * 啟動時加載的agent入口方法
     *
     * @param agentArg 啟動參數(shù)
     * @param inst     {@link Instrumentation}
     */
    public static void premain(String agentArg, Instrumentation inst) {
        init(START_MODE_NORMAL, START_ACTION_INSTALL, inst);
    }

    /**
     * attach 機制加載 agent
     *
     * @param agentArg 啟動參數(shù)
     * @param inst     {@link Instrumentation}
     */
    public static void agentmain(String agentArg, Instrumentation inst) {
        init(Module.START_MODE_ATTACH, agentArg, inst);
    }

繼續(xù)往下看,在com.baidu.openrasp.transformer.CustomClassTransformer.java為Instrumentation注冊了transformer,從此之后的類加載都會被Transformer攔截。

    public CustomClassTransformer(Instrumentation inst) {
        this.inst = inst;
        inst.addTransformer(this, true);    // 注冊Transformer
        addAnnotationHook();    // 加載所有hook點
    }

接著我們來看攔截后的操作:

    /**
     * 過濾需要hook的類,進行字節(jié)碼更改
     *
     * @see ClassFileTransformer#transform(ClassLoader, String, Class, ProtectionDomain, byte[])
     */
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
                            ProtectionDomain domain, byte[] classfileBuffer) throws IllegalClassFormatException {
        if (loader != null) {
            DependencyFinder.addJarPath(domain);
        }
        if (loader != null && jspClassLoaderNames.contains(loader.getClass().getName())) {
            jspClassLoaderCache.put(className.replace("/", "."), new SoftReference<ClassLoader>(loader));
        }
        for (final AbstractClassHook hook : hooks) {
            if (hook.isClassMatched(className)) {   
                CtClass ctClass = null;
                try {
                    ClassPool classPool = new ClassPool();
                    addLoader(classPool, loader);
                    ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));
                    if (loader == null) {
                        hook.setLoadedByBootstrapLoader(true);
                    }
                    classfileBuffer = hook.transformClass(ctClass);
                    if (classfileBuffer != null) {
                        checkNecessaryHookType(hook.getType());
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (ctClass != null) {
                        ctClass.detach();
                    }
                }
            }
        }
        serverDetector.detectServer(className, loader, domain);
        return classfileBuffer;
    }

可以看到在這里hook.isClassMatched(className)檢測當前攔截的類是否為已經(jīng)注冊的hook的類,如果是的話則利用javassist的方法創(chuàng)建ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));, javassist 與之前文章中提到的ASM相似都是修改字節(jié)碼的工具,想了解的可以的官方搜一下使用方法。

在這里classfileBuffer = hook.transformClass(ctClass); 獲取處理后的字節(jié)碼,展開看下代碼:

    /**
     * 轉(zhuǎn)化目標類
     *
     * @param ctClass 待轉(zhuǎn)化的類
     * @return 轉(zhuǎn)化之后類的字節(jié)碼數(shù)組
     */
    public byte[] transformClass(CtClass ctClass) {
        try {
            hookMethod(ctClass);
            return ctClass.toBytecode();
        } catch (Throwable e) {
            if (Config.getConfig().isDebugEnabled()) {
                LOGGER.info("transform class " + ctClass.getName() + " failed", e);
            }
        }
        return null;
    }

這里直接調(diào)用具體hook類的hookMethod(ctClass);方法來執(zhí)行具體的邏輯,完成字節(jié)碼的生成及寫入,如OgnlHook#hookMethod代碼示例如下:

    /**
     * (none-javadoc)
     *
     * @see com.baidu.openrasp.hook.AbstractClassHook#hookMethod(CtClass)
     */
    @Override
    protected void hookMethod(CtClass ctClass) throws IOException, CannotCompileException, NotFoundException {
        String src = getInvokeStaticSrc(OgnlHook.class, "checkOgnlExpression",
                "$_", Object.class);
        insertAfter(ctClass, "topLevelExpression", null, src);
    }

    /**
     * struct框架ognl語句解析hook點
     *
     * @param object ognl語句
     */
    public static void checkOgnlExpression(Object object) {

        if (object != null) {
            String expression = String.valueOf(object);
            if (expression.length() >= Config.getConfig().getOgnlMinLength()) {
                HashMap<String, Object> params = new HashMap<String, Object>();
                params.put("expression", expression);
                HookHandler.doCheck(CheckParameter.Type.OGNL, params);
            }
        }
    }

getInvokeStaticSrc用于獲取調(diào)用靜態(tài)方法的代碼字符串,然后通過insertAfter在目標類的目標方法的出口插入相應(yīng)的源代碼,從而完成一次對字節(jié)碼的修改操作。

今天就先到這兒吧,要去團建...感興趣的朋友也可以看下這篇文章實際操作一遍。

https://mp.weixin.qq.com/s/LtoDe353uXPA8oT2D9FE8A


參考鏈接:

http://blog.nsfocus.net/rasp-tech/
http://blog.nsfocus.net/openrasp-tech/
https://www.freebuf.com/articles/network/167166.html    // 文章比喻的寫法是參考這篇文章去寫的,很有意思建議大家看下原文
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容