最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

php防止SQL注入詳解及防范

 更新時(shí)間:2013年11月12日 11:27:25   作者:  
SQL 注入是PHP應(yīng)用中最常見(jiàn)的漏洞之一。事實(shí)上令人驚奇的是,開發(fā)者要同時(shí)犯兩個(gè)錯(cuò)誤才會(huì)引發(fā)一個(gè)SQL注入漏洞
一個(gè)是沒(méi)有對(duì)輸入的數(shù)據(jù)進(jìn)行過(guò)濾(過(guò)濾輸入),還有一個(gè)是沒(méi)有對(duì)發(fā)送到數(shù)據(jù)庫(kù)的數(shù)據(jù)進(jìn)行轉(zhuǎn)義(轉(zhuǎn)義輸出)。這兩個(gè)重要的步驟缺一不可,需要同時(shí)加以特別關(guān)注以減少程序錯(cuò)誤。
對(duì)于攻擊者來(lái)說(shuō),進(jìn)行SQL注入攻擊需要思考和試驗(yàn),對(duì)數(shù)據(jù)庫(kù)方案進(jìn)行有根有據(jù)的推理非常有必要(當(dāng)然假設(shè)攻擊者看不到你的源程序和數(shù)據(jù)庫(kù)方案),考慮以下簡(jiǎn)單的登錄表單:
復(fù)制代碼 代碼如下:

<form action="/login.php" method="POST">
<p>Username: <input type="text" name="username" /></p>
<p>Password: <input type="password" name="password" /></p>
<p><input type="submit" value="Log In" /></p>
</form>

作為一個(gè)攻擊者,他會(huì)從推測(cè)驗(yàn)證用戶名和密碼的查詢語(yǔ)句開始。通過(guò)查看源文件,他就能開始猜測(cè)你的習(xí)慣。
比如命名習(xí)慣。通常會(huì)假設(shè)你表單中的字段名為與數(shù)據(jù)表中的字段名相同。當(dāng)然,確保它們不同未必是一個(gè)可靠的安全措施。
第一次猜測(cè),一般會(huì)使用下面例子中的查詢:
復(fù)制代碼 代碼如下:

<?php
 $password_hash = md5($_POST['password']);

$sql = "SELECT count(*)
      FROM   users
      WHERE  username = '{$_POST['username']}'
      AND    password = '$password_hash'";
 ?>

使用用戶密碼的MD5值原來(lái)是一個(gè)通行的做法,但現(xiàn)在并不是特別安全了。最近的研究表明MD5算法有缺陷,而且大量MD5數(shù)據(jù)庫(kù)降低了MD5反向破解的難度。請(qǐng)?jiān)L問(wèn)http://md5.rednoize.com/ 查看演示(原文如此,山東大學(xué)教授王小云的研究表明可以很快的找到MD5的“碰撞”,就是可以產(chǎn)生相同的MD5值的不同兩個(gè)文件和字串。MD5是信息摘要算法,而不是加密算法,反向破解也就無(wú)從談起了。不過(guò)根據(jù)這個(gè)成果,在上面的特例中,直接使用md5是危險(xiǎn)的。)。
最好的保護(hù)方法是在密碼上附加一個(gè)你自己定義的字符串,例如:
復(fù)制代碼 代碼如下:

<?php
 $salt = 'SHIFLETT';
$password_hash = md5($salt . md5($_POST['password'] . $salt));
 ?>

當(dāng)然,攻擊者未必在第一次就能猜中,他們常常還需要做一些試驗(yàn)。有一個(gè)比較好的試驗(yàn)方式是把單引號(hào)作為用戶名錄入,原因是這樣可能會(huì)暴露一些重要信息。有很多開發(fā)人員在Mysql語(yǔ)句執(zhí)行出錯(cuò)時(shí)會(huì)調(diào)用函數(shù)mysql_error()來(lái)報(bào)告錯(cuò)誤。見(jiàn)下面的例子:
復(fù)制代碼 代碼如下:

<?php
 mysql_query($sql) or exit(mysql_error());
 ?>

雖然該方法在開發(fā)中十分有用,但它能向攻擊者暴露重要信息。如果攻擊者把單引號(hào)做為用戶名,mypass做為密碼,查詢語(yǔ)句就會(huì)變成:
復(fù)制代碼 代碼如下:

<?php
 $sql = "SELECT *
      FROM   users
      WHERE  username = '''
      AND    password = 'a029d0df84eb5549c641e04a9ef389e5'";
 ?>

當(dāng)該語(yǔ)句發(fā)送到MySQL后,系統(tǒng)就會(huì)顯示如下錯(cuò)誤信息:
復(fù)制代碼 代碼如下:

You have an error in your SQL syntax. Check the manual that corresponds to your
MySQL server version for the right syntax to use near 'WHERE username = ''' AND
password = 'a029d0df84eb55

不費(fèi)吹灰之力,攻擊者已經(jīng)知道了兩個(gè)字段名(username和password)以及他們出現(xiàn)在查詢中的順序。除此以外,攻擊者還知道了數(shù)據(jù)沒(méi)有正確進(jìn)行過(guò)濾(程序沒(méi)有提示非法用戶名)和轉(zhuǎn)義(出現(xiàn)了數(shù)據(jù)庫(kù)錯(cuò)誤),同時(shí)整個(gè)WHERE條件的格式也暴露了,這樣,攻擊者就可以嘗試操縱符合查詢的記錄了。
在這一點(diǎn)上,攻擊者有很多選擇。一是嘗試填入一個(gè)特殊的用戶名,以使查詢無(wú)論用戶名密碼是否符合,都能得到匹配:
復(fù)制代碼 代碼如下:

myuser' or 'foo' = 'foo' --

假定將mypass作為密碼,整個(gè)查詢就會(huì)變成:
復(fù)制代碼 代碼如下:

<?php

$sql = "SELECT *
      FROM   users
      WHERE  username = 'myuser' or 'foo' = 'foo' --
      AND    password = 'a029d0df84eb5549c641e04a9ef389e5'";

?>

幸運(yùn)的是,SQL注入是很容易避免的。正如前面所提及的,你必須堅(jiān)持過(guò)濾輸入和轉(zhuǎn)義輸出。
雖然兩個(gè)步驟都不能省略,但只要實(shí)現(xiàn)其中的一個(gè)就能消除大多數(shù)的SQL注入風(fēng)險(xiǎn)。如果你只是過(guò)濾輸入而沒(méi)有轉(zhuǎn)義輸出,你很可能會(huì)遇到數(shù)據(jù)庫(kù)錯(cuò)誤(合法的數(shù)據(jù)也可能影響SQL查詢的正確格式),但這也不可靠,合法的數(shù)據(jù)還可能改變SQL語(yǔ)句的行為。另一方面,如果你轉(zhuǎn)義了輸出,而沒(méi)有過(guò)濾輸入,就能保證數(shù)據(jù)不會(huì)影響SQL語(yǔ)句的格式,同時(shí)也防止了多種常見(jiàn)SQL注入攻擊的方法。
當(dāng)然,還是要堅(jiān)持同時(shí)使用這兩個(gè)步驟。過(guò)濾輸入的方式完全取決于輸入數(shù)據(jù)的類型(見(jiàn)第一章的示例),但轉(zhuǎn)義用于向數(shù)據(jù)庫(kù)發(fā)送的輸出數(shù)據(jù)只要使用同一個(gè)函數(shù)即可。對(duì)于MySQL用戶,可以使用函數(shù)mysql_real_escape_string( ):
復(fù)制代碼 代碼如下:

<?php
 $clean = array();
$mysql = array();

$clean['last_name'] = "O'Reilly";
$mysql['last_name'] = mysql_real_escape_string($clean['last_name']);

$sql = "INSERT
      INTO   user (last_name)
      VALUES ('{$mysql['last_name']}')";
 ?>

盡量使用為你的數(shù)據(jù)庫(kù)設(shè)計(jì)的轉(zhuǎn)義函數(shù)。如果沒(méi)有,使用函數(shù)addslashes()是最終的比較好的方法。
當(dāng)所有用于建立一個(gè)SQL語(yǔ)句的數(shù)據(jù)被正確過(guò)濾和轉(zhuǎn)義時(shí),實(shí)際上也就避免了SQL注入的風(fēng)險(xiǎn)。如果你正在使用支持參數(shù)化查詢語(yǔ)句和占位符的數(shù)據(jù)庫(kù)操作類(如PEAR::DB, PDO等),你就會(huì)多得到一層保護(hù)。見(jiàn)下面的使用PEAR::DB的例子:
復(fù)制代碼 代碼如下:

<?php
$sql = 'INSERT
      INTO   user (last_name)
      VALUES (?)';
$dbh->query($sql, array($clean['last_name']));
?>

由于在上例中數(shù)據(jù)不能直接影響查詢語(yǔ)句的格式,SQL注入的風(fēng)險(xiǎn)就降低了。PEAR::DB會(huì)自動(dòng)根據(jù)你的數(shù)據(jù)庫(kù)的要求進(jìn)行轉(zhuǎn)義,所以你只需要過(guò)濾輸出即可。
如果你正在使用參數(shù)化查詢語(yǔ)句,輸入的內(nèi)容就只會(huì)作為數(shù)據(jù)來(lái)處理。這樣就沒(méi)有必要進(jìn)行轉(zhuǎn)義了,盡管你可能認(rèn)為這是必要的一步(如果你希望堅(jiān)持轉(zhuǎn)義輸出習(xí)慣的話)。實(shí)際上,這時(shí)是否轉(zhuǎn)義基本上不會(huì)產(chǎn)生影響,因?yàn)檫@時(shí)沒(méi)有特殊字符需要轉(zhuǎn)換。在防止SQL注入這一點(diǎn)上,參數(shù)化查詢語(yǔ)句為你的程序提供了強(qiáng)大的保護(hù)。
注:關(guān)于SQL注入,不得不說(shuō)的是現(xiàn)在大多虛擬主機(jī)都會(huì)把magic_quotes_gpc選項(xiàng)打開,在這種情況下所有的客戶端GET和POST的數(shù)據(jù)都會(huì)自動(dòng)進(jìn)行addslashes處理,所以此時(shí)對(duì)字符串值的SQL注入是不可行的,但要防止對(duì)數(shù)字值的SQL注入,如用intval()等函數(shù)進(jìn)行處理。但如果你編寫的是通用軟件,則需要讀取服務(wù)器的magic_quotes_gpc后進(jìn)行相應(yīng)處理。

相關(guān)文章

  • PHP防CC攻擊實(shí)現(xiàn)代碼

    PHP防CC攻擊實(shí)現(xiàn)代碼

    所謂的CC攻擊就是對(duì)方利用程序或一些代理對(duì)您的網(wǎng)站進(jìn)行不間斷的訪問(wèn),造成您的網(wǎng)站處理不了而處于當(dāng)機(jī)狀態(tài)
    2011-12-12
  • Mysql的Root密碼忘記,查看或修改的解決方法(圖文介紹)

    Mysql的Root密碼忘記,查看或修改的解決方法(圖文介紹)

    本篇文章是對(duì)關(guān)于Mysql中的Root密碼忘記,查看或修改的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • PHP緩存技術(shù)的多種方法小結(jié)

    PHP緩存技術(shù)的多種方法小結(jié)

    這里所說(shuō)的數(shù)據(jù)緩存是指數(shù)據(jù)庫(kù)查詢PHP緩存機(jī)制,每次訪問(wèn)頁(yè)面的時(shí)候,都會(huì)先檢測(cè)相應(yīng)的緩存數(shù)據(jù)是否存在,如果不存在,就連接數(shù)據(jù)庫(kù),得到數(shù)據(jù),并把查詢結(jié)果序列化后保存到文件中,以后同樣的查詢結(jié)果就直接從緩存表或文件中獲得
    2012-08-08
  • PHP標(biāo)準(zhǔn)庫(kù) (SPL)——Countable用法示例

    PHP標(biāo)準(zhǔn)庫(kù) (SPL)——Countable用法示例

    這篇文章主要介紹了PHP標(biāo)準(zhǔn)庫(kù) (SPL)——Countable用法,結(jié)合實(shí)例形式分析了PHP標(biāo)準(zhǔn)庫(kù) (SPL)Countable基本功能、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下
    2020-06-06
  • PHP 獲取目錄下的圖片并隨機(jī)顯示的代碼

    PHP 獲取目錄下的圖片并隨機(jī)顯示的代碼

    從一個(gè)目錄里獲取某類型文件的清單(用在WEB的話一般是jpg/gif/png)->通過(guò)隨機(jī)函數(shù)選一個(gè)圖片->輸出代碼。
    2009-12-12
  • PHP平滑關(guān)閉/重啟的實(shí)現(xiàn)方法

    PHP平滑關(guān)閉/重啟的實(shí)現(xiàn)方法

    "平滑重啟"和"快速重啟"是兩種不同的概念,下面這篇文章主要給大家介紹了關(guān)于PHP平滑關(guān)閉/重啟的實(shí)現(xiàn)方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-05-05
  • PHP數(shù)據(jù)庫(kù)操作Helper類完整實(shí)例

    PHP數(shù)據(jù)庫(kù)操作Helper類完整實(shí)例

    這篇文章主要介紹了PHP數(shù)據(jù)庫(kù)操作Helper類,詳細(xì)分析了php操作mysql的連接、增刪改查及關(guān)閉連接等步驟,并給出了完整的mysql操作類Helper供大家參考,需要的朋友可以參考下
    2016-05-05
  • PHP遞歸遍歷多維數(shù)組實(shí)現(xiàn)無(wú)限分類的方法

    PHP遞歸遍歷多維數(shù)組實(shí)現(xiàn)無(wú)限分類的方法

    這篇文章主要介紹了PHP遞歸遍歷多維數(shù)組實(shí)現(xiàn)無(wú)限分類的方法,涉及PHP遞歸操作遍歷數(shù)組的相關(guān)技巧,在聯(lián)動(dòng)菜單及父子欄目設(shè)計(jì)等方面非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2016-05-05
  • php合并數(shù)組array_merge函數(shù)運(yùn)算符加號(hào)與的區(qū)別

    php合并數(shù)組array_merge函數(shù)運(yùn)算符加號(hào)與的區(qū)別

    “+”運(yùn)算符和array_merge():array array_merge ( array array1, array array2 [, array ...] ) 都可以合并多個(gè)數(shù)組,但使用過(guò)程中有一點(diǎn)小區(qū)別。
    2008-10-10
  • Windows下的PHP5.0詳解

    Windows下的PHP5.0詳解

    Windows下的PHP5.0詳解...
    2006-11-11

最新評(píng)論

汤原县| 兴业县| 东兰县| 碌曲县| 济南市| 获嘉县| 泗洪县| 仪征市| 科技| 昭觉县| 陆河县| 泸定县| 新泰市| 赤壁市| 新田县| 庄河市| 西吉县| 定结县| 宁明县| 北宁市| 海南省| 卫辉市| 江都市| 治县。| 乌拉特后旗| 富锦市| 江孜县| 兰坪| 岳普湖县| 彝良县| 巍山| 桐柏县| 搜索| 晋中市| 崇左市| 德兴市| 宁陵县| 桐庐县| 三明市| 枣强县| 彭阳县|