GETで数値を取得する際のセキュリティ対策

このQ&Aのポイント
  • GETリクエストで数値を取得する際、pagesパラメータのセキュリティ対策について検討しています。
  • 現在の実装では、入力値が数値のみであるかを正規表現でチェックし、正当な整数値であればその値を、そうでなければ0を設定しています。
  • ただし、パラメータが設定されていない場合は初期値として1を設定しています。改善点や危険な部分があればご指摘ください。
回答を見る
  • ベストアンサー

GETで数値を取得する際のセキュリティ

サイト内検索で検索結果を複数ページに分割して表示する際に、URLにpagesというパラメータを設定して、そこに何ページ目かという数字(整数)を入れています。 一応、色々なサイトを参考にpagesをGETして取得する際のセキュリティ対策については講じたつもりなのですが、自信がありません。以下がその部分のソースです。 $pages = htmlspecialchars($_GET['pages']); if(preg_match("/.+/",$pages)){     if(preg_match("/^[0-9]+$/", $pages)){         $pages = intval($pages);     }     else {         $pages = 0;     } } else {     $pages = 1; } 仕様としては、pagesが検索結果数から算出される総ページ数に対して正当な整数値だった場合はその数値を、正当でない場合(数値以外も含む)は0を、パラメータが設定されていない場合は1を$pagesに代入します。 上記のソースでどこか危ない部分や改善すべき部分がありましたら、教えてください。

  • PHP
  • 回答数1
  • ありがとう数1

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

  • ベストアンサー
  • mizutaki
  • ベストアンサー率33% (111/333)
回答No.1

http://php.net/manual/ja/function.htmlspecialchars.php htmlspecialcharsはいくつかの項目をHTMLで出力する際に、そのままの文字列で表示できるように、文字の置き換えをするための関数です。 つまり、文字列を扱う際に使用する関数なので、今回の処理には一切の必要性がありません。 $pages = isset($_GET['pages'][0])? (int)$_GET['pages'] : 1; この1行であなたが書いたソースコードと基本同じ動きが出来ます。 ・三項演算子を使用し、$_GET['pages']の1文字目に何かしらの文字が入っていた場合は、GETの値を数列にキャストする(intvalとまったく同じ動き。(int)の方が少し処理速度が速く、ソースコードが短いくらい。慣れてないならintvalの方が見やすいかも) 文字列が入っていない場合は1を$pagesに代入。 まぁ、pagesに値を入れる際に若干違う処理が入るのであればif文で書く必要があるので、あくまで参考程度 セキュリティに関してはいろんなパターンがあるので、一応にいえないのですが、 文字列を文字列として扱い、保存したり表示する際に、セキュリティの穴が出来やすい。 数列を扱う場合は、使用されると困る数値があるかどうかくらいがキーになります(マイナスとか0,1のみしか許さない部分とか)

twinhourse
質問者

お礼

バッチリ動きました。 確かにhtmlspecialcharsは文字列のための関数なんですが、今回もセキュリティ的に必要なのかなと思っていました。 あと、たった1行になるのは驚きでした。しかし、こっちの方が機能的にもスマートなようですね。本当にありがとうございます。

関連するQ&A

  • PHPで似たコードを繰り返す場合の簡潔な書き方??

    ご質問失礼します。 PHPでデータベースのデータを下記のようなコードを使い表示しています。 ※質問内容に該当する一部のみ記載させていただいています ・ ・ ・ ・ ・ if(preg_match("/新規/", $row['status1'])){ $table .= $row['status1']." 新規です"; } else { if(preg_match("/更新/", $row['status1'])){ $table .= $row['status1']." 更新です"; } else { if(preg_match("/削除/", $row['status1'])){ $table .= $row['status1']." 削除です"; } else { $table .= "いません"; } } } if(preg_match("/新規/", $row['status2'])){ $table .= $row['status2']." 新規です"; } else { if(preg_match("/更新/", $row['status2'])){ $table .= $row['status2']." 更新です"; } else { if(preg_match("/削除/", $row['status2'])){ $table .= $row['status2']." 削除です"; } else { $table .= "いません"; } } } if(preg_match("/新規/", $row['status3'])){ $table .= $row['status3']." 新規です"; } else { if(preg_match("/更新/", $row['status3'])){ $table .= $row['status3']." 更新です"; } else { ・ ・ ・ ・ ・ ・ status1から、5つあればstatus5まで、似たようなPHPを繰り返し書いて動作させています。 このような場合、簡潔に書く方法などありますでしょうか。 ご存知の方いらっしゃいましたらお時間のある際にお教え下さいませんでしょうか。 また、簡潔に書く方法がない場合でも無いとお教えいただければ幸いです(○ `人´ ○)

    • ベストアンサー
    • PHP
  • SB携帯のサブスクライバID取得について

    はじめて投稿いたしました。 この度、携帯で会員制のコンテンツをリリースする予定でおりまして、 会員認証の場面等でサブスクライバIDをキーとしてユーザー判別を行お うとしております。 そこで、色々なサイトを参考とさせて頂きながら、下記の様なソースで サブスクライバIDを取得を試みました。 その結果、ドコモとAUは問題ありませんでしたが、SB携帯だけサブスクラ イバIDの取得ができませんでした。 SB公式サイトや各種情報サイトを参考に、色々ソースをいじってみたので すが、どーにも取得できません。 恐れ入りますが、どなたかお分かりになる方、不具合点のご指摘をお願い 申し上げます。 ---以下、ソース------------------------ $UA = $_SERVER['HTTP_USER_AGENT']; $HostName = @gethostbyaddr($_SERVER['REMOTE_ADDR']); // DoCoMo if ( preg_match("/.docomo.ne.jp/", $HostName) ) { preg_match("/ser([a-zA-Z0-9]+)/",$UA, $dprg); if ( strlen($dprg[1]) === 11 ) { $MobileInfo = $dprg[1]; } elseif ( strlen($dprg[1]) === 15 ) { $MobileInfo = $dprg[1]; preg_match("/icc([a-zA-Z0-9]+)/",$UA, $dpeg); if ( strlen($dpeg[1]) === 20 ) { $MobileInfo = $dpeg[1]; } else { $MobileInfo = false; } } else { $MobileInfo = false; } } //SBの処理はここから elseif( preg_match("Vodafone",$UA) || preg_match("SoftBank",$UA ) ) { // SoftBank if ( preg_match("//SN([a-zA-Z0-9]+)//",$UA,$vprg) ) { $MobileInfo = $vprg[1]; } else { $MobileInfo = false; } } //SBの処理はここまで elseif ( preg_match("/.ezweb.ne.jp/", $HostName) ) { // au $MobileInfo = $_SERVER['HTTP_X_UP_SUBNO']; }

    • 締切済み
    • PHP
  • PHPで<title>タグ取得の動作が非常に重い

    PHPで<title>タグ取得の動作が非常に重い $html = file_get_contents($url); if(preg_match( "/<title>(.*?)<\/title>/i", $html, $match)) { } 上記のような方法で一度に(1ページ内で)30サイトほどの<title>タグを取得すると、不可がかかり、表示までにかなり時間がかかってしまいます。 preg_match では重いのでしょうか。 それとも一度に30サイトはそもそも無理があるのでしょうか。。

    • ベストアンサー
    • PHP
  • phpでif文内で&の記述に疑問が・・・

    とあるphpを見ていると、 $num = 90; $hom = 4; $list = '<rock>sale</rock>'; if(intval($num) & $hom && preg_match("/^<\/rock>$/", $list)){ ・・・ } というif文がありました。 これはどういった意味でしょうか? intval、preg_matchは理解できます。 また論理演算子の&&も理解できます。 $homeの直前にある&の働きがよくわかりません。 if文を日本語で直訳するとどういった意味になるのでしょうか? よろしくお願い致します。

    • ベストアンサー
    • PHP
  • v5.58でGETパラメータの取得

    サーバの移転に伴いアクセスログの移転をしているのですが、特定の機能だけ動きません。 どうもGETでパラメータが取得できていないようです。 GETパラメータの取得には *decode = &parseInput($ENV{'REQUEST_METHOD'}); $act = ($decode{'・・・'}); としています。 しかいこの$actに何も取れていないようなんです。 $actの値によってifで条件分岐しているのですが、elseになってしまい 正常に動きません。 他の機能では正常に動いているのですが、原因が分からず困っています。 どなたかご教授頂けないでしょうか? PHPはある程度わかるのですが、Perlは全然わかりませんので、大苦戦中です。 どうかご教授をお願いします。

    • ベストアンサー
    • Perl
  • preg_matchと定数について

    preg_matchと定数について $string = "○○ドメイン"; if (preg_match("/$string/", $_SERVER['SERVER_NAME'])) {  echo "○"; } else {  echo "✕"; とやると○になるのですが、 define("DOMAIN", "○○ドメイン"); if (preg_match("/DOMAIN/", $_SERVER['SERVER_NAME'])) {  echo "○"; } else {  echo "✕"; } とすると、✕になります。 なぜでしょうか?

    • ベストアンサー
    • PHP
  • file_get_contents 画像直URL

    file_get_contents($url);した際、画像の直URLがあったら、画像をローカルに保存して、URLを書き換えたいのですが、どうやればいいでしょうか? if(preg_match("/http:\/\//", file_get_contents($url))) { ?? } また、画像をローカルに保存って、PHPで出来るのでしょうか?

    • ベストアンサー
    • PHP
  • マッチ情報を取得

    $yahoo = file_get_contents(http://www.yahoo.co.jp/) で取得したソース情報の中から特定の情報だけを抜き取りたいのですが・・・。 正規表現 preg_match()などを使って欲しい情報があれば、特定の範囲を抜き取りするのかな?と思うのですが・・・。 いまいちやり方がわかっていません。 アドバイスお願いします。

    • 締切済み
    • PHP
  • i Phone 用振り分け

    以下のように携帯キャリアごとに振り分け、3キャリア以外は PCフォルダに振り分けるようにした場合ですが、PCフォルダの方で i Phone 用に幅480pxで作成したページを配置すると PCから http://mypage.net/ でアクセスしたユーザーにも i Phone 用の幅480pxページを見せるようになってしまいますか? i Phoneやスマートフォンの対処はどうされているんでしょうか? <?php $agent = $_SERVER['HTTP_USER_AGENT']; if(preg_match("/^DoCoMo/i", $agent)){ header("Location: http://mypage.net/i/index.html"); exit; }else if(preg_match("/^(J\-PHONE|Vodafone|MOT\-[CV]|SoftBank)/i", $agent)){ header("Location: http://mypage.net/s/index.html"); exit; }else if(preg_match("/^KDDI\-/i", $agent) || preg_match("/UP\.Browser/i", $agent)){ header("Location: http://mypage.net/e/index.html"); exit; }else{ header("Location: http://mypage.net/pc/index.html"); exit; } ?>

    • ベストアンサー
    • PHP
  • 特定の文字列が含むときに、専用の処理をさせたい

    最後に「_asc」「_desc」をつけた文字列がいくつかあります。 それを$_GET['aaa']で送り、そこから ・「_asc」「_desc」を削除した文字列だけにし ・「_asc」ならascという文字列を$mmmに「_desc」ならdescを$mmmに ということをしたいです。 $str = "id"; $mmm = 'asc'; if(isset($_GET['aaa'])){ $str = $_GET['aaa']; if(preg_match("/_asc$/i", $str)){ $str = rtrim ($str, "_asc"); }else if(preg_match("/_desc$/i", $str)){ $str = rtrim ($str, "_desc"); $mmm = 'desc'; } } このようにしてみたのですが、上手にできませんでした。 もっといい方法はないでしょうか。

    • ベストアンサー
    • PHP

専門家に質問してみよう