通過把sql命令插入到web表單遞交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的sql命令。具體來說,它是利用現有應用程序,將(惡意)的sql命令注入到后臺數據庫引擎執行的能力,得到一個存在安全漏洞的網站上的數據庫。
SQL Injection,SQL 注入,其實就是利用代碼漏洞改變 SQL 的語意,從而形成惡意 SQL 語句
$username?=?$_POST['username']; $password?=?$_POST['password']; $query?=?"select?*?from?users?where?username?=?'{$username}'?and?password?=?'{$password}'"; //?判斷是否登錄成功 if?(DB::select($query))?{ ????return?true; } return?false;
咋一看這段偽代碼沒啥問題,就是判斷賬號密碼是否正確,正確就返回 true,允許登錄。但是如果傳入的 username 為 123′ or 1=1;#,那么 SQL 語句就變為了
select?*?from?users?where?username?=?'123'?or?1=1; #?and?password?=?'{$password}'";
這條惡意的 SQL 語句無論何時都會返回 true,因為 1=1
通過 ORM 注入
我們前面講過 SQL Injection 就是利用代碼漏洞改變 SQL 的語意,意味著 ORM 也是一個潛在的注入點。以 tp3.2 為例,有下面這段代碼
$result?=?D('User')->where([ ????'username'?=>?$_POST['username'], ????'password'?=>?$_POST['password'], ]); if?($result)?{ ????echo?'登錄成功'; }?else?{ ????echo?'登錄失敗'; }
這段代碼咋看起來沒啥問題,但是如果 username 傳入的是 username[0]=neq&username[1]=1111,這樣就是的查詢語句變為
$result?=?D('User')->where([ ????'username'?=>?['neq',?111], ????'password'?=>?$_POST['password'], ]);
那么 $result 的結果將永遠為 true
防范方法
-
預處理語句,最有效防范 SQL Injection
-
代碼審計
預處理語句是如何防止 SQL Injection 的
預處理語句是由數據庫實現的,比如 MySQL 就有實現預處理語句。首先講下預處理的基本流程
-
MySQL 接收到 預處理 SQL Template,立刻著手進行解析(詞法和語法)
-
客戶端發送數據,去替換 SQL Template 中的占位符(?)
-
MySQL 執行語句,返回結果
-
刪除預處理語句(可選)
那么預處理語句是如何防范 SQL 注入的呢?首先所謂的 SQL Injection 就是強行去改變 SQL 語意。而在步驟一中已經處理完成語句,將 SQL 的語意固定下來,步驟二的替換占位符并不會改變 SQL 語意。下面是 PHP pdo 的例子
$stmt?=?$pdo->prepare("select?*?from?users?where?username?=?'?'?and?password?=?'?'"); $stmt->execute("123'?or?1=1;#",?'test');
相關推薦:《mysql教程》