第18章 セキュリティ

セキュリティの重要性

昨今のシステムでは悪意のあるユーザの攻撃を防ぐためのセキュリティの重要性が高まっています。またこの分野は日進月歩であるため日々新しい技術を学んでいく事が必須となります。

以下ではPHPにおけるセキュリティ対策の一例として取り上げます。最低でもこのぐらいの対策はいれるべきでしょう。


入力検証とフィルタリング

入力検証の例

// ユーザからの入力を取得
$email = $_POST['email'];

// Eメールアドレスの形式をチェック
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
  echo '有効なメールアドレスです。';
} else {
  echo '無効なメールアドレスです。';
}


SQLインジェクションの防止

プリペアドステートメントの例

$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
// ユーザ入力をプレースホルダにバインド
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->bindParam(':email', $_POST['email']);
$stmt->execute();


セッションセキュリティ

セッション固定化攻撃の防止

// セッションIDを再生成(セッションハイジャック対策)
session_regenerate_id();


パスワードセキュリティ

パスワードハッシュ化の例

// パスワードを安全にハッシュ化
$hashed_password = password_hash($_POST['password'], PASSWORD_DEFAULT);


CSRF対策

CSRFトークンの使用例

// トークンの生成
$token = bin2hex(random_bytes(32));

// セッションにトークンを保存
$_SESSION['token'] = $token;

// フォームにトークンを埋め込む
echo '<input type="hidden" name="token" value="' . $token . '">';


ディレクトリ・トラバーサル攻撃

ディレクトリ・トラバーサル攻撃の対策例

$file = $_GET['file'];
include("/var/www/html/files/" . $file);

クリックジャッキング対策

X-Frame-Optionsヘッダの設定

// クリックジャッキング対策
header('X-Frame-Options: DENY');


XSS(クロスサイトスクリプティング)対策

エスケープ処理の例

// 出力前にエスケープ
echo htmlspecialchars($_POST['username'], ENT_QUOTES, 'UTF-8');


ファイルアップロードのセキュリティ

ファイルタイプの検証

// ファイルタイプをチェック
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $_FILES['file']['tmp_name']);
if ($mimeType !== 'image/jpeg') {
  echo '許可されていないファイルタイプです。';
}


HTTPSの強制

HTTPSリダイレクトの例

if ($_SERVER['HTTPS'] !== 'on') {
  $redirectUrl = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  header('Location: ' . $redirectUrl);
  exit;
}


コンテンツセキュリティポリシー (CSP)

CSPヘッダの設定

header("Content-Security-Policy: default-src 'self'; img-src https://*; child-src 'none';");


データ暗号化

データ暗号化の例

// 暗号化キー
$key = 'secret_key';

// 暗号化
$ciphertext = openssl_encrypt('plain_text', 'aes-256-cbc', $key, 0, $iv);

// 復号
$plaintext = openssl_decrypt($ciphertext, 'aes-256-cbc', $key, 0, $iv);


クッキーの盗み取り

HttpOnlyフラグを設定

setcookie('key', 'value', 0, '/', '', false, true); // HttpOnlyフラグを設定


エラーハンドリングとログ記録

エラーログの記録

// エラーメッセージをログに記録
error_log('エラーメッセージ');


練習問題1.

あるウェブアプリケーションで、ユーザーからの入力を元にデータベースから情報を取得する機能があります。以下のコードにおいて、SQLインジェクションの脆弱性を修正してください。

$username = $_POST['username'];
$password = $_POST['password'];
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($connection, $query);


練習問題2.

ユーザーからの入力をそのままHTMLに反映する以下のコードにおいて、XSSの脆弱性を修正してください。

$userComment = $_GET['comment'];
echo "<div>$userComment</div>";


練習問題3.

ユーザーから受け取ったパスワードをデータベースに保存する際、以下のコードにおいてセキュリティを強化するための修正を加えてください。

$password = $_POST['password'];
$query = "INSERT INTO users (password) VALUES ('$password')";
$result = mysqli_query($connection, $query);