PHP Version 5.4.7の環境にて。
SQLite3::escapeStringを使って、
SQLインジェクション対策をしようと考えています。
HTMLの<form>からPOSTで値を受け取り、
その値をSQL文に入れ込み、
そのクエリ(※ちなみに、INSERTのみです。)をSQLite3のDBに対して行う、
なんてことをする際の、
SQLインジェクション対策として、お考え下さい。
POSTで受け取る値に入っていたら危険なものとして、
「シングルクオーテーション」が、まず、挙げられるかと思います。
「'」 ←これです。
さて、「"」 ←こちらはダブルクオーテーションですが、
こちらのダブルの方はエスケープする必要は無いのでしょうか?
(例)※wikipediaより
SELECT * FROM users WHERE name = '(入力値)';
SELECT * FROM users WHERE name = 't' OR 't' = 't';
→ このSQL文では条件が常に真となるため、
nameカラムの値にかかわらず、全レコードが選択される。
→ ということで、入力値に、
エスケープされていない「シングルクオーテーション」をそのまま使うのはNG。
ここまではOKです。
では、次に、ダブルクオーテーション版で、
SELECT * FROM users WHERE name = "(入力値)";
SELECT * FROM users WHERE name = "t" OR "t" = "t";
こちらはどうなのでしょうか?
(シングルをダブルに変えただけですが。)
----------
ちなみに、
SQLite3::escapeString にて、
(1)
$var = "Let's"; //←シングルクオーテーション
$db = new SQLite3(':memory:');
$escaped_var = $db->escapeString($var);
echo $escaped_var; //Let''s と表示される (「 ' 」が1つ追加される。)
(2)
$var = 'Let"s'; //←ダブルクオーテーション
$db = new SQLite3(':memory:');
$escaped_var = $db->escapeString($var);
echo $escaped_var; //Let"s と表示される (何も追加されず。)
というように、
シングルクオーテーションはエスケープされるが、
ダブルクオーテーションの方ではエスケープされませんでした。
これは、つまり、
ダブルクオーテーションの方は危険視されていない、
ということだと思いますが、
でも、本当にダブルクオーテーションをエスケープせずに、
そのまま、SQL文につっこんでも大丈夫なのでしょうか?
No.2ベストアンサー
- 回答日時:
SQL文の中で「文字列」を単引用符で括っているなら、その中にある二重引用符は「単なる文字」としてしか認識されません。
なのでエスケープする必要はありません。逆にSQL文で文字列を二重引用符で括って渡しているなら二重引用符のエスケープは必須です。「適切なエスケープをする」というのは、そういうことです。
結論としては『プレースホルダを使って』文字列を括る引用符も含めてシステム(ドライバ)に任せた方がいいということになります。
回答をありがとうございます。
>逆にSQL文で文字列を二重引用符で括って渡しているなら二重引用符のエスケープは必須です。
ですよね!
つまり、
$sql = 'SELECT * FROM users WHERE name = "(入力値)"';
というようにコーディングをしている場合には、
「二重引用符のエスケープは必須」ということですよね。
>結論としては『プレースホルダを使って』文字列を括る引用符も含めてシステム(ドライバ)に任せた方がいい
なるほど。そういう考え方があるわけですね。
ちなみに、その『プレースホルダを使う場合』においては、
エスケープ処理は、どのように、なされているのでしょうか?
システムが、渡されてきた文字列を見ながら、適宜、
SQL文内における「文字列を括る引用符」を、
適切にチョイスしてくれる、ということでしょうか。
(つまり、人間が手動でエスケープ処理をしなくてよく、
すべて、システムにお任せできてしまう?)
「'」だろうが、「"」だろうが、
また、「バイナリセーフじゃない文字列」だろうが、
そのまま、システムに丸投げできてしまう、
ということでしょうか。
※「バイナリセーフじゃない文字」までは、
さすがに丸投げはできないかもしれませんが・・・。
(さらに、色々と聞いてしまい、すみません。)
もし、宜しければ、教えて下さい。
No.5
- 回答日時:
#あ、先に書かれた(汗
thx.>agunuzさん
少なくともプリペアドステートメントが使える関数・クラスを利用しているのであれば「内容の保証がない」データはプリペアドステートメントで扱うべきですね。そうすれば括るのが単引用符か二重引用符かなんて気にする必要はありません(気にしなくても適切に処理されます)。もちろんバイナリデータでも。です。
何度もありがとうございます。
適切にプリペアドステートメントを使っていれば、
どんな文字列を打ち込まれようとも大丈夫だい!
という風に解釈いたしました。
No.4
- 回答日時:
>「そのまま」ということは、適切にエスケープすることなく、
>という意味でしょうか。
>
>つまり、マズイ という意味?
あ、いえ「普通の文字列と同じように」扱えるということです。たとえばphpスクリプトでは、文字列型の変数の内容がテキスト(asiiなのか日本語なのかも不問)であってもバイナリであっても同じように扱ってかまいません。
当然ですが『適切にエスケープする』ことが前提です。
回答をありがとうございます。
バイナリの件ですが、
「'」を含まない文字列の中で、
もし、下記の「入力値」の所に入れられてしまうと、
SELECT * FROM users WHERE name = '(入力値)';
SQLインジェクションが成立してしまうような、
そんな文字列はありますでしょうか?
あるなら、バイナリ文字でしょうか?!
もし、そうであるなら、
そのバイナリ文字さん達は、どうやってエスケープすればいいんだ?!
以上が、私が質問したかったことになります。
またよろしければ、教えてください。(ぺこり
No.3
- 回答日時:
>ちなみに、その『プレースホルダを使う場合』においては、
>エスケープ処理は、どのように、なされているのでしょうか?
基本的には文字列は単引用符で括りますので単引用符がエスケープ処理されることになります(各DBのドライバで微妙に違う部分もあります)。
何故データベースによって違いがあるかといえば、それはエスケープした結果を各データベースがどう扱うかが異なるからです。不要な部分までエスケープした結果、正しく格納できなくなったら困りますので。mysql_real_escape_stringなどは両方ともエスケープしますが、これはその状態で渡された文字列をMySQLがキチンと戻して格納するからです。
http://www.php.net/manual/ja/function.mysql-real …
データベース関係のエスケープ処理の多くは「文字列型は単引用符で括る」ことを前提に書かれています。SQLite3のescapeに関する下記のノートなどを読むと一目瞭然でしょう。
http://www.php.net/manual/ja/sqlite3.escapestrin …
またBlobなどのバイナリデータもそのまま扱います(プレースホルダを使う・使わないにかかわらず、これが出来ないデータベースの方が少数派だと思います)。
回答をありがとうございます。
また理解が深まりました。
>基本的には文字列は単引用符で括りますので単引用符がエスケープ処理されることに
>データベース関係のエスケープ処理の多くは「文字列型は単引用符で括る」ことを前提に書かれています。
ということは、SQL文で文字列型を扱う際には、慣例に従い、
「単引用符で括る」ようにしておいた方が良い、ということになりますね。
これを、二重引用符で括るようなコーディングを続けていると、
↓
「SQL文の文字列型を二重引用符で括る」
かつ
「悪意ある二重引用符を含む値をユーザから受け取る」
↓
その結果、
プリペアドステートメントを使っていても、
もともと、二重引用符にはエスケープはされないため、
最悪の場合、SQLインジェクションが成立してしまう、
ということになりますものね。
>SQLite3のescapeに関する下記のノートなどを読むと一目瞭然
二重引用符はエスケープされないから気をつけろ!
(二重引用符をエスケープしない仕様になっている理由などもゴニョゴニョ。)
みたいなことが英語で書かれていましたね。
本件と非常に関わりの深いノートでした。
>またBlobなどのバイナリデータもそのまま扱います(プレースホルダを使う・使わないにかかわらず、これが出来ないデータベースの方が少数派だと思います)。
すみません(汗)
ここの意味が、能力の低い私にはよく分かりませんでした。
>バイナリデータもそのまま扱います
「そのまま」ということは、適切にエスケープすることなく、
という意味でしょうか。
つまり、マズイ という意味?
>これが出来ないデータベース
「これ」とは、何でしょう。
バイナリデータをそのまま扱うこと。 ?
それとも、
バイナリデータをそのまま扱わず、エスケープしてから扱うこと。 ?
それとも、
また別のことでしょうか。
>これが出来ないデータベースの方が少数派
出来ない方が、マズイ という言い方なのですよね、きっと。
(そんなマズイDBの方が少数派ですよ、という風に理解しました。)
もし、またよろしければ、教えて下さい。
No.1
- 回答日時:
SELECT * FROM users WHERE name = "(入力値)";
DBによっても違うかもしれないけど、そもそも上記SQLは通るの?
http://www.dbonline.jp/sqlite/type/index4.html
回答をありがとうございます。
>そもそも上記SQLは通るの?
ここで話題にしている「SQLite3のDB」では、
SQL文の中で文字列をダブルクオーテーションで、
くくることは出来るようです。
参考:
http://programing.dip.jp/index.php?SQLite%2F%E3% …
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PHP 重複を防ぐ記述について教えて下さい。 3 2023/04/03 14:35
- Oracle sqlで質問です。 aテーブルとbテーブルがあり、下記のsqlで取得したidとnameに一致しないレ 1 2022/04/20 20:34
- PHP PHP MySql ページング 2 2022/09/20 06:38
- CGI perlで書いたcgiでsqliteの使い方を教えてください 2 2023/05/08 21:29
- PHP DBのハッシュ化したパスワードをpassword_verifyで戻し照合したのですが上手く行きません 2 2023/02/06 13:24
- MySQL 書籍の内容はまともでしょうか? 1 2023/01/22 03:07
- SQL Server [SQLServer] テーブル名からカラム名を取得する 1 2022/08/23 21:20
- PHP if(preg_match("/[^0-9]/",$gu_d)){意味を教えてください。 1 2022/05/06 05:37
- MySQL SQLです。下記の問合せを行うクエリを、PhpMyAdminで作成して実行せよ。 「昨年の各月の総降 1 2023/07/01 00:32
- Excel(エクセル) PHPプログラムをエクセルに張り付けると検索ボックスがでてくる! 3 2022/05/08 07:10
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
実行時エラー3131 FROM 句の構...
-
VBAをつかってクエリの情報を抽...
-
テキストボックスに入れた内容...
-
VB.NET
-
SQL文が実行できません
-
in 'where clause'のエラーの理由
-
SQL文の実行に失敗しました???
-
VBSの中で書くSQL文の記...
-
PDOで取得される値がすべて文字...
-
エラー3011
-
Accessのテーブルへ複数の主キ...
-
MySQLでデータベースにデータin...
-
<VB.NET>INSERT文でDBにデータ...
-
JAVA SQLServerException 列名 ...
-
while文の中にwhile文を書きた...
-
Pro*Cの構文エラー
-
SQL文2つ実行
-
ヒアドキュメントでSQLを書く事...
-
MySQLのUPDATE実行結果を受け取...
-
DBで検索結果に該当するデータ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
実行時エラー3131 FROM 句の構...
-
VBAをつかってクエリの情報を抽...
-
テキストボックスに入れた内容...
-
SQL文が実行できません
-
SQL文の実行に失敗しました???
-
in 'where clause'のエラーの理由
-
Accessのテーブルへ複数の主キ...
-
SELECT COUNTで取得した結果の表示
-
LocalのNotesメールDBをVBAで参...
-
SELECT文を発行して、ACCESSよ...
-
phpのPEARのMDB2を使って出たエ...
-
エラー3011
-
ASPでRecordCountが使用でき...
-
データフォームウィザードで追...
-
codeigniter 複数モデルでトラ...
-
Call to undefined method MDB2...
-
PHP(PDO)でDBの情報を完全一...
-
PEAR でprepareメソッドがエラーに
-
時刻型にNULLでセットしたい
-
ADOを使いDBへ読み書きしたい
おすすめ情報