欧美日韩精品在线,国内精品久久久久久久久,一级毛片恃级毛片直播,清纯唯美亚洲综合欧美色

PHP程序漏洞產(chǎn)生的原因和防范方法_PHP教程

編輯Tag賺U幣
教程Tag:暫無Tag,歡迎添加,賺取U幣!

推薦:用PHP與XML聯(lián)手進行網(wǎng)站開發(fā)
一、小序   HTML簡單易學又通用,一般的PHP程序就是嵌入在HTML語言之中實現(xiàn)的。但是隨著WEB越來越廣泛的應用,HTML的弱點也越來越明顯了。XML的出現(xiàn),彌補了這些不足,它提供

濫用include

  1.漏洞原因:

  Include是編寫PHP網(wǎng)站中最常用的函數(shù),并且支持相對路徑。有很多PHP腳本直接把某輸入變量作為Include的參數(shù),造成任意引用腳本、絕對路徑泄露等漏洞。看以下代碼:

...
$includepage=$_GET["includepage"];
include($includepage);
...

  很明顯,我們只需要提交不同的Includepage變量就可以獲得想要的頁面。如果提交一個不存在的頁面,就可以使PHP腳本發(fā)生錯誤而泄露實際絕對路徑(這個問題的解決辦法在下面的文章有說明)。

  2.漏洞解決:

  這個漏洞的解決很簡單,就是先判斷頁面是否存在再進行Include。或者更嚴格地,使用數(shù)組對可Include的文件作出規(guī)定。看以下代碼:

$pagelist=array("test1.php","test2.php","test3.php"); //這里規(guī)定可進行include的文件
if(isset($_GET["includepage"])) //判斷是否有$includepage
{
 $includepage=$_GET["includepage"];
 foreach($pagelist as $prepage)
 {
  if($includepage==$prepage) //檢查文件是否在允許列表中
  {
   include($prepage);
   $checkfind=true;
   break;
  }
 }
 if($checkfind==true){ unset($checkfind); }
 else{ die("無效引用頁!"); }
}

  這樣就可以很好地解決問題了。

  小提示:有此問題的函數(shù)還有:require(),require_once(),include_once(),readfile()等,在編寫的時候也要注意。

  未對輸入變量進行過濾

  1.漏洞原因:

  這個漏洞早在ASP中出現(xiàn)過,當時造成的注入漏洞不計其數(shù)。但由于PHP在當時的影響力較小,所以沒有太多的人能夠注意這點。對于PHP來說,這個漏洞的影響性比ASP更大,因為有比較多的PHP腳本使用到文本型數(shù)據(jù)庫。當然也存在SQL語句的注入問題。舉個比較經(jīng)典的例子,首先是數(shù)據(jù)庫的:

$id=$_GET["id"];

$query="SELECT * FROM my_table where id='".$id."'"; //很經(jīng)典的SQL注入漏洞
$result=mysql_query($query);

  這里很明顯我們可以用注入來獲得數(shù)據(jù)庫的其它內(nèi)容了。這里就不再詳細敘述,和ASP注入一樣的,大家可以看看以前的黑防。然后我們看文本數(shù)據(jù)庫的問題:

$text1=$_POST["text1"];
$text2=$_POST["text2"];
$text3=$_POST["text3"];

$fd=fopen("test.php","a");
fwrite($fd,"\r\n$text1&line;$text2&line;$text3");
fclose($fd);

  文本的漏洞可以說是更加嚴重。倘若我們的提交的變量中插入一段很小的PHP代碼,就可以另這個文本數(shù)據(jù)庫test.php變成PHP后門。甚至插入上傳代碼,讓我們可以上傳一個完善的PHP后門。接著提升權限,服務器就是你的了。

  2.漏洞解決:

  這個漏洞的解決方法其實很簡單,就是嚴格對全部提交的變量進行過濾。對一些敏感的字符進行替換。我們可以借助PHP提供的htmlspecialchars()函數(shù)來替換HTML的內(nèi)容。這里給出一段例子:

//構造過濾函數(shù)
function flt_tags($text)
{
 $badwords=array("操你媽","fuck"); //詞匯過濾列表
 $text=rtrim($text);
 foreach($badwords as $badword) //這里進行詞匯的過濾
 {
  if(stristr($text,$badword)==true){ die("錯誤:你提交的內(nèi)容含有敏感字眼,請不要提交敏感內(nèi)容。"); }
 }
 $text=htmlspecialchars($text); //HTML替換
 //這兩行把回車替換為

 $text=str_replace("\r"," ",$text);
 $text=str_replace("\n","",$text);
 $text=str_replace("&line;","│",$text); //文本數(shù)據(jù)庫分隔符"&line;"替換為全角的"│"
 $text=preg_replace("/\s{ 2 }/"," ",$text); //空格替換
 $text=preg_replace("/\t/"," ",$text); //還是空格替換
 if(get_magic_quotes_gpc()){ $text=stripslashes($text); } //如果magic_quotes開啟,則進行\(zhòng)'的替換
 return $text;
}

$text1=$_POST["text1"];
$text2=$_POST["text2"];
$text3=$_POST["text3"];

//過濾全部輸入
$text1=flt_tags($text1);
$text2=flt_tags($text2);
$text3=flt_tags($text3);

$fd=fopen("test.php","a");
fwrite($fd,"\r\n$text1&line;$text2&line;$text3");
fclose($fd);

  經(jīng)過一番替換和過濾后,你就可以安全地把數(shù)據(jù)寫入文本或數(shù)據(jù)庫了。

  管理員判斷不完全

  1.漏洞原因:

  我們用PHP寫腳本,通常要涉及管理員的權限問題。而一些腳本僅僅對管理員權限作出"是"判斷,而往往忽略了"否"判斷。在PHP配置文件中register_globals打開的情況下(4.2.0以后版本默認關閉,但有不少人為了方便而打開它,這是極度危險的行為),就會出現(xiàn)提交變量冒充管理員的情況。我們看一下的例子代碼:

$cookiesign="admincookiesign"; //判斷是否Admin的cookie變量
$adminsign=$_COOKIE["sign"]; //獲取用戶的cookie變量

if($adminsign==$cookiesign)
{
 $admin=true;
}

if($admin){ echo "現(xiàn)在是管理員狀態(tài)。"; }

  看上去好像很安全的樣子,呵呵。現(xiàn)在我們假設PHP配置文件中register_globals為打開狀態(tài)。我們提交這樣一個地址“test.php?admin=true”,結果看到了嗎?我們雖然沒有正確的Cookie,但由于register_globals為打開狀態(tài),使得我們提交的admin變量自動注冊為true。而且腳本缺少“否”判斷,就使得我們順利地通過admin=true取得管理員的權限了。這個問題存在于大部分網(wǎng)站和論壇當中。

  2.漏洞解決:

  解決這個問題,我們只需要在腳本中加入對管理員的“否”判斷即可。我們?nèi)匀患僭OPHP配置文件中register_globals為打開狀態(tài)。看一下的代碼:

$cookiesign="admincookiesign"; //判斷是否Admin的cookie變量
$adminsign=$_COOKIE["sign"]; //獲取用戶的cookie變量

if($adminsign==$cookiesign)
{
 $admin=true;
}
else
{
 $admin=false;
}
if($admin){ echo "現(xiàn)在是管理員狀態(tài)。"; }

  這樣,就算攻擊者在沒有正確Cookie的情況下提交了admin=true的變量,腳本在以后的判斷中也會把$admin設置為False。這樣就解決了部分的問題。但由于$admin是變量,倘若在以后的其他腳本引用中出現(xiàn)了漏洞使得$admin被重新賦值就會引發(fā)新的危機。因此,我們應該使用常量來存放管理員權限的判定。使用Define()語句定義一個admin常量來記錄管理員權限,在此以后若配重新賦值就會出錯,達到保護的目的。看以下代碼:

$cookiesign="admincookiesign"; //判斷是否Admin的cookie變量
$adminsign=$_COOKIE["sign"]; //獲取用戶的cookie變量

if($adminsign==$cookiesign)
{
 define(admin,true);
}
else
{
 define(admin,false);
}
if(admin){ echo "現(xiàn)在是管理員狀態(tài)。"; }

  值得注意的是,我們使用了Define語句,所以在調(diào)用Admin常量時前面不要習慣性的加變量符號$,而應該使用Admin和!admin。

  文本數(shù)據(jù)庫暴露

  1.漏洞原因:

  前面已經(jīng)說過,由于文本數(shù)據(jù)庫具有很大的靈活性,不需要任何外部支持。加上PHP對文件的處理能力十分強,因此文本數(shù)據(jù)庫在PHP腳本中的應用甚廣。甚至有幾個很好的論壇程序就是使用文本數(shù)據(jù)庫的。但有得必有失,文本數(shù)據(jù)庫的安全性也是比其他數(shù)據(jù)庫要低的。

  2.漏洞解決:

  文本數(shù)據(jù)庫作為一個普通的文件,它可以被下載,就像MDB一樣。所以我們要用保護MDB的辦法來保護文本數(shù)據(jù)庫。把文本數(shù)據(jù)庫的后綴名改為.PHP。并在數(shù)據(jù)庫的第一行加入。這樣文本數(shù)據(jù)庫就會作為一個PHP文件,并且在第一行退出執(zhí)行。也就是返回一個空頁面,從而達到保護文本數(shù)據(jù)庫的目的。

  錯誤路徑泄露

  1.漏洞原因:

  PHP遇到錯誤時,就會給出出錯腳本的位置、行數(shù)和原因,例如:

Notice: Use of undefined constant test - assumed 'test' in D:\interpub\bigfly\test.php on line 3

  有很多人說,這并沒有什么大不了。但泄露了實際路徑的后果是不堪設想的,對于某些入侵者,這個信息可是非常重要,而事實上現(xiàn)在有很多的服務器都存在這個問題。

  有些網(wǎng)管干脆把PHP配置文件中的display_errors設置為Off來解決,但本人認為這個方法過于消極。有些時候,我們的確需要PHP返回錯誤的信息以便調(diào)試。而且在出錯時也可能需要給用戶一個交待,甚至導航到另一頁面。

  2.漏洞解決:

  PHP從4.1.0開始提供了自定義錯誤處理句柄的功能函數(shù)set_error_handler(),但很少數(shù)腳本編寫者知道。在眾多的PHP論壇中,我只看見很少一部分對此情況進行了處理。set_error_handler的使用方法如下:

string set_error_handler ( callback error_handler [, int error_types])

  現(xiàn)在我們就用自定義的錯誤處理把實際路徑過濾掉。

//admin為管理員的身份判定,true為管理員。
//自定義的錯誤處理函數(shù)一定要有這4個輸入變量$errno,$errstr,$errfile,$errline,否則無效。
function my_error_handler($errno,$errstr,$errfile,$errline)
{
//如果不是管理員就過濾實際路徑
if(!admin)
{
 $errfile=str_replace(getcwd(),"",$errfile);
 $errstr=str_replace(getcwd(),"",$errstr);
}

switch($errno)
{
 case E_ERROR:
  echo "ERROR: [ID $errno] $errstr (Line: $errline of $errfile)
  \n";
  echo "程序已經(jīng)停止運行,請聯(lián)系管理員。";
   //遇到Error級錯誤時退出腳本
   exit;
  break;
 case E_WARNING:
  echo "WARNING: [ID $errno] $errstr (Line: $errline of $errfile)
  \n";
  break;
 default:
  //不顯示Notice級的錯誤
  break;
}
}

//把錯誤處理設置為my_error_handler函數(shù)
set_error_handler("my_error_handler");

  這樣,就可以很好地解決安全和調(diào)試方便的矛盾了。而且你還可以花點心思,使錯誤提示更加美觀以配合網(wǎng)站的風格。不過注意兩點是:

  (1)E_ERROR、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、E_COMPILE_ERROR、E_COMPILE_WARNING是不會被這個句柄處理的,也就是會用最原始的方式顯示出來。不過出現(xiàn)這些錯誤都是編譯或PHP內(nèi)核出錯,在通常情況下不會發(fā)生。

  (2)使用set_error_handler()后,error_reporting ()將會失效。也就是所有的錯誤(除上述的錯誤)都會交給自定義的函數(shù)處理。
其它有關于set_error_handler()的信息,大家可以參考PHP的官方手冊。

  POST漏洞

  1.漏洞原因:

  前面已經(jīng)說過,依靠register_globals來注冊變量是個不好的習慣。在一些留言本和論壇程序中,更要嚴格檢查獲得頁面的方式和提交的時間間隔。以防止灌水式發(fā)帖和外部提交。我們看一下以下某留言本程序的代碼:

...
$text1=flt_tags($text1);
$text2=flt_tags($text2);
$text3=flt_tags($text3);

$fd=fopen("data.php","a");
fwrite($fd,"\r\n$text1&line;$text2&line;$text3");
fclose($fd);
...

  很明顯的,如果我們提交網(wǎng)址”post.php?text1=testhaha&text2=testhaha&text3=testhaha”。數(shù)據(jù)就會被正常寫入文件中。此程序并沒有檢測變量的來源和瀏覽器獲得頁面的方式。如果我們向這個頁面重復多次提交,就會起到洪水的作用。現(xiàn)在也有一些軟件利用這個漏洞來在論壇或留言本上發(fā)廣告,這是可恥的行為(我朋友的留言本就在1星期內(nèi)被灌了10多頁,無奈)。

  2.漏洞解決:

  在進行數(shù)據(jù)處理和保存前,首先判斷瀏覽器的獲得頁面方式。使用$_SERVER["REQUEST_METHOD"]變量來獲得瀏覽器的獲得頁面方式。檢查其是否為”POST”。在腳本中使用session來記錄用戶是否通過正常途徑(即填寫提交內(nèi)容的頁面)來提交數(shù)據(jù)。或使用$_SERVER["HTTP_REFERER"]來檢測,但不推薦這樣做。因為部分瀏覽器沒有設置REFERER,有部分防火墻也會屏蔽REFERER。另外,我們也要對提交內(nèi)容檢查,看數(shù)據(jù)庫中是否有重復內(nèi)容。以留言本為例,使用Session進行判定:
填寫瀏覽內(nèi)容的頁面中,我們在最前端加上:

$_SESSION["allowgbookpost"]=time(); //登記填寫時的時間

  在接受留言數(shù)據(jù)并保存的頁面中我們在進行數(shù)據(jù)處理前我們也用Session進行以下處理:

if(strtoupper($_SERVER["REQUEST_METHOD"])!=”POST”){ die("錯誤:請勿在外部提交。"); } //檢查頁面獲得方法是否為POST
if(!isset($_SESSION["allowgbookpost"]) or (time()-$_SESSION["allowgbookpost"] < 10)){ die("錯誤:請勿在外部提交。"); } //檢查留言填寫時的時間
if(isset($_SESSION["gbookposttime"]) and (time()-$_SESSION["gbookposttime"] < 120)){ die("錯誤:兩次提交留言的間隔不得少于 2 分鐘。"); } //檢查留言間隔

unset($_SESSION["allowgbookpost"]); //注銷allowgbookpost變量以防止一次進入填寫頁面多次進行提交
$_SESSION["gbookposttime"]=time(); //登記發(fā)送留言的時間,防止灌水或惡意攻擊
...
數(shù)據(jù)處理及保存
...

  經(jīng)過這樣重重審查,你的程序就安全很多了。

分享:PHP中for循環(huán)語句的幾種“變態(tài)”用法
for語句可以說是PHP(同時也是多種語言)的循環(huán)控制部份最基本的一個語句了,for語句的執(zhí)行規(guī)律和基礎用法在這里就不多說,可以參見PHP手冊for語句部分。PHP手冊中對它的語法定義如下:

來源:模板無憂//所屬分類:PHP教程/更新時間:2008-08-22
相關PHP教程