WEB 攻撃と防御 - 一般的な脆弱性 & PHP デシリアライゼーション & POP チェーン構築 & マジック メソッド & ネイティブ クラス

目次

1.シリアライズとデシリアライズ

2. デシリアライゼーションの脆弱性が発生する理由

3. シリアライゼーションとデシリアライゼーションのデモンストレーション

<デモ1>

<デモ2>

<デモ2>

4. 脆弱性のデモンストレーション

<デモ1>

<デモ2>

四、ctfshow射撃場の実際の練習

<正解その1>

<正問2>

<正問3>

<正問4>


1.シリアライズとデシリアライズ

  • シリアル化: オブジェクトを配列や文字列などの形式に変換する

        serialize() // オブジェクトを文字列に変換します

  • 逆シリアル化: 配列や文字列などの形式をオブジェクトに変換する

        unserialize() //文字列をオブジェクトに戻す

  • たとえば、このようなコンテンツを送信する場合、コンテンツには多くのスペースが含まれているため、エラーが発生しやすく、スペースが無駄になります。

  • したがって、文字列または配列に変換して送信し、逆シリアル化して元のデータを出力することで、データ転送をより安定して効率的にすることができます。

2. デシリアライゼーションの脆弱性が発生する理由

        php には、何を最初に実行するか、または何を初期化するかを制御できるいくつかのマジック メソッドが存在する場合がありますが、マジック メソッドが不適切に使用されると、デシリアライゼーションの脆弱性が発生する可能性があります。

         原則 : ユーザーが入力したシリアライズされた文字列は検出されないため、攻撃者がデシリアライズ プロセスを制御できるようになり、 コードの実行、SQL インジェクション、ディレクトリ トラバーサルなどの制御不能な結果がもたらされます。逆シリアル化中に特定の魔法のメソッドが自動的にトリガーされます。逆シリアル化するとき、オブジェクトでいくつかの魔法のメソッドをトリガーすることができます。
        魔法の方法では、ポイント分析を利用します。
触发:unserialize 函数的变量可控,文件中存在可利用的类,类中有魔术方法:
__construct():     //构造函数,当对象 new 的时候会自动调用
__destruct():    //析构函数当对象被销毁时会被自动调用
__wakeup():     //unserialize()时会被自动调用
__invoke():     //当尝试以调用函数的方法调用一个对象时,会被自动调用
__call():     //在对象上下文中调用不可访问的方法时触发
__callStatci():     //在静态上下文中调用不可访问的方法时触发
__get():     //用于从不可访问的属性读取数据
__set():     //用于将数据写入不可访问的属性
__isset():     //在不可访问的属性上调用 isset()或 empty()触发
__unset():     //在不可访问的属性上使用 unset()时触发
__toString():     //把类当作字符串使用时触发
__sleep():     //serialize()函数会检查类中是否存在一个魔术方法__sleep(),如果存在,该方法会被优先调用

3. シリアライゼーションとデシリアライゼーションのデモンストレーション

<デモ1>

1. これは古典的なシリアライゼーションとデシリアライゼーションのコードです。

2. 最初に最後の 2 行をコメントアウトし、$s のみを出力させると、次のように内容が表示されます。

3. 以下、連載内容の説明です。

4. コードを次のスタイルに変更します。

5. 下図のように $u を出力します。

6. 完全な説明を下の図に示します。

        要約: これは典型的なデータ転送方法であり、コードの正確性と完全性をより確実にすることができます。

<デモ2>

1. コードをもう一度見てください。
        魔法の方法は通常、その前に2つのアンダースコアがあるかどうかを確認することです-「__」

2. まず、コードを次のスタイルに変更します。

 3. この時点で、次の返品結果にアクセスできます。

4. ここでは、オブジェクトを作成しただけで、次の 2 つの関数を呼び出して、対応するコンテンツを出力しています。

        概要: オブジェクトを作成すると、関数なしでマジック メソッドが呼び出されます。 

<デモ2>

1. コードをもう一度見てください。

 2. 実行結果を下図に示します。

3. コードを以下のスタイルに変更します。

 4. パラメータを使用して、上記のシリアル化されたコードをアップロードします。

 5. Web ページは次の結果を返します。 

6. コードでは作成していませんが、シリアル化されたコンテンツをアップロードしたため、この時点でデフォルトで呼び出されたため、それでも end が返されました。

7. コードを再度変更します。

8. この時点で再度実行すると、test() がトリガーされていることがわかります。

         概要: シリアル化された文字列を渡すことは、オブジェクト内の関数を呼び出すことを含め、デフォルトでオブジェクト内のデータを取得することと同じです。つまり、オブジェクトを作成しなくても、オブジェクト内の変数と関数をトリガーすることもできます。オブジェクト. トリガー プロセスは、マジック メソッド トリガー ロジックに基づいています。

4. 脆弱性のデモンストレーション

<デモ1>

1. 以下のコードを開きます。

2. オブジェクトを作成するには、最初に __construct が呼び出され、次にオブジェクトが破棄されるときに __destruct が呼び出されます。実行結果を下図に示します。

3. コードを変更して実行し、シリアル化された文字列を出力してコピーします。

4. コードを以下に示すスタイルに変更します。

5. シリアル化されたコードをパラメーターとしてアップロードすると、ipconfig の実行結果が引き続きページに返されることがわかります。この時点ではオブジェクトを作成せず、シリアル化された文字列を入力するだけであり、デフォルトで __destruct コードが呼び出されます。

<デモ2>

1. 以下のコードを開きます。

 2. このときアクセスすると、まず__constructが実行され、「xiaodisec」が表示された後、__destructが実行され、システムコマンドipconfigが実行されます。 

3. コードを変更してアクセスし、cc のシリアル化コードを取得します。

4. コードを次のスタイルに変更して、シリアル化されたコードを受け取ります c.

5. シリアライゼーション コード c をパラメーターとして送信します。このとき、__destruct は実行されますが、__construct は実行されません。これは、ここですべての「新しい」操作があるためです。

6. この時点で、パラメーター c の内容を変更して他のコマンドを実行することを考えることができます。以下で試​​してください。

7. パラメータの ipconfig を「var」に変更し、以前の長さを「3」に変更すると、次の戻り結果が得られ、「var」コマンドが正常に実行されました。

        これがシリアライゼーションの脆弱性の核心であり、上記で説明したことはすべて、このステップの準備です。

        要約: デシリアライズ操作では、オブジェクトに設定されているいくつかの変数も変更できます。ここでは、ipconfig を ver.2 に変更します。つまり、オブジェクトが作成されている限り、オブジェクト内のマジック メソッドが呼び出される場合や、オブジェクトが作成されていない場合でも、unserialize に似た関数が表示された場合は、入力パラメーターを制御してそれを作成することができます。コンテンツ内のオブジェクトを呼び出します。

        この種の脆弱性は一般的にホワイト ボックスに現れ、ブラック ボックスにあるものを見つけることはほとんど不可能です。なぜなら、デシリアライズの脆弱性があるかどうかを分析するには、ソース コードを見て、ソース コードのコード ロジックを分析する必要があるからです。 .

四、ctfshow射撃場の実際の練習

        射撃場アドレス:ctf.show

<正解その1>

1.該当するトピックを見つけて、撮影範囲に入ります。 

2.射撃場を開きます。

3.撮影範囲に入ります。

4. コードを分析した後、次の問題解決のアイデアが得られます。

  • 最初に vipOneKeyGetFlag をトリガーします。
  • 次に、$this->isVip を true にします。

5. コードの分析を続行します。

  • username='xxxxxx';password='xxxxxx' とします。 

 6. 操作を開始します。

http://eaece883-4d1b-411b-989d-b09aae68b5df.challenge.ctf.show/?username=xxxxxx&password=xxxxxx

7. フラグの取得に成功しました。

<正問2>

1.該当するトピックを見つけて、撮影範囲に入ります。 

 2.射撃場を開きます。

3.撮影範囲に入ります。

4. コードを分析した後、次の操作を考えることができます。

5. POP チェーンをコピーします。

O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D

6. Hack Firefox を開いて範囲リンクにアクセスします。

7. burp を使用してパケットをキャプチャします。

8. キャプチャしたデータ パケットをリピータに送信します。 

9. ソース コードによると、Cookie でユーザー データを受信し、ユーザー名とパスワードを検出することがわかるので、データ パケットに次の変更を加えます。

10. パッケージをリリースすると、フラグが正常に取得されていることがわかります。

<正問3>

1.該当するトピックを見つけて、撮影範囲に入ります。 

 2.射撃場を開きます。

 3.撮影範囲に入ります。

4. コードを分析した後、次の操作を考えることができます。

 5. POP チェーンをコピーします。

O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A1%3A%22x%22%3Bs%3A8%3A%22password%22%3Bs%3A1%3A%22y%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D

6. Hack Firefox を開いて範囲リンクにアクセスします。

7. burp を使用してパケットをキャプチャします。

 8. キャプチャしたデータ パケットをリピータに送信します。 

9. ソース コードによると、Cookie でユーザー データを受け取り、ユーザー名とパスワードを検出することがわかるので、次のようにデータ パケットを変更し、パケットを解放します。

10. フラグの取得に成功したことがわかります。

<正問4>

1.該当するトピックを見つけて、撮影範囲に入ります。 

 2.射撃場を開きます。

3.撮影範囲に入ります。

4. このレベルには複数のクラスがあることがわかります。そのため、最初にフラグを取得できる場所を確認する必要がありますが、フラグに直接関連する操作は見つかりませんでしたが、以下の関数 eval を確認しました。

        補足:eval()関数はphpのコード通りに文字列を実行できます。

5. ここでは eval が flag に関連する可能性しかないため、誰が eval をトリガーするかを判断します。

6. getInfo が eval をトリガーし、__destruct が getInfo をトリガーし、__destruct がトリガーされると class='info' となり、'info' を backDoor に変更した後に eval 関数を呼び出すことができることがわかります。

7. クラス コードをオンライン ツールにコピーし、不要なコードを削除し、修正してから実行します。 

O%3A11%3A%22ctfShouUser%22%3A1%3A%7Bs%3A18%3A%22%00ctfShouUser%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A17%3A%22system%28%22cat+f%2A%22%29%3B%22%3B%7D%7D

8. Hack Firefox を開いて範囲リンクにアクセスします。

9. burp を使用してパケットをキャプチャします。

 10. キャプチャしたデータ パケットをリピータに送信します。  

9. データ パッケージに次の変更を加え、パッケージをリリースしてフラグを取得します。

10.旗の獲得に成功。

おすすめ

転載: blog.csdn.net/weixin_62808713/article/details/129968856