PHP是一種通用的開源腳本語言,它的語法混合了C,Java,以及Perl等優秀語言的語法。除此之外,它還提供了大量的函數庫可供開發人員使用。但是,如果使用不當,PHP也會為應用程式帶來非常大的安全風險。
在這篇文章中,我們將會對PHP應用程式中經常會出現的一些問題進行深入地分析,尤其是當我們使用「==」(比較運算子)來進行字串比較時,可能會出現的一些安全問題。雖然近期有很多文章都圍繞著這一話題進行過一些探討,但我決定從「黑盒測試」的角度出發,討論一下如何利用這個問題來對目標進行滲透和攻擊。首先,我會對引起這個問題的根本原因進行分析,以便我們能夠更加深入地理解其工作機制,這樣才可以保證我們能夠盡可能地避免這種安全問題的發生。
問題的描述實際上,當使用類似「==」這樣的比較運算子進行操作時,就會出現這樣的情況。上面這個例子中出現的問題不能算是漏洞,因為它是PHP所提供的一種名為「型別轉換」的功能。從本質上來分析,當我們使用特定的比較運算子(例如== , !=, )來進行操作時,PHP首先會嘗試去確定參與比較的資料類型。但是這樣的一種類型轉換機制將有可能導致計算結果與我們預期的結果有較大出入,而且也會帶來非常嚴重的安全問題。安全研究專家在該問題的完整披露報告中寫到:這種類型轉化機制將有可能導致權限提升,甚至還會使程序的密碼驗證過程變得不安全。
正如你所看到的,當我們使用“==”來比較這些數字字符串時,參與比較的就是字符串中數字的實際大小,從安全的角度出發,這就是一個非常有趣的問題了。在這種情況下,你可以使用科學計數法來表示一個數字,並將其放在一個字串中,PHP將會自動把它作為一個數字類型來處理。我們之所以會得到這樣的輸出類型,是因為PHP使用了一種哈希演算法(通常使用十六進制數值表示)來進行處理。比如說,如果一個數字為0,那麼在進行鬆散比較的過程中,PHP會自動對其類型進行轉換,但其值永遠為0。對於一個給定的雜湊演算法而言,密碼就有可能會變成可以被替換的了。比如說,當密碼的雜湊值被轉換成使用科學計數法來表示的數字時,將有可能正好與其他的密碼雜湊相匹配。這樣一來,即使是一個完全不同的密碼,也有可能可以通過系統的驗證。但有趣的是,當某些採用科學計數法表示的數字在進行比較的時候,結果可能會讓你意想不到:
import random import hashlib import re import string import sys prof = re.compile("^0+ed*$") # you can also consider: re.compile("^d*e0+$") prefix = string.lower(sys.argv[1])+'!'+string.upper(sys.argv[1])+"%s" num=0 while True: num+=1 b = hashlib.sha256(prefix % num).hexdigest() if (b[0]=='0' and prof.match(b)): print(prefix+str(num),b)
密碼的計算結果十分相似,具體如下所示:
你可以隨意選取兩個密碼來進行對比,對比的演示結果如下:
如果你無法得到如上圖所示的計算結果,那麼你應該感到幸運。你可以嘗試將使用者名稱和密碼捆綁在一起,然後使用帶有“salt”值的雜湊演算法來進行計算。你只需要修改一小部分程式碼即可實現,點擊「這裡」取得修改後的腳本。