• ベストアンサー

ヌルバイト攻撃の対策について

ヌルバイト攻撃の対策について教えて下さい。 一般的な"\0"を削除する方法なのですが、以下の場合ですと問題無ありません。が、 $arr = "abc\0def"; if (mb_strpos($arr, "\0")) { $arr = str_replace("\0", "", $arr); } echo $arr; ※結果:abcdef POST送信された値には、全く反応しません。 $arr = $_POST["arr"];//送信データは"abc\0def" if (mb_strpos($arr, "\0")) { $arr = str_replace("\0", "", $arr); } echo $arr; ※結果:abc\0def スクリプトコードはUTF-8で、magic_quotes_gpcはOffです。 他にどこをチェックすればよいかわからず投稿しました。 チェックすべきところを教えていただけないでしょうか? 宜しくお願いいたします。

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

  • ベストアンサー
  • hrm_mmm
  • ベストアンサー率63% (292/459)
回答No.5

formの入力欄に文字列として\0を入れたのならurlencodeされて、%5C0 となります。受信した時は、urldecode して文字\と文字0になるのでヌルバイトではありません。htmlにphpでヌルバイトを書き出してもブラウザ(operaでしかチェックしてませんが)は、その文字を無視します。データの終わりと認識するので。 $_POST をvar_dumpしてみるとよいです。 本当に悪意のあるプログラムからヌルバイトが送信されていたのなら、削除法は、ご呈示のコード str_replaceで出来ます。が、if文は必要ないとおもいます、該当文字が無ければ置き換えが行われないだけですし。また、該当文字が先頭にあった場合、0が返り、スルーされてしまいますので。もしif文で文字位置を調べるなら !== false でチェックすべきです。

warawara91
質問者

お礼

こんばんはhrm_mmmさん。 そういう事だったんですね。 とりあえずは問題無かったということで一安心です。 勉強になりました。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (4)

  • march4
  • ベストアンサー率50% (12/24)
回答No.4

>間違いは無いと思うのですが・・・ 設定方法的には問題なさそうですが、 何らかの理由で、 「結果的にその指定が、効いてない」場合も考えられますので、 大事なのは、 そのスクリプトにおいて、 「実際に効いているのか、効いていないのか」 を確認することかな、と思います。 よって、以下の方法で確認頂くとして。 (※phpinfo();によっても確認できますが。) get_magic_quotes_gpc(); →magic quotes gpc の現在の設定を得る (http://php.benscom.com/manual/ja/function.get-magic-quotes-gpc.php) //そのスクリプトにおける「magic quotes gpc」の設定をチェック //1:on 0:off echo get_magic_quotes_gpc(); ここにも問題がないとなると、困りましたね^^; ちなみに、POSTする値は、 「\0」以外にも、他の記号もエスケープされるのでしょうかね。 ダブル、シングルのクオテーションもエスケープされたり? 情報が多ければ、それだけ、レスも付きやすいかなと…。^^

warawara91
質問者

お礼

他のサーバーでも試してみましたが、同じ結果でした。 違う結果がでれば、何かヒントが得られるかと思ったのですが、なかなか手強いですね。 もう少しがんばってみます。 いろいろとありがとうございました。

warawara91
質問者

補足

>echo get_magic_quotes_gpc(); 結果は0でした。 >ダブル、シングルのクオテーションもエスケープされたり? 入力した状態でそのまま表示されますので、エスケープされていない状態かと思います。

全文を見る
すると、全ての回答が全文表示されます。
  • march4
  • ベストアンサー率50% (12/24)
回答No.3

ちょっと補足を・・・ >ということは、ポストされた値は何らかの処理がされていると考えるべきでしょうか? つまり、POST経由の場合、POSTで受け取った後の時点で、 「\0」が既に無害化(文字列の「\0」へと変えられてしまっている)ということなのだと思います。 しかし、「magic_quotes_gpcはOffです。」とのことなので… なんらかの経路で、無害化が行われていると思われます。 本当に、magic_quotes_gpcはOffになっておりますでしょうか。 phpinfo()で、今一度確認されてみてはいかがでしょう? ちなみに、テストサーバのphp.iniと、運用サーバのphp.iniで、 設定が異なることも考えられます。 そのあたりのケアレスミスなども、疑ってみると良いと思います。 このような偉そうなことを書いてますが、 私自身、それほど詳しい人間ではないので、 あくまで、参考程度にお読み下さい。^^; 変なことを言っている可能性は「大」ですから。笑

warawara91
質問者

補足

何度もありがとうございます。 .htaccessで指定してあり、.htaccessは対象ディレクトリに設置してあります。 php_flag magic_quotes_gpc Off 間違いは無いと思うのですが・・・ >なんらかの経路で、無害化が行われていると思われます。 やはり、これが一番疑わしいのでしょうか? 無害になっていれば、問題は無いと思いますが、原因がわからないと気持ち悪いですね。

全文を見る
すると、全ての回答が全文表示されます。
  • march4
  • ベストアンサー率50% (12/24)
回答No.2

こちらが参考になる気がします。 ttp://d.hatena.ne.jp/elseif/20080421/1208604585 上記ページをもとに、簡単にお話しすると、 注目すべきは、クオテーションです。 POSTでキャッチする値に含まれる「\0」をサニタイズ(洗浄)したいのであれば、 $arr = str_replace('\0', "", $arr); と、シングルクオテーションで「\0」をくくれば、 希望とする結果が得られると思います。 「\0」は、 ダブルクオテーションでくくると、展開されてヌルバイトとして機能し、 シングルでくくると、展開されずに文字列として扱われるようです。

warawara91
質問者

補足

お返事が遅くなりました。 シングルクオテーションは何度も試しましたが(もちろん今一度試しましたが)、結果は同じでした。

全文を見る
すると、全ての回答が全文表示されます。
  • march4
  • ベストアンサー率50% (12/24)
回答No.1

回答にはなっていないかもしれませんが、 $arr = "abc\0def"; //$arr = "abc\0def";をチェック echo var_dump($arr); echo '<br>'; echo mb_detect_encoding($arr); echo '<br>'; //-------------------------------------- //ポストで受け取った値をチェック echo var_dump($_POST["arr"]); echo '<br>'; echo mb_detect_encoding($_POST["arr"]); echo '<br>'; //-------------------------------------- として、両者を比較し、 データの型とか、文字コードの種類などに違いがないか、 チェックされてみたらいかがでしょうか。 同じ文字列であるはずの両者で、結果が異なるわけですから、 恐らく、両者の文字列で何らかの違いが生じているのでは、 と私は思います。 以上、参考までに。^^

warawara91
質問者

補足

こんにちはmarch4さん。 ありがとうございました。 以下、結果です。 > $arr = "abc\0def"; > //$arr = "abc\0def";をチェック > echo var_dump($arr); > echo '<br>'; > echo mb_detect_encoding($arr); > echo '<br>'; string(7) "abc�def" UTF-8 > //ポストで受け取った値をチェック > echo var_dump($_POST["arr"]); > echo '<br>'; > echo mb_detect_encoding($_POST["arr"]); > echo '<br>'; string(8) "abc\0def" UTF-8 ポストされてない方は文字化けしていません。 ということは、ポストされた値は何らかの処理がされていると考えるべきでしょうか?

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 「checkText3」が処理されない

    とあるHOWTO本を見ながら、独学でPHPを勉強中です。 サンプルプログラムを動作させようとマニュアル通りに記述してみたのですが、一部分だけが上手く処理されません。 付属CDに収められているphpファイル自体がこのような記述になっている為、マニュアル自体に間違いがあるのかな?と思うのですが、 どこがおかしいのか解らずにいます。 お分かりになる方がいれば、ご教授願えませんでしょうか? 上手く処理されないのは「//テキストチェック3.バイバイされたらバイバイを返す」の部分です。 よろしくお願い致します<(_ _)> <?php $res = ""; if(isset($_POST['text1']) == false) {$res = getAisatsu();} else{$text1 = $_POST['text1']; if($text1 == "") {$res = "え? なんていったの?";} else{$flag =false; //まずcheckTextであいさつ文をチェック $str = checkText($text1); if($str != false) {$flag = true; $res = $str; } //続いてcheckText2で悪口の対応 if($flag == false) {$str = checkText2($text1); if($str != false) {$flag = true; $res = $str; } } //最後にcheckText3でさよならの対応 if($flag == false) {$srt = checkText3($text1); if($str != false) {$flag = true; $res = $str; } } //すべてダメならテキストを分解してチェック if($flag == false) {$arr = bunkatsu($text1); foreach($arr as $str) {if(getWordCheck($str) == true) {$flag = true; $res = $str . "って、なぁに?"; break; } } } //それでもダメなら全文で聞き返す if($flag == false) {$res = delTouten($text1) . "って、なぁに?";} } } //時間によって異なるあいさつ文を返す function getAisatsu(){ $arr = array('……ね、眠い','おはよう!','こんにちは~','こんばんわ',); $d = getdate(); $t = $d['hours']; $t2 = (int)($t / 6); return $arr[$t2]; } //テキストチェック。あいさつ文があれば対応する挨拶を返す function checkText($s){ if($s == ""){return false;} $res = false; $data = array('こんにちは','こんにちわ','こんちは','こんちわ'); foreach($data as $str) {if (mb_strpos($s,$str) !== false) {$res = 'どうも、' . $str . '!'; break; } } return $res; } //テキストチェック2.悪口が書かれていたら文句をいう function checkText2($s) {if ($s ==""){return false;} $res = false; $data = array('バカ','馬鹿','あほ','アホ','阿呆'); foreach($data as $str) {if(mb_strpos($s,$str) !== false) {$res =$str . 'じゃないもん!'; break; } } return $res; } //テキストチェック3.バイバイされたらバイバイを返す function checkText3($s) {if ($s == ""){return false;} $res = false; $data = array('ばいばい','バイバイ','じゃあね'); foreach($data as $str) {if(mb_strpos($s,$str) !== false) {$res = 'それじゃ' . $str . '!'; break; } } return $res; } //句読点を削除する function delTouten($s) {$res = str_replace('。','',$s); $res = str_replace('?','',$res); $res = str_replace('!','',$res); $res = str_replace('.','',$s); $res = str_replace('?','',$res); $res = str_replace('!','',$res); return $res; } //テキストを句読点で分割し、配列として返す function bunkatsu($s) {mb_regex_encoding("sjis"); $res = mb_ereg_replace('[。、?!,.!?]','',$s); $arr = mb_split(' ',$res); return $arr; } //主語や接続詞が含まれているかを調べる function getWordCheck($s) {if ($s == ""){return false;} $res = $s; $data = array('私','わたし','僕','ぼく','俺','おれ','オレ'); foreach($data as $str) {if(mb_strpos($s,$str) !== false) {$res = false; break; } } return $res; } //サニタライズ function getSeftyText($s) {$res = str_replace("<","<",$s); $res = str_replace(">",">",$res); return $res; } ?>

    • ベストアンサー
    • PHP
  • 初めてばかりのPHPでメールフォーム作ったのですが

    メールフォームを制作したのですが、動いたのはいいのですが、 別々にformの値を送っているのですが、うまく動きません。 どうしたらいいでしょうか? mb_language("Japanese"); mb_internal_encoding("UTF-8"); if($_SERVER['REQUEST_METHOD']=="POST"){ $array = array(); $vacation_radio = htmlspecialchars($_POST["vacation_radio"], ENT_QUOTES); $name = htmlspecialchars($_POST["name"], ENT_QUOTES); $vacation_helo = htmlspecialchars($_POST["vacation_helo"], ENT_QUOTES); $kanso = htmlspecialchars($_POST["kanso"], ENT_QUOTES); $h = htmlspecialchars($_POST["h"], ENT_QUOTES); $m = htmlspecialchars($_POST["m"], ENT_QUOTES); if(isset($_POST["vacation"])){ $vacation_radio_search = array("1", "2", "3"); $vacation_radio_replace = array('午前', '午後', '深夜); $vacation_radio_a = str_replace($vacation_radio_search, $vacation_radio_replace, $vacation_radio); $vacation_helo_search = array("5", "6"); $vacation_helo_replace = array('おはようございます。', 'おつかれさまです。'); $vacation_helo_a = str_replace($vacation_helo_search, $vacation_helo_replace, $vacation_helo); mb_convert_variables('UTF-8', 'EUC-JP', $name); mb_convert_variables('UTF-8', 'EUC-JP', $kanso); $mail_object = "ITSG ". $vacation_radio_a ." ". $name ; $mail_ob = $vacation_helo_a. "\n". $name ."\n\n". $vacation_radio_a ."\n". $kanso; if (mb_send_mail("test@test.com", $mail_object, $mail_ob, "From: test@test.com")) { echo "メールが送信されました。"; } else { echo "メールの送信に失敗しました。"; } } if(isset($_POST["flex"])) { $vacation_helo_search = array("7", "8"); $vacation_helo_replace = array('おはようございます。', 'おつかれさまです。'); $vacation_helo_a = str_replace($vacation_helo_search, $vacation_helo_replace, $vacation_helo); mb_convert_variables('UTF-8', 'EUC-JP', $name); mb_convert_variables('UTF-8', 'EUC-JP', $kanso); $mail_object_a = $name . " " . $h . ":" . $m ; //$mail_ob_a = $vacation_helo_a. "\n". $name ."\n\n". $h .":" . $m ."\n". $kanso; $mail_ob_a = $vacation_helo_a; if (mb_send_mail("test@test.com", $mail_object_a, $mail_ob_a, "From: test@test.com")) { echo "メールが送信されました。"; } else { echo "メールの送信に失敗しました。"; } } } flexの7と8の値が帰って来ません。 どうしたらよいのでしょうか? わからないなりにつくってみたのでソースが汚いと思いますが、よろしくお願い致します。

    • ベストアンサー
    • PHP
  • str_replace()で、なぜ置き換わらないのでしょうか?

    下記でエスケープのtestをしていますが、何故か& の置換えが出来ず、「abc & def」としか表示されません。 <?php $memo="abc & def"; $memo=str_replace('&','&amp',$memo); echo $memo; ?> 幼稚な質問で恐縮ですが、どこが不具合の原因か教えて頂けるとありがたいです。

    • ベストアンサー
    • PHP
  • 改行処理がうまくいきません

    今現在、PHPで掲示板を運用しています。 PHP初心者です。 掲示板で訪問者のユーザーのコメントを以下のように処理しています。 $post_arr[$h] = htmlspecialchars($post_arr[$h]); $post_arr[$h] = str_replace("\r\n", "\r", $post_arr[$h]); $post_arr[$h] = str_replace("\r", "\n", $post_arr[$h]); $post_arr[$h] = str_replace("\n", "<br>", $post_arr[$h]); 改行→<br>変換を行っているのですが、ごくたまに(特定の訪問者)改行処理がされず困っています。 これをcsvでログを保存しているのですが、<br>処理をされずデータがずれてしまいます。 ログを調べるとその訪問者の方は、古いものをお使いなのかなと思いましたが、WIN XP,IE6でしたので訪問者側に問題ないと思うのですが。 初心者で大変恐縮ですが、ご返答よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • バックスラッシュの対策について

    formでデータを送信するとバックスラッシュが入ってしまうので、stripslashes()で処理しています。 POSTでデータを送信しているのですが、 $prmarray_post = $_POST; $data1 = stripslashes($prmarray_post["data1"]); というような処理だと大丈夫なのですが、受け取るデータがいくつもあるので function cnv_formstr($array) { foreach($array as $k => $v){ if (get_magic_quotes_gpc()) { $v = stripslashes($v); } $v = htmlspecialchars($v, ENT_QUOTES); $$k = $v; } return $array; } $prmarray_post = cnv_formstr($_POST); $data1 = $prmarray_post["data1"]; という感じでやりたいのですが、これだとうまくいきません。 どのようにすればよいのでしょうか。 よろしくお願いしますm(__)m

    • ベストアンサー
    • PHP
  • C++文字列の挿入、結合のコードについて

    実行結果のような出力をするためには、 以下のコードの(ウ)(エ)(オ)の部分には何を入れたらよいのでしょうか? よろしくお願いします。 #include <iostream> #include <string> using namespace std; int main( ) { string str1="ABCDEF"; string str2="0123"; string str3; string q; do { (ウ) ; cout << str3 << endl; (エ) ; cout << str1 << endl; cout << "quit?"; cin >> q; } while ( (オ) ); cout << "終了" << endl; return 0; } <実行結果(出力結果)> ABCDEF0123 ABC123DEF quit?q ABC123DEF0123 ABC123123DEF quit?qu ABC123123DEF0123 ABC123123123DEF quit?quit 終了

  • チェックボックスが複数選択できない

    アンケートフォームを作成していますが、チェックボックスで複数項目を選択しても最後のひとつしか表示されずに困っています。 配列での処理にすれば良いという事なので自分なりにやってみたのですが、今度は「Array」と表示されてしまい、具体的にどうしたらいいのか分かりません。 ※html側 <input type="checkbox" name="cat[]" value="abc"> <input type="checkbox" name="cat[]" value="def"> ※php側 <FORM action="<? echo $script; ?>" method="POST"> <? echo $err_message; ?> <?php foreach($_POST as $key=>$var) { $key = strtr($key, $string_from, $string_to); if(get_magic_quotes_gpc()) $var = stripslashes($var); $var = htmlspecialchars($var); print("項目:".$key."選択したのは".$var); ?> <INPUT type="hidden" name="<?= $key ?>" value="<?= $var ?>"> <?php print("です。\n"); } ?> となっています。 また、選択内容をメール送信するようになっており、 foreach($_POST as $key=>$var) { $key = strtr($key, $string_from, $string_to); if(get_magic_quotes_gpc()) $var = stripslashes($var); if($var == "eweb_submit") ; else $rebody.="[".$key."] ".$var."\n"; です。 複数項目をまとめて処理しているようで、どうしたらいいのか分かりません。ちなみに、http://www.eweb-design.com/のフリーのメールフォームを使っています。

    • ベストアンサー
    • PHP
  • PHPです2つのスクリプトの相違がわかりません

    PHPですが、以下の2つのスクリプトで同じ結果がでると思ったのですが現実は違いました。 henkan.php <html> <body> <?php $uketori=$_POST['UKETORI']; $uketori=str_replace("pen","pencil", $uketori); $uketori=strtoupper($uketori); print "$uketori"; ?> </body> </html> henkan2.php <?php $str=$_POST['UKETORI']; echo str_replace("です。","だよん。", $str) . "<br>\n"; echo "<br>\n"; echo mb_ereg_replace("です。","だよん。", $str) . "<br>\n"; echo "<br>\n"; ?> フォームに です。 という文字を入れたら変換されて だよん。 と表示さしたいのですが、上の2つで相違がでました。なぜなんでしょうか。 henkan.php では変換されませんでした。 henkan2.php では変換されました。

    • ベストアンサー
    • PHP
  • エスケープ解除

    以下のようなPHP構文の時に、 magic_quotes_gpcがOnであっっとしたら、 どのようにエスケープを解除すればいいのでしょうか? // フォームの値を取得します。 if ($_SERVER["REQUEST_METHOD"] == "POST") { foreach($_POST as $k = $v){ // 「magic_quotes_gpc = On」のときはエスケープ解除 if (get_magic_quotes_gpc()) { $v = stripslashes($v); } $v = htmlspecialchars($v); $$k = $v; } } else { exit(); }

    • 締切済み
    • PHP
  • エスケープ文字にstr_replaceが効かない

    フォームで送信された文字列のうち、str_replace関数を使って半角記号を全角記号に置換したいのですが、一部のエスケープ文字が含まれている文字列の置換が上手くいきません。 ソースは以下に記しますが、現状では、"(ダブルクォート)は\&quot;、&(半角アンド)は&amp;と置換されてしまいます。 この場合であれば、”(全角ダブルクォート),&(全角アンド)と出力させたいのですが・・・ どなたかお気づきの点ありましたらご教示宜しくお願いします! ===============ソースコード================================= <?php $system = ""; if (isset($_POST["submit"])) { $system = htmlspecialchars($_POST["system"], ENT_QUOTES); $system = mb_convert_encoding($system, "EUC-JP", "SJIS"); $system = str_replace('&', '&', $system); $system = str_replace('"', '”', $system); $system = str_replace('あ', '”', $system); $_SESSION["system"] = $system; } $str = <<<STRING <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> </head> <body> <form method="post" action="{$SERVER['PHP_SELF']}" enctype="multipart/form-data" > <textarea name="system" cols=40 rows=5 wrap=soft>{$system}</textarea> <input type="submit" name="submit" value="送信"> </form> ----------------------------------------------------------<br> {$_SESSION["system"]} </body> </html> STRING; $str = mb_convert_encoding($str, "SJIS", "EUC-JP"); echo $str; ?> ============================================================ ちなみに、『あ』→『”(全角ダブルクォート)』と、正しく置換されます。

    • ベストアンサー
    • PHP