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

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

新規登録して質問してみよう
ただいま回答率
85.50%
セキュリティー

このタグは、コンピューターシステムの安全性やデータの機密性に関連したトピックの為に使われます。

PHP

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

Q&A

解決済

1回答

799閲覧

htmlspecialcharsとhtmlspecialchars_decodeのセキュリティ対策につきまして

dondondon

総合スコア13

セキュリティー

このタグは、コンピューターシステムの安全性やデータの機密性に関連したトピックの為に使われます。

PHP

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

0グッド

0クリップ

投稿2018/12/07 05:46

お世話になります。

PHPの「htmlspecialchars」と「htmlspecialchars_decode」につきましてご教授頂けますでしょうか。

【前提】
データベースに「<script>alert(1)</script>」というデータが登録されている。

【やりたいこと】
データベースに登録されている「<script>alert(1)</script>」というデータを「<script>alert(1)</script>」という文字列として表示したい。ただし、XSS対策はされていて、アラート表示はされない状態で単なる文字列として「<script>alert(1)</script>」を画面上に表示したい。

下記のような流れでXSS対策としてエスケープ処理をしました。

① phpで上記【前提】のデータをSQLで抽出(抽出したデータは「$name」に格納)
② <?php echo $name; ?>でブラウザで表示
③ ブラウザで表示するとアラートが表示される(XSSできてしまう状態)
④ 表示内容は「<script>alert(1)</script>」なのでNG。

⑤ XSS対策のため、①で抽出したデータをhtmlspecialcharsで変換($name = htmlspecialchars($name, ENT_QUOTES, 'UTF-8')
⑥ 表示を正しくするため、変換した$nameをhtmlspecialchars_decodeで変換($name = htmlspecialchars_decode($name, ENT_QUOTES)
⑦ <?php echo $name; ?>でブラウザで表示
⑧ アラート表示はなくなり、「<script>alert(1)</script>」という文字列が表示された

【ご教授頂きたいこと】
・上記はエンコードした後にデコードして表示していますが、そもそもこのやり方でXSS対策になっているのでしょうか。結果だけを見るとアラートは表示されず(javascriptは機能せず)、かつ表示も意図した通りになっていますが、「たまたまうまくいっているだけ」や「別の方法で攻撃されたときに対処できない」などがございましたらご指摘頂ければ幸いです。

・上記のような「エンコード⇒デコード」をする以外の方法がございましたら教えて頂けますと幸いです。

※テストの方法が拙いため、「なんでこんなやり方しているのか?」などの疑問がありましたらそちらもご指摘頂ければ説明致します。

以上です。宜しくお願い致します。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2018/12/07 05:51

なんでhtmlspecialchars()で処理したような文字列をそのままDBに持たせたりする悪手をやったのだろう。DBには実文字列そのまま保存するべきなのに。
guest

回答1

0

ベストアンサー

XSS対策は基本的に「画面出力時・表示時に」行うものです。
DBにはそのまま<script>alert(1)</script>を登録して表示時にhtmlspecialchars()を行ってください。
htmlspecialchars()はあくまで「HTMLエスケープ」を行うものです。
SQLインジェクション対策で使うものではありません。

投稿2018/12/07 05:55

m.ts10806

総合スコア80765

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

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

dondondon

2018/12/07 06:03

ご回答ありがとうございます。 DBには入力フォームからデータ入力する仕様にしており、「<script>alert(1)</script>」を入力すると「&lt;script&gt;alert(1)&lt;/script&gt;」に変換されて格納されます。これを「htmlspecialchars()」で表示するとそのまま「&lt;script&gt;alert(1)&lt;/script&gt;」が表示されてしまうため、デコードしています。 そもそもDB格納時の「変換される」のが一般的ではないのでしょうか・・・
m.ts10806

2018/12/07 06:07

勝手に変換はされないですよ。どこかに保存直前にhtmlspecialchars()されてるんでしょう。 ユーザの入力はもちろんバリデーションは行われた前提でありますが、 そのまま登録するのが原則です。勝手に加工してはいけません。 表示時はXSS対策のためにhtmlspecialchars()でHTMLエスケープは行いますが、それも「登録時のままの情報を表示するため」という意味も含んでいます。
dondondon

2018/12/07 06:16

>勝手に変換はされないですよ。どこかに保存直前にhtmlspecialchars()されてるんでしょう。 テスト環境を構築して、mysqlを使って入力データを確認しています。 phpは入力フォームだけなので変換処理はかけておりません。入力したデータを確認したところ「あれ?<が&lt;に変換されてる・・・」ということがあったため疑問を抱きました。疑問を調べていく過程でXSSには変換処理が必要であることを知り、「<を&lt;に変換しているのもDB側の仕様で、XSS対策の一環だろう」と考えておりました。 これはDB側の設定か何かと考えた方がよろしいでしょうか? (説明が拙くて申し訳ございません。phpの勉強中のため知識不足なところがあります)
退会済みユーザー

退会済みユーザー

2018/12/07 06:35

表示用に加工した文字列を収めた変数を、DB保存用にそのまま流用したら、そうなるわな。
m.ts10806

2018/12/07 06:43 編集

ためしに下記を提示願います ・入力画面のコード ・入力、送信された情報を受け取りDBに保存するコード ・DBから情報を取得し画面に表示するコード プログラムは指示した通りにしか動かないので勝手にXSS対策してはくれません。
dondondon

2018/12/07 07:25

下記のようなコードを作成しました(見にくいコードで申し訳ございません) 【入力画面のコード(test.php)】 <div class="test1">  <input type="text" class="test2" id="perUser" name="namae" placeholder="ユーザーネーム"> </div> 【入力、送信された情報を受け取りDBに保存するコード(test.phpとは別ファイル)】  try{ $db = new PDO($dsn, $user, $password); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $stmt = $db->prepare(' UPDATE user SET user.name = ? WHERE user.id='1' '); $udata[] = $namae; $stmt->execute($udata); print '<script>alert("変更完了")</script>'; }catch(Exception $e){ print 'エラー'; exit(); } 【DBから情報を取得し画面に表示するコード(test.php)】  try{ $db = new PDO($dsn, $user, $password); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $stmt = $db->prepare("SELECT * FROM user WHERE id = '1' AND name = ?"); $data[] = $name;    } catch(PDOException $e){   echo "エラー:" . $e->getMessage();   } <div class="profile">  <button class="test3">&emsp;<?php echo $name . 'さん';?><br></button> </div>
退会済みユーザー

退会済みユーザー

2018/12/07 07:31 編集

$namaeに格納している箇所も示してね。$_POST['namae']から加工してあるはずだから。
m.ts10806

2018/12/07 07:32

コードは質問本文にマークダウン<code>利用してご提示ください。
dondondon

2018/12/07 07:55

>コードは質問本文にマークダウン<code>利用してご提示ください。  ご指摘ありがとうございます。初質問でしたのでルールを把握しておりませんでした。 >$namaeに格納している箇所も示してね。$_POST['namae']から加工してあるはずだから。  格納しているコードは以下となります。 <code> $namae=$_POST["namae"]; $namae=htmlspecialchars($namae,ENT_QUOTES,'UTF-8'); </code> お二人のご指摘を受け、再度「データ入力⇒DB確認⇒表示」の流れのコードを追ってみました。 そこで上記のようにDB登録時にhtmlspecialcharsで変換していることがわかりました。 当初ご指摘頂いた「勝手に変換されるはずはない」が正にその通りでした。 この度は私の勘違いでお時間を取らせてしまい申し訳ございません。 大変助かりました。 ※DBへの登録時に変換しているのはミスなので出力(表示)時に変換するよう修正します。
m.ts10806

2018/12/07 08:05

解決されたようで何よりです。 「指示した通りにしか動かない」は常に念頭に置いて問題に取り組んでくださいね
dondondon

2018/12/07 08:07

>「指示した通りにしか動かない」は常に念頭に置いて問題に取り組んでくださいね  仰る通りですね。「勝手にDB側で処理をかけているのではないか」と疑念を抱いていましたが、私のミスなだけでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問