ホームページ > バックエンド開発 > PHPチュートリアル > XSS インジェクションは怖くない - フレームワーク レベルから XSS をシールドする PHP の思考と実践

XSS インジェクションは怖くない - フレームワーク レベルから XSS をシールドする PHP の思考と実践

WBOY
リリース: 2016-06-23 13:07:21
オリジナル
1154 人が閲覧しました

この記事は Tencent WeTest チームによって提供されており、詳細については、リンクを直接クリックして表示できます: http://wetest.qq.com/lab/WeChat ID: TencentWeTest

次の学生向け。 Web開発の初心者、XSSインジェクション それは非常に面倒なことです。長年 Web 開発に携わってきたベテランであっても、自分が作成したコードに XSS インジェクションのリスクが完全にないことを保証することはできません。

現在主流の XSS 防止方法は 2 つあり、1 つはユーザー入力時に異常なキーワードをフィルタリングする方法、もう 1 つはページのレンダリング時に HTML コンテンツを実体化してエスケープする方法です。

ただし、最初の方法はビジネスデータに対する要件がある程度高く、「プログラムのヘルプドキュメントの編集と保存」、「外部サイトの投稿クローラー」など、シールドされたデータとビジネスデータの間に競合が発生する可能性があります。 。異常なキーワードを無差別に除外することはできず、元の入力コンテンツの整合性を維持する必要があります。

HTML コンテンツを具体化するもう 1 つの方法は、開発プログラミングの習慣に大きく依存します。うっかり見逃してしまった場合、それは安全作業命令となるため、Web で働くフロントエンドの同僚はこのことを深く理解している必要があります。そこで私は、開発習慣に頼ることができなくなり、XSS をフレームワーク レベルから完全に保護できないかどうかを検討し始めました。

ここで最初に私の PHP Web サーバー フレームワークを紹介します。これは私が Web 開発に取り組み始めてから維持し、更新してきたフレームワークです。興味のある学生はここを参照してください。または、さらなる改善を提案してください。

まず、通常の PHP が HTML エンティティをエスケープする方法を見てみましょう:

htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE)ENT_QUOTES は二重引用符 (") と一重引用符 (') をエスケープする必要があることを意味します

ENT_SUBSTITUTE は置換を意味します無効なエンコーディングを指定された Unicode 置換文字で置き換えます

最初に考えやすいのは、PHP テンプレート内のすべての文字列を置き換えることです

smarty に詳しい学生は、smarty テンプレートのレンダリングも使用されることを知っているはずです。文字列をエスケープするため、ページをレンダリングするコードは次のように記述できます

/*** テンプレートのレンダリングされたコンテンツを取得します* @return string*/public function getContent(){//Prevent XSS インジェクション foreach ([数学処理エラー]

param) { [数学処理エラー]param) ? htmlspecialchars( [数学処理エラー]param;}unset($param);
    extract($this->params);    ob_start();    //include template    $file = sprintf('%s/template/%s.tpl.php', TXApp::$app_root, $this->view);    include $file;    $content = ob_get_clean();    return $content;}
ログイン後にコピー

この場合、渡されたすべての文字列型変数が置き換えられます。しかし、問題も明らかです。 、配列またはオブジェクトの場合、コンテンツはエスケープできません。これは Smarty の欠点でもありますが、配列またはオブジェクトの場合は無視されます。さらにエスケープします。

これを見た学生は間違いなく、エスケープ処理を行うだけで十分ではないでしょうか

実際、最初は私もそうでした。これも可能ですが、再帰の層が増えるほどパフォーマンスの低下が大きくなり、必要なときにエスケープを実行するとパフォーマンスが無駄になります。

そこで私は自分でクラスを書き始め、それに TXArray という名前を付け、配列のいくつかのプロパティを持ちました。以下はコードの一部です

class TXArray extends ArrayObject{private [Math Processing Error]

encodes = [];
public function __construct($storage=array()){    $this->storage = $storage;}public function getIterator(){    foreach ($this->storage as $key => $value){        $key = $this->encode($key);        if (!isset($this->encodes[$key])){            $this->encodes[$key] = $this->encode($value);        }    }    return new ArrayIterator($this->encodes);}public function offsetGet($k){    if (isset($this->storage[$k])){        $key = $this->encode($k);        if (!isset($this->encodes[$key])){            $this->encodes[$key] = $this->encode($this->storage[$k]);        }        return $this->encodes[$key];    }    return null;}public function offsetExists($k){    return isset($this->storage[$k]);}public function offsetUnset($k){            unset($this->storage[$k]);    $k = $this->encode($k);    unset($this->encodes[$k]);}public function offsetSet($k, $value){    $this->storage[$k] = $value;    $this->encodes[$k] = $this->encode($value);}public function count(){    return count($this->storage);}private function encode($value){    if (is_string($value)){        $value = is_string($value) ? htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE) : $value    } elseif (is_array($value)){        $value = new self($value);    }    return $value;}
ログイン後にコピー

}offsetGet will be in [Math Processing Error ]

key] が呼び出されます。 getIterator() メソッドは、foreach ループ中に呼び出されます。内部パラメータが配列であることが判明すると、再度再帰的に自身を呼び出し、上記の手順を繰り返します。効果は以下の図に示すとおりです。

このような再帰的エスケープ モデルが作成されました。使用すると脱出するという目的も達成されます。

しかし、まだ問題があります。すべてのフィールドをエスケープする必要はありません。たとえば、当社のプラットフォームの世論監視データは主に主要な Tieba フォーラムから取得されており、データ自体には画像画像やフォントの色などの HTML 要素が含まれています。表示時にテンプレートをエスケープする必要はありません。そこで私はフレームワークの最適化を続けました。 PHP マジックメソッド __get() を追加しました

public function __get($k){    return isset($this->storage[$k]) ? $this->storage[$k] : null;}public function get($key){    return $this->__get($key);}
ログイン後にコピー

つまり、[数学処理エラー]

array->get(0) を呼び出すだけで、エスケープせずに元のデータを直接取得できます。

さらに、ビジネスによっては、array_key_exists、in_array、join などのいくつかの配列処理メソッドを追加する必要もあります。または、__call() マジック メソッドを直接使用します

public function __call($method, $args){    $args[] = &$this->storage;    return call_user_func_array($method, $args);}public function serialize(){    return serialize($this->storage);}public function __invoke(){    return $this->storage ? true : false;}public function keys(){    return array_keys($this->values(false));}
ログイン後にコピー

そうすれば、ページ テンプレートで問題なく使用できます

しかし、この TXArray にはまだ問題があります。つまり、json に変換して js に送信する必要があるかどうかです。 use、ここでデータはエスケープできません。もちろん、再帰的にすべてをエスケープすることもできますが、コードが十分美しくないようにいつも感じます。この問題については引き続き研究していきます。新しい進捗状況と最適化を私の PHP オープン ソース コンポーネント フレームワークにアップロードします。何か良い提案があれば、RTX して私と話し合ってください。

この記事は Tencent WeTest チームによって提供されています。詳細については、直接ご覧ください。リンクをクリックして表示: http://wetest.qq.com/lab/WeChat ID: TencentWeTest

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート