今日は、フレームワークでこれらのセキュリティ問題をオーバーライドする方法について説明します。
1 つ目は SQL インジェクションです。PDO を使用している場合は、まだ mysql_* などの API を使用している場合は、フレームワークで bindingParameter を実装するか、事前に文字変更を行うことができると思います。データベースに文字列エスケープを挿入します。
2 日前に最後の記事を書き終えた後、Vian はメッセージを残して、SQL インジェクションの解決策は DB に挿入する前に ''.addslashes($id).'' を実行することであると述べました。 、これは、最初に addslashes 操作を実行してから、それを一重引用符で強制的に囲むことを意味します。これにより、アウトアンドアウト文字列になるため、挿入できなくなります。この方法は良いと思います。 !
SQL インジェクションはモデルに接続する必要があるため、XSS はビューに接続する必要があります。この 2 つの部分についてはまだ話が始まっていないので、フレームワークで解決する方法については後ほど説明します。もちろん、後で忘れた場合は、思い出させてもらうこともできます。
前回 CSRF について話しましたが、解決策を提供しませんでした。今日はこの解決策を提供します。実際、解決策は非常に簡単です。乱数を生成し、渡された数値が正しい数値と一致するかどうかをバックエンドが判断します。一致しない場合、対応するコードは実行されません。トークンと呼ばれます。
簡単にするために、トークンの生成とトークンの取得の関数をコントローラー (Controller.php) に記述します。
1 つ目は、乱数を生成することです。最も簡単な方法は、mt_rand() を使用して整数を直接生成することですが、ここでは、CSRF を解決するために initphp フレームワークで見た方法を使用します。アイデアについては initphp の作者に:
initphp のコードは次のとおりです:
1 | private function set_token() { |
2 | if (!$_COOKIE['init_token']) { |
プライベート関数 set_token() {
3 | $str = substr(md5(time(). $this->get_useragent()), 5, 8); |
4 | setcookie("init_token", $str, NULL, '/'); |
2
5 | $_COOKIE['init_token'] = $str; |
6 | } |
7 | } |
簡単にするために、ここでは userAgent を使用しません。initphp は現在のタイムスタンプと userAgent を文字列に連結し、それを md5 で暗号化し、5 桁目から 8 桁目を取り出します。現在時刻 スタンプに対して md5 暗号化を実行し、0 番目の位置から開始して取得された文字列の長さをランダムに生成します:
1 | $token = substr(md5(time()),0,mt_rand(10,15)); |
$token = substr(md5(time()),0,mt_rand(10,15));
乱数が大きすぎたり小さすぎたりしないように、mt_rand の値の範囲を 10 ~ 15 に設定しました。つまり、生成されるトークンの数は 10 ~ 15 桁になります。
1 | private function _setToken() { |
2 | if(empty($_COOKIE['_csrfToken'])) { |
3 | $token = substr(md5(time()),0,mt_rand(10,15)); |
1
4 | $this->_token = $token; |
5 | setcookie('_csrfToken',$token,time() + 3600 * 24 * 7); |
6 | } else { |
7 | $this->_token = $_COOKIE['_csrfToken']; |
8 | } |
9 | } |
トークンの生成処理はフレームワークによって自動的に完了するため、ユーザーがこの処理を見る必要はありません。そのため、この関数をプライベートにして、Controller クラスのコンストラクター内で呼び出します。
トークンを生成したばかりですが、トークンを取得するにはどうすればよいでしょうか? 実際、トークンを取得する方法は非常に簡単で、単純なゲッターです:
1 | protected function _getToken() { |
2 | return $this->_token; |
保護された関数 _getToken() {
3 | } |
2
}
テーブル>
3
01 |
02 | class IndexController extends Controller { |
03 | public function test() { |
04 | $token = empty($_GET['token']) ? '' : $_GET['token']; |
05 | if($token === $this->_getToken()) { |
06 | //判定为正常 |
07 | } else { |
08 | $this->_redirect(array( |
09 | //跳转到某一个控制器的某一个Action |
10 | )); |
11 | } |
12 | } |
13 | } |
URL のトークン値がどのように設定され、渡されるのか疑問に思う人もいるかもしれません。
前のページが Index コントローラーの test2 アクションであると仮定すると、まず test2 アクションで $this->_getToken を使用してトークン値を取得し、次に渡すことができます。データをビューに送信し、ビューで使用した後、ユーザーはリンクをクリックしてトークン値を転送できます。
ここで質問したいと思います。ユーザーがページ A にアクセスしたときにトークンを取得したとします。ユーザーは 3 秒後にトークンを含むリンクをクリックしてページ B にアクセスします。 Page B は COOKIE 内のトークンが期限切れになっているため、新しいトークンを生成し、渡されたトークンと比較すると当然一致せず、ジャンプしてしまいます。これは問題ではありません。 ?
まだ少し時間があるので、ユーザーが test.php などのページをアップロードした後、ファイルの種類を決定しない場合について説明します。 、リンクに従ってこのページにアクセスすると、このページには破壊的なコードが含まれている可能性があり、Web サイト全体が危険になります。
おそらく、プログラムで jpg、png、gif の 3 種類のサフィックスのみが許可されると判断したので、アップロードが成功したら、この JSP ページのサフィックスを jpg などに変更します。 Web サイトに特定の脆弱性が存在すると、ファイルのサフィックスが変更される可能性があり、Web サイトが再び危険にさらされます。 !
Web サイトではファイル拡張子の変更が許可されていないと想定されますが、アップロードされた画像の後に JS スクリプトが追加されたり、アップロードされたファイル名にスクリプトが書き込まれたりする場合があります。これらは危険である可能性があります。 !