Deserialization
Last updated
Last updated
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
シリアライズは、オブジェクトを保存可能な形式に変換する方法として理解されており、オブジェクトを保存するか、通信プロセスの一部として送信することを意図しています。この技術は、オブジェクトが後で再作成できるようにし、その構造と状態を維持するために一般的に使用されます。
デシリアライズは、逆にシリアライズに対抗するプロセスです。特定の形式で構造化されたデータを取り、それをオブジェクトに再構築することを含みます。
デシリアライズは危険である可能性があります。なぜなら、攻撃者がシリアライズされたデータを操作して有害なコードを実行したり、オブジェクト再構築プロセス中にアプリケーションに予期しない動作を引き起こすことを許す可能性があるからです。
PHPでは、シリアライズおよびデシリアライズプロセス中に特定のマジックメソッドが利用されます:
__sleep
:オブジェクトがシリアライズされるときに呼び出されます。このメソッドは、シリアライズされるべきオブジェクトのすべてのプロパティの名前の配列を返す必要があります。保留中のデータをコミットしたり、同様のクリーンアップタスクを実行するために一般的に使用されます。
__wakeup
:オブジェクトがデシリアライズされるときに呼び出されます。シリアライズ中に失われた可能性のあるデータベース接続を再確立し、他の再初期化タスクを実行するために使用されます。
__unserialize
:オブジェクトがデシリアライズされるときに、__wakeup
の代わりに呼び出されるメソッドです。__wakeup
に比べてデシリアライズプロセスに対する制御がより強化されます。
__destruct
:オブジェクトが破棄される直前またはスクリプトが終了するときに呼び出されるメソッドです。ファイルハンドルやデータベース接続を閉じるなどのクリーンアップタスクに一般的に使用されます。
__toString
:このメソッドは、オブジェクトを文字列として扱うことを可能にします。ファイルを読み取るためや、その中の関数呼び出しに基づく他のタスクに使用でき、オブジェクトのテキスト表現を効果的に提供します。
結果を見ると、オブジェクトがデシリアライズされるときに関数 __wakeup
と __destruct
が呼び出されることがわかります。いくつかのチュートリアルでは、属性を印刷しようとすると __toString
関数が呼び出されるとされていますが、どうやらそれは もう起こっていない ようです。
メソッド __unserialize(array $data)
は、クラスに実装されている場合、__wakeup()
の代わりに呼び出されます。これは、シリアライズされたデータを配列として提供することでオブジェクトをデシリアライズすることを可能にします。このメソッドを使用して、プロパティをデシリアライズし、デシリアライズ時に必要なタスクを実行できます。
説明されたPHPの例をこちらで読むことができます: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/、こちら https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf またはこちら https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
PHPのオートロード機能を悪用して、任意のphpファイルを読み込むことができます:
PHP - Deserialization + Autoload Classes何らかの理由で、別のシリアル化された値への参照として値をシリアル化したい場合は、次のようにできます:
PHPGGC は、PHP のデシリアライズを悪用するためのペイロードを生成するのに役立ちます。
アプリケーションのソースコード内でデシリアライズを悪用する方法を見つけられない場合もありますが、外部 PHP 拡張のコードを悪用できるかもしれません。
ですので、可能であれば、サーバーの phpinfo()
を確認し、インターネットで検索(さらには PHPGGC の gadgets でも)して、悪用できる可能性のあるガジェットを探してください。
ファイルを読み取るだけで、内部の PHP コードを実行しない LFI を見つけた場合、例えば file_get_contents(), fopen(), file() または file_exists(), md5_file(), filemtime() または filesize()** のような関数を使用している場合、phar プロトコルを使用してファイルを読み取る際に発生する デシリアライズ を悪用しようとすることができます。 詳細については、以下の投稿をお読みください:
phar:// deserializationオブジェクトがアンピクルされると、関数 __reduce__ が実行されます。 悪用されると、サーバーはエラーを返す可能性があります。
Before checking the bypass technique, try using print(base64.b64encode(pickle.dumps(P(),2)))
to generate an object that is compatible with python2 if you're running python3.
For more information about escaping from pickle jails check:
Bypass Python sandboxes次のページでは、yamlの安全でないデシリアライズを悪用する技術を紹介し、Pickle、PyYAML、jsonpickle、ruamel.yamlのためのRCEデシリアライズペイロードを生成するために使用できるツールで締めくくります:
Python Yaml DeserializationJS には、PHPやPythonのようにオブジェクトを作成するためだけに実行される「マジック」関数はありません。しかし、toString
、valueOf
、toJSON
のように、直接呼び出さなくても頻繁に使用される関数があります。
デシリアライズを悪用する場合、これらの関数を妥協して他のコードを実行することができれば、呼び出されたときに任意のコードを実行できます。
関数を直接呼び出さずに**「マジック」な方法で関数を呼び出すもう一つの方法は、非同期関数(プロミス)によって返されるオブジェクトを妥協することです。なぜなら、その返されるオブジェクトを関数型の「then」というプロパティを持つ別のプロミスに変換すると、別のプロミスによって返されるだけで実行される**からです。 詳細については このリンク を参照してください。
__proto__
と prototype
の汚染この技術について学びたい場合は、次のチュートリアルを見てください:
NodeJS - __proto__ & prototype Pollutionこのライブラリは関数をシリアライズすることを可能にします。例:
The serialised object will looks like: シリアライズされたオブジェクトは次のようになります:
例では、関数がシリアライズされると、_$$ND_FUNC$$_
フラグがシリアライズされたオブジェクトに追加されることがわかります。
node-serialize/lib/serialize.js
ファイル内で、同じフラグとそのコードの使用方法を見つけることができます。
最後のコードのチャンクでわかるように、フラグが見つかった場合、eval
が使用されて関数がデシリアライズされるため、基本的に ユーザー入力が eval
関数内で使用されていることになります。
しかし、関数をシリアライズするだけでは、それを実行することはありません。なぜなら、コードの一部が**y.rce
を呼び出す必要があるからで、これは非常にありそうにありません**。
とにかく、シリアライズされたオブジェクトを修正して、いくつかの括弧を追加することで、オブジェクトがデシリアライズされるときにシリアライズされた関数を自動的に実行させることができます。
次のコードのチャンクで、最後の括弧と、unserialize
関数がどのように自動的にコードを実行するかに注意してください:
以前に示したように、このライブラリは_$$ND_FUNC$$_
の後のコードを取得し、eval
を使用して実行します。したがって、コードを自動実行するためには、関数作成部分と最後の括弧を削除し、次の例のようにJSのワンライナーを実行することができます:
You can find here この脆弱性を悪用する方法に関するさらなる情報.
funcsterの注目すべき点は、標準の組み込みオブジェクトへのアクセスができないことです。これらはアクセス可能なスコープの外にあります。この制限により、組み込みオブジェクトのメソッドを呼び出そうとするコードの実行が妨げられ、console.log()
やrequire(something)
のようなコマンドを使用すると、"ReferenceError: console is not defined"
のような例外が発生します。
この制限にもかかわらず、特定のアプローチを通じて、すべての標準の組み込みオブジェクトを含むグローバルコンテキストへの完全なアクセスを復元することが可能です。グローバルコンテキストを直接利用することで、この制限を回避できます。たとえば、次のスニペットを使用してアクセスを再確立できます:
詳細については、このソースを読む。**
serialize-javascriptパッケージは、シリアル化専用に設計されており、組み込みのデシリアル化機能はありません。ユーザーはデシリアル化のための独自のメソッドを実装する責任があります。シリアル化されたデータをデシリアル化するための公式の例では、eval
の直接使用が推奨されています:
この関数がオブジェクトをデシリアライズするために使用される場合、あなたは簡単にそれを悪用できます:
詳細についてはこのソースを読んでください more information read this source.
以下のページでは、このライブラリを悪用して任意のコマンドを実行する方法に関する情報を見つけることができます:
Javaでは、デシリアライズコールバックはデシリアライズのプロセス中に実行されます。この実行は、これらのコールバックをトリガーする悪意のあるペイロードを作成する攻撃者によって悪用される可能性があり、有害なアクションの実行につながることがあります。
コードベース内の潜在的なシリアライズ脆弱性を特定するには、次のものを検索してください:
Serializable
インターフェースを実装しているクラス。
java.io.ObjectInputStream
、readObject
、readUnshared
関数の使用。
特に注意を払うべき点:
外部ユーザーによって定義されたパラメータで使用されるXMLDecoder
。
XStream
のfromXML
メソッド、特にXStreamのバージョンが1.46以下の場合、シリアライズの問題に対して脆弱です。
readObject
メソッドと組み合わされたObjectInputStream
。
readObject
、readObjectNodData
、readResolve
、またはreadExternal
などのメソッドの実装。
ObjectInputStream.readUnshared
。
Serializable
の一般的な使用。
ブラックボックステストでは、javaシリアライズオブジェクトを示す特定の**シグネチャまたは「マジックバイト」**を探してください(ObjectInputStream
から発生):
16進パターン:AC ED 00 05
。
Base64パターン:rO0
。
Content-type
がapplication/x-java-serialized-object
に設定されたHTTPレスポンスヘッダー。
以前の圧縮を示す16進パターン:1F 8B 08 00
。
以前の圧縮を示すBase64パターン:H4sIA
。
.faces
拡張子を持つWebファイルとfaces.ViewState
パラメータ。これらのパターンをWebアプリケーションで発見した場合、Java JSF ViewStateデシリアライズに関する投稿に詳述されているように調査を促すべきです。
Javaのデシリアライズ攻撃がどのように機能するかを学びたい場合は、Basic Java Deserialization、Java DNS Deserialization、およびCommonsCollection1 Payloadを確認してください。
既知の脆弱性を持つアプリケーションがインストールされているかどうかを確認できます。
あなたは、脆弱性が知られているすべてのライブラリを確認し、Ysoserialがエクスプロイトを提供できるかどうかを試すことができます。また、Java-Deserialization-Cheat-Sheetに示されているライブラリを確認することもできます。 gadgetinspectorを使用して、エクスプロイト可能な可能性のあるガジェットチェーンを検索することもできます。 gadgetinspectorを実行する際(ビルド後)は、発生する多数の警告/エラーを気にせず、完了するまで待ってください。すべての結果は_gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt_に書き込まれます。gadgetinspectorはエクスプロイトを作成せず、偽陽性を示す可能性があることに注意してください。
Burp拡張機能gadgetprobeを使用すると、どのライブラリが利用可能か(バージョンも含む)を特定できます。この情報をもとに、脆弱性をエクスプロイトするためのペイロードを選択しやすくなるかもしれません。
GadgetProbeについて詳しく学ぶにはこちらをお読みください。
GadgetProbeは**ObjectInputStream
のデシリアライズ**に焦点を当てています。
Burp拡張機能Java Deserialization Scannerを使用すると、ysoserialでエクスプロイト可能な脆弱なライブラリを特定し、それをエクスプロイトできます。
Java Deserialization Scannerについて詳しく学ぶにはこちらをお読みください。
Java Deserialization Scannerは**ObjectInputStream
**のデシリアライズに焦点を当てています。
Freddyを使用して、Burp内のデシリアライズの脆弱性を検出することもできます。このプラグインは、ObjectInputStream
関連の脆弱性だけでなく、JsonおよびYmlデシリアライズライブラリの脆弱性も検出します。アクティブモードでは、スリープまたはDNSペイロードを使用して確認を試みます。
Freddyについての詳細情報はこちらで確認できます。
シリアライズテスト
サーバーが使用している脆弱なライブラリを確認することだけが全てではありません。時には、シリアライズされたオブジェクト内のデータを変更し、いくつかのチェックをバイパスすることができるかもしれません(ウェブアプリ内で管理者権限を付与するかもしれません)。 ウェブアプリケーションに送信されるJavaシリアライズオブジェクトを見つけた場合、**SerializationDumper**を使用して、送信されるシリアライズオブジェクトをより人間が読みやすい形式で印刷することができます。送信しているデータを知ることで、それを変更しやすくなり、いくつかのチェックをバイパスできます。
Javaデシリアライズをエクスプロイトするための主なツールはysoserialです(こちらからダウンロード)。また、複雑なコマンド(例えばパイプを使用)を使用できるysoseral-modifiedの使用も検討できます。
このツールは**ObjectInputStream
のエクスプロイトに焦点を当てていることに注意してください。
私はRCEペイロードの前に「URLDNS」ペイロードを使用して、インジェクションが可能かどうかをテストすることをお勧めします**。いずれにせよ、「URLDNS」ペイロードが機能しない場合でも、他のRCEペイロードが機能する可能性があることに注意してください。
When creating a payload for java.lang.Runtime.exec() you cannot use special characters like ">" or "|" to redirect the output of an execution, "$()" to execute commands or even pass arguments to a command separated by spaces (you can do echo -n "hello world"
but you can't do python2 -c 'print "Hello world"'
). In order to encode correctly the payload you could use this webpage.
次のスクリプトを使用して、WindowsとLinuxのすべての可能なコード実行ペイロードを作成し、脆弱なウェブページでテストしてください:
あなたは https://github.com/pwntester/SerialKillerBypassGadgetCollection を ysoserialと一緒に使用して、より多くのエクスプロイトを作成することができます。このツールに関する詳細は、ツールが発表された トークのスライド にあります: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1
marshalsec は、Javaの異なる Json および Yml シリアル化ライブラリを悪用するためのペイロードを生成するために使用できます。
プロジェクトをコンパイルするために、私は pom.xml
にこの 依存関係 を 追加する必要がありました:
Mavenをインストールし、プロジェクトをコンパイルします:
このJava JSONライブラリについての詳細はこちら: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html
いくつかのysoserialペイロードをテストしたい場合は、このウェブアプリを実行できます: https://github.com/hvqzao/java-deserialize-webapp
Javaはさまざまな目的で多くのシリアル化を使用します:
HTTPリクエスト: シリアル化は、パラメータ、ViewState、クッキーなどの管理に広く使用されています。
RMI (リモートメソッド呼び出し): Java RMIプロトコルは、シリアル化に完全に依存しており、Javaアプリケーションにおけるリモート通信の基盤です。
HTTP経由のRMI: この方法は、Javaベースの厚いクライアントウェブアプリケーションによって一般的に使用され、すべてのオブジェクト通信にシリアル化を利用します。
JMX (Java管理拡張): JMXは、ネットワーク上でオブジェクトを送信するためにシリアル化を利用します。
カスタムプロトコル: Javaでは、標準的な慣行として、生のJavaオブジェクトの送信が含まれ、今後のエクスプロイト例で示されます。
Serializable
を実装するクラスは、シリアル化されるべきでないクラス内の任意のオブジェクトをtransient
として実装できます。例えば:
特定の**オブジェクトがクラス階層のためにSerializable
**インターフェースを実装しなければならないシナリオでは、意図しないデシリアライズのリスクがあります。これを防ぐために、以下のように常に例外をスローするfinal
なreadObject()
メソッドを定義して、これらのオブジェクトがデシリアライズ不可能であることを確認してください。
java.io.ObjectInputStream
のカスタマイズは、デシリアライズプロセスを保護するための実用的なアプローチです。この方法は、次の場合に適しています。
デシリアライズコードがあなたの管理下にある。
デシリアライズのために期待されるクラスが知られている。
**resolveClass()
**メソッドをオーバーライドして、許可されたクラスのみにデシリアライズを制限します。これにより、明示的に許可されたクラス以外のデシリアライズが防止されます。以下の例のように、Bicycle
クラスのみにデシリアライズを制限します:
セキュリティ強化のためのJavaエージェントの使用は、コードの修正が不可能な場合のフォールバックソリューションを提供します。この方法は主に有害なクラスのブラックリスト化に適用され、JVMパラメータを使用します:
動的にデシリアライズを保護する方法を提供し、即時のコード変更が実用的でない環境に理想的です。
rO0 by Contrast Securityの例を確認してください。
シリアライゼーションフィルターの実装: Java 9は**ObjectInputFilter
**インターフェースを介してシリアライゼーションフィルターを導入し、デシリアライズされる前にシリアライズされたオブジェクトが満たすべき基準を指定するための強力なメカニズムを提供します。これらのフィルターは、グローバルにまたはストリームごとに適用でき、デシリアライズプロセスに対する詳細な制御を提供します。
シリアライゼーションフィルターを利用するには、すべてのデシリアライズ操作に適用されるグローバルフィルターを設定するか、特定のストリームのために動的に構成することができます。例えば:
外部ライブラリを活用したセキュリティの強化: NotSoSerial、jdeserialize、およびKryoなどのライブラリは、Javaのデシリアライズを制御および監視するための高度な機能を提供します。これらのライブラリは、デシリアライズ前にシリアライズされたオブジェクトを分析したり、クラスのホワイトリストやブラックリストを作成したり、カスタムシリアライズ戦略を実装したりするなど、追加のセキュリティ層を提供できます。
NotSoSerialは、信頼できないコードの実行を防ぐためにデシリアライズプロセスを傍受します。
jdeserializeは、デシリアライズせずにシリアライズされたJavaオブジェクトを分析でき、潜在的に悪意のあるコンテンツを特定するのに役立ちます。
Kryoは、スピードと効率を重視した代替シリアライズフレームワークで、セキュリティを強化できる構成可能なシリアライズ戦略を提供します。
デシリアライズとysoserialのトーク: http://frohoff.github.io/appseccali-marshalling-pickles/
デシリアライズのCVE: https://paper.seebug.org/123/
JNDIインジェクションとは何か、RMI、CORBA、LDAPを介してどのように悪用するか、log4shellをどのように悪用するか(およびこの脆弱性の例)については、以下のページを参照してください。
JNDI - Java Naming and Directory Interface & Log4ShellJavaメッセージサービス(JMS)APIは、2つ以上のクライアント間でメッセージを送信するためのJavaメッセージ指向ミドルウェアAPIです。これは、プロデューサー–コンシューマー問題を処理するための実装です。JMSはJavaプラットフォーム、エンタープライズエディション(Java EE)の一部であり、Sun Microsystemsで開発された仕様によって定義されましたが、その後Javaコミュニティプロセスによって指導されています。これは、Java EEに基づくアプリケーションコンポーネントがメッセージを作成、送信、受信、および読み取ることを可能にするメッセージング標準です。これにより、分散アプリケーションの異なるコンポーネント間の通信が緩く結合され、信頼性が高く、非同期になります。(出典: Wikipedia)
このミドルウェアを使用してメッセージを送信する製品がいくつかあります。
基本的に、危険な方法でJMSを使用しているサービスがたくさんあります。したがって、これらのサービスにメッセージを送信するための十分な権限がある場合(通常は有効な資格情報が必要)、デシリアライズされる悪意のあるオブジェクトを送信できる可能性があります。 これは、この悪用において、そのメッセージを使用するすべてのクライアントが感染することを意味します。
サービスが脆弱である場合(ユーザー入力を安全でない方法でデシリアライズしているため)、脆弱性を悪用するための有効なガジェットを見つける必要があることを忘れないでください。
ツールJMETは、既知のガジェットを使用してシリアライズされた複数の悪意のあるオブジェクトを送信するためにこれらのサービスに接続して攻撃するために作成されました。これらのエクスプロイトは、サービスが依然として脆弱であり、使用されるガジェットのいずれかが脆弱なアプリケーション内に存在する場合に機能します。
.Netの文脈において、デシリアライズの悪用は、Javaで見られるものと同様の方法で動作し、ガジェットがデシリアライズ中に特定のコードを実行するために悪用されます。
ソースコードを検査して、以下の出現を探すべきです:
TypeNameHandling
JavaScriptTypeResolver
ユーザー制御下の変数によって型が決定されることを許可するシリアライザーに焦点を当てるべきです。
Base64エンコードされた文字列 AAEAAAD///// またはサーバー側でデシリアライズされる可能性のある類似のパターンをターゲットにする必要があります。これには、TypeObject
や$type
を含むJSONやXML構造が含まれる可能性がありますが、これに限定されません。
この場合、ツールysoserial.netを使用してデシリアライズの悪用を作成することができます。gitリポジトリをダウンロードしたら、Visual Studioなどを使用してツールをコンパイルする必要があります。
ysoserial.netがどのように悪用を作成するかについて学びたい場合は、ObjectDataProviderガジェット + ExpandedWrapper + Json.Netフォーマッターが説明されているこのページを確認してください。
ysoserial.netの主なオプションは、--gadget
、--formatter
、--output
、および**--plugin
**です。
**--gadget
**は、悪用するガジェットを示すために使用されます(デシリアライズ中にコマンドを実行するために悪用されるクラス/関数を示します)。
**--formatter
**は、悪用をシリアライズする方法を示すために使用されます(ペイロードをデシリアライズするためにバックエンドが使用しているライブラリを知り、それを使用してシリアライズする必要があります)。
--output
は、悪用を生またはbase64エンコードで取得したいかどうかを示すために使用されます。注意してください、ysoserial.netはペイロードをUTF-16LE(Windowsでデフォルトで使用されるエンコーディング)を使用してエンコードするため、Linuxコンソールから生のペイロードをエンコードすると、悪用が正しく機能しないエンコーディング互換性の問題が発生する可能性があります(HTB JSONボックスではペイロードはUTF-16LEとASCIIの両方で機能しましたが、これは常に機能するとは限りません)。
--plugin
ysoserial.netは、ViewStateのような特定のフレームワーク用の悪用を作成するためのプラグインをサポートしています。
--minify
は、小さなペイロードを提供します(可能な場合)。
--raf -f Json.Net -c "anything"
これは、提供されたフォーマッター(この場合はJson.Net
)で使用できるすべてのガジェットを示します。
--sf xml
は、ガジェット(-g
)を示すことができ、ysoserial.netは「xml」を含むフォーマッターを検索します(大文字と小文字を区別しません)。
ysoserialの例を使用して悪用を作成します:
ysoserial.net には、各エクスプロイトがどのように機能するかをよりよく理解するのに役立つ 非常に興味深いパラメータ があります: --test
このパラメータを指定すると、ysoserial.net は ローカルでエクスプロイトを試みます ので、ペイロードが正しく機能するかどうかをテストできます。
このパラメータは便利です。なぜなら、コードをレビューすると、次のようなコードの断片が見つかるからです (from ObjectDataProviderGenerator.cs):
これは、エクスプロイトをテストするために、コードが serializersHelper.JsonNet_deserialize を呼び出すことを意味します。
In the 前のコードは作成されたエクスプロイトに脆弱です。したがって、.Netアプリケーションで類似のものを見つけた場合、そのアプリケーションも脆弱である可能性が高いです。
したがって、--test
パラメータは、ysoserial.netが作成できるデシリアライズエクスプロイトに対してどのコードのチャンクが脆弱であるかを理解するのに役立ちます。
.Netの__ViewStateパラメータをエクスプロイトする方法についてのこのPOSTを見てください 任意のコードを実行するために。 もしあなたが被害者のマシンで使用されている秘密をすでに知っているなら、コードを実行する方法を知るためにこの投稿を読んでください。**
.Netにおけるデシリアライズに関連するリスクを軽減するために:
データストリームにオブジェクトタイプを定義させないようにします。 可能な場合はDataContractSerializer
またはXmlSerializer
を利用してください。
JSON.Net
の場合、TypeNameHandling
をNone
に設定します: %%%TypeNameHandling = TypeNameHandling.None%%%
JavaScriptSerializer
をJavaScriptTypeResolver
と一緒に使用しないでください。
デシリアライズ可能なタイプを制限し、System.IO.FileInfo
のような.Netタイプに内在するリスクを理解します。これはサーバーファイルのプロパティを変更し、サービス拒否攻撃を引き起こす可能性があります。
リスクのあるプロパティを持つタイプに注意してください。 例えば、System.ComponentModel.DataAnnotations.ValidationException
のValue
プロパティは悪用される可能性があります。
タイプのインスタンス化を安全に制御し、攻撃者がデシリアライズプロセスに影響を与えないようにします。これにより、DataContractSerializer
やXmlSerializer
でさえ脆弱になります。
BinaryFormatter
およびJSON.Net
のためにカスタムSerializationBinder
を使用してホワイトリスト制御を実装します。
.Net内の既知の不安全なデシリアライズガジェットについて情報を得て、デシリアライザがそのようなタイプをインスタンス化しないようにします。
インターネットアクセスのあるコードから潜在的にリスクのあるコードを隔離し、System.Windows.Data.ObjectDataProvider
のような既知のガジェットを信頼できないデータソースにさらさないようにします。
Rubyでは、シリアル化はmarshalライブラリ内の2つのメソッドによって促進されます。最初のメソッドはdumpとして知られ、オブジェクトをバイトストリームに変換するために使用されます。このプロセスはシリアル化と呼ばれます。逆に、2番目のメソッドloadは、バイトストリームをオブジェクトに戻すために使用され、このプロセスはデシリアライズと呼ばれます。
シリアル化されたオブジェクトを保護するために、RubyはHMAC(ハッシュベースのメッセージ認証コード)を使用し、データの整合性と真正性を確保します。 この目的のために使用されるキーは、いくつかの可能な場所の1つに保存されます:
config/environment.rb
config/initializers/secret_token.rb
config/secrets.yml
/proc/self/environ
Ruby 2.Xの一般的なデシリアライズからRCEガジェットチェーン(詳細は https://www.elttam.com/blog/ruby-deserialization/):
他のRCEチェーンを利用してRuby On Railsを攻撃する: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/
この脆弱性レポートで説明されているように、ユーザーの未サニタイズ入力がrubyオブジェクトの.send()
メソッドに到達すると、このメソッドはオブジェクトの他の任意のメソッドを任意のパラメータで呼び出すことを可能にします。
例えば、evalを呼び出し、次にrubyコードを第二パラメータとして渡すことで、任意のコードを実行することができます:
さらに、.send()
のパラメータのうち、攻撃者によって制御されるのが1つだけの場合、前回の記述で述べたように、引数を必要としないか、デフォルト値を持つ引数を持つオブジェクトの任意のメソッドを呼び出すことが可能です。
これには、オブジェクトのすべてのメソッドを列挙して、その要件を満たす興味深いメソッドを見つけることが可能です。
この技術は このブログ記事から取られました。
オブジェクトをシリアライズするために使用できる他のRubyライブラリがあり、したがって、安全でないデシリアライズ中にRCEを得るために悪用される可能性があります。以下の表は、これらのライブラリのいくつかと、それがデシリアライズされるときに呼び出されるメソッドを示しています(基本的にRCEを得るために悪用する関数):
ライブラリ
入力データ
クラス内のキックオフメソッド
Marshal (Ruby)
バイナリ
_load
Oj
JSON
hash
(クラスはハッシュ(マップ)にキーとして入れる必要があります)
Ox
XML
hash
(クラスはハッシュ(マップ)にキーとして入れる必要があります)
Psych (Ruby)
YAML
hash
(クラスはハッシュ(マップ)にキーとして入れる必要があります)
init_with
JSON (Ruby)
JSON
json_create
([json_createに関するノートを参照](#table-vulnerable-sinks)の最後)
基本的な例:
Ojを悪用しようとした場合、hash
関数内でto_s
を呼び出し、次にspecを呼び出し、fetch_pathを呼び出すガジェットクラスを見つけることができました。これにより、ランダムなURLを取得させることが可能になり、この種の未サニタイズのデシリアライズ脆弱性の優れた検出器を提供しました。
さらに、前述の技術により、システムにフォルダーが作成されることが判明しました。これは、別のガジェットを悪用してこれを完全なRCEに変換するための要件です。
詳細については、元の投稿を確認してください。
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)