質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

8810閲覧

SQLのテーブル名のバインドに関してのご質問です。

space_sss

総合スコア81

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

2クリップ

投稿2018/01/12 19:03

環境は
PHP version: 7.1.12
MySQL version: 5.7.20
となっております。

sql

1$arrParams=[1,"atype"]; 2$sql='SELECT id, type, category FROM test WHERE id = ? AND category = ?'; 3$stmt=$dbh->prepare($sql); 4$stmt->execute($arrParams); 5

といったものでWHERE部分をバインドしSQLインジェクションを防ぐ対策をすると学びました。

その際
テーブル名やSELECTを指定する部分がもし動的に変化する場合どのような対策を行なうものなのでしょうか?

例1

sql

1$arrParams=[1,"atype"]; 2$selectarray=["id","type","category"]; 3$selectArrayAll=implode(",", $selectarray); 4$sql = 'SELECT '; 5$sql .= $selectArrayAll 6$sql .= FROM test WHERE id = ? AND category = ?'; 7$stmt=$dbh->prepare($sql); 8$stmt->bindValue(1, $category_0, PDO::PARAM_INT); 9$stmt->execute($arrParams);

セレクトの部分が外部より決定する場合

例2

sql

1$arrParams= [1,"atype"]; 2$table = "test"; 3$sql = 'SELECT id, type, category FROM $table WHERE id = ? AND category = ?'; 4$stmt = $dbh->prepare($sql); 5$stmt->bindValue(1, $category_0, PDO::PARAM_INT); 6$stmt->execute($arrParams);

テーブル名が変更になる可能性がある場合

例3

sql

1$selectarray=["id","type","category"]; 2$selectArrayAll=implode(",", $selectarray); 3$table = "test"; 4$sql = 'SELECT '; 5$sql .= $selectArrayAll 6$sql .= FROM $table WHERE id = ? AND category = ?'; 7$stmt=$dbh->prepare($sql); 8$stmt->bindValue(1, $category_0, PDO::PARAM_INT); 9$stmt->execute($arrParams);

例1と例2が組み合わさった場合

上記の3つはどのような対策が考えられるのでしょうか?

御解答お待ちしております。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

基本的にTomakさんの回答に同意なのですが…

テーブル名やSELECTを指定する部分がもし動的に変化する場合どのような対策を行なうものなのでしょうか?

こういうことをしなければならないケースはありますよね。
まあまあ無難な方法としては、テーブル名や列名としてとり得る文字列(とってよい文字列=ホワイトリスト)を配列として持っていて、そのインデックス(添字番号)を外部から渡すというやり方があります。これですと、攻撃文字列を外部から指定することはできず、テーブル名や列名を可変にできます。

投稿2018/01/13 00:29

ockeghem

総合スコア11701

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

といったものでWHERE部分をバインドしSQLインジェクションを防ぐ対策をすると学びました。

その際テーブル名やSELECTを指定する部分がもし動的に変化する場合どのような対策を行なうものなのでしょうか?

SQLインジェクション対策とは、ブラウザ(ユーザーサイド、クライアントサイド)からPOSTなどによって値がPHP(サーバーサイド)にやってきた時に、このSQL的に信用できない値をきちんとSQLの値だと認識させてあげるための対策です。インジェクションとは注入・挿入という意味なので、SQLを注入されないための対策ということになります。

カラムやテーブルがPOST値などによって変化したとしても、その変化部分は完全にPHPコード依存になるはずなので、これらのSQLインジェクション対策は必要ありません。

ただし、POST値などからカラム名やテーブル名を受け取ってそのままSQLに流し込むようなコードを書いてはいけません。

なぜSQLインジェクション対策が重要かというと、例えばPOST値などにSQL文を混ぜて書いたときに、テーブル削除とか、他人の個人情報を取得などのプログラム上意図しない動作が可能になってしまうからです。

下記のようにブラウザ(ユーザーサイド、クライアントサイド)からPOSTで$_POST['id'], $_POST['category']を取得する場合、これらの値についてのみSQLインジェクション対策が必要です。何かの条件によってテーブル名や取得カラムが変更になっても、それらの値はPHP側にコーディングされているわけで、ユーザー入力値とは関係ありませんので。

php

1//POST値をサニタイズして取得 2$id = filter_input('INPUT_POST', 'id', FILTER_SANITIZE_NUMBER_INT); 3$category = filter_input('INPUT_POST', 'category', FILTER_SANITIZE_NUMBER_INT); 4 5//取得するカラム・テーブルを条件によって変更 6if (何かの条件) { 7 $selectArrayAll = implode(",", ["id","type","category"]); 8 $table = "test"; 9} 10else { 11 $selectArrayAll = 'COUNT(id)'; 12 $table = 'test_something'; 13} 14 15//try,catch()で囲む 16try { 17 //... 18 //SQLクエリ 19 $sql = 'SELECT '. $selectArrayAll .' '; 20 $sql .= 'FROM '. $table .' WHERE id = ? AND category = ?'; 21 22 //プリペアードステートメント 23 $stmt = $dbh->prepare($sql); 24 25 //ユーザー入力値のSQLインジェクション対策 26 $stmt->bindValue(1, $id, PDO::PARAM_INT); 27 $stmt->bindValue(2, $category, PDO::PARAM_INT); 28 $stmt->execute(); 29 30 //結果取得 31 $result = $stmt->fetchAll(); 32 var_dump($result); 33} 34catch(\PDOException $e) { 35 echo $e->getMessage(); 36} 37catch(\Exception $e) { 38 echo $e->getMessage(); 39}

投稿2018/01/12 22:19

Tomak

総合スコア1652

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まずテーブル名やカラム名のチェックをするところからでしょうね

SQL

1show tables from DB名 where Tables_in_DB名='table名'; 2show columns from tablewhere Field ='カラム名';

のようなチェックをした上で存在を確認しておけば
あとはconcatでもなんでもPHP側でSQLを組み立てればいいでしょう。
もちろん、table名やカラム名が存在したからと言って文法エラーにならない
保証はありませんので、きちんと例外処理をいれる必要はあります。

投稿2018/01/15 00:55

yambejp

総合スコア114843

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問