防止SQL注入總結


0x00 背景

自己一個人學了這么久的web安全,感覺需要一些總結,加上今天下午電話面試總被問到的問題,自己總結了一下寫出來和大家分享。(小白一個,也算自己記錄一下,大佬勿噴)

0x01SQL注入實例

這里就以DVWA來做個示范,畢竟主要講防御

low等級的注入無過濾直接提交id

LOW SQL

medium等級使用了mysqli_real_escape_string函數進行轉義,被轉義的包括\x00,\n,\r,\,’,”,\x1a(參考菜鳥教程)但是這種簡單的轉義很容易就被各種編碼方式繞過。

high等級的代碼采用了窗口跳轉的方式,但是對於上交的數據始終沒有處理就提交了,只是簡單的在其后加了一個LIMIT 1,來限制取數據的行數,但是只要簡單的使用#或者--+來注釋掉就可以了。(感覺這個應該屬於midium)

high等級的代碼加入了token機制和PDO,基本防御了SQL注入。反正以我的水平和在網上查找的資料來看,好像沒有成功注入的。

 
 

0x02

首先大前提是驗證都處於服務器端,前端的驗證形同虛設。

(1)使用PDO

PDO是PHP的一個擴展,為PHP訪問數據庫提供一個統一的接口,這就表明PDO可以連接不同類型的數據庫系統,但是我們還是需要自己編寫SQL語句。PDO隨PHP5.1發行,在PHP5.0的PECL擴展中也可以使用,無法運行於之前的PHP版本,可以在phpinfo()中查看是否支持PDO。

$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root');//設置編碼以防止亂碼

$sql ="SELECT id FROM user WHERE email=:email";

$stmt = $pdo->prepare($sql);

$email = filter_input(INPUT_GET,'email');

$stmt->bindValue(':email', $email);

上述代碼中,:email是具名占位符,可以安全的綁定任意值。預處理語句會自動過濾$email的值,防止數據庫收到SQL注入攻擊。一個sql語句字符串中可以綁定多個具名占位符,然后在預處理語句中通過bindValue()方法綁定各個占位符的值。

(2)使用mysqli_query

MySQLi 擴展是在 PHP 5.0.0 版本中引進的,且只針對mysql數據庫,但是其實大概原理和DBO相似,都是采用了prepare + bind 的寫法。

$mysqli = new mysqli('localhost','username','password','database');  

$query = $mysqli->prepare('  

   SELECT * FROM users  

   WHERE username = ?  

   AND email = ?  

   AND last_login > ?'); 

$query->bind_param('sss', 'test', $mail, time() - 3600);  

$query->execute();

這個問號(?)綁定參數看上去很短,但是相比名稱式參數缺少了靈活性,而且迫使開發者必須保證參數的順序,有時候讓人覺得很蛋疼。而且不幸的是MySQLi並不支持名稱式參數。

(3)對輸入進行轉義處理

這一類主要是通過編程語言的預定義函數對輸入轉義,包括mysql_real_escape_string、addslashes()等,但是這一類函數存在一定的安全風險,不推薦使用。參見文章:PHP防SQL注入不要再用addslashes和mysql_real_escape_string了

(4)限制輸入的內容

比如限制為數字或者字母,又或者是對select、union、insert等這一類SQL語句進行過濾,但是這樣一方面帶來了對於用戶使用的舒適性也有可能過濾不嚴格導致形同虛設。

(5)對輸入編碼

//這也算是一種處理各種注入的萬能方法了,但是不足就是每次存取都需要編碼或者解密,效率可能會降低。

SELECT password FROM users WHERE name = 'root'            --普通方式  

SELECT password FROM users WHERE name = 0x726f6f74        --防止注入  

SELECT password FROM users WHERE name = UNHEX('726f6f74') --防止注入  

(6)使用存儲過程

存儲過程是各種數據庫的一種函數式編程方法,類似於預處理,只分配必要的數據庫許可權限,有助於減輕SQL注入的影響——限制攻擊者只能調用存儲過程,從而限制了能夠訪問或修改的數據。由於SQL注入不僅能發生在應用層,還能發生在數據庫層,因此如果攻擊者將惡意語句寫入到存儲過程中,雖然訪問和修改數據受到限制,但是如果在后續的動態SQL中使用了該輸入,仍可能造成SQL注入。

以上就是目前我能知道的所有了,需要學習的還很多。FIGHTING~~~

如果誰看到我這個覺得不深入,給大家推薦一篇更詳細的文章:SQL注入之代碼層防御


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM