php 編寫(xiě)安全的代碼時(shí)容易犯的錯(cuò)誤小結(jié)
更新時(shí)間:2010年05月20日 23:33:00 作者:
PHP是個(gè)偉大的web開(kāi)發(fā)語(yǔ)言,靈活的語(yǔ)言,但是看到php程序員周而復(fù)始的犯的一些錯(cuò)誤。我做了下面這個(gè)列表,列出了PHP程序員經(jīng)常犯的10中錯(cuò)誤,大多數(shù)和安全相關(guān)??纯茨惴噶藥追N
1.不轉(zhuǎn)意html entities
一個(gè)基本的常識(shí):所有不可信任的輸入(特別是用戶從form中提交的數(shù)據(jù)) ,輸出之前都要轉(zhuǎn)意。
echo $_GET['usename'] ;
這個(gè)例子有可能輸出:
<script>/*更改admin密碼的腳本或設(shè)置cookie的腳本*/</script>
這是一個(gè)明顯的安全隱患,除非你保證你的用戶都正確的輸入。
如何修復(fù) :
我們需要將"< ",">","and" 等轉(zhuǎn)換成正確的HTML表示(< , >', and "),函數(shù)htmlspecialchars 和 htmlentities()正是干這個(gè)活的。
正確的方法:
echo htmlspecialchars($_GET['username'], ENT_QUOTES);
2. 不轉(zhuǎn)意SQL輸入
我曾經(jīng)在一篇文章中最簡(jiǎn)單的防止sql注入的方法(php+mysql中)討論過(guò)這個(gè)問(wèn)題并給出了一個(gè)簡(jiǎn)單的方法 。有人對(duì)我說(shuō),他們已經(jīng)在php.ini中將magic_quotes設(shè)置為On,所以不必?fù)?dān)心這個(gè)問(wèn)題,但是不是所有的輸入都是從$_GET, $_POST或 $_COOKIE中的得到的!
如何修復(fù):
和在最簡(jiǎn)單的防止sql注入的方法(php+mysql中)中一樣我還是推薦使用mysql_real_escape_string()函數(shù)
正確做法:
<?php
$sql = "UPDATE users SET
name='.mysql_real_escape_string($name).'
WHERE id='.mysql_real_escape_string ($id).'";
mysql_query($sql);
?>
3.錯(cuò)誤的使用HTTP-header 相關(guān)的函數(shù): header(), session_start(), setcookie()
遇到過(guò)這個(gè)警告嗎?"warning: Cannot add header information - headers already sent [....]
每次從服務(wù)器下載一個(gè)網(wǎng)頁(yè)的時(shí)候,服務(wù)器的輸出都分成兩個(gè)部分:頭部和正文。
頭部包含了一些非可視的數(shù)據(jù),例如cookie。頭部總是先到達(dá)。正文部分包括可視的html,圖片等數(shù)據(jù)。
如果output_buffering設(shè)置為Off,所有的HTTP-header相關(guān)的函數(shù)必須在有輸出之前調(diào)用。問(wèn)題在于你在一個(gè)環(huán)境中開(kāi)發(fā),而在部署到另一個(gè)環(huán)境中去的時(shí)候,output_buffering的設(shè)置可能不一樣。結(jié)果轉(zhuǎn)向停止了,cookie和session都沒(méi)有正確的設(shè)置........。
如何修復(fù):
確保在輸出之前調(diào)用http-header相關(guān)的函數(shù),并且令output_buffering = Off
。
4. Require 或 include 的文件使用不安全的數(shù)據(jù)
再次強(qiáng)調(diào):不要相信不是你自己顯式聲明的數(shù)據(jù)。不要 Include 或 require 從$_GET, $_POST 或 $_COOKIE 中得到的文件。
例如:
index.php
<?
//including header, config, database connection, etc
include($_GET['filename']);
//including footer
?>
現(xiàn)在任一個(gè)黑客現(xiàn)在都可以用:http://www.yourdomain.com/index.php?filename=anyfile.txt
來(lái)獲取你的機(jī)密信息,或執(zhí)行一個(gè)PHP腳本。
如果allow_url_fopen=On,你更是死定了:
試試這個(gè)輸入:
http://www.yourdomain.com/index.php?filename=http%3A%2F%2Fdomain.com%2Fphphack.php
現(xiàn)在你的網(wǎng)頁(yè)中包含了http://www.youaredoomed.com/phphack.php的輸出. 黑客可以發(fā)送垃圾郵件,改變密碼,刪除文件等等。只要你能想得到。
如何修復(fù):
你必須自己控制哪些文件可以包含在的include或require指令中。
下面是一個(gè)快速但不全面的解決方法:
<?
//Include only files that are allowed.
$allowedFiles = array('file1.txt','file2.txt','file3.txt');
if(in_array((string)$_GET['filename'],$allowedFiles)) {
include($_GET['filename']);
}
else{
exit('not allowed');
}
?>
5. 語(yǔ)法錯(cuò)誤
語(yǔ)法錯(cuò)誤包括所有的詞法和語(yǔ)法錯(cuò)誤,太常見(jiàn)了,以至于我不得不在這里列出。解決辦法就是認(rèn)真學(xué)習(xí)PHP的語(yǔ)法,仔細(xì)一點(diǎn)不要漏掉一個(gè)括號(hào),大括號(hào),分號(hào),引號(hào)。還有就是換個(gè)好的編輯器,就不要用記事本了!
6.很少使用或不用面向?qū)ο?
很多的項(xiàng)目都沒(méi)有使用PHP的面向?qū)ο蠹夹g(shù),結(jié)果就是代碼的維護(hù)變得非常耗時(shí)耗力。PHP支持的面向?qū)ο蠹夹g(shù)越來(lái)越多,越來(lái)越好,我們沒(méi)有理由不使用面向?qū)ο蟆?
7. 不使用framework
95% 的PHP項(xiàng)目都在做同樣的四件事: Create, edit, list 和delete. 現(xiàn)在有很多MVC的框架來(lái)幫我們完成這四件事,我們?yōu)楹尾皇褂盟麄兡兀?
8. 不知道PHP中已經(jīng)有的功能
PHP的核心包含很多功能。很多程序員重復(fù)的發(fā)明輪子。浪費(fèi)了大量時(shí)間。編碼之前搜索一下PHP mamual,在google上檢索一下,也許會(huì)有新的發(fā)現(xiàn)!PHP中的exec()是一個(gè)強(qiáng)大的函數(shù),可以執(zhí)行cmd shell,并把執(zhí)行結(jié)果的最后一行以字符串的形式返回??紤]到安全可以使用EscapeShellCmd()
9.使用舊版本的PHP
很多程序員還在使用PHP4,在PHP4上開(kāi)發(fā)不能充分發(fā)揮PHP的潛能,還存在一些安全的隱患。轉(zhuǎn)到PHP5上來(lái)吧,并不費(fèi)很多功夫。大部分PHP4程序只要改動(dòng)很少的語(yǔ)句甚至無(wú)需改動(dòng)就可以遷移到PHP5上來(lái)。根據(jù)http://www.nexen.net的調(diào)查 只有12%的PHP服務(wù)器使用PHP5,所以有88%的PHP開(kāi)發(fā)者還在使用PHP4.
10.對(duì)引號(hào)做兩次轉(zhuǎn)意
見(jiàn)過(guò)網(wǎng)頁(yè)中出現(xiàn)\'或\'"嗎?這通常是因?yàn)樵陂_(kāi)發(fā)者的環(huán)境中magic_quotes 設(shè)置為off,而在部署的服務(wù)器上magic_quotes =on. PHP會(huì)在 GET, POST 和 COOKIE中的數(shù)據(jù)上重復(fù)運(yùn)行addslashes() 。
原始文本:
It's a string
magic quotes on :
It\'s a string
又運(yùn)行一次
addslashes():
It\\'s a string
HTML輸出:
It\'s a string
還有一種情況就是,用戶一開(kāi)始輸入了錯(cuò)誤的登錄信息,服務(wù)器檢測(cè)到錯(cuò)誤輸入后,輸出同樣的form要求用戶再次輸入,導(dǎo)致用戶的輸入轉(zhuǎn)意兩次!
一個(gè)基本的常識(shí):所有不可信任的輸入(特別是用戶從form中提交的數(shù)據(jù)) ,輸出之前都要轉(zhuǎn)意。
echo $_GET['usename'] ;
這個(gè)例子有可能輸出:
<script>/*更改admin密碼的腳本或設(shè)置cookie的腳本*/</script>
這是一個(gè)明顯的安全隱患,除非你保證你的用戶都正確的輸入。
如何修復(fù) :
我們需要將"< ",">","and" 等轉(zhuǎn)換成正確的HTML表示(< , >', and "),函數(shù)htmlspecialchars 和 htmlentities()正是干這個(gè)活的。
正確的方法:
echo htmlspecialchars($_GET['username'], ENT_QUOTES);
2. 不轉(zhuǎn)意SQL輸入
我曾經(jīng)在一篇文章中最簡(jiǎn)單的防止sql注入的方法(php+mysql中)討論過(guò)這個(gè)問(wèn)題并給出了一個(gè)簡(jiǎn)單的方法 。有人對(duì)我說(shuō),他們已經(jīng)在php.ini中將magic_quotes設(shè)置為On,所以不必?fù)?dān)心這個(gè)問(wèn)題,但是不是所有的輸入都是從$_GET, $_POST或 $_COOKIE中的得到的!
如何修復(fù):
和在最簡(jiǎn)單的防止sql注入的方法(php+mysql中)中一樣我還是推薦使用mysql_real_escape_string()函數(shù)
正確做法:
復(fù)制代碼 代碼如下:
<?php
$sql = "UPDATE users SET
name='.mysql_real_escape_string($name).'
WHERE id='.mysql_real_escape_string ($id).'";
mysql_query($sql);
?>
3.錯(cuò)誤的使用HTTP-header 相關(guān)的函數(shù): header(), session_start(), setcookie()
遇到過(guò)這個(gè)警告嗎?"warning: Cannot add header information - headers already sent [....]
每次從服務(wù)器下載一個(gè)網(wǎng)頁(yè)的時(shí)候,服務(wù)器的輸出都分成兩個(gè)部分:頭部和正文。
頭部包含了一些非可視的數(shù)據(jù),例如cookie。頭部總是先到達(dá)。正文部分包括可視的html,圖片等數(shù)據(jù)。
如果output_buffering設(shè)置為Off,所有的HTTP-header相關(guān)的函數(shù)必須在有輸出之前調(diào)用。問(wèn)題在于你在一個(gè)環(huán)境中開(kāi)發(fā),而在部署到另一個(gè)環(huán)境中去的時(shí)候,output_buffering的設(shè)置可能不一樣。結(jié)果轉(zhuǎn)向停止了,cookie和session都沒(méi)有正確的設(shè)置........。
如何修復(fù):
確保在輸出之前調(diào)用http-header相關(guān)的函數(shù),并且令output_buffering = Off
。
4. Require 或 include 的文件使用不安全的數(shù)據(jù)
再次強(qiáng)調(diào):不要相信不是你自己顯式聲明的數(shù)據(jù)。不要 Include 或 require 從$_GET, $_POST 或 $_COOKIE 中得到的文件。
例如:
復(fù)制代碼 代碼如下:
index.php
<?
//including header, config, database connection, etc
include($_GET['filename']);
//including footer
?>
現(xiàn)在任一個(gè)黑客現(xiàn)在都可以用:http://www.yourdomain.com/index.php?filename=anyfile.txt
來(lái)獲取你的機(jī)密信息,或執(zhí)行一個(gè)PHP腳本。
如果allow_url_fopen=On,你更是死定了:
試試這個(gè)輸入:
http://www.yourdomain.com/index.php?filename=http%3A%2F%2Fdomain.com%2Fphphack.php
現(xiàn)在你的網(wǎng)頁(yè)中包含了http://www.youaredoomed.com/phphack.php的輸出. 黑客可以發(fā)送垃圾郵件,改變密碼,刪除文件等等。只要你能想得到。
如何修復(fù):
你必須自己控制哪些文件可以包含在的include或require指令中。
下面是一個(gè)快速但不全面的解決方法:
復(fù)制代碼 代碼如下:
<?
//Include only files that are allowed.
$allowedFiles = array('file1.txt','file2.txt','file3.txt');
if(in_array((string)$_GET['filename'],$allowedFiles)) {
include($_GET['filename']);
}
else{
exit('not allowed');
}
?>
5. 語(yǔ)法錯(cuò)誤
語(yǔ)法錯(cuò)誤包括所有的詞法和語(yǔ)法錯(cuò)誤,太常見(jiàn)了,以至于我不得不在這里列出。解決辦法就是認(rèn)真學(xué)習(xí)PHP的語(yǔ)法,仔細(xì)一點(diǎn)不要漏掉一個(gè)括號(hào),大括號(hào),分號(hào),引號(hào)。還有就是換個(gè)好的編輯器,就不要用記事本了!
6.很少使用或不用面向?qū)ο?
很多的項(xiàng)目都沒(méi)有使用PHP的面向?qū)ο蠹夹g(shù),結(jié)果就是代碼的維護(hù)變得非常耗時(shí)耗力。PHP支持的面向?qū)ο蠹夹g(shù)越來(lái)越多,越來(lái)越好,我們沒(méi)有理由不使用面向?qū)ο蟆?
7. 不使用framework
95% 的PHP項(xiàng)目都在做同樣的四件事: Create, edit, list 和delete. 現(xiàn)在有很多MVC的框架來(lái)幫我們完成這四件事,我們?yōu)楹尾皇褂盟麄兡兀?
8. 不知道PHP中已經(jīng)有的功能
PHP的核心包含很多功能。很多程序員重復(fù)的發(fā)明輪子。浪費(fèi)了大量時(shí)間。編碼之前搜索一下PHP mamual,在google上檢索一下,也許會(huì)有新的發(fā)現(xiàn)!PHP中的exec()是一個(gè)強(qiáng)大的函數(shù),可以執(zhí)行cmd shell,并把執(zhí)行結(jié)果的最后一行以字符串的形式返回??紤]到安全可以使用EscapeShellCmd()
9.使用舊版本的PHP
很多程序員還在使用PHP4,在PHP4上開(kāi)發(fā)不能充分發(fā)揮PHP的潛能,還存在一些安全的隱患。轉(zhuǎn)到PHP5上來(lái)吧,并不費(fèi)很多功夫。大部分PHP4程序只要改動(dòng)很少的語(yǔ)句甚至無(wú)需改動(dòng)就可以遷移到PHP5上來(lái)。根據(jù)http://www.nexen.net的調(diào)查 只有12%的PHP服務(wù)器使用PHP5,所以有88%的PHP開(kāi)發(fā)者還在使用PHP4.
10.對(duì)引號(hào)做兩次轉(zhuǎn)意
見(jiàn)過(guò)網(wǎng)頁(yè)中出現(xiàn)\'或\'"嗎?這通常是因?yàn)樵陂_(kāi)發(fā)者的環(huán)境中magic_quotes 設(shè)置為off,而在部署的服務(wù)器上magic_quotes =on. PHP會(huì)在 GET, POST 和 COOKIE中的數(shù)據(jù)上重復(fù)運(yùn)行addslashes() 。
原始文本:
It's a string
magic quotes on :
It\'s a string
又運(yùn)行一次
addslashes():
It\\'s a string
HTML輸出:
It\'s a string
還有一種情況就是,用戶一開(kāi)始輸入了錯(cuò)誤的登錄信息,服務(wù)器檢測(cè)到錯(cuò)誤輸入后,輸出同樣的form要求用戶再次輸入,導(dǎo)致用戶的輸入轉(zhuǎn)意兩次!
相關(guān)文章
使用Codeigniter重寫(xiě)insert的方法(推薦)
下面小編就為大家?guī)?lái)一篇使用Codeigniter重寫(xiě)insert的方法(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03PHP面向?qū)ο笕筇攸c(diǎn)學(xué)習(xí)(充分理解抽象、封裝、繼承、多態(tài))
PHP面向?qū)ο笕筇攸c(diǎn)學(xué)習(xí) 學(xué)習(xí)目標(biāo):充分理解抽象、封裝、繼承、多態(tài)2012-05-05php addslashes和mysql_real_escape_string
本文介紹的是用 mysql_real_escape_string對(duì)用戶提交數(shù)據(jù)進(jìn)行整理處理和通過(guò)addslashes以及mysql_escape_string這3個(gè)類(lèi)似的功能函數(shù)的區(qū)別。經(jīng)過(guò)轉(zhuǎn)義的數(shù)據(jù)可以直接插入到數(shù)據(jù)庫(kù)中。2010-01-01jQuery ajax+PHP實(shí)現(xiàn)的級(jí)聯(lián)下拉列表框功能示例
這篇文章主要介紹了jQuery ajax+PHP實(shí)現(xiàn)的級(jí)聯(lián)下拉列表框功能,涉及php結(jié)合jQuery的$.get方法動(dòng)態(tài)交互實(shí)現(xiàn)省市二級(jí)聯(lián)動(dòng)下拉列表框相關(guān)操作技巧,需要的朋友可以參考下2019-02-02mysql數(shù)據(jù)庫(kù)差異比較的PHP代碼
這天遇見(jiàn)個(gè)需求:由于升級(jí)系統(tǒng) 這些系統(tǒng)從A庫(kù)升級(jí)到B庫(kù),但是不知道數(shù)據(jù)庫(kù)添加了哪些字段和增加了哪些表2012-02-02PHP最常用的2種設(shè)計(jì)模式工廠模式和單例模式介紹
當(dāng)你在不斷的試圖從你的應(yīng)用程序中發(fā)現(xiàn)新的特征時(shí),你是否發(fā)現(xiàn)你提出的解決方法和一些以前你已經(jīng)實(shí)現(xiàn)的東西是如此的類(lèi)似呢2012-08-08初步介紹PHP擴(kuò)展開(kāi)發(fā)經(jīng)驗(yàn)分享
在PHP開(kāi)發(fā)的過(guò)程中,有時(shí)候?yàn)榱颂岣咝阅?,需要選擇擴(kuò)展的方式去實(shí)現(xiàn),本文簡(jiǎn)單介紹怎么開(kāi)發(fā)一個(gè)簡(jiǎn)單的PHP擴(kuò)展,解開(kāi)PHP擴(kuò)展開(kāi)發(fā)的神秘面紗2012-09-09