如何保護web 站點免受 sql注入攻擊?
SQL注入攻擊是指攻擊者利用站點中合法用戶的輸入機制發(fā)送 SQL 代碼到數(shù)據(jù)庫執(zhí)行,避免SQL 注入攻擊的黃金法則是:再來自外部源的所有數(shù)據(jù)到達數(shù)據(jù)庫之前將其轉義。該法則不僅適用于 INSERT 和 UPDATE 語句,也適用于SELECT查詢~
在腳本的查詢中使用預編譯語句幾乎可以消除所有的SQL注入攻擊問題,但是如果選擇使用 query()方法,將不具備這種保護一一必須對添加到查詢中的用戶輸入手工轉義。其代碼如下:
<?php $dbms = "mysql"; // 數(shù)據(jù)庫的類型 $dbName ="php_cn"; //使用的數(shù)據(jù)庫名稱 $user = "root"; //使用的數(shù)據(jù)庫用戶名 $pwd = "root"; //使用的數(shù)據(jù)庫密碼 $host = "localhost"; //使用的主機名稱 $dsn = "$dbms:host=$host;dbname=$dbName"; $name ='mr'; $name ="'or Name LIKE'%"; $query="select * from user where username = '".$name."'";//sql語句 try { $pdo = new PDO($dsn, $user, $pwd);//初始化一個PDO對象,就是創(chuàng)建了數(shù)據(jù)庫連接對象$pdo $result = $pdo->query($query);????//輸出結果集中的數(shù)據(jù) ????foreach?($result?as?$row){????????//輸出結果集中的數(shù)據(jù) ?????????> <tr> ????<td><div><?php echo $row['username'];?></div></td> </tr><?php } }catch (Exception $e){ echo "ERROR!!".$e->getMessage()."<br>"; } ?>
在這個實例中,假定SQL語句中的 $name 變量來自于用戶提交的表單。通常用戶會提交像“mr”這種內容,這就將會生成下面的SQL語句:
select?*?from?user?where?username?=?'mr'
這在腳本中不會造成任何問題,然而,一個“聰明”的攻擊者可能會輸入 “‘OR Name LIKE’%”,從而得到下面的SQL 語句:
select?*?from?user?where?username?=?'mr'
這在腳本中不會造成任何問題,然而,一個“聰明”的攻擊者可能會輸入 “‘OR Name LIKE’%”,從而得到下面的SQL 語句:
select?*?from?user?where?username?="OR?Name?LIKE'%'
這種輸入會為攻擊者打開整個表,如果是非常敏感的數(shù)據(jù),將被完全暴露在外。那么采用什么方法才能解決這個問題呢?
解決辦法
要想解決這個問題,可以使用PDO中的quote 方法轉義傳遞給SQL 字符串的數(shù)據(jù),只需要將SQL代碼修改成:
$sql="select?*?from?user?where?username?=?'".$pdo->quote($name)."'";
記住需要引用SQL 查詢中使用的每塊數(shù)據(jù),這個沒有快捷途徑,除非考慮使用prepare()和 execute()方法。
說明:
如果正在使用PDO->query()方法,那么總需要使用quote()方法引用用戶的輸入,記住是“總需要”。
如果選擇使用prepare()和 execute()方法,那么不必引用那些需要綁定到預編譯SQL 的值(比如:將被插入導數(shù)據(jù)庫的值),驅動會為用戶做所有的事,然而,有時可能無法將一個變量綁定到預編譯 SQL 語句,在這種情況下,如果正在創(chuàng)建一個動態(tài)SQL語句,那么需要引用所有用到的無法被綁定的值(如:GROUP BY 子句或ORDER BY或表名稱)。
那么關于如何保護Web 站點免受 SQL注入攻擊的解決辦法到這里就介紹完了,相信小伙伴們都可以輕松的掌握這節(jié)的知識點~