• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:WordPressの質問(q10155839)の続)

WordPressのSQL取得エラーとテーブル操作の対策まとめ

このQ&Aのポイント
  • WordPressの質問で、var_dump($row);で確認したところ登録結果画面と質問表示画面でNULLが表示され、SQLのSELECT文が失敗している原因を考察しています。
  • データベースにURLが格納されているにも関わらず、取得に失敗する例を検討し、IPアドレスの保存およびメッセージの一部を取得するコードの作成や<a>タグを適用する方法について質問しています。
  • 提供されたコードの解析と、画像や動画ファイルの表示、メッセージの一部を表示する方法について、具体的なサンプルコードを元に議論しています。

質問者が選んだベストアンサー

  • ベストアンサー
  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.29

・JavascriptのinnerHTMLがDOM-based XSSの発生源となるようで、HTMLのエスケープ処理が行うべきだとご指摘を頂きました。 それは入力された文字をそのままどこかに表示する場合だと思います。 質問者さまが使っているinnerHTMLは自前の文字なので問題ない気がします。 入力された文字の文字数を計算で使っているだけですし。 参考サイトも見てみましたが、例えばこことか、攻撃者が云々と言うのは入力可能な文字と言うことだと思います。 ---- var text = "...."; // 変数 text は攻撃者がコントロール可能な文字列 form.innerHTML = '<input type="text" name="key" value="' + text + '">'; ---- 質問者さまのコードではこのような入力された文字をそのまま表示する処理がないので大丈夫だと思います。 ・デフォルトでカウント文が表示されずにカウントもされていない状態です… dell_okさんにお聞きしてよいものか迷ったのですが、アドバイスお願い致します… そうですね。 あちらの質問は勉強になるので読むだけ読んでいます。 インターネット上での暗黙のルールみたいなものでマルチポスト扱いされるといけないので、こちらでの回答は控えておきます。 あちらで回答してくださるお返事もあったことですし、しばらく待ってみましょう。

php_learn
質問者

お礼

こちらが最新の回答になります。XSSセキュリティについてコードがまとまった為、 質問一覧表示画面について新たに質問させていただきました。よろしくお願い致します。 https://okwave.jp/qa/q10177232.html

Powered by GRATICA
php_learn
質問者

補足

A.アドバイスありがとうございます、脆弱性はinnerHTMLに設定する内容が制御できない内容である場合であり、変数leftが数値であることが保証されているように思われますので問題ないのではないかとアドバイスを頂いたのですが、少し神経質になりすぎていたかもしれません… leftの値が数値であることを証明されている場合は(エスケープ)必要なさそうですね、Wordpressを通すことでHTML側とJavascript側のかみ合わせが悪いようなので、再度確認して原因となりそうな部分を探してみます。 ※ページソース http://www.irasuto.cfbx.jp/%e9%9b%91%e8%ab%87%e6%8e%b2%e7%a4%ba%e6%9d%bf/

その他の回答 (28)

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.18

回答No.17が中途半端でした。 結局のところ、httpもhttpsも禁止することになると思いますが、そのチェックにはピリオドのことが含まれています。 反対に、ピリオドのチェックがあればhttpやhttpsのチェックは不要なので、2つの条件を合わせる必要はありません。 片方に該当する場合はもう片方にも該当します。 この話しはURLを入力できなくする話しなので、XSSとはあまり関係ない気がします。

php_learn
質問者

補足

回答ありがとうございます、XSSとは直接は関係ありませんでした申し訳ありません。

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.17

・http://やhttps://から始まるか判定して、始まらない場合は書き込みを禁止にすることがXSS対策で推奨されておりました。 こちらはXSS防御に必須なことなのでどうすべきか迷っております、ピリオドで判定するのはとても良い案だと思ったのですが2つの条件を合わせることは可能でしょうか? 質問者さまが心配されているのはよく伝わってきているので理解しているつもりです。 ただ、それは、URL欄の入力がある場合の話しだと思います。 URL欄がある場合は、それを表示する画面でリンクタグにするので、クリックされたり実行されたりするので対策が必要なのです。 質問者さまのサイトではURL欄の入力はありませんし、投稿内容をリンクタグにもしないので、htmlspecialchars()でエスケープするだけで問題ないと思います。 どのサイトにもhtmlspecialchars()でエスケープとしか書かれていないと思います。

php_learn
質問者

補足

A.回答ありがとうございます、一度試してみたのですが.だけをブロックしても危険なサイトに誘導できる可能性がありそうです。下記のコードはalertを表示させるものですがプロトコルとなっております。アラートループ事件のようにコメントに書き込まれた際に無限に発火してしまう可能性がありそうです。 .と,と:と;で判定するように考えてみます。 テラテイルでカンマやどっとについてのコードを見つけたので使用したいのですが、function CheckUrl()の中の関数をどうすれば良いか分かりませんでした。方法も3つあるようですが、3つ目が難しく2つ目まで書いております、アドバイスお願い致します。 ※現在の雑談掲示板コード https://wandbox.org/permlink/4lKVqjaUL2s2E02Z ※プロトコル data:text/html;base64,PHNjcmlwdD5hbGVydCgnY3JhY2snKTwvc2NyaXB0Pg== ※ケース2. リンクにスクリプトを挿入するから引用 https://qiita.com/tomochan154/items/a93c56536c78d1faff0f ※PHP 正規表現のカンマやドットについて https://teratail.com/questions/56491 ※パターン1 function CheckUrl($str, $mes) { global $errors; mb_internal_encoding("UTF-8"); $pattern="/[\.,:;]/u"; if ('' == $str,$mes) { $errors[] = $mes; } return false; } ※パターン2 function CheckUrl($str, $mes) { global $errors; if (strpos($str, ',') !== FALSE || strpos($str, '.') !== FALSE || strpos($str, ',') !== FALSE || strpos($str, '.') !== FALSE || strpos($str, ':') !== FALSE || strpos($str, ';') !== FALSE || strpos($str, ': ') !== FALSE || strpos($str, '; ') !== FALSE) { $errors[] = $mes; } }

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.16

・後者の方が被害を防げるのではないかと考えております。 そうですね。 被害を最小限に抑えるのが目的なのでそれがいいと思います。 ・httpを書き込めないようにしたい理由が2つあるのですが これはあまり意味がありません。 投稿者が見て欲しいサイトのURLは、 yahoo.co.jp とプロトコル(httpやhttps)を除いて書くことができます。 必要に応じてそのサイトを見る場合は、 プロトコルなしでアドレスバーに入力すれば、 ブラウザが勝手にhttpやhttpsを付加してアクセスしてくれたり、 仕組みはわかりませんがhttpでアクセスされてもhttpsに飛ばされたりするので、 プロトコルを記述する意味がなくなってしまっているからです。 ですが、おもむろに「http」と記述されている場合は、 書き込めないようにしておくのが無難ですね。 ただ、それ以外はURLなのかどうかを判定することは、 実際のところ無理があるような気がします。 URLの構成についてこちらを参考にすると、 https://ferret-plus.com/8736 ホスト名とドメインの間には「.」ピリオドが必ずあるということです。 なので、ピリオドがあれば投稿できなくするのでもいいかも知れません。 日本人でピリオドを入力する人はあまりいないでしょうし。 外国人が英語などで投稿されるとピリオドを入力することが想定されます。 ですが、文章を記述するとピリオドの次にはスペースを入れているのが一般のような気がします。 URLにはスペースを含められないので、 なので、ピリオドの次に文字がある場合だけ投稿できなくする、とかですね。 ・2点目はURLにウイルスが含まれる場合になります これはURLを入力する前提の話しです。 リンクタグにして表示するわけではないので問題ありません。 ・便利さを優先するのであればURLの書き込みを許可すべきですがセキュリティ重視で考えております… それでいいのですよ。 私は私が思ったことを言わないと気が済まないので言っているだけなので、質問者さまが望む方向でかまわないので、気にしないでくださいね。 ・何が適切なのか分からない状態ですが、どこまで制限すべきでしょうか? スクリプトはエスケープしているので解決済みです。 不安にならなくても大丈夫です。 気になるのでしたら、そのスクリプトを投稿して確認してください。 大丈夫であることが確認できればいいと思います。 URLの判定はピリオドでいいと思います。 これほど安全な方法はないと思います。

php_learn
質問者

お礼

説明不足で申し訳ありません、試しに名前とメッセージに入力したURLは 下記サイトのテストコードになります。 https://kuzunoha-ne.hateblo.jp/entry/2020/02/01/011747

php_learn
質問者

補足

Q.そうですね。 被害を最小限に抑えるのが目的なのでそれがいいと思います。 A.回答ありがとうございます、神経質になりすぎているかもしれませんがセキュリティ重視のほうが安心かと思いました申し訳ありません。 Q.プロトコル(httpやhttps)を除いて書くことができます。 仕組みはわかりませんがhttpでアクセスされてもhttpsに飛ばされたりするので、 プロトコルを記述する意味がなくなってしまっているからです。 A.回答ありがとうございます、何となく認識はしていたのですが調べてみると下記サイトのように自動保管されると書いてありました。 ※参考サイト http://faq.tank.jp/skill/archives/291 Q.おもむろに「http」と記述されている場合は、 書き込めないようにしておくのが無難ですね。 ただ、それ以外はURLなのかどうかを判定することは、 実際のところ無理があるような気がします。 ピリオドがあれば投稿できなくするのでもいいかも知れません。 日本人でピリオドを入力する人はあまりいないでしょうし。 スクリプトはエスケープしているので解決済みです。 不安にならなくても大丈夫です。 A.回答ありがとうございます、どうやらプロトコルにも種類があるようでhttp://やhttps://から始まらない危険なURLがあるようです。 なのでhttp://やhttps://から始まるか判定して、始まらない場合は書き込みを禁止にすることがXSS対策で推奨されておりました。 こちらはXSS防御に必須なことなのでどうすべきか迷っております、ピリオドで判定するのはとても良い案だと思ったのですが2つの条件を合わせることは可能でしょうか? 名前とメッセージにhttp://127.0.0.1:9000/?hogehoge=<script>alert('aaa')</script>を入れてみたところ送信できないようですね、失礼いたしました。 ※http:// または https:// で始まる URL かどうかを判定 function isUrl($url) { if (!preg_match('/\Ahttps?:\/\//', $url)) { return false; } return true; } ※参考サイト https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1284006897 https://qiita.com/tomochan154/items/a93c56536c78d1faff0f ※疑似スキームについて(tokenの代わりにセッションIDを使う場合) https://www.securify.jp/blog/cross-site-scripting/ Q.それでいいのですよ。 私は私が思ったことを言わないと気が済まないので言っているだけなので、質問者さまが望む方向でかまわないので、気にしないでくださいね。 A.アドバイスありがとうございます、意見として受け取るように致します。

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.15

・掲示板やコメント等にスパムなどのURLが大量に張られたことがヤフー知恵袋でも過去多発していて一時期URL付き投稿を禁止したこともあるため、 可能であれば禁止にしておきたいです… なるほどですね。 気持ちはわかりました。 では、そのようにしましょう。 ですが、わかっておいて欲しいことがあります。 いえ、わかっているとは思いますが言わせてください。 おそらくですが、ヤフー知恵袋でも、OKWAVEのように、投稿内容にURLがあるとそれをリンクタグに置換していたからだと思います。 つまり、簡単にワンクリックで誘導できる、と言うことです。 OKWAVEは「これより先は外部サイトへ移動します。OKWAVEが運営するページではありませんのでご確認ください。」の画面を表示して、本人の意思で移動するかどうかを確認させています。 一方、私の案は、リンクタグにしないこと、です。 今回、URLのチェックを施したとしても、以下のようなURLもどきは投稿できます。 ttp://yahoo.co.jp これは、OKWAVEでもリンクタグには置換されないはずです。 URLではないからです。 ヤフー知恵袋でもこれは投稿できると思われます。 ではですよ。 スパム目的の人がもし、このように先頭のhをなくしたURLをたくさん投稿してきたらどうでしょう。 ヤフー知恵袋でもリンクではないURLもどきが投稿できるわけです。 そんなことをしてもスパムの目的は達成できませんが、やろうと思えばやってくるわけです。 クリックできないURLもどきがたくさんです。 これは私の案のクリックできないURLとなんの違いがあるでしょうか。 もうひとつ。 もしスパムではない純粋な質問者が見て欲しいサイトがあってURLを投稿したかったとします。 その時には先頭のhをなくして投稿してください、と言う案内になってきます。 案内しなくても、そうしてくるでしょう。 そうした場合、閲覧者がそのサイトに行ってみようとすると、URLもどきをコピーして、先頭にhを付けてアクセスすることになります。 手間であってもそうするでしょう。 それなら、その手間が省けるよう、URLをそのまま投稿できた方が便利です。 もし、純粋な質問者がURLもどきをなんどもなんども貼り付けてくるようであれば、なおさらその手間を省きたくなるものです。 と私は思うわけです。 それではチェックを追加してみましょう。 とりあえず single-index.php にしてみるので、それでよければ、他にも応用していただければと思います。 ---- function check() { global $errors; global $namae; global $message; $namae = Chk_StrMode($namae); $message = Chk_StrMode($message); Chk_InputMode($namae, '・お名前をご記入ください。'); Chk_InputMode($message, '・お問い合わせ内容をご記入ください。'); CheckUrl($namae, '・お名前にURLは記入できません。'); // 追加 CheckUrl($message, '・お問い合わせ内容にURLは記入できません。'); // 追加 if (!empty($_FILES)) { 省略 /* 未入力チェックファンクション */ function Chk_InputMode($str, $mes) { global $errors; if ('' == $str) { $errors[] = $mes; } } /* 以下追加 */ function CheckUrl($checkurl, $mes) { global $errors; if (preg_match('/(http|https|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i', $checkurl)) { $errors[] = $mes; } } ---- チェック関数は、//関数版?を元にしていますが、正規表現の「先頭から」を示す ^ をなくしています。 preg_match('/^(http|https|ftp): 元 preg_match('/(http|https|ftp): ^なし このチェック関数を、名前とメッセージにかけています。

php_learn
質問者

お礼

申し訳ありません回答No.15の補足でhttp://はブロックしたほうがよいとお伝えしたのですが、多くのサイトはどちらも許容しているようです… どうやら最も対策すべきはhttp://とhttps://以外のjavascript:から始まるURLのようです。 その他にXSSについても調べてみたのですが、Javascriptのコードはgoo質問のように書き込み禁止にした方が良いかもしれないです… 何が適切なのか分からない状態ですが、どこまで制限すべきでしょうか?アドバイスお願い致します。 ※セッションIDを使わずに危険なURLをブロック function isUrl($url) { if (!preg_match('/\Ahttps?:\/\//', $url)) { return false; } return true; } ※疑似スキームについて(tokenの代わりにセッションIDを使う場合) https://www.securify.jp/blog/cross-site-scripting/ ※preg_matchでhttp:// または https:// で始まる URL かどうかを判定 https://qiita.com/tomochan154/items/a93c56536c78d1faff0f ※XSS の 3つの攻撃手法について https://www.tohoho-web.com/ex/xss.html

php_learn
質問者

補足

Q.OKWAVEは「これより先は外部サイトへ移動します。OKWAVEが運営するページではありませんのでご確認ください。」の画面を表示して、本人の意思で移動するかどうかを確認させています。 一方、私の案は、リンクタグにしないこと、です。 A.回答ありがとうございます、OKWABEのように一度チェックを入れることは考えておりませんでした、良さそうですね。 Q.今回、URLのチェックを施したとしても、以下のようなURLもどきは投稿できます。 ttp://yahoo.co.jp ヤフー知恵袋でもこれは投稿できると思われます。 A.回答ありがとうございます、ヤフー知恵袋が規制していたころもhttpを抜いた物は投稿できていたようです。 https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12149394027 Q.スパム目的の人がもし、このように先頭のhをなくしたURLをたくさん投稿してきたらどうでしょう。 ヤフー知恵袋でもリンクではないURLもどきが投稿できるわけです。 そんなことをしてもスパムの目的は達成できませんが、やろうと思えばやってくるわけです。 クリックできないURLもどきがたくさんです。 これは私の案のクリックできないURLとなんの違いがあるでしょうか。 A.回答ありがとうございます。 こちらに関して自分なりの推測になるのですが、もしOKWABEのように一度アクセス前に確認をいれる方法とhttpを入力できない方法の2つ設置した場合、後者の方が被害を防げるのではないかと考えております。 OKWABEのように一度アクセス前に確認をいれたとしても大半の人がアクセスしてしまう危険があるのに対して、もしhttpを書き込めないようにしていた場合URLだと認識してhttpを付け足す人は少ないのではないでしょうか…? httpを付け足しアクセスしてくださいとウイルスを流した人がメッセージで伝えない限り多くの被害はでないことが想定されます。 httpを書き込めないようにしたい理由が2つあるのですが、1点目はデータが暗号化されていないサイトはウイルスに感染している可能性が高いことになります。調べたところHTTPSをドメイン設定で行っているサイト以外はすべて書き込み禁止にしたほうがよいと書いてありました。 確認画面を挟む場合もデータが暗号化されていないサイトはコメントできないようにしたいと考えております。 ※HTTPS通信について https://securitynews.so-net.ne.jp/topics/sec_20051.html 2点目はURLにウイルスが含まれる場合になります、XSS対策の1つに危険なURLか確かめる方法があるのですが、javascript等のURLを別途対策する必要が出てくるようです。 httpと危険なURLの書き込みを禁止にしてhttps://のみ入力可能にする方法が分からず、すべてのURLの書き込みを禁止にする方法が最善なのではないかと考えました。 function isUrl($url) { if (preg_match('/javascript:/', $url)){ return false; } return true; } ※XSSについて https://qiita.com/tomochan154/items/a93c56536c78d1faff0f Q.もしスパムではない純粋な質問者が見て欲しいサイトがあってURLを投稿したかったとします。 その時には先頭のhをなくして投稿してください、と言う案内になってきます。 そうした場合、閲覧者がそのサイトに行ってみようとすると、URLもどきをコピーして、先頭にhを付けてアクセスすることになります。 手間であってもそうするでしょう。 それなら、その手間が省けるよう、URLをそのまま投稿できた方が便利です。 A.アドバイスありがとうございます、便利さを優先するのであればURLの書き込みを許可すべきですがセキュリティ重視で考えております… 過去にウイルスサイトに誘導されて爆破予告などをしてしまい、パソコン遠隔操作された事件や無限アラート事件などあった為すべて禁止にした方がよさそうな気がしております… コメント欄にコードを書き込まれて開くたびに実行されるようなスクリプトなど対策すべきものがたくさんあるようです。 https://以外の書き込みを許可することは非常に難しいのではないでしょうか…

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.14

・URLを投稿された際に危険なサイトに誘導される可能せいがあるため出来れば禁止しておきたいと考えております。 禁止と言うか、送信された投稿内容から削除する方法(PHP)はあるような気がします。 送信前に投稿内容を判定して送信できないようにする方法(JavaScript)もあるでしょう。 ですが、検索してもそのような情報を見つけられませんでした。 URLを入力されたとしても、ワンクリックで誘導されなければいいような気もします。 つまり、それがリンクになっていなければいいと言うことです。 テストフォームを作ってみました。 http://oksample.starfree.jp/test/ ここに http://yahoo.co.jp と入力して送信してみてください。 表示されるのはそのままの文字なのでクリックできません。 次にリンクタグ <a href="http://yahoo.co.jp">Yahoo!</a> を入力して送信してみてください。 これもそのままの文字が表示されるだけでクリックできません。 コードは、htmlspecialchars()をかけているだけです。 ---- $str = filter_input(INPUT_GET, 's'); $str = htmlspecialchars($str); ----

php_learn
質問者

補足

A.アドバイスありがとうございます。掲示板やコメント等にスパムなどのURLが大量に張られたことがヤフー知恵袋でも過去多発していて一時期URL付き投稿を禁止したこともあるため、 可能であれば禁止にしておきたいです… ヤフー知恵袋のようにデフォルトでは書き込みOKにしてあまりにもひどい場合はブロックしたいのですが、関数は$strでいいのでしょうか? お問合せぺージ、検索フォーム、掲示板、記事コメント欄に設置したいと考えております。 //関数版? function CheckUrl($checkurl){ if(preg_match('/^(http|https|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i', $checkurl)){ return true; } return false; } //書き込みを調べてHTTPが含まれるURLの書き込み禁止 function CheckUrl($txtdata){ if (preg_match("/^(?!.*HTTP).+$/i",$txtdata) > 0){ return true; } return false; } //「http:またはftp:以外で始まる文字列」ならfalseで正規表現を使い不正なデータの入力を防ぐ(バリデーション) function CheckUrl($checkurl){ if(preg_match('/^(http|ftp)(:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)$/', $checkurl))? 'true': 'false'; } ※参考サイト ※URLチェック https://arkgame.com/2017/02/03/php%E5%85%A5%E9%96%80-%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE%E5%BC%8F%E3%81%A7%E8%8B%B1%E6%95%B0%E5%AD%97%E3%81%A8url%E3%82%92%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%81%99%E3%82%8B/ ※URL書き込み禁止 https://okwave.jp/qa/q5065030.html ※「文頭から最初の:までの間の文字列がhttp:またはftp:以外」ならばtrue、かつ「:がなければtrue」 https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1317261273?__ysp=aHR0cHPku6XlpJbjg5bjg63jg4Pjgq8gcHJlZ19tYXRjaA%3D%3D ※ヤフー知恵袋のURL付き投稿を禁止について https://www.japan-secure.com/entry/blog-entry-443.html#google_vignette ※正規表現一覧 https://qiita.com/lampt/items/675d7f96abd2776ae85d ※掲示板コード https://wandbox.org/permlink/O3xpi6vJpg0Q7HKp

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.13

・心配だったのでJavascriptでより厳重にチェックすべきではないかと考えております 不要だと思います。 第一に、JavaScriptはローカルにソースコードがあるので、 改ざんしたり無効にしたりできるため、あまり意味がありません。 第二に、PHPでhtmlspecialchars()にかけたものを、 JavaScriptでも同様なことをすると正しく表示されなくなります。 例えば、検索文字に <script> と入力したとします。 PHPでエスケープするとHTML内の文字列は &lt;script&gt; となります。 < と > が &lt; と &gt; に変換されます。 HTML内はエスケープされた文字列ですが、 ブラウザに表示されるのは <script> です。 これでJavaScriptとしては実行されなくなっています。 このエスケープされた文字に対して、以下のような変換をおこなうと、  str = str.replace(/&/g, '&amp;'); これは & を &amp; に置換するわけですが、 先ほどの &lt;script&gt; が &amp;lt;script&amp;gt; になってしまい、 ブラウザの表示も &amp;lt;script&amp;gt; となるので、  <script> が見れなくなってしまいます。 エスケープを重複するとおかしくなると言うことです。

php_learn
質問者

補足

アドバイスありがとうございます、2重に掛けることになるのですね… strip_tags()を使用したあとにhtmlspecialchars()を通したら、「許可するタグ」を指定してもブラウザ上でタグとは判断されないとのことだったので、下記コードを削除するのみにしておきます。 1点心配なことがるのですが、コメント欄にURLが投稿されるのを防ぐことは可能でしょうか? URLを投稿された際に危険なサイトに誘導される可能せいがあるため出来れば禁止しておきたいと考えております。 正規表現でブロックするのが良いのではないかと考えております。 // タグを除去 $str = strip_tags($str);

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.12

・検索フォームでJavascripを埋め込んで外部ページに飛ばされてしまうことに気が付きました。 それは試してみましたか。 本当に危ないんだ、と言う事を自分で試して把握しておいてくださいね。 ・対策をしておきたいのですが、コードをどのように変更すべきか分からないためアドバイスお願い致します。 参考サイトに書かれている htmlspecialchars()関数 を使えばよさそうです。 この関数はすでにお問い合わせで使っていますね。 そこでは他にもなにか対策されています。 ---- function Chk_StrMode($str) { // タグを除去 $str = strip_tags($str); // 空白を除去 $str = mb_ereg_replace('^( ){0,}', '', $str); $str = mb_ereg_replace('( ){0,}$', '', $str); $str = trim($str); // 特殊文字を HTML エンティティに変換する $str = htmlspecialchars($str); return $str; } ---- 例えば search.php で問題になるとしたらこの部分ですね。 送信された検索文字列を取得している部分です。 ---- $search_query = filter_input(INPUT_GET, 's'); ---- なので、ここで関数を使います。 ---- $search_query = filter_input(INPUT_GET, 's'); $search_query = htmlspecialchars($search_query); ---- もしくは、先の自作関数を使って、 ---- $search_query = filter_input(INPUT_GET, 's'); $search_query = Chk_StrMode($search_query); ---- 方法はこのように関数をひとつ呼ぶだけですので、他のコードも同じようにしてください。 自作関数を使う場合は、これを functions.php に定義するか、 すでに定義されている single-refication.php を読み込むか、 そのファイル自身に追加してください。

php_learn
質問者

お礼

A.回答ありがとうございます、参考サイトのJavascriptを入れたところ外部ページにリダイレクトされたため脆弱性はありそうです。 お問合せで使用した文字入力コードも見直しが必要なようです… どうやら $str = strip_tags($str); がXSSに対して警告されているようで、文字列からHTMLおよびPHPタグを取り除くことは特に必要ないように見えましたので、コードを削除する予定です。 よりセキュリティを高めるためにXSS対策に必要である特殊文字を文字参照に変換コードを考えてみました。 PHPではhtmlspecialcharsを使うことで対策出来るようですが、心配だったのでJavascriptでより厳重にチェックすべきではないかと考えております(XSSが一番強いウイルスとアドバイスを頂いたため)。 Javascriptで考えてみたのですが、出力の仕方がわからないため困っております。アドバイスお願い致します。 ※エスケープ <script> const escapeHTML = function (str) { //特殊文字を文字参照に変換 str = str.replace(/&/g,'&amp;'); str = str.replace(/</g, '&lt;') str = str.replace(/>/g, '&gt;') str = str.replace(/"/g, '&quot;') str = str.replace(/'/g, '''); str = .replace(/&/g, '&amp;'); str = .replace(/(\/\/)/g, '//') str = .replace(/\(/g, '(') str = .replace(/\)/g, ')') str = .replace(/\[/g, '[') str = .replace(/\]/g, ']') str = .replace(/\{/g, '{') str = .replace(/\}/g, '}'); return str; } /* 未入力チェックファンクション */ function Chk_InputMode($str,$mes){ $errmes = ""; if($str == ""){$errmes .= "{$mes}<br>\n";} return $errmes; } ※XSSについて https://qiita.com/hrdaya/items/4beebbdb57009b405d2d ※デコードは https://qiita.com/hrdaya/items/4beebbdb57009b405d2d ※strip_tagsの機能について https://tech.kurojica.com/archives/58923/ ※strip_tagsのXSS脆弱性警告 https://www.php.net/manual/ja/function.strip-tags.php#refsect1-function.strip-tags-notes https://gihyo.jp/dev/serial/01/php-security/0011

php_learn
質問者

補足

A.回答ありがとうございます、参考サイトのJavascriptを入れたところ外部ページにリダイレクトされたため脆弱性はありそうです。 お問合せで使用した文字入力コードも見直しが必要なようです… どうやら $str = strip_tags($str); がXSSに対して警告されているようで、文字列からHTMLおよびPHPタグを取り除くことは特に必要ないように見えましたので、コードを削除する予定です。 よりセキュリティを高めるためにXSS対策に必要である特殊文字を文字参照に変換コードを考えてみました。 PHPではhtmlspecialcharsを使うことで対策出来るようですが、心配だったのでJavascriptでより厳重にチェックすべきではないかと考えております(XSSが一番強いウイルスとアドバイスを頂いたため)。 Javascriptで考えてみたのですが、出力の仕方がわからないため困っております。アドバイスお願い致します。 ※エスケープ <script> const escapeHTML = function (str) { //特殊文字を文字参照に変換 str = str.replace(/&/g,'&amp;'); str = str.replace(/</g, '&lt;') str = str.replace(/>/g, '&gt;') str = str.replace(/"/g, '&quot;') str = str.replace(/'/g, '''); str = .replace(/&/g, '&amp;'); str = .replace(/(\/\/)/g, '//') str = .replace(/\(/g, '(') str = .replace(/\)/g, ')') str = .replace(/\[/g, '[') str = .replace(/\]/g, ']') str = .replace(/\{/g, '{') str = .replace(/\}/g, '}'); return str; } /* 未入力チェックファンクション */ function Chk_InputMode($str,$mes){ $errmes = ""; if($str == ""){$errmes .= "{$mes}<br>\n";} return $errmes; } ※XSSについて https://www.wantedly.com/companies/tsunagu-grp/post_articles/375157 https://qiita.com/hrdaya/items/4beebbdb57009b405d2d ※デコードは https://qiita.com/hrdaya/items/4beebbdb57009b405d2d ※strip_tagsの機能について https://tech.kurojica.com/archives/58923/ ※strip_tagsのXSS脆弱性警告 https://www.php.net/manual/ja/function.strip-tags.php#refsect1-function.strip-tags-notes https://gihyo.jp/dev/serial/01/php-security/0011

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.11

クロスサイトリクエストフォージェリについてですが、 質問者さまのサイトはログインしないで投稿できるので、 あまり関係ないような気がします。 なので現在のトークンだけでいいのではないでしょうか。

php_learn
質問者

補足

アドバイスありがとうございます、インターネットの調子が悪く回答が遅れてしまいました申し訳ありません。 コードを調べてみたところトークンだけで問題ないようでした。 XSSについて調べていた時に発見した下記のサイトを読んでいたところ検索フォームでJavascripを埋め込んで外部ページに飛ばされてしまうことに気が付きました。 対策をしておきたいのですが、コードをどのように変更すべきか分からないためアドバイスお願い致します。 ※該当ページ http://www.irasuto.cfbx.jp/ ※該当コード https://wandbox.org/permlink/RiyV4IkWjQaf2eVL ※参考サイト https://zenn.dev/ad5/articles/5e4e67c9663e4e0d0cb0

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.10

・single-complete.phpが回答可能なページになるのでしょうか? そうですね、そうなると思います。 ・原因を調べてみたところDEFAULT uuid();を設定時に取得に失敗しているようです。 本当にそうですか。 新しく投稿した質問のデータをphpMyAdminで確認するとunique_idに何か入っていませんか。 ・データベースのテーブル設計が難しく分かりませんでした、アドバイスお願い致します。 バイナリーで保存しなくていいと思います。 $_SERVER['REMOTE_ADDR']をそのまま保存すればいいと思います。 IPv4は最大で15文字(10進数3文字×4、区切り文字ピリオド×3)、 IPv6は最大で39文字(16進数4文字×8、区切り文字コロン×7)、 文字数が多いのはIPv6の39文字なので、 データベースにはvarchar(39)があればどちらの場合でも保存できます。 ---- ALTER TABLE `sortable` ADD `ip` varchar(39) NOT NULL; ---- single-regist.php ---- /* データベースに登録 */ $ip_address = $_SERVER['REMOTE_ADDR']; $sql = 'INSERT INTO sortable(message,namae,stamp,ip) VALUES(%s,%s,%d,%s)'; $query = $wpdb->prepare($sql, $_SESSION['message'], $_SESSION['namae'], $_SESSION['stamp'], $ip_address); ---- ・セキュリティについてお聞きしたところ掲示板、お問い合わせフォームともにすべてのセキュリティチェックの追加が必要なようです。 それはすでに対応されているはずです。 現在、セキュリティに関してこれとこれとこれを施しているけれども、他に追加すべきことはありますか、と言う質問をした方がいいと思います。 いただいているアドバイス内容からするとトークンのことについてですが、それはすでに施していますよね。

php_learn
質問者

補足

Q.本当にそうですか。 新しく投稿した質問のデータをphpMyAdminで確認するとunique_idに何か入っていませんか。 A.回答ありがとうございます、格納されているのですがuuid();を設定すると質問表示画面でindex.phpが表示されております。uuid();をなくした場合正常に表示されるようです。 Q.バイナリーで保存しなくていいと思います。 $_SERVER['REMOTE_ADDR']をそのまま保存すればいいと思います。 A.アドバイスありがとうございます、そのまま保存するように変更いたしました。 Q.それはすでに対応されているはずです。 現在、セキュリティに関してこれとこれとこれを施しているけれども、他に追加すべきことはありますか、と言う質問をした方がいいと思います。 いただいているアドバイス内容からするとトークンのことについてですが、それはすでに施していますよね。 A.回答ありがとうございます、質問の仕方が悪かったかもしれないです申し訳ありません。 いくつか調べてみたところ5つほど対策が必要なようです。 クロスサイトリクエストフォージェリで悩んでいるのですが、対策としてあがっているものと少し異なるためdell_okさんにお聞きしたいです。 入力画面 → 確認画面 → 登録処理のようなページが該当するのですが、秘密情報を「hidden パラメータ」に出力するようにして入力画面と確認画面でセッションIDの成否を調べる方法になるようです。 トークンで回避も可能なようですが実装方法に工夫が必要なようで何が基準になっているのか理解できず…アドバイスお願い致します。 ※トークンの実装方法について https://webukatu.com/wordpress/blog/11993/ ※トークンは使われているが脆弱性あり? https://teratail.com/questions/71592 ※引用文 まず、利用者の入力内容を確認画面として出力する際、合わせて秘密情報を「hidden パラメータ」に出力するようにします。この秘密情報は、セッション管理に使用しているセッションIDを用いる方法の他、セッションIDとは別のもうひとつのID(第2セッションID)をログイン時に生成して用いる方法等が考えられます。生成するIDは暗号論的擬似乱数生成器を用いて、第三者に予測困難なように生成する必要があります。次に確認画面から登録処理のリクエストを受けた際は、リクエスト内容に含まれる「hiddenパラメータ」の値と、秘密情報とを比較し、一致しない場合は登録処理を行わないようにします(脚注2)。このような実装であれば、攻撃者が「hiddenパラメータ」に出力された秘密情報を入手できなければ、攻撃は成立しません。 ※該当ページ https://www.ipa.go.jp/security/vuln/websecurity/csrf.html 上記のクロスサイトリクエストフォージェリ対策にセッションIDを使用した場合に別途気をつけるルールがあるようでした。 ※セッションIDをつける際のルール https://www.ipa.go.jp/security/vuln/websecurity/session-management.html ※対策済みか調べたもの SQLインジェクションはプレースホルダで対策ができるようで、Wordpressのprepareですべて対策ずみとなっておりました。 https://developer.wordpress.org/reference/classes/wpdb/prepare/ メールヘッダ・インジェクションはメールヘッダを固定値にして、外部からの入力はすべてメール本文に出力する必要があるのですが、。From ヘ ッダに"From:".mb_encode_mimeheader(WEBMST_NAME)."<".WEBMST_MAIL.">\n"; Subject ヘッダにWEBMST_NAME."お問い合わせ自動返信".$_POST['subject']; という固定値を設定しているため外部から与えられた入力値を挿入できないようになっておりました。

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.9

次の回答は17日以降になります。

php_learn
質問者

補足

セキュリティについてお聞きしたところ掲示板、お問い合わせフォームともにすべてのセキュリティチェックの追加が必要なようです。 index.php(ファイル還移)を必ず経由するような作りにしてもウイルスを送って攻撃を仕掛けられる危険があるようです。 お問合せ掲示板あわせて複数あるため、先にIPアドレスの方から対応していこうと考えております。 ※お問い合わせフォーム参考コード https://ara-web.net/blog/wordpress/post-3683/ ※アドバイス頂いた内容 プログラムが独立していても、1本でリクエスト分岐していても、送信処理は必ず存在してhiddenであれなんであれ、リクエストは必ず存在するため、最終リクエストには必ずトークンを埋め、処理前にかならず値を検証するべき。

関連するQ&A