リクエスト/レスポンスオブジェクト検索に基づくJavaミドルウェアの一般的なエコーメソッド(HTTP用)

sczのボスからのブログの推薦ありがとうございます。+ 10086に感謝します。

気まぐれでそのようなアイデアを持っている、それを確認します。

アイデアだけを話し合い、道具はありません〜

序文

  1. Javaミドルウェア+ Java逆シリアル化の脆弱性のエコーについて調査している多くのマスターを見てきました。

    • https://xz.aliyun.com/t/7740
    • https://xz.aliyun.com/t/7348
    • https://paper.seebug.org/1233/
    • (...たくさんあるはずなので、ひっくり返さない)
  2. マスターc0ny1 「Javaメモリオブジェクト検索アシスタントツール」の作業を見ました

    IDEAと連携して、Javaアプリケーションの実行中にメモリ内のオブジェクトを検索します。たとえば、エコーなどのシナリオでマイニングリクエストオブジェクトを使用できます。

    経験によれば、Webミドルウェアはマルチスレッドアプリケーションであり、一般にrequstオブジェクトはスレッドオブジェクトに格納され、渡しThread.currentThread()たりThread.getThreads()取得たりできます

  3. そして、現在のエコーの考え方は主に、クラスのロード、静的ブロックの実行、またはメソッドの構築(ネイティブの逆シリアル化、FastJson、Jacksonなど)に基づいています。

    • TemplatesImplクラスの逆シリアル化チェーン、埋め込みクラスのバイトコード、およびdefineClass。
    • 他の逆シリアル化チェーンは、URLClassLoaderを使用してリモートでクラスをロードします。
    • JNDIはリモートでクラスをロードします。

だから私は思った:トリガーできるときに単一のクラスを書いて、2のアイデアを使用してリクエストとレスポンスを見つけ、リクエストからコマンドパラメータを取得して、それをレスポンスに書き込むことができるか?

最初に結論についてお話ししましょう。それは達成可能であり、Tomcat、Jetty、およびWeblogicで使用でき(これら3つだけがテストされ、他のJavaミドルウェアは悪くないと思います)、Shiro、Fastjson、Jacksonの逆シリアル化シナリオもテストされています。

Tomcat6 + Shiro java.io.StreamCorruptedException: invalid type code:は非常に魅力的なエラーを報告します。

合理化されたコンパイル済みクラスファイルのサイズは約2800〜2900Bで、Shiroの逆シリアル化に使用されるCookie値は約5000バイトに制御できますが、これはほとんど受け入れられません。

応答時間は通常3秒以内です。

基本的な考え方

javax.servlet.http.HttpServletRequest

javax.servlet.http.HTTPServletResponse

  1. Javaクラスミドルウェアの要求と応答は、上記の2つのインターフェースをそれぞれ実装します。
  2. Thread.currentThread()から開始して、上記の2つのインターフェースを実装するオブジェクトを検索します
  3. リクエストヘッダーは、HttpServletRequestのgetHeaderメソッドを介して取得できます。
  4. 応答Writerは、HTTPServletResponseのgetWriterメソッドを介して取得できます(最初にServletResponseのgetOutputStreamインターフェースが使用されましたが、繰り返し取得される出力ストリームのエラーが報告されるため、代わりにgetWriterを使用します)。
  5. すべて検索した後、実行が実行され、出力が出力されます

初期コード

たくさんありますが、いずれも疑わしい言葉が貼られているので、要旨リンクを貼ってみましょう。┓(´∀`)┏

https://gist.github.com/fnmsd/89118c2967cd53c244389564d2f8b368

コンパイルされたクラスは3888バイトです、頑張ってください〜

  • クラスを小さくするために、マスターc0ny1ほど細心の注意を払って検索とプルーニングを行いませんでした。

  • 便宜上、純粋に深さ優先検索(DFS)を使用し、フィールドを順番に検索します

  • しかし、減量するためには、さまざまな所定のロジックが絶え間なく切り続けなければなりません。

** PS:** Tomcatのリクエストを検索するプロセスで、現在のリクエストではないオブジェクトが見つかった理由がわからないため、リクエストにcmdヘッダーを含める必要があると制限されており、実際のリクエストが見つかったと思います。レスポンスではまだ見つかりません。問題。

コードをスリムにする

NginxのCookieの長さ制限は4096Bで、Tomcatは8096Bの長さ制限があるため(マスターc0ny1に感謝)、テンプレートクラスチェーンを使用できるようにするには、コンパイルされたクラスファイルをできるだけ小さくする必要があります。

次のコンテンツは乱雑です、それは徐々にClassファイルを縮小しようとするプロセスです。興味がなければスキップできます

分析プロセス全体では、classpy-0.4.jarを使用してClassファイルを分析します。

https://github.com/zxh0/classpy

ここに画像の説明を挿入

1.初期

3888バイト

2.オプションの静的フィールドを削除する

    static Class ReqC = HttpServletRequest.class;
    static Class RespC = HttpServletResponse.class;       
    static int max_depth = 50;

3734バイト

  1. 文字列接続を削除します。
    ここに画像の説明を挿入
    ここに画像の説明を挿入

3640バイト

  1. 冗長ロジックを削除するための制限ロジック

            if(depth > 50||(req!=null&&resp!=null)){
          
          
                return;
            }
    

    3611バイト

  2. getModifiersの呼び出しを削除します(メソッドを削除するには約60バイトですか?)

3551バイト

空の判断を減らし、約4バイト

3547

  1. ローカル変数の定義を減らす

    Class a = obj.getClass();
    if(a.isPrimitive()||a.toString().startsWith("java.lang")){
          
          
        return true;
    }
    

    になる:

    if(obj.getClass().isPrimitive()||obj.getClass().toString().startsWith("java.lang")){
          
          
                return true;
            }
    

    3525、22バイト少ない

  2. デバッグに使用されたprintStackTraceを削除します

    3488バイト

  3. flushとwaitForを削除します

    3451バイト、それほど少なくないようです

  4. 静的ブロックと開始メソッドを削除し、コンストラクタートリガーのみを保持する

    3372

  5. PrintWriterの変数割り当てを削除し、fnmsd文字列によるテストを削除します

    3260

  6. procの定義を削除し、getInputStreamで直接呼び出します。

    3220

  7. スキャナー関連のロジックを1つの文に結合します。

    resp.getWriter().println(new Scanner(Runtime.getRuntime().exec(req.getHeader("cmd")).getInputStream()).useDelimiter("\\A").next())

    3130

判断されるべきだった次のプルーニングは、例外処理に置き換えられます

  1. java.langクラスの検索プルーニングを削除します

    obj.getClass().toString().startsWith("java.lang")

    保存されたtoStringとstartsWith

    3009

  2. アレイパッケージタイプが非プリミティブであるという判断を削除します。

    obj.getClass().getComponentType().isPrimitive()

    2962

  3. isPrimitiveの判断をすべて削除します

    2917

  4. 検索時にフィールド値がnullであるという判断を削除します

    2908

  5. クラス名、フィールド名、メソッド名、ローカル変数名を1文字に変更します

    2850

    ここでローカル変数を変更しても、実際には機能しません。

  6. 静的フィールドかどうかの判断を削除します

    if((declaredField.getModifiers()&0x00000008) == 0)

    2803(最終的なサイズは2800から2900の間で、それほど大きな違いはありません。後で変更する場所がわからないため、約2900です)

痩身サマリー

最終的な結果コード(構築メソッドによってトリガーされ、静的に変更することもできます。すべて同じです):https : //gist.github.com/fnmsd/8165cedd9fe735d7ef438b2e977af327
(中間のバグバージョンが以前に送信され、繰り返されます。見つけるのを手伝ってくれたマスターl1nk3rに感謝)

  1. 参照メソッドと型を最小限に抑える(文字列連結などの暗黙的な呼び出しを含む)
  2. フィールドとローカル変数の定義を最小限に抑える
  3. 例外処理で収益を処理し、判断を減らす能力。
  4. 蚊の足も肉です。フィールド名、パラメーター名、変数名を小さいサイズに変更してください(これは確かではありません。フィールド名だけが有効な場合があります)
  5. 大きな部分は主にConstantPoolと変数定義にあります(ConstantPoolは理解しやすく、変数定義はあまり明確ではありません。フォローアップはまだクラスファイル構造を学習しています)

テスト

  1. それらはすべて新しいオブジェクトまたは静的ブロックによって実行されるので、私は怠惰を盗んで単純にjspページを作成しました。出力ステートメントはないが、オブジェクトは新しいことがわかります。

    <%@ page import="aa.a" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <%
        new a();
      %>
    

    Weblogic(パッケージ化には少し問題があり、ページは最も単純なバージョンに変更されていません):

ここに画像の説明を挿入

Tomcat:
ここに画像の説明を挿入
Jetty:
ここに画像の説明を挿入

  1. Tomat8 + Shiroの逆シリアル化

    Jdk7u21チェーン(TemplatesImplによってトリガーされる)は、ここで私が記述したクラスを新規作成するために使用されます。rememberMeの長さは5036です

    怠惰で環境を使用できない学生は、VulhubのShiro環境(SpringBootに組み込まれたTomcat9)を使用できますが、CommonsBeanutils1チェーンを使用する必要があります。

ここに画像の説明を挿入
3. Fastjson JNDIロードシーン(vulhubのfastjson / 1.2.47-rce、SpringBoot用の組み込みTomcat9)

ここに画像の説明を挿入
4. weblogic12 + Jacksonの逆シリアル化

これは以前にジャクソンに話したチェーンを使用していますが、残念ながらCVE番号geto(╥﹏╥)oを取得できませんでした
ここに画像の説明を挿入

その他の

  1. 元々、最大の深さ優先検索は50レイヤーに設定されていました。その結果、weblogicでは、リクエストは50番目のレイヤーで検索され、レスポンスはリクエストの下の51番目のレイヤーにありました。そこで、後で最大深度を52レイヤーに変更しました。
  2. TemplatesImplの特定の使用にはクラスチェーンが必要であり、Javassistを使用してAbstractTransletインターフェースを追加する必要があります。もちろん、直接実装することもできますが、実装する必要のあるインターフェースがさらに2つあり、クラスはさらに大きくなります。詳細については、https://xz.aliyunを参照してください。 com / t / 6227

少し考えてみましょう:非HTTPを逆シリアル化し、Socketオブジェクトを検索して、getOutputStreamから書き込むことは可能ですか?

参照

修士研究:

https://xz.aliyun.com/t/7740

https://xz.aliyun.com/t/7348

https://paper.seebug.org/1233/

https://github.com/c0ny1/java-object-searcher

http://gv7.me/articles/2020/semi-automatic-mining-request-implements-multiple-middleware-echo/

J2EEインターフェースドキュメント:

https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html

https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html

おすすめ

転載: blog.csdn.net/fnmsd/article/details/106709736