《白帽子講Web安全》14-PHP安全

第14章 PHP安全

PHP的語法過於靈活,這也給安全工作帶來了一些困擾。同時PHP也存在很多歷史遺留的安全問題。

PHP語言的安全問題有其自身語言的一些特點。

14.1 文件包含漏洞

  1. 文件包含漏洞是“代碼注入”的一種。
  2. 文件包含可能會出現在JSP、PHP、ASP等語言中。
  3. 常見的導致文件包含的函數如下:
    • PHP: include(), include_once(), require(), require_once(), fopne(), readfile(), …
    • JSP/Servlet: ava.io.File(), java.io.FileReader(), …
    • ASP: include file, include virtual, …
  4. 文件包含是PHP的一種常見用法,主要由4個函數完成:
    • include()
    • require()
    • include_once()
    • require_once()
  5. 當使用這4個函數包含一個新的文件時,該文件將作爲PHP代碼執行,PHP內核並不會在意該被包含的文件是什麼類型。
    • 這一特性,在實施攻擊時將非常有用。
  6. 要想成功利用文件包含漏洞,需要滿足下面兩個條件:
    • include()等函數通過動態變量的方式引入需要包含的文件
    • 用戶能夠控制該動態變量

14.1.1 本地文件包含

  1. 能夠打開幷包含本地文件的漏洞,被稱爲本地文件包含漏洞(Local File Inclusion,簡稱LFI)
  2. 字符串截斷的技巧,也是文件包含中最常見的技巧。
    • 在連接字符串時,0字節(\x00)將作爲字符串結束符。
      • PHP內核是由C語言實現的,因此使用了C語言中的一些字符串處理函數。
      • 在一般的Web應用中,0字節用戶其實時不需要使用的,因此完全可以禁用0字節。
    • 利用操作系統對目錄最大長度的限制,可以不需要0字節而達到截斷的目的。
  3. 除了include()等4個函數外,PHP中能夠對文件進行操作的額函數都有可能出現漏洞。能夠讀取敏感文件帶來的後果也是比較嚴重的。
    • fopen()
    • fread()
  4. 文件包含漏洞能夠讀取敏感文件或者服務器端腳本的源代碼,從而爲攻擊者實施進一步攻擊奠定基礎。
  5. 目錄遍歷(Path Traversal)漏洞
    • 跨越目錄讀取文件
    • 當PHP配置了open_basedir時,將很好地保護服務器,使得這種攻擊無效。
    • open_basedir的作用是限制在某個特定目錄下PHP能打開的文件,其作用與safe_mode是否開啓無關。
  6. 要解決文件包含漏洞,應該儘量避免動態的變量,尤其是用戶可以控制的變量。
    • 一種變通方式:使用枚舉。

14.1.2 遠程文件包含

  1. 如果PHP的配置選項allow_url_include爲ON的話,則include/require函數是可以加載遠程文件的。這種漏洞被稱爲遠程文件包含漏洞(Remote File Inclusion,簡稱RFI)。
  2. 遠程文件包含漏洞可以直接用來執行任意命令。

14.1.3 本地文件包含的利用技巧

  1. 本地文件包含漏洞,其實也是有機會執行PHP代碼的,這取決於一些條件。
  2. 遠程文件包含漏洞之所以能夠執行命令,就是因爲攻擊者能夠自定義被包含的文件內容。因此本地文件包含漏洞想要執行命令,也需要找到一個攻擊者能夠控制內容的本地文件。
  3. 一些常用的技巧,用於本地文件包含後執行PHP代碼:
    • 包含用戶上傳的文件
    • 包含data://或php://input等僞協議
    • 包含Session文件
    • 包含日誌文件,比如Web Server的access log
    • 包含/proc/self/environ文件
    • 包含上傳的臨時文件(RFC1867)
    • 包含其他應用創建的文件,比如數據庫文件、緩存文件、應用日誌等,需要具體文件具體分析。
  4. 上述技巧的具體討論

14.2 變量覆蓋漏洞

  • 安全建議:
    • 確保register_globals=OFF。若不能自定義php.ini,則應該在代碼中控制。
    • 熟悉可能造成變量覆蓋的函數和方法,檢查用戶能否控制變量的來源。
    • 養成初始化變量的好習慣。

14.2.1 全局變量覆蓋

14.2.2 extract()變量覆蓋

14.2.3 遍歷初始化變量

14.2.4 import_request_variable變量覆蓋

14.2.5 parse_str()變量覆蓋

14.3 代碼執行漏洞

  • PHP終端代碼執行情況非常靈活,但是依然離不開兩個關鍵條件:
    • 用戶能夠控制的函數輸入
    • 存在可以執行代碼的危險函數

14.3.1 “危險函數”執行代碼

  1. PHP中,能夠執行代碼的方式遠不止文件包含漏洞一種:

    • 比如危險函數popen()、system()、passthru()、exec()等都可以執行系統命令。
    • eval()函數可以執行PHP代碼
    • 允許用戶上傳PHP代碼
    • 應用寫入到服務器的文件內容和文件類型可以由用戶控制
  2. 幾個真實案例

14.3.2 “文件寫入”執行代碼

14.3.3 其他執行代碼方式

  1. 直接執行代碼的函數
    • eval()
    • assert()
    • system()
    • exec()
    • shell_exec()
    • passthru()
    • escapeshellcmd()
    • pcntl_exec()
  2. 文件包含
    • include()
    • include_once()
    • require()
    • require_once()
  3. 本地文件寫入
  4. preg_replace()代碼執行
  5. 動態函數執行
  6. Curly Syntax
  7. 回調函數執行代碼
  8. unserialize()導致代碼執行

14.4 定製安全的PHP環境

  1. 熟悉各種PHP漏洞
  2. 配置php.ini來加固PHP的運行環境
    • 推薦php.ini中一些安全相關參數的配置
      • register_globals
      • open_basedir
      • allow_url_include
      • display_errors
      • log_errors
      • magic_quotes_gpc
      • cgi.fix_pathinfo
      • session.cookie_httponly
      • session.cookie_secure
      • safe_mode
      • disable_functions
    • 推薦禁用的類
      • XMLWriter
      • DOMDocument
      • DOMNotation
      • DOMXPath
      • SQLiteDatabase
      • SQLiteResult
      • SQLiteUnbuffered
      • SQLiteException

14.5 小結

本章先後介紹了PHP中一些特別的安全問題,比如文件包含漏洞、代碼執行漏洞,最後對如何定製一個安全的PHP環境給出了建議。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章