広く使用されているサーバー側のプログラミング言語として、PHPはWeb開発において重要な位置を占めています。ますます多くのPHPアプリケーションがインターネットにさらされるにつれて、セキュリティの問題は徐々に開発者の焦点になりつつあります。 PHPでは、 Serialize()およびunserialize()関数は、オブジェクトと配列のシリアル化と脱滑りを処理するために広く使用されています。ただし、これらの機能は、攻撃者が「オブジェクトインジェクション攻撃」を行う潜在的な脆弱性になる可能性があります。防止されない場合、攻撃者は慎重に構築された悪意のあるデータを介してアプリケーションの動作を変更し、リモートコード実行(RCE)などの深刻なセキュリティ問題にさえつながる可能性があります。
この記事では、PHPのSerialize()およびUnserialize()関数のセキュリティ問題を分析し、オブジェクト注入攻撃を防ぐための効果的な手段を提供します。
serialize()およびunserialize()は、オブジェクトと配列のシリアル化と降下のためのPHPの2つの重要な機能です。
Serialize() :PHP変数(オブジェクト、配列などを含む)を保存または転送できる文字列に変換します。たとえば、オブジェクトまたは配列を文字列に変換してデータベースに保存できます。
Unserialize() :シリアル化された文字列をPHPの元のデータ型(オブジェクトや配列など)に再構成することです。
$data = ['name' => 'John', 'age' => 30];
$serializedData = serialize($data);
echo $serializedData; // 出力:a:2:{s:4:"name";s:4:"John";s:3:"age";i:30;}
上記のコードは、配列$データを文字列にシリアル化します。データベースに保存すると、後でunserialize()を介して元の配列に復元できます。
オブジェクトインジェクション攻撃とは、攻撃者が特別なシリアル化データを構築することを指し、PHP Unserialize()関数が悪意のあるコードを実行するか、データを脱却するときにアプリケーションの動作を変更します。このタイプの攻撃は通常、PHPアプリケーションが入力データを完全に検証しない場合に発生します。
たとえば、攻撃者が次の悪意のあるデータを構築するとします。
$maliciousData = 'O:8:"UserClass":1:{s:4:"name";s:4:"evil";}';
unserialize($maliciousData);
その中で、 UserClassはアプリケーションのクラスです。攻撃者は、シリアル化されたデータを介して悪意のあるオブジェクトを作成し、検証なしでunserialize()関数に渡し、それによりオブジェクトのコンストラクターをトリガーし、セキュリティの脆弱性につながる可能性があります。
オブジェクト注入攻撃を防ぐために、開発者は次の効果的な測定値をとることができます。
脱必要なプロセス中、データにクラス名が含まれている場合、 Unserialize()関数はクラスをロードしようとします。適切なセキュリティ対策なしにクラスがアプリケーションに存在する場合、悪意のあるオブジェクトを作成および実行することができます。したがって、脱介入中にロードされることが許可されているクラスは、 unserialize()のapproad_classesパラメーターによって制限される可能性があります。
$data = 'O:8:"UserClass":1:{s:4:"name";s:4:"evil";}';
$unserializedData = unserialize($data, ['allowed_classes' => ['UserClass']]);
クラス名が明示的にリストされていない場合、PHPは不明なクラス名を含むデータの降伏を許可しません。
入ってくるシリアル化されたデータを厳密に検証およびフィルタリングして、悪いコンテンツが含まれていないことを確認します。データを受け入れる前に、正規表現またはその他の方法を使用して、シリアル化された文字列の構造が合法かどうかを確認できます。
if (preg_match('/^[O|a|s|i|d|b|f|N|r|C|l|n]/', $inputData)) {
$unserializedData = unserialize($inputData);
} else {
die('Invalid serialized data');
}
特別な要件がない場合は、 serialize()とunserialize()の代わりにjson_encode()とjson_decode()を使用することをお勧めします。 JSON_ENCODE()およびJSON_DECODE()は、シンプルなデータ型(配列、オブジェクト、文字列、数字など)のみを扱うことができ、複雑なクラスやオブジェクトを含むことができないため、オブジェクトインジェクション攻撃に簡単に悪用されません。
$data = json_encode($dataArray);
$decodedData = json_decode($data, true);
PHP.ini構成ファイルでは、特定の機能を無効にして、これらの機能の開発者の偶発的な使用を避けることにより、セキュリティを強化できます。攻撃者がUnserialize()を介してセキュリティの脆弱性を引き起こすのを防ぐために、 Unserialize()関数を無効にするか、それを信頼できる範囲に制限することができます。
disable_functions = "unserialize"
PHPコミュニティは、潜在的なセキュリティの脆弱性を修正するために、更新とセキュリティパッチを定期的にリリースします。開発者は常にPHPの最新バージョンを使用し、セキュリティを確保するためにタイムリーにシステムを更新する必要があります。
Serialize()およびUnserialize()関数を直接保護することに加えて、開発者は機密データの全体的なセキュリティ管理を強化する必要もあります。セキュリティベストプラクティスは次のとおりです。
暗号化された機密データ:AS暗号化などの強力な暗号化アルゴリズムを使用して暗号化された機密データが保存または送信された場合、攻撃者がデータを取得しても、簡単にクラックできないことを確認します。
入力検証:すべてのユーザー入力、特にURL、フォーム、またはAPIを介して受信したデータを厳密に検証します。既存のライブラリを使用して、SQL注入、XSS、CSRFなどの一般的な攻撃を防ぐことができます。
オブジェクトの露出を最小限に抑える:敏感なオブジェクトや複雑なオブジェクトがクライアントに直接露出しないようにしてください。シリアル化する必要があるデータには、必要な情報のみが含まれている必要があります。
PHPのSerialize()およびUnserialize()関数は、開発者に便利なデータストレージと伝送メカニズムを提供しますが、制限なしでそれらを使用すると、深刻なセキュリティリスクが発生します。合理的な構成、入力検証、代替の使用、PHPバージョンのタイムリーな更新により、オブジェクトインジェクション攻撃を効果的に防ぐことができます。
最も重要なことは、ユーザー入力を決して信用しないでください!合理的なセキュリティ戦略と保護対策は、アプリケーションのセキュリティを効果的に改善し、潜在的なリスクを減らすことができます。