PHPで修行中の者です。

以下のようなフォームを作ってテストしていますが
XSS対策を施そう四苦八苦しています。
通常のタグ<a>や<html>などはエスケープ出来るのですが、
<script>や$_GET['test']などを入力すると403エラーが出てしまいます。

なにか良い解決方法がありましたらご教授ください。
strip_tagsタグを取り除くのではなく、エンティティでhtmlにスクリプトが動作せず、表示するのが目的です。

↓↓↓↓main.php↓↓↓↓
<?php
session_start();
if (!empty($_POST)) {
if ($_POST['contents'] == '') {
$error['contents'] = 'blank';
}
if (empty($error)) {
$tages = htmlspecialchars($_POST['contents'], ENT_QUOTES, 'UTF-8');
$_POST['contents_test'] = $tages;
$_SESSION['join'] = $_POST;
header('Location: exp.php');
exit();
}
}
?><!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body>
<form method="post" action="" enctype="multipart/form-data">
<textarea id="contents" name="contents"></textarea><br>
<?php if ($error['contents'] == 'blank'): ?>内容を入力してください。<?php endif; ?>
<input type="submit" value="内容確認">
</form>
</body>
</html>

↓↓↓↓exp.php↓↓↓↓
<?php
session_start();
$comment = $_SESSION['join']['contents_test'];
?>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<?php echo $comment; ?>
</body>
</html>

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2014/06/06 06:21:09
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:JULY No.1

回答回数966ベストアンサー獲得回数247

ポイント100pt

直接、今発生している問題解決につながるかどうか分かりませんが、根本的な誤りとして、htmlspecialchars によるエスケープ処理を「入力時」の行っている点です。

XSS: 今こそXSS対策についてまとめよう - 徳丸浩の日記(2008-08-22)

徳丸浩さんのちょっと古い記事ですが、基本は、

  • 入力時は処理はアプリケーションの要件で決まる。
  • 出力時にエスケープ処理を行う。

です。

XSS を含めた Web アプリケーションのセキュリティ対策にとしては、まずは IPA から出ている下記の資料を読んでみてください。

安全なウェブサイトの作り方:IPA 独立行政法人 情報処理推進機構

あと、通称「徳丸本」と呼ばれる「体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践」はバイブル的存在で、持っておいて損は無いと思います。

他1件のコメントを見る
id:JULY

出力時にエスケープ処理を行うとのことですが、DBにインサートするときも、悪意のあるスクリプトをそのまま格納して、出力時にエスケープ処理を行う方がよいのでしょうか?


PHP のプログラムから見れば、「DB へ出力」なので、DB に保存する上で必要なエスケープ処理を行う、という事になります。ただ、DB へ格納する時に、プレースホルダ、プリペアドステートメントを使っていれば、「DB へ出力」する上でエスケープする必要は基本的にありません。逆に、ここを「SQL 文を組み立てて...」とすると、SQL 用のエスケープ処理が必要になり、それが不完全だと SQL インジェクションを引き起こします。

エスケープ処理は、出力相手に合わせて行うもので、htmlspecialchars は出力先が HTML 形式の時に利用しますが、出力先が単純なテキストファイルであれば、htmlspecialchars でエスケープ処理されると都合が悪い場合もあります。

また、動的に出力されるのは、何も POST されたデータだけとは限りません。例えば、DB から読み出した物を出力する場合、以前に POST したデータを読み出すだけではなく、サーバ側で管理者が設定したデータを読み込む可能性もあります。なので、「出力時にエスケープ」とした方がシンプルになります。

2014/06/05 20:36:09
id:admn

感激しております、徳丸浩さんの本も合わせて買って勉強してみます。
この度はありがとうございました。
また何かありましたら宜しくお願いします!

2014/06/06 06:20:55

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません