たとえ大規模案件でも発生するSQL Injection(SQLインジェクション:SQLの挿入)。
SQLインジェクションとは
リクエストのパラメータにSQL文を与えてSQLデータベースを不正に操作する攻撃、
またはその攻撃を可能にする入力値の未チェックの脆弱性のことをいいます。
これを避けるための処理にaddslashesというのがあります。
が、addslashesだといろいろと問題が起こったりします。
(SJISの5C問題とか)
そのあたりの面倒なことをやってくれるのがDB_common::quoteSmart。
キャストをきちっとしておくと、
DBに依って扱いが変わるBOOLIAN型をきちっと処理してくれます。
DB_common::autoExecuteを使うとDB_common::quoteSmartの処理を一緒にしてくれます。
例えば
<form method="POST"> username:<input name="input_userid" /><br /> password:<input name="input_password" /><br /> <input type="submit" /> </form>
という入力フォームがあり、
$SQL = "SELECT * FROM user WHERE userid='".$_POST["input_userid"]. "' AND password='".$_POST["input_password"]."'";
というSQLがあったとします。
まぁ、パッと見てユーザー認証のコードでしょうか?
レコードの有無やパスワードの一致などを見て認証を掛けているのでしょう。
入力値をこんな感じにしてみるとどうなるでしょう。
username:username password:'or'A'='A'
展開してみると
$SQL = " SELECT * FROM user WHERE userid='username' AND password=''or'A'='A'
>*0*<キャアアッ
passwordが・・・passwordがぁぁぁぁぁぁぁぁぁ!!!
っていう感じになります。
やりようによっては
username:username password:';TRUNCATE user
いやーすっきりしたー。
良い気分〜〜〜〜。。。
とそのまま天国に召されます。
(案外データベースのテーブル名をformタグやサブミットの名前に使ったりしますからねぇ。)
ということできちっと処理してあげましょう。
さっきのソースコードに
$db = & DB :: connect( $dsn ); $user_id = $db->quoteSmart( (string)$_POST["input_userid"] ); $pass = $db->quoteSmart( (string)$_POST["input_password"]); $SQL = "SELECT * FROM user WHERE userid=$user_id AND password=$pass";
とすると
$SQL = " SELECT * FROM user WHERE userid='username' AND password='''or''A''=''A'''
になって変な問題から解放されます。