ラボ > PHP:セキュリティ関連、Javascript関連

PHP+jquery、formなどの組み合わせのセキュリティ関連

SQLインジェクションやCSRF対策など。

作成日:2018-05-02, 更新日:2018-05-24

基本

もろもろ偽装もあり得るので、絶対的に安心という訳ではない。

以下は順不同。

呼び出し元の確認

PHP側で「$_SERVER['HTTP_REFERER']」をチェック。

想定外なドメインやページなどから来てたら、拒否するなり、終了させるなりする。

ajaxから来たのか確認

jqueryなどのライブラリを使ったajax通信の場合は「$_SERVER['HTTP_X_REQUESTED_WITH']」が「XMLHttpRequest」になる。

ファイルのup

例えば、PHPファイルなどのような何かを実行できるようなファイルをup。
そのファイルにアクセス(実行させる)→悪いコトされる可能性を考慮する

ファイル名を変更して、実行されにくくする

推測されにくいファイル名にする。

upしたファイルにアクセスできないようにする

.htacessなどで、非公開にしたフォルダに入れるなり、アクセス禁止にするなり・・・。

▼.htacessでアクセス拒否(ブラウザのみ)

Deny from all

CSRF対策

form送信時のCSRF(Cross-site Request Forgery:リクエスト強要)対策。
規定のフォームを通さずに来たデータを無視するってヤツ。

・FuelPHPの場合:FuelphpでCSRF対策

不正なデータ:XSS、Script Insertion

「XSS(クロス・サイト・スクリプティング)」、「Script Insertion(スクリプト埋め込み)」ってヤツらの対策。
パラメータにスクリプトを埋め込んで何かするってヤツ。

・「XSS」は「他所のページにリダイレクトさせる」。
・「Script Insertion」は「スクリプトを実行させる」って感じ。

例えばスクリプトじゃないけど・・・「<b>zebra</b>」という値を受け取った場合。
・処理せず表示→「zebra」:「<b>」が「bタグ」として扱われる。
・処理して表示→「<b>zebra</b>」:「<b>」を「&lt;b>」に変換して表示することによってタグじゃなく文字列として扱う。

対策は、スクリプトをただの文字列扱いにする。

PHPで対策:htmlspecialchars()

$hoge = htmlspecialchars($_GET['hoge'], ENT_QUOTES);

SQL Injection

「XSS」、「Script Insertion」のSQL版。

DBへのクエリ発行時に何かを実行させようとするってヤツ。

対策は、受け取ったデータを文字列等に変換してからクエリ発行。

PHP

▼例えば下記のような命令とクエリ(PHP)

$q = 'select * from 〇〇〇 where 〇〇〇 = "' . $_GET[〇〇〇] . '"';

▼「$_GET[〇〇〇]」の値の例
・「zebra」などのような文字列なら「select * from 〇〇〇 where 〇〇〇 = "zebra"」となり、問題無し。
・「"; delete 〇〇〇 "」などのようなクエリだったら「select * from 〇〇〇 where 〇〇〇 = ""; delete 〇〇〇 ""」となり、問題アリ。
これは、「管理者が用意したクエリを実行」ってのを希望しているのに「利用者が用意したクエリも実行」となるのが問題。

PDOを使っているならバインディングが用意されている。
※PDOを使っていなくても似たような何かが用意されているはず。最悪、自分でエンコードするなりすればOK。

具体例:下記のようなソース

$val = 'hoge';
$sql = 'select * from `kushi` where id="' . $val . '"';

▼想定している「$val="1";」なSQL

SELECT * FROM `kushi` where id="1"

→実行結果は「id="1"」を満たすレコードのみ表示。

▼想定外の「$val='" or 1="1';」なSQL

SELECT * FROM `kushi` where id="" or 1="1"

→実行結果は全件表示

インラインフレームでの読込み拒否

対象ページで、何かを出力する前に下記。

header('X-Frame-Options: DENY');          // 拒否
// header('X-Frame-Options: SAMEORIGIN'); // 同一ドメインのみOK