• ベストアンサー

レコード削除・sqlインジェクション対策

このようなSQL文は危険でしょうか? $sql = "delete テーブル名 where id = :id"; $stmt = $dbh->prepare($sql); $stmt->execute(array(":id" => $_POST['id'])); 上記の例だと、$_POST['id']は、 ちゃんとエスケープできているのでしょうか?

  • k5z
  • お礼率34% (9/26)
  • MySQL
  • 回答数3
  • ありがとう数2

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

  • ベストアンサー
  • t_ohta
  • ベストアンサー率38% (5043/13172)
回答No.1

プログラムの書き方からすると言語はPHPでしょうか。 プリペアドステートメントを使っていれば、ドライバーの方でエスケープ処理やクォートで囲む処理を行ってくれるのでSQLインジェクション対策になります。

k5z
質問者

お礼

教えて頂いてありがとうございます!m(_ _)m

その他の回答 (2)

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

なんかうまく伝わってないみたいで、すみません。 POSTでidを送りつけてデータが削除できるなら、 ユーザーが1から順番に100番、1000番・・・と適当におくってきたときに 全部消されちゃいますよという意味です。 インジェクションの場合、SELECT文の参照時に、不正にUPDATEやDELETE されないような処理とか、本来アクセスできないSELECT文にオールの パラメータをあたえて不正にデータを引き出すのを防ぐ処理なので DELETE文などは特殊な権限をもったユーザーに処理させるために リンクを調整するところから入ると思います

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

インジェクションはともかく、ユーザーから渡されたIDでデータを削除 することができるのであれば、インジェクションに近い全データ削除だって されちゃうんじゃないですか? delete文の発行するのはかなり条件を厳しくした方がよいですよ

k5z
質問者

お礼

アドバイス、ありがとうございます! 現状で、「:id」に入る文字は、 どのような制限がかけられているのでしょうか? 整数のみでしょうか? それとも、英数字も入力可能なのでしょうか?

関連するQ&A

  • SQLインジェクション対策

    SQLインジェクション対策として、変数を直接SQLに埋め込むのではなく、PDOのprepareメソッドを利用して作成したステートメントに値をバインドする形式にする場合、ユーザー定義関数をどのように 修正すればいいですか? function update_item_stock($db, $item_id, $stock){ $sql = " UPDATE items SET stock = {$stock} WHERE item_id = {$item_id} LIMIT 1"; return execute_query($db, $sql); } function execute_query($db, $sql, $params = array()){ try{ $stmt = $db->prepare($sql); return $stmt->execute($params); }catch(PDOException $e){ set_error('更新に失敗しました。'); } return false; } 上記のユーザー定義関数を下記のようにbindValueを用いて表す場合、$stmt->bindValueの部分を 上記のどこに追加すればいいですか? try { $sql = 'UPDATE item_stock SET stock = ?, update_date = ? WHERE item_id = ?'; $stmt = $db->prepare($sql); $stmt->bindValue(1, $update_stock, PDO::PARAM_INT); $stmt->bindValue(2, $date, PDO::PARAM_STR); $stmt->bindValue(3, $item_id, PDO::PARAM_INT); $stmt->execute(); $complete_msg[] = '在庫変更に成功しました。'; } catch (PDOException $e) { $err_msg[] = '更新に失敗しました。理由:' . $e->getMessage(); }

    • 締切済み
    • PHP
  • sql エラー

    エラーが出ます。どこかおかしな点はありますでしょうか。 エラー文 Call to a member function prepare() on a non-object ソース $page = 1; $limit = 2; $offset = $limit * ($page - 1); $sql='SELECT COUNT(*) FROM message WHERE memberid=? GROUP BY aid'; $stmt=$dbh->prepare($sql); $data[]=$memberid; var_dump($data); $stmt->execute($data); $dbh=null; $total=$stmt->fetchColumn(); $lastpage= ceil($total/$limit); $sql='SELECT aid,max(kaisyamei),max(day) FROM message WHERE memberid=? GROUP BY aid LIMIT '.$limit.' OFFSET '.$offset; $stmt=$dbh->prepare($sql); $stmt->execute($data); $dbh=null; ご教授お願いいたします。

    • ベストアンサー
    • MySQL
  • PHPとSQLをコンパクトにまとめたいです

    部分一致検索して商品が見つかった場合はその商品だけを表示して、もし検索して見つからなかったときはエラーメッセージと商品一覧を表示しています。動作上は問題ありませんが、コンパクトにまとめることは可能でしょうか? // ユーザーが検索した場合の処理 if (isset($_POST['keyword']) === TRUE && mb_strlen ($_POST['keyword']) > 0) { $keyword = trim($_POST['keyword']); try { $sql = 'SELECT product.id, name, price, img, status, stock FROM product JOIN item_stock ON product.id = item_stock.stock_id WHERE name like ?'; $stmt = $dbh->prepare($sql); $stmt->bindValue(1, $keyword, PDO::PARAM_STR); // SQLを実行 $stmt->execute(['%' . $keyword . '%']); $result = $stmt->fetchALL(); // 上記で検索した名前と部分一致する商品を探す if (count($result) > 0 ) { $msg[] = ($keyword . 'を含む商品が見つかりました!'); } else { try { // ステータスが1(公開)の販売商品のみを一覧で表示する $sql = 'SELECT product.id, name, price, img, status, stock FROM product JOIN item_stock ON product.id = item_stock.stock_id WHERE status = 1'; $stmt = $dbh->prepare($sql); $stmt->execute(); //全て取得するのでfetchALLでレコードを取得する $result = $stmt->fetchALL(); $err_msg[] = ($keyword . 'を含む商品は見つかりませんでした。'); } catch (PDOException $e) { $err_msg[] = '商品を取得できませんでした。'; } } } catch (PDOException $e) { $err_msg[] = '商品を検索できませんでした。'; } } else { try { // ステータスが1(公開)の販売商品のみを一覧で表示する。 $sql = 'SELECT product.id, name, price, img, status, stock FROM product JOIN item_stock ON product.id = item_stock.stock_id WHERE status = 1'; $stmt = $dbh->prepare($sql); $stmt->execute(); //全て取得するのでfetchALLでレコードを取得する $result = $stmt->fetchALL(); } catch (PDOException $e) { $err_msg[] = '商品を取得できませんでした。'; } }

    • ベストアンサー
    • PHP
  • SQL文の処理を関数化したいです

    SQL文をユーザー定義関数でまとめたいのですが、うまくいきません。 以下の処理を全てfunction search() { }の中に入れるのは間違っていますか? 関数名はsearchとしました。 try { $sql = 'SELECT product.id, name, price, img, status, stock FROM product JOIN item_stock ON product.id = item_stock.stock_id WHERE status = 1'; $stmt = $dbh->prepare($sql); $stmt->execute(); $result = $stmt->fetchALL(); $err_msg[] = ($keyword . 'を含む商品は見つかりませんでした。'); } catch (PDOException $e) { $err_msg[] = '商品を取得できませんでした。'; }

    • ベストアンサー
    • PHP
  • mysqlのデータをPDOでDELETEできない

    PDOオブジェクト(PHP)を使用したmysqlのデータ削除について、質問させてください。 PDOオブジェクトを使用して、mysqlのデータ読み込み・削除を行っています。 特定のデータを読み込み、処理を行わせた後、対象のデータの削除をしたいのですが 読み込みは出来るのに、削除で失敗してしまいます。 処理を行わせるSQLをvar_dumpで出力させ、 それを直接phpMyAdminでSQL実行してみたのですが、 問題なく削除が行われています。 SQLの問題ではなく、PHP側の問題だと思うのですが、 解決方法が見つかっておりません。 知恵を貸していただけないでしょうか。 $post_data = explode('¥t', $_POST['data_array']); $user_id = $post_data[0]; $account_name = $post_data[1]; $data_id = $post_data[2]; $gunre_id = $post_data[3]; try { // DB接続 $dbh = new PDO($serverInfo["SERVER"], $serverInfo["USER"], $serverInfo["PASS"]); $dbh -> query('SET NAMES utf8'); // 処理させる対象アカウント情報を取得 $sql_account; $sql_account = 'SELECT * FROM '. $serverInfo['TBL_ACCOUNT']. ' WHERE GUNRE_ID = :gunre'; } $stmt_account = $dbh -> prepare($sql_account); $stmt_account -> bindParam(':gunre', $gunre_id, PDO::PARAM_STR); $stmt_account -> execute(); while($account = $stmt_account -> fetch(PDO::FETCH_ASSOC)) { // 取得してきたデータを使用して処理 // この処理は正常に行われているので、SELECTは正常に行われていると考えられます } // 処理が完了したら、データを削除 // ↓ここで組み立てたSQLを出力し、phpMyAdminでSQL実行すると、データは削除されました $sql_delete = 'DELETE FROM '. $serverInfo['TBL_DATA']. ' WHERE USER_ID = "'. $user_id. '" AND ACCOUNT_NAME = "'. $account_name. '" AND DATA_ID = "'. $data_id. '"'; $stmt_delete = $dbh -> prepare($sql_delete); // ↓元々はbindParamで指定していたのですが、処理が出来なかったので // $SQL_deleteの中に値を埋め込み、処理を行わせました。結局出来なかったのですが・・・ // $stmt_delete -> bindParam(':id', $user_id, PDO::PARAM_STR); // $stmt_delete -> bindParam(':account', $account_name, PDO::PARAM_STR); // $stmt_delete -> bindParam(':data', $data_id, PDO::PARAM_STR); $result = $stmt_delete -> execute(); var_dump($result); // ←出力結果は「false」です } catch (Exception $ex) { echo '<font color="red">システムエラーが発生しました</font><br />'; exit(); } 以上、よろしくお願いします。

    • ベストアンサー
    • PHP
  • SQLインジェクションの対策

    SQLインジェクションの対策 いつもお世話になっております。 SQLインジェクションの対策についてお伺いいたします。 もともと↓のようなSQL文だったものを "select user_id from table where user_id='{$user_id}'" 以下のように変更しました。 "select user_id from table where user_id='" . mysql_real_escape_string($user_id) . "'" 以下のように実行されていたSQL文は select user_idfrom table where user_id='10001' and 'a'='a' ↓のようにエスケープ処理して実行されるようになりました。(入力値は「10001' and 'a'='a」) select user_id from table where user_id='10001\' and \'a\'=\'a' ですが、phpMyAdminで実行してみるとどちらのSQL文も同じ結果が取得できてしまいます。 これでは対策になっていないと思ったので、質問させていただきました。 (magic_quotes_gpcはoffに設定しています。) なにか他の方法がいいのでしょうか。 ご教示よろしくお願いいたします。 <環境> PHP 5.1.6 MySQL 5.0.45

    • ベストアンサー
    • PHP
  • 【PHP+MySQL 】レコード追加できない

    配列に入っているタブ区切りのデータを MySQLのテーブルに入れたいと思い 下記のようにコーディングしたのですが (因みにDB接続はちゃんと確立されております) ------------------------------------------ $arrData[0] = "1001 ^ あ"; $arrData[1] = "1002 ^ い";     ・     ・     ・ $sql = 'insert into table_a values (?,?)'; $stmt = $dbh->prepare($sql); for($i=0;$i<=count($arrData);$i++){ $tmp = split("\t",$arrData[$i]); $flag = $stmt->execute(array($tmp[0],$tmp[1])); if (!$flag){ die('データの追加に失敗しました'); } } ------------------------------------------ データの追加に失敗しましたが表示されうまくできません。 ■ どのように直せばよいかご教示願います。 ■ また、mysql関数にはPDO関数のprepare→executeのような 書き方は無いのでしょうか。 ご存知の方いらっしゃいましたら教えて下さい。 よろしくお願い致します。

    • 締切済み
    • PHP
  • phpプリペアードステートメントについて質問です。

    phpの練習で、以下のようなhtmlファイルとphpファイルを作り XAMPで作業をおこなっています。 以下にあるhtml.phpファイルでのやり取りはうまくいっているのですが、 このphpをプリペアードステートメントにする所で躓いています。 いろいろ調べてやってはみたものの、どうしても%を使った あいまい検索のところがわかりません。 ---------------------------------------------------------------- 以下、プリペアードステートメントにする前の ページ内容です。こちらではうまくいっています。 html <form method="post" action="kensaku.php"> ご意見コードを入力してください。<br /> <input name="code" type="text" style="width:100px"><br /> <br /> <input type="submit" value="送信"> </form> php <?php $code=$_POST['code']; $dsn = 'mysql:dbname=phpkiso;host=localhost'; $user = 'root'; $password =''; $dbh = new PDO($dsn,$user,$password); $dbh->query('SET NAMES UTF-8'); $sql = "select * from `anketo` where `goiken` like '%{$code}%' "; $stmt = $dbh->prepare($sql); $stmt-> execute(); while(1) { $rec=$stmt->fetch(PDO::FETCH_ASSOC); if($rec==false) { break; } print $rec['code']; print $rec['nickname']; print $rec['email']; print $rec['goiken']; print '<br />'; } $dbh = null; ?> ---------------------------------------------------------------- 以上のphpの中の以下の分を $sql = "select * from `anketo` where `goiken` like '%{$code}%' "; $stmt = $dbh->prepare($sql); $stmt-> execute(); ↓ $sql ="SELECT*FROM anketo WHERE goiken like ?"; $stmt = $dbh->prepare($sql); $data[] = $code; $stmt->execute(array("%$_GET[$data]%")); こんな風に直しては見たのですが、なんだか うまくい行かずです。 よろしければ教えてください。 宜しくお願い致します。

    • 締切済み
    • PHP
  • MySQLのテーブル名を変数に置いた場合

    お世話になります。 jQueryのプラグインを使用してDBから吐き出したデータを並べ替えをして、 UPDATEをさせているのですが、UPDATE先のテーブル名を変数に置いた場合、 例えば、 $id_set = "1"; if (isset($_POST['result'])) { $sql = "UPDATE `{$id_set}` SET no = ? WHERE id = ?"; $stmt = $conn->prepare($sql); foreach (explode(',', $_POST['result']) as $i => $id) { $stmt->execute(array(++$i, $id)); } //foreachの終了 } //if (isset($_POST['result'])) の終了 $sql1 = "SELECT id, name, price, no FROM `{$id_set}` ORDER BY no"; $stmt = $conn->prepare($sql1); $stmt->execute(); foreach ($stmt as $row) { $state[] = array("id"=>$row['id'], "name"=>$row['name'], "price"=>$row['price'], "no"=>$row['no']); $this->smarty_obj->assign("state_loop",$state); } //foreachの終了 とすれば、「 1 」というテーブルのデータをSELECTしてUPDATEと正常に走るのですが、 $id_set = $_POST["id"]; 等としてpostした場合、UPDATEの際に「 Call to a member function execute 」のエラーが 吐かれます。該当のテーブルが存在しないと認識されているのだと思いますが、 ページ遷移してくる際に持ってきたデータを活用してテーブル名にセットして、 尚且つ正常にUPDATEさせるにはどの様な構文にすれば良いのでしょうか? ご教示の程、どうぞよろしくお願い申し上げます。 ---------------- ▼スペック PHP 5.3.3 MySQL 5.0.95 ----------------

    • ベストアンサー
    • PHP
  • ハッシュのキー追加について

    とある既存プログラムに機能追加したいのですが上手くいきません。 ハッシュだとは思うのですが、%だったり$だったりしてよくわからなくなってしまいました。 どこがおかしいか教えていただけないでしょうか。 <概要> もともとあった(1)と(3)の処理の間に、(2)を行う <ソース> (1)DBから1レコードを取得する $sql = "select * from tenpo where id=5;"; $sth = $dbh->prepare($sql); $sth->execute(); $shop = $sth->fetchrow_hashref(); (2)別TABLEから値を取得し、(1)に追加する $sql = "select todoufuken from area where id=5;"; $sth = $dbh->prepare($sql); $sth->execute(); @todoufuken= $sth->fetchrow_array; $shop{place} = $todoufuken[0]; (3)$shopの情報をサブルーチンに渡す ソース略

    • ベストアンサー
    • Perl