注入的來源
http請求的路徑、參數和header,比如cookie等都可能作為sql注入的來源。
在實際的開發工作中,因為現有框架中header、路徑作為參數直接查詢數據庫的使用比較少。因此,主要處理參數sql注入。
防止sql注入PHP已知方案
未經轉義的參數直接作為sql語句發給db就會發生sql注入,防止sql注入主要有以下幾種方式:
- 強類型參數校驗和轉義,禁止特殊字符的參數傳遞。
- 框架和數據庫統一提供的PREPARE, EXECUTE語法。
- 讀寫分離。
需要注意的是addslashes和mysql_real_escape_string都不能作為防SQL注入的方式。原因請參考:
https://blog.csdn.net/qq_36705093/article/details/79865601
詳細說明
強類型參數校驗和轉義
1. thinkphp框架input()幫助函數提供了以下幾種參數轉義:`d`:轉義int類型,`a`:轉義數組類型,`f`: 轉義浮點類型, `b`:轉義bool類型,`s`: 轉義字符串類型.
2. 也可以用intval, doubleval, floatval相關的函數進行參數過濾。識別無效的參數返回。
prepare, EXECUTE語法
thinkphp框架提供了prepare, execute語法來處理參數。詳細的mysql prepare語法可以查看:
執行步驟:
- 發送sql語句。
- 設置變量。
- 使用變量執行語句。
舉個例子:
prepare example from 'select * from sdb_user where id=?'; set @a=1; EXECUTE example USING @a;
步驟1中的sql語句會被mysql認為是需要執行的部分。步驟2, 3的語句傳入的變量不會被mysql執行。因此這種方式是最安全的mysql防注入的方式。對於thinkphp框架來說,是語句部分還是需要綁定的參數,是根據是否是變量來標識的。對於直接字符串拼接的部分,框架會認為是是sql語句而直接在步驟1發送給mysql,如果這部分有參數拼接就可能發生sql注入。
讀寫分離
thinkphp提供了方便的讀寫分離的配置。對於大部分業務來說,讀的接口都是在其中占據較大的部分,因此可以使用讀寫分離的方式來降低sql注入時對db造成嚴重破壞的概率,比如改寫數據,刪庫等。
主要包含以下database.php配置
<?php return [ "hostname":[ "127.0.0.1", //master "127.0.0.1" //readonly ], "username": [ "foo_write", //master "foo_read", //readonly ], "password": [ "bar_write", //master "bar_read", //readonly ], 'hostport' => '3306', 'deploy' => 1, 'rw_separate' => true, ];
因此使用tp框架防止sql注入可以做以下改進:
- 強類型參數校驗。
- 使用參數的方式傳遞查詢條件,禁止直接拼接參數。
- 讀寫分離。
by: zhangfeng