質問編集履歴

1 初心者マーク付加

yyyyyk

yyyyyk score 13

2018/02/04 02:45  投稿

PHP CSRF対策について
初めまして。
現在PHPを勉強していて、クイズサイトを作成しています。
問題の編集画面にて、CSRFの対策を取ろうと思っているのですがうまくいきません。
```PHP
<?php
session_start();
//変数宣言
$num = $_GET['num'];
$msg = '';
//セッションがセットされていない場合の処理
if(!isset($_SESSION['NAME'])) {
header("Location: Login.php");
exit();
}
//管理者権限以外がページにアクセスした場合の処理
if($_SESSION['kengen'] != 'kanri') {
header("Location: main.php");
exit();
}
//GETで受け取った値が不正だった場合の処理
if(!preg_match("/^[0-9]+$/", $num)) {
header("Location: error.php");
exit();
}
//GETで受け取ったNumのデータを引っ張る
try{
//データベースから問題を引っ張る
$DB = new PDO('mysql:host=localhost;dbname=question;charset=utf8','root','');
$stmt = $DB->query("SELECT * FROM question WHERE num=".$num);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
} catch(PDOException $e) {
$err_msg = 'データベースエラー';
}
//更新機能
if(isset($_POST['update'])) {
//token発行
$token = sha1(uniqid(mt_rand(), true));
$_SESSION['token'] = $token;
//CSRF対策
if($_SESSION['token'] != $_POST['token']) {
header("Location: error.php");
exit();
}
$title = $_POST['title'];
$content = $_POST['content'];
$question1 = $_POST['question1'];
$question2 = $_POST['question2'];
$question3 = $_POST['question3'];
$answer = $_POST['answer'];
if(!empty($title)) {
try{
$DB = new PDO('mysql:host=localhost;dbname=question;charset=utf8','root','');
$stmt = $DB->prepare("UPDATE question set title = :title WHERE num =".$num);
$stmt->bindParam(':title', $title, PDO::PARAM_STR);
$stmt->execute();
} catch(PDOException $e) {
$err_msg = 'データベースエラー';
}
}
if(!empty($content)) {
try{
$DB = new PDO('mysql:host=localhost;dbname=question;charset=utf8','root','');
$stmt = $DB->prepare("UPDATE question set content = :content WHERE num =".$num);
$stmt->bindParam(':content', $content, PDO::PARAM_STR);
$stmt->execute();
} catch(PDOException $e) {
$err_msg = 'データベースエラー';
}
}
if(!empty($question1)) {
try{
$DB = new PDO('mysql:host=localhost;dbname=question;charset=utf8','root','');
$stmt = $DB->prepare("UPDATE question set question1 = :question1 WHERE num =".$num);
$stmt->bindParam(':question1', $question1, PDO::PARAM_STR);
$stmt->execute();
} catch(PDOException $e) {
$err_msg = 'データベースエラー';
}
}
if(!empty($question2)) {
try{
$DB = new PDO('mysql:host=localhost;dbname=question;charset=utf8','root','');
$stmt = $DB->prepare("UPDATE question set question2 = :question2 WHERE num =".$num);
$stmt->bindParam(':question2', $question2, PDO::PARAM_STR);
$stmt->execute();
} catch(PDOException $e) {
$err_msg = 'データベースエラー';
}
}
if(!empty($question3)) {
try{
$DB = new PDO('mysql:host=localhost;dbname=question;charset=utf8','root','');
$stmt = $DB->prepare("UPDATE question set question3 = :question3 WHERE num =".$num);
$stmt->bindParam(':question3', $question3, PDO::PARAM_STR);
$stmt->execute();
} catch(PDOException $e) {
$err_msg = 'データベースエラー';
}
}
if(!empty($answer)) {
try{
$DB = new PDO('mysql:host=localhost;dbname=question;charset=utf8','root','');
$stmt = $DB->prepare("UPDATE question set answer = :answer WHERE num =".$num);
$stmt->bindParam(':answer', $answer, PDO::PARAM_STR);
$stmt->execute();
} catch(PDOException $e) {
$err_msg = 'データベースエラー';
}
}
$msg = '更新しました';
}
try{
//データベースから問題を引っ張る
$DB = new PDO('mysql:host=localhost;dbname=question;charset=utf8','root','');
$stmt = $DB->query("SELECT * FROM question WHERE num=".$num);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
} catch(PDOException $e) {
$err_msg = 'データベースエラー';
}
?>
<!DOCTYPE html>
<html>
<head>
<title>問題編集</title>
</head>
<body>
<h3>問題編集</h3>
<p><?php echo $msg; ?></p>
<?php var_dump($_SESSION['token']); ?>
<form method="POST" action="">
タイトル:<input type="text" name="title" value="" placeholder="<?php echo htmlspecialchars($row['title'], ENT_QUOTES); ?>">
<br>
クイズ内容:<input type="text" name="content" value="" placeholder="<?php echo htmlspecialchars($row['content'], ENT_QUOTES); ?>">
<br>
質問1:<input type="text" name="question1" value="" placeholder="<?php echo htmlspecialchars($row['question1'], ENT_QUOTES); ?>">
<br>
質問2:<input type="text" name="question2" value="" placeholder="<?php echo htmlspecialchars($row['question2'], ENT_QUOTES); ?>">
<br>
質問3:<input type="text" name="question3" value="" placeholder="<?php echo htmlspecialchars($row['question3'], ENT_QUOTES); ?>">
<br>
回答:<input type="text" name="answer" value="" placeholder="<?php echo htmlspecialchars($row['answer'], ENT_QUOTES); ?>">
<br>
<input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
<input type="submit" name="update" value="変更">
</form>
<a href="main.php">戻る</a>
</body>
</html>
```
問題箇所としては、//更新処理 の頭です。
現状、token自体は合っていると思うのですが変更ボタンを押下するとエラーページに遷移してしまいます。
宜しければご教示願います。
  • PHP

    31380 questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • CSRF

    71 questions

    クロスサイトリクエストフォージェリ (Cross site request forgeries、CSRF)は、 外部Webページから、HTTPリクエストによって、 Webサイトの機能の一部が実行されてしまうWWWにおける攻撃手法です。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る