资讯动态

Web安全攻防实战01:巧用文件包含漏洞获取flag.php

发布时间:2026/8/20 0:07:16 来源:尧图企业网站定制
1. 从零开始理解文件包含漏洞到底是什么大家好我是老张在Web安全这个圈子里摸爬滚打了十来年今天咱们不聊那些虚头巴脑的理论直接上手开干。很多刚入门的朋友一听到“文件包含漏洞”就觉得头大感觉又是代码又是协议的其实没那么复杂。你可以把它想象成你家里的一个智能音箱你平时对它说“播放周杰伦的歌”它就会去曲库里找周杰伦的歌放给你听。这个“曲库”就相当于服务器上的一个目录里面放着很多文件歌曲。文件包含漏洞简单说就是这个“智能音箱”太听话了听话到有点“傻”。你本来应该说“播放周杰伦的《晴天》”但它却允许你说“播放隔壁老王硬盘里的秘密文件”然后它真的去尝试读取并播放那个本不该被访问的文件了。在Web开发中程序员为了省事经常会把一些通用的内容比如网页的头部、尾部、菜单栏单独写成一个个小文件比如header.php,footer.php。然后在不同的页面里用一个“包含”函数在PHP里就是include或require把这些小文件“拉”进来拼成一个完整的页面。这本来是个提高效率的好方法。但问题就出在这个“包含”函数上。如果程序员没有对“包含哪个文件”这个参数进行严格的检查而是直接使用了用户能控制的数据比如网址里的参数、或者浏览器提交的表单、Cookie那么攻击者就可以通过精心构造这个参数让服务器去包含并执行一些它本不该接触的文件比如系统的密码文件、网站的数据库配置文件或者像我们今天的目标——flag.php。所以文件包含漏洞的核心就两点第一程序使用了文件包含函数include,require等第二包含的文件路径用户说了算。抓住了这两点你就抓住了这个漏洞的命门。咱们今天要实战的这个靶场题目就是一个非常典型、也非常适合新手入门的案例。它把flag明明白白地告诉你就在flag.php里剩下的就是看我们怎么利用漏洞去“拿到”它了。2. 实战环境与目标分析靶场初探与代码审计咱们先来看看今天要攻克的“城堡”长什么样。打开题目给的网页首先映入眼帘的是一行英文或中文的选择提示但更关键的是下面那一行大字“Hi, EveryOne, The flag is in flag.php”。这简直是出题人最友好的“剧透”了直接告诉我们终极目标在哪里省去了我们漫无目的的信息搜集时间。按照咱们搞安全的习惯拿到一个Web应用第一件事永远是“看源码”。在网页空白处右键选择“查看网页源代码”或者直接用快捷键CtrlU。这里藏着的往往是开发人员留下的“笔记”和“地图”。果然在源代码里我们看到了完整的PHP代码逻辑。我把它整理一下用更易懂的方式复述一遍// 开启错误显示方便我们调试也方便我们发现漏洞 error_reporting(E_ALL); if(!ini_get(display_errors)) { ini_set(display_errors, On); } // 关键的一行从浏览器的Cookie中读取‘language’的值 $lan $_COOKIE[language]; // 判断如果Cookie里没有‘language’这个东西 if(!$lan) { // 那就给浏览器设置一个Cookielanguageenglish setcookie(language, english); // 然后去包含引入english.php这个文件 include(english.php); } else { // 如果Cookie里有language那就包含“$lan的值.php”这个文件 include($lan . .php); } // 最后把当前页面index.php的内容读出来再显示一遍这行不影响我们利用 $x file_get_contents(index.php); echo $x;这段代码就是我们今天的“作战地图”。我们来逐行分析一下攻击点在哪里。首先程序运行后它会去检查你的浏览器请求里有没有带一个叫做language的Cookie。如果没有!$lan为真它就会帮你设置一个值为“english”的Cookie然后去包含english.php文件。这看起来是正常功能选择语言嘛。但是重点来了如果我们的请求里有这个Cookie程序就会走到第else分支执行include($lan . .php)。这句话的意思是把变量$lan的值后面加上.php后缀然后把这个文件包含进来。而$lan的值完全来自于我们浏览器发送的Cookie中的language字段。漏洞这就出现了$lan这个变量是我们可以完全控制的。程序员原意可能是让我们传“english”或“chinese”这样就会包含english.php或chinese.php。但由于没有做任何过滤比如检查$lan是不是只有字母或者是不是在白名单里我们可以传任何我们想传的路径。比如我们传一个../../../../etc/passwd程序就会尝试包含../../../../etc/passwd.php这显然会失败因为后缀被强制加了.php。但PHP提供了一个非常强大的特性——PHP伪协议它可以帮助我们绕过这个后缀限制直接读取任意文件的内容这正是我们拿到flag的关键。3. 漏洞利用的核心PHP伪协议详解与Payload构造上面我们说到直接传文件路径会因为自动添加.php后缀而失败。这时候PHP伪协议就是我们的“瑞士军刀”。PHP内置了很多类似php://、file://、http://这样的伪协议可以让我们用“协议”的方式去访问各种输入输出流或文件。对于文件包含漏洞最常用、也最适合新手理解的就是php://filter这个伪协议。php://filter可以理解为一种“过滤器”。它本身不直接读取文件而是像一个管道文件内容流经这个管道时可以被我们指定的各种过滤器处理一下比如编码、解码、压缩等等。我们这次要用的组合拳是php://filter/readconvert.base64-encode/resource目标文件路径。我来拆解一下这个“魔法咒语”php://filter声明我要使用过滤器伪协议。/read指定这个过滤器用于“读”操作。convert.base64-encode这是具体的过滤器名字作用是把流经它的数据也就是文件内容进行Base64编码。/resource这个后面跟上我们真正想读取的文件在服务器上的绝对路径比如/var/www/html/flag.php。为什么要用Base64编码这是一个非常实用的技巧。因为我们要读取的flag.php是一个PHP文件里面很可能包含PHP代码?php ... ?。如果我们直接让服务器去包含include它服务器会把它当作PHP代码来执行。执行的结果可能只是输出了一个变量$flag的值或者干脆什么都不显示因为可能没有直接的输出语句。更糟糕的是如果文件里包含一些非文本字符或者包含语句本身被包含后产生语法错误我们可能什么都看不到。而用Base64编码后我们得到的是文件原始内容的、纯文本的、可打印的编码字符串。我们再在本地把它解码就能原原本本地看到文件里的所有内容包括注释和代码逻辑万无一失。那么目标文件的路径/var/www/html/flag.php我们是怎么知道的呢这就是信息搜集的一部分。在第一步查看网页源代码时页面上有一个错误信息Undefined index: language in /var/www/html/index.php on line 9。这个错误信息非常友好地泄露了网站根目录的绝对路径/var/www/html/。既然index.php在这个目录下题目又提示flag在flag.php那么flag.php极大概率就在同一个目录。所以完整的路径就是/var/www/html/flag.php。注意代码include($lan . .php)会自动给我们传入的$lan加上.php后缀。所以我们在构造Payload时资源路径部分不应该包含.php后缀。我们的$lan值应该是php://filter/readconvert.base64-encode/resource/var/www/html/flag。这样经过代码拼接后实际去包含的资源就是php://filter/readconvert.base64-encode/resource/var/www/html/flag.php完美匹配。4. 工具实战Burp Suite拦截与修改Cookie理论准备就绪现在进入激动人心的实操环节。我们需要一个能拦截和修改HTTP请求的工具这里我首推Burp Suite它是Web安全测试的“屠龙刀”虽然功能强大但咱们今天只用它最基础的功能完全不用担心。第一步环境配置。确保你的浏览器网络代理设置成了Burp Suite通常是127.0.0.1:8080并且Burp Suite的代理拦截功能Proxy - Intercept是打开Intercept is on状态。这些基础配置网上教程很多这里就不赘述了。第二步抓取初始请求。用浏览器访问靶场题目地址。此时请求会被Burp Suite拦截下来显示在“Proxy” - “Intercept”标签页里。你会看到类似如下的HTTP请求GET / HTTP/1.1 Host: xxx.xxx.xxx.xxx User-Agent: Mozilla/5.0... Accept: text/html... ...仔细看这个请求的头部你会发现并没有Cookie这个字段。这正对应了源代码里的逻辑因为没有Cookie所以服务器会给我们设置一个languageenglish的Cookie然后包含english.php。我们的任务就是手动给它加上Cookie。第三步注入恶意Cookie。在Burp Suite拦截到的请求报文里我们手动添加一行Cookie: languagephp://filter/readconvert.base64-encode/resource/var/www/html/flag你可以直接在请求头部的空白行添加或者找到Burp Suite界面右下角的 “Request Cookies” 区域点击添加Name填languageValue填我们上面构造的完整Payload。这里有个细节需要注意Cookie值里的冒号、斜杠等字符在HTTP协议中有特殊含义直接写入可能会被错误解析。所以更稳妥的做法是使用URL编码。我们的Payload编码后是这样的php%3a%2f%2ffilter%2fread%3dconvert.base64-encode%2fresource%3d%2fvar%2fwww%2fhtml%2fflag。你可以直接把这个编码后的字符串作为Value填入。Burp Suite很智能你填原始字符串或编码后的字符串通常都可以。第四步发送请求并获取结果。点击 “Forward” 按钮放行这个被我们修改过的请求。很快在 “HTTP history” 标签页里找到对应的响应包。查看响应体Response你很可能看到一大串由字母、数字、加号、斜杠组成的、看起来毫无规律的字符串比如PGh0bWwCiAgPGhlYWQCiAgICA8dGl0bGURmxhZzwvdGl0bGUCiAgPC9oZWFkPgogIDxi b2R5PgogICAgPD9waHAKICAgICAgJGZsYWcgPSAiY3liZXJwZWFjZXs5ZmJkMWYwMjM3NDlj NDg5MDBjZjIxNWZlOTAyYzIwNH0iOwogICAgPz4KICA8L2JvZHkCjwvaHRtbD4没错这就是经过Base64编码后的flag.php文件内容它看起来像乱码但正是我们想要的。第五步解码获取Flag。Burp Suite自带一个强大的解码模块叫 “Decoder”。我们选中这一长串Base64编码的字符串右键选择 “Send to Decoder”。在Decoder标签页的输入框里确保编码类型选择 “Base64”然后Burp会自动在下方显示解码后的结果。你会看到解码后的HTML/PHP代码flag就明明白白地躺在里面$flag cyberpeace{9fbd1f023749c48900cf215fe902c204};。至此利用Burp Suite的攻击就大功告成了。5. 工具实战浏览器HackBar插件快速利用如果你觉得配置Burp Suite有点麻烦或者想追求更轻量、更快速的攻击那么浏览器的HackBar插件是你的绝佳选择。它尤其适合在一些在线CTF平台或简单的测试环境中使用。我以Chrome浏览器为例Firefox也有类似插件。第一步安装与激活。在Chrome网上应用店搜索 “HackBar” 并安装。安装后在浏览器工具栏点击它的图标或者直接按F12打开开发者工具你通常能在顶部或底部找到一个叫 “HackBar” 的标签页。点击它界面就出来了。第二步加载目标与设置请求。首先在浏览器地址栏正常访问靶场题目URL。然后打开HackBar你会看到它已经自动把当前页面的URL加载到了 “URL” 输入框里。HackBar通常有 “Load URL” 按钮点击它确保我们针对当前页面操作。第三步构造并发送Payload。HackBar的核心功能区域允许我们直接编辑请求。我们需要做两件事选择请求方法保持为GET。添加Cookie在HackBar的 “Cookies” 区域或者可能在 “Header” 或一个独立的输入框添加我们的Cookie。格式同样是languagephp://filter/readconvert.base64-encode/resource/var/www/html/flag。有些版本的HackBar可能需要你在一个大的输入框里手动编写整个请求头。如果是这样你可以这样写GET / HTTP/1.1 Host: [靶机地址] Cookie: languagephp://filter/readconvert.base64-encode/resource/var/www/html/flag ...第四步执行与解码。设置好之后点击 HackBar 上的 “Execute” 或 “Send” 按钮。请求会被发送响应内容会显示在HackBar下方或页面本身。同样你会看到那串Base64编码的字符串直接回显在了网页上。接下来HackBar另一个方便的功能就派上用场了内置的编码解码工具。找到HackBar的 “Encoding” 或 “Tools” 相关选项里面会有 “base64 encode/decode”。我们把页面返回的那串Base64字符串复制过来选择decode解码瞬间原始的flag.php源代码和宝贵的flag就呈现出来了。整个流程非常流畅几乎是在一个界面里完成了所有操作非常适合快速验证漏洞。6. 漏洞的深入挖掘与防御思考成功拿到flag固然开心但作为一个安全爱好者我们不应该止步于此。这个简单的靶场背后隐藏着许多可以深入思考的点。首先我们这次利用的是php://filter协议进行文件读取这只是文件包含漏洞的利用方式之一。如果服务器配置不当allow_url_include参数为On我们甚至可以利用http://或ftp://协议进行远程文件包含RFI让服务器去包含我们远程主机上的一个恶意PHP文件从而直接获得服务器命令执行的能力危害等级飙升。其次我们注意到源代码中使用了符号错误控制运算符来抑制include函数可能产生的错误或警告信息。这在生产环境中是常见的做法为了不让用户看到不友好的错误信息。但这同时也掩盖了攻击的痕迹。如果没有详细的访问日志管理员可能很难发现有人正在尝试包含异常路径的文件。作为攻击方这有利于我们隐蔽作为防御方这提醒我们必须依赖完善的日志审计。那么作为开发者应该如何避免写出有文件包含漏洞的代码呢我给大家分享几个从实战中总结的“金科玉律”避免动态包含尽可能不要使用变量来动态拼接文件路径进行包含。如果必须这么做那么白名单校验对用户输入的文件名参数采用白名单机制进行校验。只允许包含预定义的、安全的几个文件如 ‘english.php‘, ‘chinese.php‘。任何不在名单内的输入直接拒绝。固定后缀如果功能允许可以强制给包含的文件加上固定的后缀而不是让用户输入或拼接。但注意我们这次的漏洞就是利用伪协议绕过了后缀限制所以这招不是绝对安全。设置目录限制使用open_basedir指令在php.ini中配置将PHP可操作的文件限制在指定的目录树中防止跨越目录访问敏感文件。关闭危险配置在非必要的情况下确保php.ini中的allow_url_include和allow_url_fopen设置为Off从根本上杜绝远程文件包含的可能。回过头看这个靶场它完美地展示了一个“教科书式”的文件包含漏洞用户输入Cookie未经检查直接传入文件包含函数。通过这次实战我希望大家不仅能掌握“如何利用”更能理解“为何能被利用”以及“如何防止被利用”。安全攻防就像一场博弈知其然更要知其所以然才能在不断的学习和实践中真正成长起来。下次遇到类似的代码希望你就能一眼看穿其中的玄机。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价