PHPの逆シーケンス化を読み取る

13820 ワード

主な目的
この机会を借りてシステムの学习の反シーケンス化の抜け穴を借りて、PHPのいくつかの文の具体的な使い方と
問題の原因:
脆弱性の根源はunserialize()関数のパラメータ制御にある.逆シーケンス化オブジェクトにマジックメソッドが存在し、マジックメソッドのコードまたは変数ユーザーが制御可能である場合、逆シーケンス化の脆弱性が発生する可能性があります.逆シーケンス化後のコードによって、コード注入、SQL注入、ディレクトリ遍歴など、さまざまな攻撃を引き起こす可能性があります.マジックメソッド:PHPのクラスにはマジック関数という特殊な関数が含まれている可能性があります.マジック関数の名前は記号__です.冒頭の;以下のマジック方法があります:_construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set(), _state(), __clone(), __debugInfo()
__sleepと_wakeup
シーケンス化serializeは、変数にオブジェクトを含む、連続bytesデータに変換することができる.シーケンス化された変数をファイルに保存したり、ネットワーク上で転送したりすることができます.その後、逆シーケンス化して元のデータに復元する.クラスのオブジェクトを逆シーケンス化する前に定義したクラスで、PHPはそのオブジェクトの属性と方法を正常に格納することができます.逆シーケンス化後すぐにオブジェクトを実行する必要がある場合があります.このような目的のためにPHPは自動的に探します_sleepと_wakeupメソッド
オブジェクトがシーケンス化されると、PHPは__を呼び出します.sleepメソッド(存在する場合).シーケンスがオブジェクトを1つ行化すると、PHPは__を呼び出します.wakeupメソッドどちらの方法もパラメータを受け入れません.sleepメソッドは、シーケンス化が必要な属性を含む配列を返さなければならない.PHPは他の属性の値を捨てる.もしなかったらsleepメソッドでは、PHPはすべての属性を保存します.
プログラムが実行される前に、serialize()関数はまずマジックメソッドが存在するかどうかをチェックします.sleep.存在する場合sleep()メソッドは、シリアル化(シーケンス化)操作を実行する前に呼び出されます.この機能は、オブジェクトをクリーンアップし、オブジェクト内のすべての変数名を含む配列を返すために使用できます.メソッドが何も返さない場合、NULLがシーケンス化され、E_NOTICEエラーが発生します.逆にunserialize()は、1つの__が存在するかどうかを確認します.wakeupメソッド.存在する場合は、先に__が呼び出されます.wakeupメソッドは、オブジェクトデータを予め準備します.
__sleep()メソッドは、コミットされていないデータをコミットしたり、類似のクリーンアップ操作を実行したりするためによく使用されます.また、いくつかの大きなオブジェクトがあるが、すべて保存する必要がなければ、この機能は使いやすい.これに対してunserialize()は1つの__が存在するかどうかをチェックします.wakeup()メソッド.存在する場合は、先に__が呼び出されます.wakeupメソッドは、オブジェクトに必要なリソースを事前に準備します._wakeup()は、データベース接続の再確立や他の初期化操作の実行など、逆シーケンス化操作でよく使用されます.
server = $server;
        $this->username = $username;
        $this->password = $password;
        $this->db = $db;
        $this->connect();
    }
    
    private function connect()
    {
        $this->link = mysql_connect($this->server, $this->username, $this->password);
        mysql_select_db($this->db, $this->link);
    }
    
    public function __sleep()
    {
        return array('server', 'username', 'password', 'db');
    }
    
    public function __wakeup()
    {
        $this->connect();
    }
}
?>


次の例では、__の使い方を示します.sleepと_wakeupメソッドはオブジェクトをシーケンス化する.Idプロパティは、オブジェクトに保持する予定のない一時プロパティです.sleep法は、シリアル化するオブジェクトにid属性が含まれないことを保証する.Userオブジェクトを逆シリアル化すると、_wakeupメソッドはid属性の新しい値を確立する.この例は自己保持に設計する.実際の開発では、画像やデータストリームなどのリソースを含むオブジェクトにこれらの方法が必要であることがわかります.
id = uniqid();
        }
         
    function __sleep() {       //      id  
        return(array('name'));
        }
         
    function __wakeup() {
        $this->id = uniqid();
        }
    }
$u = new user();
$u->name = "Leo";
$s = serialize($u); //serialize     u,      id  ,id    
$u2 = unserialize($s); //unserialize    ,id      
//  u u2    id  
print_r($u);
print_r($u2);
 
?>
user Object
(
   [name] => Leo
   [id] => 5d0d9c66b9a03
)
user Object
(
   [name] => Leo
   [id] => 5d0d9c66b9a45
)
name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
        $this->info = sprintf("prepared by construct magic functionname: %s age: %d sex: %s",
            $this->name, $this->age, $this->sex);
    }

    public function getInfo()
    {
        echo $this->info . PHP_EOL;
    }
    /**
     * serialize                     
     * @return array [description]
     */
    public function __sleep()
    {
        echo __METHOD__ . PHP_EOL;
        //         name age sex, info       
        return ['name', 'age', 'sex'];
    }
    /**
     * unserialize              
     */
    public function __wakeup()
    {
        echo __METHOD__ . PHP_EOL;
        $this->info = sprintf("prepared by wakeup magic function name: %s age: %d sex: %s",
            $this->name, $this->age, $this->sex);
    }
}

$boy = new Person( 'sallency', 25, 'male' );
//        $info
$boy->getInfo();
echo "
"; // $info $temp = serialize($boy); echo $temp . PHP_EOL; echo "
"; // __wakeup() $boy = unserialize($temp); //__wakeup() $info $boy->getInfo(); echo "
"; ?>
prepared by construct magic functionname: sallency age: 25 sex: male

Person::__sleep O:6:"Person":3:{s:12:"Personname";s:8:"sallency";s:11:"Personage";i:25;s:11:"Personsex";s:4:"male";}
Person::__wakeup prepared by wakeup magic function name: sallency age: 25 sex: male

まずコードを書きます
class myClass{
    public $myContent;
    function outMycontent(){
        //dosomething
    }
}
$content = new myClass();
echo serialize($content);

出力された結果はO:7:myClass":1:{s:9:"myContent";N;}
クラスをシーケンス化しました.つまり、クラスを文字列に変換して、転送したり保存したりすることができます.
上のコードを修正します
class myClass{
    public $myContent;
    function __construct($string){
        $this->myContent = $string;
    }
}
$content = new myClass('my china');
echo serialize($content);

出力された結果はO:7:“myClass”:1:{s:9:“myContent”;s:8:“my china”;
シーケンス化後も対応する値に対応していますが、今問題があります.例えば、私の変数は秘密ですか?そして私はまたこのクラスを他の場所にシーケンス化しなければなりませんか?次のコードを見て
class myClass{
    public $myContent;
    function __construct($string){
        $this->myContent = $string;
    }
}
$content = new myClass('     ,      ');
echo serialize($content);

出力の結果はO:7:“myClass”:1:{s:9:“myContent”;s:36:“私は宋祖英を爱して、これは秘密です”;
私の秘密はシーケンス化されてからまだ存在していますが、私の心の中の話は他の人に見られたくありません.この時PHPはとても親切で、彼女はあなたの問題を知っているので、マジックの方法を設定しました.
__sleep()は、serialize()というシーケンス化関数を実行する前のことを表し、コールバック関数のようなものなので、このコールバック関数の中で私たちは何かをして、私の秘密を隠すことができます.
class myClass{
    public $myContent;
    function __construct($string){
        $this->myContent = $string;
    }
    public function __sleep(){
        $this->myContent = '      ';
        return array('myContent');

    }
}
$content = new myClass('     ,      ');
echo serialize($content);

出力された結果は、O:7:myClass":1:{s:9:"myContent";s:18:「これは私の秘密です」;
私の本音は暗号化されています.これは__です.sleep()の役割.に至ってはwakeup()と_sleep()は大同小異であり,逆シーケンス化以前に行われたコールバック関数にすぎない.詳しくは言いませんが、次のコードを見てください.
class myClass{
    public $myContent;
    function __construct($string){
        $this->myContent = $string;
    }
    public function __sleep(){
        $this->myContent = '      ';
        return array('myContent');

    }
    public function __wakeup(){
        $this->myContent = '        ';
        //            ,           ,              
    }
}
$content = new myClass('     ,      ');
print_r(unserialize(serialize($content)));

出力内容は、myClass Object([myContent]=>私の秘密が戻ってきました)
__toString
__toString()メソッドは、クラスが文字列として扱われる場合の処理方法を定義します.
__TOStringは、オブジェクトリファレンスを直接出力するときに自動的に呼び出されます.前述したオブジェクトリファレンスはポインタです.例えば、「pは参照であり、echoを使用して$pを直接出力することはできません.これにより出力されます」Catchable fatal error:Object of class Person could not be converted to string「このようなエラーは、クラスで「_toString()」メソッドを定義した場合、オブジェクト参照を直接出力する際にエラーは発生せず、自動的に呼び出されます」_toString()メソッドは、"_toString()メソッドで返す文字を出力するので、"_toString()メソッドには必ず戻り値(return文)がある.
name = $name; 
    } 
    function say(){ 

        echo "Hello,".$this->name."!
"; } function __tostring(){// __toString return "Hello,".$this->name."!
"; } } $WBlog = new Person('WBlog'); echo $WBlog;// __toString() $WBlog->say();// ?>

プログラム出力:Hello,Wblog!Hello,WBlog! 「_tostring()」メソッドを定義しないとどうなりますか?例えば、上のコードを元に「_tostring()」メソッドをブロックし、プログラム出力結果:Catchable fatal error:Object of class Person could not be converted to stringを見てみると、クラスに「_tostring()」メソッドが定義されていなければ、そのまま象の参照を出力すると誤算エラーが発生し、また_tostring()メソッドボディには、戻り値が必要です.
__invoke
関数を呼び出すようにオブジェクトを呼び出そうとすると、_invoke()メソッドが自動的に呼び出されます.(本特性はPHP 5.3.0以上でのみ有効です.)
 

そうすると、直接オブジェクト名で関数として使用され、呼び出されたのは_invokeの方法;しゅつりょくしけん
__construct構築方法_destruct析出方法
__construct()このメソッドは、新しいオブジェクトを作成するたびに呼び出されます.destruct()を使用すると、クラスを破棄する前にプロファイルメソッドを実行できます.
';
        var_dump(self::$link);
        mysql_close(self::$link);
        var_dump(self::$link);
    }
 
}
 
$mysql = new Example('localhost', 'root', 'root', 'test');

結果:
resource(2) of type (mysql link)
resource(2) of type (Unknown)

__set __get
__get()メソッド:このメソッドは、プライベートメンバーのプロパティ値を取得するために使用されます.パラメータがあり、取得するメンバーのプロパティの名前を入力し、取得したプロパティ値を返します.メンバー属性がプライベートにカプセル化されていない場合、オブジェクト自体はこのメソッドを自動的に呼び出すことはありません.set()メソッド:このメソッドは、プライベートメンバーのプロパティに値を設定するために使用されます.2つのパラメータがあります.最初のパラメータは、値を設定するプロパティ名であり、2番目のパラメータは、プロパティに設定する値であり、戻り値はありません.(key=>value) __set()メソッドは、プライベート属性値を設定するために使用されます.
function __set($property_name, $value)
{ 
    $this->$property_name = $value; 
}

クラスで使用しました_set()メソッドを使用すると、$p 1->name=「張三」が使用されます.このようにオブジェクトのプライベート属性の値を設定すると、自動的に__が呼び出されます.set()メソッドを使用して、プライベート属性の値を設定します.
__get() __get()メソッドは、プライベート属性値を取得するために使用されます.
function __set($property_name, $value)
{ 
    return isset($this->$property_name) ? $this->$property_name : null;
}

例:
";
        $this->$property_name = $value; 
    }
    //__get()          
    function __get($property_name) {  
        echo "             ,        __get()   
"; return isset($this->$property_name) ? $this->$property_name : null; } } $p1=new Person(); // , __set() $p1->name = " "; // , __get() , echo " :".$p1->name; ?>

この例を実行して、出力:
             ,        __set()          
             ,        __get()   

     :  

__isset() __unset()
__isset() __isset()メソッドは、プライベート属性値が設定されているかどうかを検出するために使用されます.
オブジェクト内のメンバーが共有されている場合はisset()関数を直接使用できます.プライベートメンバー属性の場合は、クラスに__を追加する必要があります.isset()メソッド:
private function __isset($property_name)
{
    return isset($this->$property_name);
}

これによりクラス外部でisset()関数を用いてオブジェクト内のプライベートメンバーが設定されているか否かを測定すると自動的に__が呼び出される.isset()メソッドで検出します.
__unset() __unset()メソッドは、プライベート属性を削除するために使用されます.
isset()関数と同様にunset()関数はオブジェクトの共通メンバー属性のみを削除し、オブジェクト内部のプライベートメンバー属性を削除する場合は__を使用します.unset()メソッド:
private function __unset($property_name)
{
    unset($this->$property_name);
}

### __call __callStatic  

1.__call()メソッド.クラスに宣言されていないメソッドを呼び出すと、__を呼び出すことができます.call()メソッドは、メソッドを宣言する代わりに使用されます.メソッド名と配列をパラメータとして受け入れます.
コードの例:
';  
    echo '       
'; echo print_r($arg),'
'; } $list=new test(); $list->say(1,2,3); ?>

実行結果:私が存在しないメソッドsayメソッドを呼び出したい場合は、パラメータArray([0]=>1[1]=>2[2]=>3)も渡されます.
2.__callStatic()メソッド.PHP 5から.3このメソッドは、クラスに存在しないメソッドを呼び出すために静的メソッドを作成するときに使用されます.と_call()メソッドは同じで、メソッド名と配列をパラメータとして受け入れます.コードの例:
';  
    echo '       
'; echo print_r($arg),'
'; } } test::cry(' ',' ',' '); ?>

実行結果:私が存在しないcry静的メソッドを呼び出したい場合は、パラメータArray([0]=>痛泣[1]=>鬼泣[2]=>号泣)も伝えられます.
参照先:https://www.cnblogs.com/uduemc/p/4122156.html https://blog.csdn.net/guiyecheng/article/details/60590646 https://blog.csdn.net/wong_gilbert/article/details/76679108 http://www.5idev.com/p-php_member_overloading.shtml https://blog.csdn.net/sunyinggang/article/details/78906048