質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

2047閲覧

掲示板で、送信や出力でいつエスケープするのか知りたいです

owly

総合スコア3

PHP

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

2クリップ

投稿2020/10/07 07:25

JavaScriptとPHPで掲示板を作っています。

コメントの入力値を安全に受け取って安全に出力したいので、エスケープすべきタイミングを知りたいのですが、次の流れであっていますか?

###コメントの投稿と出力の流れ
➀JavaScriptからPHPへコメントをPOSTする際はエスケープ不要

➁PHPでその $_PSOT['comment_str'] というコメントを次のようにエスケープする

php

1$comment_str = filter_input(INPUT_POST, 'comment_str', FILTER_SANITIZE_SPECIAL_CHARS);

➂データベースにinsertする値も次のようにそのまま$comment_strを渡しエスケープ不要

MySQL

1$query = "insert into comments ( comment_str ) ( {$comment_str} )";

➃コメントの出力時は、XSSを防止するために以下を通してエスケープする

JavaScript

1// AJAXでデータベースから取得した値 2var json = { 3 0: { 4 author: 'Aさん', 5 comment: 'こんにちは' 6 }, 7 1: { 8 author: 'Bさん', 9 comment: '<p>さようなら</p>' 10 }, 11}; 12 13// ループでエスケープしながら出力 14for (var item in json) { 15 var obj = json[item]; 16 var comment = obj.comment 17 var comment = escStr(comment); 18 $('ul').append('<li>' + comment + '<li>'); 19} 20 21// エスケープ関数 22function escStr(str){ 23 return str.replace(/&/g,"&amp;") 24 .replace(/"/g,"&quot;") 25 .replace(/'/g,"&#039;") 26 .replace(/</g,"&lt;") 27 .replace(/>/g,"&gt;"); 28}

ざっとこちらの流れで実装したところなのですが、何かたりない部分ございませんでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

前置き

まずは
IPA 安全なウェブサイトの作り方
を熟読されることを強くお勧めします。
体系的に学ぶ 安全なWebアプリケーションの作り方 第2版もド定番の超良書です。

回答

エスケープは、
出力時にその処理系のメタ文字をその処理系に合った方法でエスケープする
事が必要です。

その観点から見ると

➀JavaScriptからPHPへコメントをPOSTする際はエスケープ不要

不要です。
理由

  • PHP側でPOSTされた値を直接eval()に渡すようなケースを除いてはただの文字列となるため
  • JavaScriptでのエスケープはブラウザ側で処理を変更出来てしまうのでセキュリティ上の意味が薄いため

➁PHPでその $_PSOT['comment_str'] というコメントを次のようにエスケープする

不適切です。
FILTER_SANITIZE_SPECIAL_CHARS

'"<>& および ASCII 値が 32 未満の文字を HTML エスケープします。オプションで、 特殊文字を取り除いたりエンコードしたりします。

であり、これが使用するRDBMSのメタ文字を全てカバーできる保証はありませんし、入力時にエスケープしてしまうと他の用途で使う際にエスケープを解除するような操作が必要になってしまいます。

➂データベースにinsertする値も次のようにそのまま$comment_strを渡しエスケープ不要

必要です。
理由は②の通り。
セキュリティと保守性を考慮した場合、プリペアードステートメントを使用してSQLインジェクションが原理的に発生しないようにすることがベストでしょう。

➃コメントの出力時は、XSSを防止するために以下を通してエスケープする

2011年の記事なのでブラウザの対応状況などは現在と異なっていますが、
PHPのイタい入門書を読んでAjaxのXSSについて検討した(3)〜JSON等の想定外読み出しによる攻撃〜
がとても参考になると思います。

体系的に学ぶ 安全なWebアプリケーションの作り方 第2版にはより詳細&最近の状態に沿った記述があります。

例えばPHP側でこんな感じのJSON出力をしてしまっている場合で
IEで直接このPHPにアクセスした場合はXSSが成立してしまいますので、
少なくともサーバサイドでJSONとしての出力に対しては対応(エスケープおよび正確なメタデータの出力)が必要です。

<?php $a = ["html","<body onload=alert(1)>"]; echo json_encode($a);

対応としては(引用)

対策の基本はX-Requested-Withヘッダのチェック
Content-Typeは正しく application/json; charset=UTF-8 と指定
IEに顔を立てて、X-Content-Type-Options: nosniff を指定(あるいは不要か?)
JSON生成ライブラリで設定できる最大限のエスケープ

になります。

また、HTMLのエスケープ(質問中ではJavaScriptで実施)されているものに関しては(引用)

 残る課題としては、HTMLエスケープをサーバー側で行うか、クライアント側で行う(エスケープする、あるいはタグ生成しない)かがあります。これについては、どちらかとは決められないような気もしますが、少なくとも、プロジェクト毎にはルールを決めておかないと、過剰エスケープ等バグや、脆弱性の原因になります。

にあるように、プロジェクト内で統一すればPHPでもJavaScriptでもどちらでもいいと思います。

投稿2020/10/07 08:54

編集2020/10/07 09:17
tanat

総合スコア18713

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

owly

2020/10/08 09:26

質問一つずつに対し丁寧なご回答をありがとうございます。浅い知識を見直す大きなきっかけとなりました。
tanat

2020/10/08 10:13

良かったです。 前置きで紹介したものはどちらもとても良い文書なので、是非そちらも読んでみてください。
guest

0

「画面出力時」です。
HTMLとして画面から参照されるときにエスケープしてください。

取得時にするのは間違いです。

$comment_str = filter_input(INPUT_POST, 'comment_str', FILTER_SANITIZE_SPECIAL_CHARS);

htmlspecialcharsとFILTER_SANITIZE_SPECIAL_CHARS

➂データベースにinsertする値も次のようにそのまま$comment_strを渡しエスケープ不要
$query = "insert into comments ( comment_str ) ( {$comment_str} )";

そもそもinsert文として正しくない構文ですが、SQLインジェクションが発生するのでSQLエスケープは必要です。
(プリペアドステートメントで対応するのがベター)

サニタイズ/入力値検証/エスケープの考え方

投稿2020/10/07 07:38

m.ts10806

総合スコア80850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

owly

2020/10/08 09:26

ありがとうございます。プリペアドステートメントを知りませんでしたので教えていただき助かりました。
m.ts10806

2020/10/08 09:29

XSSはあくまで脆弱性のほんの一部にしか過ぎないというところが伝わればと。
guest

0

まず大前提として、エスケープ処理は、
・文字列の持つルールが異なるシステム間でデータをやり取りする
場面で必要となります。

で、本件では
・ブラウザからデータ伝送時
・DB へのデータ投入時
・サーバからブラウザへのデータ伝送時
のそれぞれで、エスケープ処理が必要となります。

ブラウザからデータ伝送時

これは、ブラウザが処理してくれているので、あまり意識する必要がありません。
隠れた処理として、web サーバと php の間のやり取りも併せて発生しますが、こちらも意識する必要はないです。
POST/GET するときには raw データをブラウザに渡すと適当に処理が実行され、php で受け取る際には、親切にパースまでされた状態で使用できます。

DB へのデータ投入時

受け取ったデータをそのまま投入したいので、SQL として適切な指示となるよう、エスケープしてやる必要があります。
質問にある変数展開による SQL の組み立ては、SQL と php の文字列の持つルールが反映できないので、一般的には避けるべき実装となります。

本質問の範囲では、プリペアードステートメントが利用できるので、プリペアードステートメントを使用したエスケープ処理を実施させるのが、もっともセキュアな実装となります。

サーバからブラウザへのデータ伝送時

ajax を利用して json を利用するという事なので、php の文字列の持つルールと json のルールを合わせてやる必要があります。
php の json encode は、そのままでは RFC に準じた json を作ってくれません。

結構ややこしいので、以下を参照してください。
(json の安全な使用法まで言及があります)
JSONのエスケープ - yohgaki's blog 書かない日記

また、ブラウザからのデータ伝送時と同様、ブラウザへのデータ伝送時にも自動処理されるエンコード/デコードがありますが、こちらも意識しなくて良いです。

どの処理も、処理漏れを防止するため、処理のタイミングはシステムをまたぐ直前に行うことが(現在は)推奨されています。

以下、参考まで
そもそもエスケープとは何なのか? - yohgaki's blog 書かない日記
エスケープの必要な処理とは? - teratail

投稿2020/10/07 09:57

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

owly

2020/10/08 09:21

ありがとうございます。プリペアードステートメントやjson のルールは意識していませんでした。気を付けます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問