Perl DBI 防止 SQL Injection

現在很多地方都用上資料庫系統, 有一些是檢查用戶名稱及密碼的登入系統, 但如果沒有對用戶輸入進行過濾, 會有很多潛在危除, 例如以下程式碼:

my $sth = $dbh->prepare(“select * from user where user=’$user’ and pass=’$pass'”);

以上這句 SQL 會檢索 user 資料表, 找出 user 及 pass 與用戶輸入匹配的紀錄, 有回傳便可以登入, 沒有回傳便登入失敗, 這個很容易理解。但如果用戶的輸入包括了一些特定的 sql 指令, 那便有問題了, 例如用戶將 $pass 輸入成:

“‘ or user=’user'”

那麼程式處理的 sql 語句會是:

“select * from user where user=’$user’ and pass=’$pass’ or user=’user'”

即使密碼錯誤, 只要用戶名與 user 匹配也可以進入。另一個做法是輸入 SQL 語句中表示結束的 “;” 符號, 那麼除了登入系統外, 也可以進行 update, delete, drop table 等語句。

PHP 可以用 mysql_real_escape_string() 處理, 而 Perl 用做法有點不同, DBI 已經內置防止 SQL Injection 功能, 會處理傳入的所有特殊字符, 例如引號及分號, 用回上面的例子, 做法如下:

my $sth = $dbh->prepare(“select * from user where user=’?’ and pass=’?'”);
my $sth = $dbh->prepare( $sql );
$sth->execute( $user, $pass );

可以看到 SQL 語句用了 ? 替代要傳入的 $user 及 $pass, 而在 $sth->execute() 才傳入 $user 及 $pass, DBI 會自動將 execute 傳入的參數, 順序填補到 prepare “?” 的位置, 這樣就可以預防 SQL Injection 攻擊了.




Leave a Reply