一分鐘帶你了解SQL Injection

通過把sql命令插入到web表單遞交或輸入域名或頁面請求的查詢字符串,最終達(dá)到欺騙服務(wù)器執(zhí)行惡意的sql命令。具體來說,它是利用現(xiàn)有應(yīng)用程序,將(惡意)的sql命令注入到后臺數(shù)據(jù)庫引擎執(zhí)行的能力,得到一個存在安全漏洞的網(wǎng)站上的數(shù)據(jù)庫。

一分鐘帶你了解SQL Injection

SQL Injection,SQL 注入,其實(shí)就是利用代碼漏洞改變 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 語句就變?yōu)榱?/p>

select?*?from?users?where?username?=?'123'?or?1=1; #?and?password?=?'{$password}'";

這條惡意的 SQL 語句無論何時都會返回 true,因?yàn)?1=1

通過 ORM 注入

我們前面講過 SQL Injection 就是利用代碼漏洞改變 SQL 的語意,意味著 ORM 也是一個潛在的注入點(diǎn)。以 tp3.2 為例,有下面這段代碼

$result?=?D('User')->where([ ????'username'?=>?$_POST['username'], ????'password'?=>?$_POST['password'], ]);  if?($result)?{ ????echo?'登錄成功'; }?else?{ ????echo?'登錄失敗'; }

這段代碼咋看起來沒啥問題,但是如果 username 傳入的是 username[0]=neq&username[1]=1111,這樣就是的查詢語句變?yōu)?/p>

$result?=?D('User')->where([ ????'username'?=>?['neq',?111], ????'password'?=>?$_POST['password'], ]);

那么 $result 的結(jié)果將永遠(yuǎn)為 true

防范方法

  • 對傳入的參數(shù)進(jìn)行數(shù)據(jù)類型判斷和數(shù)據(jù)類型轉(zhuǎn)換

  • 對引號進(jìn)行轉(zhuǎn)義,php 可以使用 addslashes,mysql_real_escape_string 等函數(shù)

  • 預(yù)處理語句,最有效防范 SQL Injection

  • 代碼審計(jì)

預(yù)處理語句是如何防止 SQL Injection 的

預(yù)處理語句是由數(shù)據(jù)庫實(shí)現(xiàn)的,比如 MySQL 就有實(shí)現(xiàn)預(yù)處理語句。首先講下預(yù)處理的基本流程

  • MySQL 接收到 預(yù)處理 SQL Template,立刻著手進(jìn)行解析(詞法和語法)

  • 客戶端發(fā)送數(shù)據(jù),去替換 SQL Template 中的占位符(?)

  • MySQL 執(zhí)行語句,返回結(jié)果

  • 刪除預(yù)處理語句(可選)

那么預(yù)處理語句是如何防范 SQL 注入的呢?首先所謂的 SQL Injection 就是強(qiáng)行去改變 SQL 語意。而在步驟一中已經(jīng)處理完成語句,將 SQL 的語意固定下來,步驟二的替換占位符并不會改變 SQL 語意。下面是 PHP pdo 的例子

$stmt?=?$pdo->prepare("select?*?from?users?where?username?=?'?'?and?password?=?'?'");  $stmt->execute("123'?or?1=1;#",?'test');

相關(guān)推薦:《mysql教程

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊6 分享