• 締切済み

SQLインジェンクション対応について

現在、PHPでのセキュリティ対策の一環として、SQLインジェンクション対応のためのユーザ入力値をチェックするための関数を検討しています。 以下のサイトなどを参考に、以下のようなサンプルコードを検討してみました。 特筆すべき点は、PHPのマジッククォートがONになっているかどうかのチェックを最初に入れ、余分に不正コードをエスケープしないようにしたことでしょうか。 あまりセキュリティについて詳しくないので、有識者の方の見解を伺いたく投稿いたしました。その他付け加えるべきチェックなどありましたら、ご意見賜りたく存じます。 (参考にしたサイト) http://jp.php.net/manual/ja/security.database.sql-injection.php (サンプルコード) function str_check($value) { // strip slashes if (get_magic_quotes_gpc()) { $value = stripslashes($value); } // quote except numbers if (!is_numeric($value)) { $value = "'" . mysql_real_escape_string($value) . "'"; } return $value; } (使用例) $query = sprintf("SELECT * FROM users WHERE user=%s AND password=%s", str_chec($_POST['username']), str_chec($_POST['password'])); mysql_query($query);

みんなの回答

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.2

インジェクション処理にはやりすぎと言うものはありません。 どんなにチェックしても抜けるときは抜けますので 「余分にエスケープしない」など考える余裕はないはずです。 以下注意すると方針がきめやすくなると思います ・基本はエスケープしづらいshiftjisは排除する。 ・各SQL用に用意されたエスケープ関数は積極的に使う  例:mysql_real_escape_string()とかpg_escape_string() ・怪しいデータがとんできたときはとにかく早期にはじく

ny_cs
質問者

お礼

ご指摘ありがとうございました。いただいたコメントを踏まえ、もう少し考えてみます。

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

無識者です. 処理の定義域と値域を考えることが大切です. 処理が何を入力として取り,何を出力するかですね. str_checで考えれば,定義域はユーザIDか,パスワードですが 単に何かの文字列というだけで何が入っているかや長さは不明です. JavaScriptで入力を制限していたとしても,攻撃者の作ったフォームから送信されたら終わりですね. ですから,値域はstripslashesでバックスラッシュが取り除かれ mysql_real_escape_stringでエスケープ関連の文字が取り除かれ?た長さ不明の文字列です. 英数字以外に漢字やひらがなが混じっているかもしれません. 次にsprintfですが,入力が何が入っているともわからない長さ不明の(いちおう危なそうな文字は除いた)文字列が定義域です. となると,値域はSQL文に内容不明の文字列が含まれる長さ不明の文字列です. という風に,考えていくとあなたがSQL文に与えるクエリは内容不明,長さ不明の危なっかしい文字列だと言うことになります. ユーザ名とパスの文字種別と長さを確認するだけでだいぶよくなります. またこの場合は処理の大半が外部の関数に丸投げされていますが 使っている関数の入出力,それが本当に信用できるかも確認した方が良いです. 古いバージョンなら既知の脆弱性がある可能性がありますし, 新しい脆弱性が見つかる可能性があるのでこまめに確認が必要です. と,素人が何となく思い浮かぶくらいでこれくらいありますね. 間違った内容があるかもしれませんが,プロならもっと考慮すべき事項があるかもしれません.

ny_cs
質問者

お礼

詳細なコメントありがとうございました。 たしかに、セキュリティ対策って対策を施してもまた破られたり、イタチごっこだったりすることもあるので、難しいですよね。いろいろな観点から、もう少し考えをめぐらせてみます。

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

関連するQ&A

  • SQLインジェクションの危険性について[MYSQL]

    下記のコードはPHPプログラマ一年生の自分から見ても、 POST入力値をチェックしていない危険なコード(一部を抜粋)だと 思うのですが先輩は問題ないと言い、修正する気がありません。 そこで、SQLインジェクションのようなSQL文を送信された場合に ユーザー名とパスワードが表示されれば納得すると思い いろいろテストしてみたのですが、うまく表示されません。 実はSQLインジェクションなどの問題ないソースなのでしょうか? ご教授、よろしくお願いいたします。 ■テーブル構成(ユーザ・パスワード管理テーブル) CREATE TABLE `sample`.`test` ( `user_id` INT NOT NULL , `passwd` VARCHAR( 32 ) NOT NULL ) ■問題の処理分 <?php $user_val = "" ; $pass_val = "" ; if (isset($_POST["user_id"]) == TRUE) {   $mysql_c = mysql_pconnect('******' , "******" , "******");   mysql_select_db("******" , $mysql_c);   $sql = 'select * from test where user_id = ' . $_POST["user_id"] ;   $result = mysql_query($sql , $mysql_c);   if ( $result != false)   {     if(($row = mysql_fetch_object($result)) != false )     {       // パスワードチェック       if ( $row->passwd != $_POST["pass"] )       {         echo "check NG" ;       }       else       {         $user_val = $row->user_id ;         $pass_val = $row->passwd ;       }     }   } } ?> <FORM action="index.php" method="post" > <input type="text" name="user_id" value="<?php echo $user_val ?>" > <input type="text" name="pass" value="<?php echo $pass_val ?>" > <input type="submit"> </FORM>

    • ベストアンサー
    • MySQL
  • 簡単なif文でちゃんと分岐しません

    今参考書を見ながらやっていますがうまくいきません。 postからusernameとpasswordの値を受け取って処理する スクリプトなんですが、うまく作動してくれません。 ■問題点 分岐点が4箇所ありますが、 パスワードだけ間違っても、すべて■1■ ログイン処理状態になります。 どうしてもパスワード再設定の画面に切り替わりません。 入力されたデータはデータベースにきちんと入ります。 3日間これで悩んでいて、ついに投稿してみました。 こんなこともわからない私ですが なんとかお願い致します。 ----ここから---- <?php session_start(); $username = $_POST["username"]; $sql = "SELECT * FROM `art_users` WHERE `user_name` = '%{$username}%'"; $query = mysql_query($sql) or die("データ追加エラー" . mysql_error()); $record = mysql_fetch_array($query, MYSQL_ASSOC); if ( $_POST["mode"] == "login" && mysql_num_rows($query) > 0 && $_POST["password"] == $record["user_password"] ) { $_SESSION["userid"] = $record["user_id"]; header("Location: kaukau_top.php"); } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>ログイン処理</title> </head> <body> <?php // ■1■ ログイン処理状態 if ( $_POST["mode"] == "login" ) { // 新規登録:クエリ実行結果が0行=既存ユーザー名と一致しない if ( mysql_num_rows($query) == 0 ) { echo '新規ユーザー登録<br>'; echo '<form action="kaukau_login.php" method="POST">'; echo '<input type="hidden" name="mode" value="register">'; echo '<input type="submit" value="登録">'; echo '</form>'; } // パスワードミス:クエリ実行結果のパスワードと入力されたパスワードが一致しない elseif ( $_POST["password"] != $record["user_password"] ) { echo 'パスワードが違います。<br>'; echo 'ひみつの質問に答えると、パスワードを変更できます。<br>'; echo '<form action="kaukau_login.php" method="POST">'; echo '<input type="hidden" name="username" value="' . $username . '">'; echo '<input type="hidden" name="mode" value="resetpassword">'; echo '<input type="submit" value="送信">'; echo '</form>'; } } // ■2■ パスワード再設定状態 elseif ( $_POST["mode"] == "resetpassword" ) { if( $record["user_answer"] == $_POST["answer"] ) { echo 'パスワード再設定<br>'; echo '<form action="kaukau_login.php" method="POST">'; echo '<input type="hidden" name="username" value="' . $username . '">'; echo '<input type="hidden" name="mode" value="modifypassword">'; echo '<input type="submit" value="登録">'; echo '</form>'; } else{ echo "ひみつの答えが違います"; } } // ■3■ 新規ユーザー登録状態 elseif ( $_POST["mode"] == "register" ) { if( $_POST["password"] == $_POST["confirm"] ) { $sql = "INSERT INTO users (user_name, user_password, user_question, user_answer) VALUES ("; $sql .= " '" . $_POST["username"] ."',"; $sql .= " '" . $_POST["password"] ."',"; $sql .= " '" . $_POST["question"] ."',"; $sql .= " '" . $_POST["answer"] ."')"; $result = mysql_query($sql); echo '登録しました。'; } else { echo 'パスワードを再確認してください。'; } } // ■4■ パスワード変更状態 elseif ( $_POST["mode"] == "modifypassword" ) { if ( $_POST["password"] == $_POST["confirm"] ) { $sql = "UPDATE users"; $sql .= " SET user_password = '" . $_POST["password"] . "'"; $sql .= " WHERE user_name = '" . $_POST["username"] . "'"; mysql_query( $db, $sql ); echo '登録しました。'; } else { echo 'パスワードを再確認してください。'; } } ?> </body> </html>

    • 締切済み
    • PHP
  • MySQLに日本語を登録すると文字化けする

    お世話になります。 PHPを使用して日本語文字を登録しようとすると文字化けします。 どこをどのようにすれば文字化けはなおるのでしょうか? ソースは以下で書いています。 よろしくお願いします。 <?php function blank($value){ if(isset($value)){ if(is_array($value)){ return count($value)==0; }else{ return $value==""; } } return true; } if(blank($_POST["phonenumber"])||blank($_POST["password"])||blank($_POST["name"])||blank($_POST["mail"])){ ?> <p>名前、E-mail、携帯番号またはパスワードを入力してください</p> <p><a href="input.html">戻る</a></p> <?php }else{ $name= $_POST["name"]; $mail= $_POST["mail"]; $phonenumber = $_POST["phonenumber"]; $password= $_POST["password"]; $link=mysql_connect("localhost","id","password"); if(!$link){ die("データベースに接続できません"); } $db=mysql_select_db("id"); if(!$db){ die("データベースを選択できません"); } $sql=<<<SQL insert into password(phonenumber,password,name,mail)value("{$phonenumber}","{$password}","{$name}","{$mail}") SQL; $result=mysql_query($sql,$link); if(!$result){ die("同じ携帯番号で登録済です。"); }else{ print("正常に登録が終了しました"); } } ?>

    • ベストアンサー
    • PHP
  • phpのif文について

    phpでログイン処理のif文を書いています。 nameとpasswordのフィールドが記入されているのかをチェックするif文を書いたのですが、機能してくれません。何かが間違っているのでしょうか。 何も入力しないor間違った情報を入力する ということをしてもログインが出来てしまいます。 どなたかテェックお願い致します。 <?php require('dbconnect.php'); session_start(); if ($_COOKIE['name'] != '') { $_POST['name'] = $_COOKIE['name']; $_POST['password'] = $_COOKIE['password']; $_POST['save'] = 'on'; } if (!empty($_POST)) { // ログインの処理 if ($_POST['name'] != '' && $_POST['password'] != '') { $sql = sprintf('SELECT * FROM members WHERE name="%s" AND password="%s"', mysql_real_escape_string($_POST['name']), sha1(mysql_real_escape_string($_POST['password'])) ); $record = mysql_query($sql) or die(mysql_error()); if ($table = mysql_fetch_assoc($record)) { // ログイン成功 $_SESSION['id'] = $table['id']; $_SESSION['time'] = time(); // ログイン情報を記録する if ($_POST['save'] == 'on') { setcookie('name', $_POST['name'], time()+60*60*24*14); setcookie('password', $_POST['password'], time()+60*60*24*14); } header('Location: index.php'); exit(); } else { $error['login'] = 'failed'; } } else { $error['login'] = 'blank'; } } ?>

    • ベストアンサー
    • PHP
  • php sqlでログイン認証システムについてです。

    このようなソースを書いてログインシステムを書いています。 ここで接続はできたのですが、クエリーが失敗しましたと出てきます。 このソースをどのように修正すればよいのかアドバイスお願いできないでしょうか。よろしくお願いします。 <?php session_start(); $link = mysql_connect('localhost', 'root', 'root'); if (!$link) { die('接続失敗です。'.mysql_error()); } $db_selected = mysql_select_db('mydb', $link); if (!$db_selected){ die('データベース選択失敗です。'.mysql_error()); } mysql_set_charset('utf8'); // エラーメッセージの初期化 $errorMessage = ""; // ログインボタンが押された場合 if (isset($_POST["login"])) { // 1.ユーザIDの入力チェック if (empty($_POST["userid"])) { $errorMessage = "ユーザIDが未入力です。"; } else if (empty($_POST["password"])) { $errorMessage = "パスワードが未入力です。"; } // 2.ユーザIDとパスワードが入力されていたら認証する if (!empty($_POST["userid"]) && !empty($_POST["password"])) { // mysqlへの接続 $mysqli = new mysqli($db['localhost'], $db['root'], $db['root']); if ($mysqli->connect_errno) { print('<p>データベースへの接続に失敗しました。</p>' . $mysqli->connect_error); exit(); } // データベースの選択 $mysqli->select_db($db['mydb']); // 入力値のサニタイズ $userid = $mysqli->real_escape_string($_POST["userid"]); // クエリの実行 $query = "SELECT * FROM db_user WHERE name = '" . $userid . "'"; $result = $mysqli->query($query); if (!$result) { print('クエリーが失敗しました。' . $mysqli->error); $mysqli->close(); exit(); } while ($row = $result->fetch_assoc()) { // パスワード(暗号化済み)の取り出し $db_hashed_pwd = $row['password']; } // データベースの切断 $mysqli->close(); // 3.画面から入力されたパスワードとデータベースから取得したパスワードのハッシュを比較します。 //if ($_POST["password"] == $pw) { if (password_verify($_POST["password"], $db_hashed_pwd)) { // 4.認証成功なら、セッションIDを新規に発行する session_regenerate_id(true); $_SESSION["USERID"] = $_POST["userid"]; header("Location: main.php"); exit; } else { // 認証失敗 $errorMessage = "ユーザIDあるいはパスワードに誤りがあります。"; } } else { // 未入力なら何もしない } } ?>

    • 締切済み
    • PHP
  • XAMPPでSQL文を流すとフリーズしてしまいます

    現在、PHPでホームページを開発中で、XAMPPで試行錯誤しています。 数回(5~10回程度) SQL文を流すとApach自体が落ちる?サーバに接続出来ない状態になってしまいます。 自分の予想だと、接続が解除出来ていず複数接続になってしまい落ちているのかと思っています。 XAMPPのバージョンは1.7.3です。 実際に作成したログイン画面のソースコードを貼ります。 よろしくお願いいたします。 $server = "localhost"; $id = "ID"; $pw = "パスワード"; $dbname = "dbname"; $conn = mysql_connect($server, $id, $pw ); if( $conn == false ) { die("MySQL 接続エラー"); } mysql_select_db( $dbname ); $sql = " SELECT * FROM user where user_id='".$_POST["user_name"]."'"; $res = mysql_query( $sql ); while( $row = mysql_fetch_array( $res ) ) { // ログイン画面から取得したPWとデータベースのパスワード(pass)を照合する if($cryptpass == $row["password"]){ $user = new User($row["user_id"], $row["mail"]); $_SESSION["user"] = serialize($user); } } mysql_free_result($resource); mysql_close();

    • ベストアンサー
    • PHP
  • PHP ログインシステムについて

    お世話になります 現在ローカルで下記PHPのテストを行っています PHP初心者の為、セキュリティ面並びに不具合が心配で書き込みさせて頂きました 恐れ入りますがおかしな点がないかチェックして頂けませんでしょうか 宜しくお願いいたします データベースのバージョンはMySQL 5.5です ***************************************** <?php session_start(); $error_message = ""; if (isset($_POST["login"])) { $id = htmlspecialchars($_POST['id']); $password = htmlspecialchars(base64_encode(pack('H*', sha1($_POST['password'])))); $_SESSION['id'] = $_POST['id']; $_SESSION['password'] = $_POST['password']; $db = mysql_connect("***","***","***"); if (!$db) { die('接続失敗です。'.mysql_error()); } mysql_set_charset("utf8"); $db_selected = mysql_select_db("***", $db); if (!$db_selected){ die('データベース選択失敗です。'.mysql_error()); } $result = mysql_query("SELECT * FROM ***"); if (!$result) { die('クエリーが失敗しました。'.mysql_error()); } function x($result) { return mysql_real_escape_string($result); } while ($row = mysql_fetch_assoc($result)) { if($id == $row['id'] && $password == $row['password']){ header("Location:./instance.php"); } } $_SESSION = array(); if (isset($_COOKIE[session_name()])) { setcookie(session_name(), '', time()-42000, '/'); } session_destroy(); $error_message = "ユーザ名もしくはパスワードが違っています。"; } ?> <html> <head><title>ログイン</title> <meta http-equiv=Content-Type content="text/html; charset=utf-8"> <link rel="stylesheet" type="text/css" href="style.css" media="screen" /> </head> <body> <?php if ($error_message) { print '<font color="red">'.$error_message.'</font>'; } ?> <form action="login.php" method="post"> ID:<input type="text" name="id"><br /> PASS:<input type="password" name="password"><br /> <input type="submit" name=login value="認証"> </form> </body> </html>

    • 締切済み
    • PHP
  • 会員専用のログインページを作っているのですが、分からない事があります。

    会員専用のログインページを作っているのですが、分からない事があります。 1.フォームにIDとPASSWORDを入力 2.login.phpで会員データーベースに入りIDとPASSWORDが存在すれば会員専用ページに移動 ----form.html---- <form action="" method="post"> <table> <tr> <td>あなたのID:</td> <td><input type="text" name="usrid" size="15" value="<?php echo htmlspecialchars($_POST['usrid']); ?>" /></td> </tr> <tr> <td>パスワード:</td> <td><input type="password" name="usrpw" size="16" value="<?php echo htmlspecialchars($_POST['usrpw']); ?>" /></td> </tr> <tr> <td><input type="submit" value="ログイン" /></td><td> </td> </table> </form> ----login.php---- //MYSQLに接続 require_once('sql.php'); //セッションを開始します。 session_start(); $_SESSION["usrid"] = ""; //自分のID $_SESSION["usrpw"] = ""; //自分のPASS //変数の初期化 $usrid = ''; //ユーザーID $usrpw = ''; //パスワード //POSTされたとき if ($_SERVER["REQUEST_METHOD"]=="POST") { //ログインボタンが押されたとき if (isset($_POST["submit"])) { //POSTされたデータを取得 $usrid = htmlspecialchars($_POST["usrid"], ENT_QUOTES); //ID $usrpw = htmlspecialchars($_POST["usrpw"], ENT_QUOTES); //パスワード //入力内容チェック if (strlen($usrid)==0){$error = "ユーザIDが入力されていません";} if (strlen($usrpw)==0){$error = "パスワードが入力されていません";} //エラーがない場合 if (strlen($error)==0){ //meiboテーブルをチェック $mysql->query("SELECT usrid,usrpw FROM meibo"); if ($mysql->rows()>0){ //行が存在した場合 $row = $mysql->fetch(); if ($row["usrpw"] == $usrpw){ $_SESSION["usrid"] = $usrid; header("Location: http://$host/php/page.php"); exit; } } } $error = "ユーザIDかパスワードに誤りがあります"; } } 教科書を参考に作ったコードです。 フォームにIDとPASSを入力後ログインボタンを押してもそのままフォーム画面のままになってしまいます。 data.txtだと比較的簡単に出来たのですがMYSQLを使いだしたとたん分からなくなってしまいました。 どなたか親切な方、お教えください。

    • ベストアンサー
    • PHP
  • phpでログイン時のIDチェック

    phpでIDとパスワードを入力してもらいそれをチェックしてログインするシステムを作っています。 普通にログインはできるのですがIDがsから始まりその後に数字が7桁来れば会員専用のメイン画面に移行し、それ以外のIDであれば普通のメイン画面に移行するプログラムを書きたいです。 例)IDがs1234567であれば会員用の画面、それ以外s1234,1234567,d1234567などのIDであれば違う画面に移行したいです。 自分が書いたコードはこのようになっておりこちらをどのように改良していけばこのようなプログラムが書けるか知りたいです。 どなたかご教授お願いします。 <?php require('dbconnect.php'); session_start(); if (!empty($_POST)) { // ログインの処理 if ($_POST['name'] != '' && $_POST['password'] != '') { $sql = sprintf('SELECT * FROM members WHERE name="%s" AND password="%s"', mysql_real_escape_string($_POST['name']), sha1(mysql_real_escape_string($_POST['password'])) ); $record = mysql_query($sql) or die(mysql_error()); if ($table = mysql_fetch_assoc($record)) { // ログイン成功 $_SESSION['id'] = $table['id']; $_SESSION['time'] = time(); header('Location: group.php'); exit(); } else { $error['login'] = 'failed'; } } else { $error['login'] = 'blank'; } } ?>

    • ベストアンサー
    • PHP
  • 別画面から遷移してきた時はDBを読み、それ以外のときはPHP_SELFを使いたい

    http://oshiete1.goo.ne.jp/kotaeru_thanks.php3?a=7486449 の#3さんにご提示いただいたサンプル(→update.phpとします)を 組み込んでみたのですが、 投稿者名<input type="text" name="name" value="{$_POST["name"]}">{$errStr["name"]}<br> の「value=""」の値について、 update.phpに遷移してきた際は、↓みたいなプロセスを経てMySQLから 読み込んだ$col["name"]を直に表示させたいです。 $myID = GetmyID(); $con = mysql_connect(localhost, root, pw); $selectdb = mysql_select_db(serv, $con); $sql = "SELECT * FROM MyTab WHERE ID = '$myID'"; $rst = mysql_query($sql, $con); $col = mysql_fetch_array($rst); $name = $col["name"]; その場合、冒頭の#3さんのサンプルの value="{$_POST["name"]}" …を、 value="if (PHP_SELFでなく別画面から遷移してきて表示する場合) {   {$_POST["name"]} } else {   {$_POST["name"]} }" みたいに分岐すればいいのではないかと思いますが、 「PHP_SELFでなく別画面から遷移してきて表示する場合」の判断は どのようにしたらできますでしょうか。

    • ベストアンサー
    • PHP
このQ&Aのポイント
  • 職務経歴書の書き方について、1社目と再入社2社目の記載方法について悩んでいます。ひとつずつ書くか、まとめて書くか迷っています。
  • ほぼ同じ職務内容でも、1社目と再入社2社目をひとつずつ書いた方が丁寧で良いと思える一方で、効率的にまとめて書くことも考えられます。
  • 履歴書と職務経歴書が合体している場合、時系列順に入退社を記載した後、職務経歴書で補足することが難しい場合もあります。
回答を見る