ホームページ >バックエンド開発 >PHPチュートリアル >PHP の逆シリアル化オブジェクト インジェクションの脆弱性について

PHP の逆シリアル化オブジェクト インジェクションの脆弱性について

小云云
小云云オリジナル
2018-03-10 13:16:332796ブラウズ


PHP オブジェクト インジェクションは非常に一般的な脆弱性ですが、このタイプの脆弱性を悪用するのは多少困難ですが、それでも非常に危険です。この記事では主に、PHP の逆シリアル化オブジェクト インジェクションの脆弱性について詳しく説明します。お役に立てれば幸いです。

分析

phpの基本

serializeはオブジェクトを文字列形式に変換し、保存に使用できます
unserializeはシリアル化された文字列をオブジェクトに変換します

PHPクラスには、マジック関数、マジック関数名と呼ばれるいくつかの特別な関数が含まれる場合があります__construct、__destruct、__toString、__sleep、__wakeup などのシンボル __ で始まります。

これらの関数は、オブジェクトが作成されるときに

__construct が呼び出され、オブジェクトが破棄されるときに
__destruct が呼び出され、オブジェクトが文字列として使用されるときに
__toString が呼び出されるなど、特定の状況下で自動的に呼び出されます。

例:

    <?php    

    class TestClass    
    {    
        public $variable = &#39;This is a string&#39;;    

        public function PrintVariable()    
        {    
            echo $this->variable . &#39;<br />&#39;;    
        }     

        public function __construct()    
        {    
            echo &#39;__construct <br />&#39;;    
        }      

        public function __destruct()    
        {    
            echo &#39;__destruct <br />&#39;;    
        }    

        public function __toString()    
        {    
            return &#39;__toString<br />&#39;;    
        }    
    }    

    $object = new TestClass();        
    $object->PrintVariable();    
    echo $object;      

    ?>

PHP の逆シリアル化オブジェクト インジェクションの脆弱性について

phpを使用すると、後で再利用できるようにオブジェクトを保存できます。このプロセスはシリアル化と呼ばれます。

シリアル化メカニズムがあるのはなぜですか?

変数を渡すプロセスで、スクリプト ファイル間で変数値を渡すプロセスが発生する可能性があります。想像してみてください。スクリプト内で前のスクリプトの変数を呼び出したいが、前のスクリプトが実行されてすべての変数と内容が解放された場合、どのようにすれば前のスクリプトをループして待機する必要があるでしょうか。次のスクリプト呼び出しについてはどうですか? これは明らかに非現実的です。

serialize と unserialize は、この問題を解決するために使用されます。 Serialize は変数を文字列に変換し、変換中に現在の変数の値を保存します。Unserialize は Serialize によって生成された文字列を変数に変換し直します。これにより、クロススクリプトの送信と実行が完全に解決されます。

マジック関数 __construct と __destruct は、オブジェクトが作成または破棄されるときに自動的に呼び出されます。

__sleep マジック メソッドは、オブジェクトがシリアル化されるときに呼び出されます。
__wakeup マジック メソッドは、オブジェクトが逆シリアル化されるときに呼び出されます。

<?phpclass User    {    
    public $age = 0;    
    public $name = &#39;&#39;;  
    public function Printx()
    {
      echo $this->name.&#39; is &#39;.$this->age.&#39; years old.<br/>&#39;;
    }    public function __construct()    
    {    
        echo &#39;__construct<br />&#39;;    
    }    

    public function __destruct()    
    {    
        echo &#39;__destruct<br />&#39;;    
    }    

    public function __wakeup()    
    {    
        echo &#39;__wakeup<br />&#39;;    
    }    

    public function __sleep()    
    {    
        echo &#39;__sleep<br />&#39;;    

        return array(&#39;name&#39;, &#39;age&#39;);    
    }    
}$usr = new User(); 
$usr->age = 20;    
$usr->name = &#39;John&#39;;    
$usr->Printx();    
echo serialize($usr);echo &#39;<br/>&#39;;   

$str = &#39;O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John";}&#39;;  
$user2 = unserialize($str);$user2->Printx();?>

PHP の逆シリアル化オブジェクト インジェクションの脆弱性について

これでシリアル化がどのように機能するか理解できましたが、それをどのように利用すればよいでしょうか? アプリケーション、利用可能なクラス、およびマジック関数に応じて、複数の方法が考えられます。


シリアル化されたオブジェクトには、攻撃者が制御するオブジェクト値が含まれていることを覚えておいてください。

Web アプリケーションのソース コードで __wakeup または __destruct を定義するクラスが見つかる場合があります。これらの関数は Web アプリケーションに影響します。


たとえば、ログをファイルに一時的に保存するクラスが見つかるかもしれません。オブジェクトが破棄されると、ログ ファイルは不要になり、削除される可能性があります。次のコードを log.php として保存します。

<?php     //log.php     class LogFile    {    
    // log文件名    

    public $filename = &#39;error.log&#39;;    

    // 储存日志文件    

    public function LogData($text)    
    {    
        echo &#39;Log some data: &#39; . $text . &#39;<br />&#39;;    
        file_put_contents($this->filename, $text, FILE_APPEND);    
    }    

    // 删除日志文件    

    public function __destruct()    
    {    
        echo &#39;__destruct deletes "&#39; . $this->filename . &#39;" file. <br />&#39;;    
        unlink(dirname(__FILE__) . &#39;/&#39; . $this->filename);    
    }    
}    

?>

test.php これがユーザーの php であると仮定します。

    <?php    
    //test.php     
    include &#39;logfile.php&#39;;    

    // ... 一些使用LogFile类的代码...    

    // 简单的类定义    

    class User    
    {    
        // 类数据    

        public $age = 0;    
        public $name = &#39;&#39;;    

        // 输出数据    

        public function PrintData()    
        {    
            echo &#39;User &#39; . $this->name . &#39; is &#39; . $this->age . &#39; years old. <br />&#39;;    
        }    
    }    

    // 重建用户输入的数据    

    $usr = unserialize($_GET[&#39;usr_serialized&#39;]);    

    ?>

123.php

<?php    
    //123.php  
    include &#39;logfile.php&#39;;    

    $obj = new LogFile();    
    $obj->filename = &#39;1.php&#39;;    

    echo serialize($obj) . &#39;<br />&#39;;    

    ?>

1.php から始めます:


PHP の逆シリアル化オブジェクト インジェクションの脆弱性について ここで、ユーザーがシリアル化された文字列を渡し、test.php がそれを逆シリアル化します。 usr_serialized=

O:7:%22LogFile%22:1:{s:8:%22filename%22;s:5:%221.php%22;}

結果はリリースプロセス中に解析されますオブジェクトに対して、log.php の __destruct() 関数が呼び出され、ファイル 1.php が削除されました。


PHP の逆シリアル化オブジェクト インジェクションの脆弱性について使用法の概要

変数が制御可能であり、シリアル化されていない操作が実行される場所にシリアル化されたオブジェクトを挿入して、コードの実行やその他の不正な動作を実現します。 PHP の逆シリアル化オブジェクト インジェクションの脆弱性について

__wakeup と __destruct はさておき、このタイプの脆弱性を悪用できる非常に一般的なインジェクション ポイントがいくつかあり、すべてはプログラム ロジックに依存します。

たとえば、ユーザー クラスは __toString を定義して、アプリケーションがクラスを文字列 (echo $obj) として出力できるようにします。また、他のクラスも、__toString が特定のファイルを読み取ることができるようにクラスを定義する場合があります。

他のマジック関数も使用できます:

オブジェクトが存在しない関数を呼び出す場合は __call が呼び出されます。
オブジェクトが存在しないクラス変数にアクセスしようとする場合は __get と __set が呼び出されます。

しかし、この脆弱性の悪用はマジック関数に限定されるものではなく、同じ考え方は通常の関数にも適用できます。

たとえば、User クラスは一部のユーザー データを検索して出力する get メソッドを定義できますが、他のクラスはデータベースからデータを取得する get メソッドを定義する可能性があり、これが SQL インジェクションの脆弱性を引き起こす可能性があります。

set メソッドまたは write メソッドは、リモート コード実行を取得するために使用できる任意のファイルにデータを書き込みます。

唯一の技術的な問題は、注入ポイントで使用できるクラスですが、一部のフレームワークまたはスクリプトには自動読み込み機能があります。最大の問題は人です。コードを読んで理解するには時間がかかるため、この種の脆弱性を悪用できるアプリケーションを理解する必要があります。

関連するおすすめ:

PHPのシリアル化と逆シリアル化の原理の詳細な説明

シリアル化と逆シリアル化の詳細な紹介

jsonのシリアル化と逆シリアル化関数のJavaScript実装の例

以上がPHP の逆シリアル化オブジェクト インジェクションの脆弱性についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。