摘要:利用和產(chǎn)生原因主要就是一些數(shù)據(jù)沒(méi)有經(jīng)過(guò)嚴(yán)格的驗(yàn)證,然后直接拼接去查詢。導(dǎo)致漏洞產(chǎn)生,比如因?yàn)闆](méi)有對(duì)做數(shù)據(jù)類型驗(yàn)證,注入者可提交任何類型的數(shù)據(jù),比如等不安全的數(shù)據(jù)。如果按照下面方式寫,就安全一些。把轉(zhuǎn)換成類型,就可以去掉不安全的東西。
利用Mysqli和PDO
產(chǎn)生原因
主要就是一些數(shù)據(jù)沒(méi)有經(jīng)過(guò)嚴(yán)格的驗(yàn)證,然后直接拼接 SQL 去查詢。導(dǎo)致漏洞產(chǎn)生,比如:
$id = $_GET["id"]; $sql = "SELECT name FROM users WHERE id = $id";
因?yàn)闆](méi)有對(duì) $_GET["id"] 做數(shù)據(jù)類型驗(yàn)證,注入者可提交任何類型的數(shù)據(jù),比如 " and 1= 1 or " 等不安全的數(shù)據(jù)。如果按照下面方式寫,就安全一些。
$id = intval($_GET["id"]); $sql = "SELECT name FROM users WHERE id = $id";
把 id 轉(zhuǎn)換成 int 類型,就可以去掉不安全的東西。
驗(yàn)證數(shù)據(jù)
防止注入的第一步就是驗(yàn)證數(shù)據(jù),可以根據(jù)相應(yīng)類型進(jìn)行嚴(yán)格的驗(yàn)證。比如 int 類型直接同過(guò) intval 進(jìn)行轉(zhuǎn)換就行:
$id =intval( $_GET["id"]);
字符處理起來(lái)比較復(fù)雜些,首先通過(guò) sprintf 函數(shù)格式話輸出,確保它是一個(gè)字符串。然后通過(guò)一些安全函數(shù)去掉一些不合法的字符,比如:
$str = addslashes(sprintf("%s",$str));
//也可以用 mysqli_real_escape_string 函數(shù)替代addslashes
這樣處理以后會(huì)比較安全。當(dāng)然還可以進(jìn)一步去判斷字符串長(zhǎng)度,去防止「緩沖區(qū)溢出攻擊」比如:
$str = addslashes(sprintf("%s",$str)); $str = substr($str,0,40); //最大長(zhǎng)度為40
參數(shù)化綁定
參數(shù)化綁定,防止 SQL 注入的又一道屏障。php MySQLi 和 PDO 均提供這樣的功能。比如 MySQLi 可以這樣去查詢:
$mysqli = new mysqli("localhost", "my_user", "my_password", "world"); $stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)"); $code = "DEU"; $language = "Bavarian"; $official = "F"; $percent = 11.2; $stmt->bind_param("sssd", $code, $language, $official, $percent);
PDO 的更是方便,比如:
/* Execute a prepared statement by passing an array of values */ $sql = "SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour"; $sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY)); $sth->execute(array(":calories" => 150, ":colour" => "red")); $red = $sth->fetchAll(); $sth->execute(array(":calories" => 175, ":colour" => "yellow")); $yellow = $sth->fetchAll();
我們多數(shù)使用 php 的框架進(jìn)行編程,所以最好不要自己拼寫 SQL,按照框架給定參數(shù)綁定進(jìn)行查詢。遇到較為復(fù)雜的 SQL 語(yǔ)句,一定要自己拼寫的時(shí)候,一定要注意嚴(yán)格的判斷。沒(méi)有用 PDO 或者 MySQLi 也可以自己寫個(gè) prepared,比如 wordprss db 查詢語(yǔ)句,可以看出也是經(jīng)過(guò)嚴(yán)格的類型驗(yàn)證。
function prepare( $query, $args ) { if ( is_null( $query ) ) return; // This is not meant to be foolproof -- but it will catch obviously incorrect usage. if ( strpos( $query, "%" ) === false ) { _doing_it_wrong( "wpdb::prepare" , sprintf ( __( "The query argument of %s must have a placeholder." ), "wpdb::prepare()" ), "3.9" ); } $args = func_get_args(); array_shift( $args ); // If args were passed as an array (as in vsprintf), move them up if ( isset( $args[ 0] ) && is_array( $args[0]) ) $args = $args [0]; $query = str_replace( ""%s"", "%s" , $query ); // in case someone mistakenly already singlequoted it $query = str_replace( ""%s"", "%s" , $query ); // doublequote unquoting $query = preg_replace( "|(?總結(jié)
安全性很重要,也可以看出一個(gè)人基本功,項(xiàng)目漏洞百出,擴(kuò)展性和可維護(hù)性再好也沒(méi)有用。平時(shí)多留意,樹(shù)立安全意識(shí),養(yǎng)成一種習(xí)慣,一些基本的安全當(dāng)然也不會(huì)占用用 coding 的時(shí)間。養(yǎng)成這個(gè)習(xí)慣,即便在項(xiàng)目急,時(shí)間短的情況一下,依然可以做的質(zhì)量很高。不要等到自己以后負(fù)責(zé)的東西,數(shù)據(jù)庫(kù)都被拿走了,造成損失才重視。共勉!
雖然國(guó)內(nèi)很多PHP程序員仍在依靠addslashes防止SQL注入,還是建議大家加強(qiáng)中文防止SQL注入的檢查。addslashes的問(wèn)題在于黑客可以用0xbf27來(lái)代替單引號(hào),而addslashes只是將0xbf27修改為0xbf5c27,成為一個(gè)有效的多字節(jié)字符,其中的0xbf5c仍會(huì)被看作是單引號(hào),所以addslashes無(wú)法成功攔截。
當(dāng)然addslashes也不是毫無(wú)用處,它是用于單字節(jié)字符串的處理,多字節(jié)字符還是用mysql_real_escape_string吧。
另外對(duì)于php手冊(cè)中g(shù)et_magic_quotes_gpc的舉例:
if (!get_magic_quotes_gpc()) { $lastname = addslashes($_POST[‘lastname’]); } else { $lastname = $_POST[‘lastname’]; }最好對(duì)magic_quotes_gpc已經(jīng)開(kāi)放的情況下,還是對(duì)$_POST[’lastname’]進(jìn)行檢查一下。
再說(shuō)下mysql_real_escape_string和mysql_escape_string這2個(gè)函數(shù)的區(qū)別:
mysql_real_escape_string 必須在(PHP 4 >= 4.3.0, PHP 5)的情況下才能使用。否則只能用 mysql_escape_string ,兩者的區(qū)別是:mysql_real_escape_string 考慮到連接的當(dāng)前字符集,而mysql_escape_string 不考慮。
總結(jié)一下:
addslashes() 是強(qiáng)行加;
mysql_real_escape_string() 會(huì)判斷字符集,但是對(duì)PHP版本有要求;
mysql_escape_string不考慮連接的當(dāng)前字符集。
服務(wù)端配置方面
(1) 打開(kāi)php的安全模式
php的安全模式是個(gè)非常重要的內(nèi)嵌的安全機(jī)制,能夠控制一些php中的函數(shù),比如system(),
同時(shí)把很多文件操作函數(shù)進(jìn)行了權(quán)限控制,也不允許對(duì)某些關(guān)鍵文件的文件,比如/etc/passwd,
但是默認(rèn)的php.ini是沒(méi)有打開(kāi)安全模式的,我們把它打開(kāi):
safe_mode = on(2) 用戶組安全
當(dāng)safe_mode打開(kāi)時(shí),safe_mode_gid被關(guān)閉,那么php腳本能夠?qū)ξ募M(jìn)行訪問(wèn),而且相同
組的用戶也能夠?qū)ξ募M(jìn)行訪問(wèn)。建議設(shè)置為:
safe_mode_gid = off如果不進(jìn)行設(shè)置,可能我們無(wú)法對(duì)我們服務(wù)器網(wǎng)站目錄下的文件進(jìn)行操作了,比如我們需要
對(duì)文件進(jìn)行操作的時(shí)候。(3) 安全模式下執(zhí)行程序主目錄
如果安全模式打開(kāi)了,但是卻是要執(zhí)行某些程序的時(shí)候,可以指定要執(zhí)行程序的主目錄:safe_mode_exec_dir = D:/usr/bin一般情況下是不需要執(zhí)行什么程序的,所以推薦不要執(zhí)行系統(tǒng)程序目錄,可以指向一個(gè)目錄,
然后把需要執(zhí)行的程序拷貝過(guò)去,比如:safe_mode_exec_dir = D:/tmp/cmd但是,我更推薦不要執(zhí)行任何程序,那么就可以指向我們網(wǎng)頁(yè)目錄:
safe_mode_exec_dir = D:/usr/www(4) 安全模式下包含文件
如果要在安全模式下包含某些公共文件,那么就修改一下選項(xiàng):safe_mode_include_dir = D:/usr/www/include/其實(shí)一般php腳本中包含文件都是在程序自己已經(jīng)寫好了,這個(gè)可以根據(jù)具體需要設(shè)置。
(5) 控制php腳本能訪問(wèn)的目錄
使用open_basedir選項(xiàng)能夠控制PHP腳本只能訪問(wèn)指定的目錄,這樣能夠避免PHP腳本訪問(wèn)
不應(yīng)該訪問(wèn)的文件,一定程度上限制了phpshell的危害,我們一般可以設(shè)置為只能訪問(wèn)網(wǎng)站目錄:open_basedir = D:/usr/www(6) 關(guān)閉危險(xiǎn)函數(shù)
如果打開(kāi)了安全模式,那么函數(shù)禁止是可以不需要的,但是我們?yōu)榱税踩€是考慮進(jìn)去。比如,
我們覺(jué)得不希望執(zhí)行包括system()等在那的能夠執(zhí)行命令的php函數(shù),或者能夠查看php信息的
phpinfo()等函數(shù),那么我們就可以禁止它們:disable_functions = system,passthru,exec,shell_exec,popen,phpinfo如果你要禁止任何文件和目錄的操作,那么可以關(guān)閉很多文件操作
disable_functions = chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen,unlink,delete,copy,mkdir, rmdir,rename,file,file_get_contents,fputs,fwrite,chgrp,chmod,chown以上只是列了部分不叫常用的文件處理函數(shù),你也可以把上面執(zhí)行命令函數(shù)和這個(gè)函數(shù)結(jié)合,
就能夠抵制大部分的phpshell了。(7) 關(guān)閉PHP版本信息在http頭中的泄漏
我們?yōu)榱朔乐购诳瞳@取服務(wù)器中php版本的信息,可以關(guān)閉該信息斜路在http頭中:expose_php = Off比如黑客在 telnet www.12345.com 80 的時(shí)候,那么將無(wú)法看到PHP的信息。
(8) 關(guān)閉注冊(cè)全局變量
在PHP中提交的變量,包括使用POST或者GET提交的變量,都將自動(dòng)注冊(cè)為全局變量,能夠直接訪問(wèn),
這是對(duì)服務(wù)器非常不安全的,所以我們不能讓它注冊(cè)為全局變量,就把注冊(cè)全局變量選項(xiàng)關(guān)閉:register_globals = Off當(dāng)然,如果這樣設(shè)置了,那么獲取對(duì)應(yīng)變量的時(shí)候就要采用合理方式,比如獲取GET提交的變量var,
那么就要用$_GET["var"]來(lái)進(jìn)行獲取,這個(gè)php程序員要注意。(9) 打開(kāi)magic_quotes_gpc來(lái)防止SQL注入
SQL注入是非常危險(xiǎn)的問(wèn)題,小則網(wǎng)站后臺(tái)被入侵,重則整個(gè)服務(wù)器淪陷,
所以一定要小心。php.ini中有一個(gè)設(shè)置:magic_quotes_gpc = Off這個(gè)默認(rèn)是關(guān)閉的,如果它打開(kāi)后將自動(dòng)把用戶提交對(duì)sql的查詢進(jìn)行轉(zhuǎn)換,
比如把 " 轉(zhuǎn)為 '等,這對(duì)防止sql注射有重大作用。所以我們推薦設(shè)置為:magic_quotes_gpc = On(10) 錯(cuò)誤信息控制
一般php在沒(méi)有連接到數(shù)據(jù)庫(kù)或者其他情況下會(huì)有提示錯(cuò)誤,一般錯(cuò)誤信息中會(huì)包含php腳本當(dāng)
前的路徑信息或者查詢的SQL語(yǔ)句等信息,這類信息提供給黑客后,是不安全的,所以一般服務(wù)器建議禁止錯(cuò)誤提示:display_errors = Off如果你卻是是要顯示錯(cuò)誤信息,一定要設(shè)置顯示錯(cuò)誤的級(jí)別,比如只顯示警告以上的信息:
error_reporting = E_WARNING & E_ERROR當(dāng)然,我還是建議關(guān)閉錯(cuò)誤提示。
(11) 錯(cuò)誤日志
建議在關(guān)閉display_errors后能夠把錯(cuò)誤信息記錄下來(lái),便于查找服務(wù)器運(yùn)行的原因:log_errors = On同時(shí)也要設(shè)置錯(cuò)誤日志存放的目錄,建議根apache的日志存在一起:
error_log = D:/usr/local/apache2/logs/php_error.log注意:給文件必須允許apache用戶的和組具有寫的權(quán)限。
MYSQL的降權(quán)運(yùn)行
新建立一個(gè)用戶比如mysqlstartnet user mysqlstart fuckmicrosoft /add net localgroup users mysqlstart /del不屬于任何組
如果MYSQL裝在d:mysql ,那么,給 mysqlstart 完全控制 的權(quán)限
然后在系統(tǒng)服務(wù)中設(shè)置,MYSQL的服務(wù)屬性,在登錄屬性當(dāng)中,選擇此用戶 mysqlstart 然后輸入密碼,確定。
重新啟動(dòng) MYSQL服務(wù),然后MYSQL就運(yùn)行在低權(quán)限下了。
如果是在windos平臺(tái)下搭建的apache我們還需要注意一點(diǎn),apache默認(rèn)運(yùn)行是system權(quán)限,
這很恐怖,這讓人感覺(jué)很不爽.那我們就給apache降降權(quán)限吧。net user apache fuckmicrosoft /add net localgroup users apache /delok.我們建立了一個(gè)不屬于任何組的用戶apche。
我們打開(kāi)計(jì)算機(jī)管理器,選服務(wù),點(diǎn)apache服務(wù)的屬性,我們選擇log on,選擇this account,我們填入上面所建立的賬戶和密碼,
重啟apache服務(wù),ok,apache運(yùn)行在低權(quán)限下了。
實(shí)際上我們還可以通過(guò)設(shè)置各個(gè)文件夾的權(quán)限,來(lái)讓apache用戶只能執(zhí)行我們想讓它能干的事情,給每一個(gè)目錄建立一個(gè)多帶帶能讀寫的用戶。
這也是當(dāng)前很多虛擬主機(jī)提供商的流行配置方法哦,不過(guò)這種方法用于防止這里就顯的有點(diǎn)大材小用了。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/28150.html
摘要:參考中如何防止注入?yún)?shù)化查詢?yōu)槭裁茨軌蚍乐棺⑷肷厦嫣峁┑馁Y料比較多,下面根據(jù)自己的理解整理出來(lái)。使用的預(yù)處理參數(shù)化查詢可以有效防止注入。我們?cè)谏厦骖A(yù)處理參數(shù)化查詢是在中進(jìn)行防注入操作的,其實(shí)也內(nèi)置了一個(gè)預(yù)處理的模擬器,叫做。 由于segmentfault在處理特殊字符時(shí)也并非完美,所以下面文章中有些符號(hào)被轉(zhuǎn)換了,請(qǐng)到本人博客下載原文txt http://www.yunxi365.cn/...
閱讀 2678·2023-04-25 17:33
閱讀 716·2021-11-23 09:51
閱讀 3033·2021-07-30 15:32
閱讀 1492·2019-08-29 18:40
閱讀 2023·2019-08-28 18:19
閱讀 1526·2019-08-26 13:48
閱讀 2311·2019-08-23 16:48
閱讀 2354·2019-08-23 15:56