PHP的$_SERVER['PHP_SELF']造成的XSS漏洞攻擊及其解決方案

來源:互聯網
上載者:User

標籤:

$_SERVER[‘PHP_SELF‘]簡介

$_SERVER[‘PHP_SELF‘] 表示當前 PHP檔案相對於網站根目錄的位置地址,與 document root 相關。

假設我們有如下網址,$_SERVER[‘PHP_SELF‘]得到的結果分別為:

http://www.php-note.com/php/    :   /php/test.php
http://www.php-note.com/php/test.php    :    /php/test.php
http://www.php-note.com/php/test.php?test=foo    :    /php/test.php
http://www.php-note.com/php/test.php/test/foo    :    /php/test.php/test/foo

 因此,可以使用 $_SERVER[‘PHP_SELF‘] 很方便的擷取當前頁面的地址:

$url = "http://". $_SERVER[‘HTTP_HOST‘] . $_SERVER[‘PHP_SELF‘];

上面是簡單擷取 http 協議的當前頁面 URL ,只是要注意該地址是不包含 URL 中請求的參數(?及後面的字串)的。如果希望得到包含請求參數的完整 URL 地址,請使用 $_SERVER[‘REQUEST_URI‘] 。

 

PHP $_SERVER[‘PHP_SELF‘] 安全性

由於利用 $_SERVER[‘PHP_SELF‘] 可以很方便的擷取當前頁面地址,因此一些程式員在提交表單資料到當前頁面進行處理時,往往喜歡使用如下這種方式:

<form method="post" action="<?php echo $_SERVER[‘PHP_SELF‘]; ?>">

假設該頁面地址為:

http://www.php-note.com/php/test.php 

訪問該頁面,得到的表單 html 代碼如下:

<form method="post" action="/php/test.php">

這段代碼是正確的,但是當訪問地址變成:

http://www.php-note.com/php/test.php/test/foo /a=1

頁面正常執行了,表單 html 代碼變成:

<form method="post" action="/php/test.php/test/foo/a=1"> 

顯然,這已經超出了我們的期望,Web伺服器居然沒有產生諸如404之類的錯誤,頁面正常執行了,並且在產生的html代碼中居然有使用者可以輸入的部分,恐怖的地方就在這裡。別小看那個“a=1”,如果把它換成一段js代碼,就顯得更危險了,比如這麼調用: 

 http://…/test.php/%22%3E%3Cscript%3Ealert(’xss’)%3C/script%3E%3Cfoo

 是不是看到了js的alert函數執行的效果?檢查一下產生的html原始碼找找原因吧。 

通過這種嵌入js代碼的方式,攻擊者能夠獲得512~4k的代碼空間,甚至還可以串連外部網站的js代碼或者通過image調用來偽裝js代碼的方式,那樣js代碼的長度就不受限制了,然後通過js,他們可以輕鬆的擷取使用者的cookie,或者更改當前頁面的任何內容,比如更改表單提交的目的地,更改顯示的內容(比如給一個連結地址增加一個onclick=…的屬性,這樣使用者點擊的時候就會執行攻擊者指定的代碼,甚至串連到並非此連結地址本身的網站),甚至作出一個ajax效果來也不一定,總之,不要忽視js的威力。 

那麼,再來看看這個漏洞產生的原理,首先test.php/….這種調用是web伺服器允許的,很多cms系統,比如我以前用過的plog,好像也是採用這種方式,在伺服器不支援rewrite的情況下實現諸如http://… /index.php/archive/999這樣的固定網址的(我以前還以為是對404錯誤頁下的手),所以帶“/”的地址無法從web伺服器上禁止。然後再看看php中對$_SERVER[‘PHP_SELF‘]的識別,他就是一個包含當前網址值的全域變數,天知道使用者會輸入什麼樣的網址,在上面的例子中是惡意的,可是在wikipedia這樣的網站上,卻又是可以正常使用這種方式的地址的。所以,最終的結論要落在開發人員身上了,沒有很好的處理與使用者互動的資料。 

從安全形度來講,在開發應用尤其是web應用的時候,所有使用者提交的資料都是不安全的,這是基本原則,所以我們才不厭其煩的又是用戶端驗證又是服務端驗證。從上面說的這個安全性漏洞來講,不安全的內容中又要增加“網址”一條了。要解決$_SERVER[‘PHP_SELF‘]的安全隱患,主要有以下2種方式: 

1、htmlentities 

用htmlentities($_SERVER[‘PHP_SELF‘])來替代簡單的$_SERVER[‘PHP_SELF‘],這樣即使網址中包含惡意代碼,也會被“轉換”為用於顯示的html代碼,而不是被直接嵌入html代碼中執行,簡單一點說,就是“<”會變成“&lt;”,變成無害的了。 

2、REQUEST_URI

用$_SERVER["REQUEST_URI"]來替代$_SERVER[‘PHP_SELF‘],在phpinfo()中可以看到這兩個變數的區別:

$_SERVER[”REQUEST_URI”]    :   /fwolf/temp/test.php/%22%3E%3Cscript%3Ealert(’xss’)%3C/script%3E%3Cfoo
$_SERVER[”PHP_SELF”]     :    /fwolf/temp/test.php/”> 

 

$_SERVER["REQUEST_URI"]會原封不動的反映網址本身,網址中如果有%3C,那麼你得到的也將會是%3C,而$ _SERVER[‘PHP_SELF‘]會對網址進行一次urldecode操作,網址中的%3C將會變成字元“<”,所以就產生了漏洞。需要注意的是,在很多情況下,瀏覽器會對使用者輸入要提交給web伺服器的內容進行encode,然後伺服器端程式會自動進行decode,得到相應的原指,在我們進行post或者get操作的時候都是這樣。 

另外還有兩點需要指出,第一是這種寫法雖然沒有直接用到$_SERVER[‘PHP_SELF‘],但實際效果卻是一樣的,只是發生的時間錯後到了使用者提交之後的下一個頁面,所以,form的action還是不要留空的好。第二點,除了PHP_SELF之外,其他的$_SERVER變數也許也會有類似的漏洞,比如SCRIPT_URI、 SCRIPT_URL、 QUERY_STRING、PATH_INFO、PATH_TRANSLATED等等,在使用他們之前一定要先作htmlentities之類的。

 

 

延伸閱讀:

$_SERVER["SCRIPT_NAME"]、$_SERVER["PHP_SELF"]、$_SERVER["QUERY_STRING"]、$_SERVER["REQUEST_URI"]

 

PHP的$_SERVER['PHP_SELF']造成的XSS漏洞攻擊及其解決方案

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.