(1) SQLインジェクション対策

SQL は prepare() を使って記述する。
ここで、変数は「?」を使う。「.」等で変数を接続してはいけない。

$user_id = "1234";
$kind = "test";
$sql = "SELECT id, data FROM table_name WHERE id=? AND kind=?";
$stmt = $pdo->prepare($sql);
$stmt->bindParam( 1, $user_id, PDO::PARAM_STR);  // 1つめの ? に 1234
$stmt->bindParam( 2, $kind, PDO::PARAM_STR);     // 2つめの ? に test
$stmt->execute();

(2) XSS対策

変数を画面に表示する場合は htmlspecialchars() を使う。

echo '<h1>idは'.htmlspecialchars($user_id).'です。</h1>';

(3) スクリプトインジェクション対策

ユーザーが画面から入力する文字列などは、HTMLタグや PHPタグを取り除くと安心。

$comment = strip_tags($_POST["comment"])

(4) CSRF対策

ログイン後に、session_regenerate_id を実行する。

session_regenerate_id(true);

ログアウト後に、session_destroy を実行する。

// セッションクリア
session_destroy();

(5) CSRF対策 その2

遷移元画面でユーザーが情報を選択し、OKボタンをクリックして、
遷移先画面でSQLでデータを更新(INSERT,UPDATE、DELETE)する。
選択情報は、GETデータで選択内容を引き継ぐ。
という場合、ユーザがログインセッションを保持している状態で、悪意のあるページが遷移先画面のURLをたたかせると意図しないSQLが発行される。
(ぼくはまちちゃん! 的な問題)
このため、遷移元画面から遷移先画面へはトークンを連携するなどして、正しい遷移元である確認をする。

遷移元

// ランダムな8桁の数字でトークンを作る
$token = random_int( 10000000, 99999999 );
// セッションにトークンを入れる
$_SESSION["TOKEN"] = $token;

// URLにもトークンを入れる
echo '<a href="next.php?token='.$token.'">次のページ</a>';

遷移先

// セッションとURLのトークンが一致しなかったら処理しない
if( $_SESSION["TOKEN"] != $_GET["token"] ) {
  die("トークンが一致しません。");
}

(6) クリックジャッキング対策

.htaccessファイルに下記の命令を記述する。

Header set X-FRAME-OPTIONS "DENY"

または、PHPでHTMLを書く前に、header()をコールする。

<?php
  // クリックジャッキング対策
  header('X-FRAME-OPTIONS: DENY');
?>
<!doctype html>
<html>

クリックジャッキング対策ができているか確認。
下記のような感じで、適当なファイル(hoge.html)を作る。
「http://…/index.php」の部分にテストしたいURLを入れる。
なにもしていないと画面が表示されるが、クリックジャッキング対策をすると、空白になる。

<html>
  <iframe src="http://…/index.php" width="800" height="1000">
  </iframe>
</html>