セキュリティ基礎勉強会#2(PHP)

non-security.phpをコピーして、
セキュリティ対策済みの security.phpファイルをつくってみよう。

クロスサイト・スクリプティング対策

security.php (一部抜粋)

       <?php foreach($results as $result): ?>
                <section class='card my-4'>
                    <div class='card-header'>
                        <h5><?php echo htmlspecialchars($result["title"],ENT_QUOTES,"UTF-8") ?></h5>
                    </div>
                    <div class='card-body'>
                        <p class='card-text'>
                            <?php echo htmlspecialchars($result["body"],ENT_QUOTES,"UTF-8") ?>
                        </p>
                    </div>
                    <div class='card-footer'>
                    </div>
                </section>
            <?php endforeach; ?>

CSRF対策

security.php (一部抜粋)

<?php
//セッションの開始
session_start();
// MySQLサーバ接続に必要な値を変数に代入
$userName = 'root';
$password = '';
// PDO のインスタンスを生成して、MySQLサーバに接続
$dbh = new PDO('mysql:host=localhost;dbname=bbs;charset=UTF8;', $userName, $password);
$title = $_POST['title'];
$body = $_POST['body'];
//CSRFトークン確認
//echo "session:".$_SESSION["csrfToken"]."<br>";
//echo "post:".$_POST["csrfToken"]."<br>";
if(isset($title) && isset($body)){
    // CSRF対策
    if($_POST["csrfToken"] !== $_SESSION["csrfToken"]){
        echo "エラー:不正なリクエストです!";
        return;
    }
    try{
        $sql = 'INSERT INTO posts(title, body) VALUES("'. $title .'","'. $body .'");';
        $stmt = $dbh->query($sql);
    }catch(PDOException $e){
        print($e->getMessage());
    }
}
// CSRFトークン生成
$csrfToken = md5(uniqid(rand()));
$_SESSION["csrfToken"] = $csrfToken;
//CSRFトークン確認
//echo "session:".$_SESSION["csrfToken"]."<br>";
//echo "post:".$_POST["csrfToken"]."<br>";
// ここにMySQLを使ったなんらかの処理を書く
$sql = 'SELECT * FROM posts';
$stmt = $dbh->query($sql);

SQLインジェクション対策

security.php (一部抜粋)

    try{
        //$sql = 'INSERT INTO posts(title, body) VALUES("'. $title .'","'. $body .'");';
        $sql = 'INSERT INTO posts(title, body) VALUES(:title, :body)';
        $stmt = $dbh->prepare($sql);
        $stmt->bindValue(':title', $title, PDO::PARAM_STR);
        $stmt->bindValue(':body', $body, PDO::PARAM_STR);
        $stmt->execute();
    }catch(PDOException $e){
        print($e->getMessage());
    }