拓冰建站拓冰建站
首页 / 资讯中心 / 正文

从LFI到RCE:CTF本地文件包含漏洞全流程实战拆解

打CTF打了一段时间Web方向入门最难的不是漏洞利用本身而是很多人拿到题目不知道从哪下手。今天拿BUUCTF上BUU LFI COURSE 1这道题做个完整拆解把LFI本地文件包含漏洞从触发原理到实际利用流程一条线讲清楚。这道题是典型的入门级LFI但考点覆盖得很完整从基础文件读取、目录穿越绕过、伪协议利用到远程代码执行一层层递进非常适合用来建立Web题目的解题框架。先说结论如果你能独立把这道题做出来那你在面对大部分LFI类题目时至少知道第一步该看什么、参数在哪里、文件包含能干什么、哪些协议可以帮你拿权限。这套思路不只在BUUCTF能用在其他平台的CTF题里也完全通用。1. 题目环境观察与信息收集1.1 拿到题目后的第一件事打开题目页面先别急着点。观察环境是CTF的第一步也是最容易被忽略的一步。BUU LFI COURSE 1的页面非常简洁整体干净得几乎没有什么内容。页面上最显眼的元素就是一个超链接通常指向类似?filehello.php这样的URL。这个参数就是本题的核心突破口。任何出现在URL中的file、page、path、include、template这类参数都意味着后端可能存在文件包含逻辑这是LFI漏洞最常见的入口。很多新手在页面里只看到一个链接后会觉得“这题没什么东西”然后卡住。实际上CTF题目的设计逻辑就是给你一个最小的攻击面让你通过这个攻击面去挖掘更深层的东西。这道题的file参数就是整个题目的钥匙。1.2 确认存在文件包含点击页面上的链接URL变成类似http://target/?filehello.php页面返回了正常的hello内容。这时候就可以初步判断后端代码里很可能存在include($_GET[file]);这样的写法。怎么确认它不是普通的参数传递而是文件包含一个简单的测试方法尝试修改file参数的值看页面响应是否随之变化。当然直接上/etc/passwd探测属于常规操作不过新手做题的时候容易着急一上来就用../../../../etc/passwd然后发现页面白屏或者报错就慌了。正确的做法是逐步加深度。先用file/etc/passwd试试如果没反应再试file../../../../etc/passwd。这里有个隐藏的细节很多CTF题目环境下找到正确的目录深度是一个需要反复试的过程。BUU LFI COURSE 1这道题里直接使用?file../../../../etc/passwd就能看到root:x:0:0:root:/root:/bin/bash之类的系统账号信息说明存在本地文件包含漏洞且包含路径没有进行任何过滤。看到/etc/passwd被成功读取出来的那一刻这道题就算开了个好头。接下来要做的就是顺着这个漏洞继续深挖。1.3 先建立解题全局观在写writeup的时候很多人容易陷入“罗列操作步骤”的误区——先做了什么又做了什么最后出了flag像流水账一样。但实际上一份好的writeup应该让读者理解每一步背后的判断逻辑。LFI题目的通用解题思路我总结下来就是三步确定参数位置和程序行为判定过滤规则有没有过滤、过滤了什么、能不能绕过根据过滤规则选择利用方式直接读文件、伪协议读源码、伪协议写代码执行这道题完全遵循这三步。建议你做题的时候也按照这个思路来做笔记这样不仅解题效率高复盘起来也清晰。2. 本地文件包含漏洞的核心原理2.1 为什么include函数会成为漏洞在解释LFI漏洞之前可以先问问自己为什么PHP的include、require这些函数会有安全风险原因在于当一个Web应用需要动态加载文件时开发者往往会将文件名作为参数传入。比如一个多语言网站可能要切换语言文件URL可能是index.php?langcn.php。如果这个参数完全由用户控制且没有经过严格的过滤和校验攻击者就可以把它改成任意文件路径从而读取服务器上的敏感文件。PHP中常见的文件包含函数有四个include包含文件出错时发出警告脚本继续执行require包含文件出错时致命错误脚本终止include_once/require_once同上但会检查文件是否已经被包含从攻击面来看这些函数的危险程度是等同的。只要存在用户可控的文件名拼接进上述函数就存在LFI。2.2 LFI能做什么LFI的利用场景按照攻击效果从低到高可以这样排第一读取任意文件。这是最基础的利用方式可以读取/etc/passwd、web目录下的源码文件、配置文件、日志文件等获取系统信息和应用敏感数据。第二配合伪协议执行代码。利用php://filter读取文件源码进行进一步审计或者利用data://、php://input等协议直接注入PHP代码并执行从而直接获得目标服务器的权限。这一步是RCE远程代码执行也是LFI漏洞的最高危利用形式。第三配合文件上传功能getshell。如果目标存在文件上传功能但上传的文件只能存放在特定目录攻击者就可以通过LFI包含上传的图片马等文件从而触发执行其中的PHP代码。第四读取日志文件getshell。在无法上传文件的情况下通过User-Agent等字段向Web日志中注入PHP代码再利用LFI包含日志文件实现代码执行。把这些攻击路径梳理清楚再来看BUU LFI COURSE 1这道题的关卡设计就会发现它其实是在带你走一遍完整的学习路径。2.3 目录穿越的路径计算很多初学者在构造../../../../etc/passwd时只是机械地复制粘贴并不理解每一级../的含义。我们先明确目录结构假设当前工作目录是/var/www/html目标文件是/etc/passwd。从/var/www/html到根目录需要向上跳四级html-www-var-/。所以需要../../../../etc/passwd。但这个深度是理论上算出来的。实际做题时不同题目的目录深度可能不同。有的题目是/var/www/html有的是/var/www还有的直接放在根目录下的某个自定义目录。所以正确的做法是先尝试一级../不行就加一级直到成功或者已经到很深比如十级为止。BUU LFI COURSE 1直接四层即可说明站点目录就在标准路径下。这里还有一个细节如果../被过滤了怎么办这是后面关卡要解决的问题但可以先记下一个规律——过滤方式决定了绕过方式。过滤../你就考虑编码绕过或者双重写绕过过滤关键字你就考虑用伪协议绕过。遇到任何过滤先别急分析它过滤了什么再找绕过方案。3. BUU LFI COURSE 1逐层解谜实操3.1 第一层直接包含读取系统文件题目第一关就是把file参数改成/etc/passwd的路径。我用的是http://target/?file../../../../etc/passwd服务器返回了passwd文件的部分内容。注意PHP的include函数在包含这个文件的时候由于文件内容不是PHP代码会原样输出。如果你在做题时发现直接读取失败优先排查以下几项当前工作目录深度是不是不够往上跳少了使用的系统是不是类Unix系统Windows下路径结构不同服务器的PHP配置中allow_url_include是否为On影响伪协议利用读取/etc/passwd成功之后第一层就算过了。这个结果本身已经足够证明漏洞的存在但题目肯定不会在这里结束。3.2 第二层目录穿越被过滤后的绕过点击按钮进入第二层后会发现页面结构跟第一层类似但尝试使用同样的payload页面返回了异常。这层题目对../做了过滤。测试一下发现?file../../../../etc/passwd会返回空白或者提示路径错误而?file/etc/passwd可以正常读取。先明确过滤的是什么这里过滤的是../这个字符串。最常见的绕过方式就是双写构造....//。原理很简单当程序对../做替换删除处理时如果你传入的是....//它会把中间的../识别出来并删除剩下来的还是../从而构造出目录穿越的效果。针对这一层我用的payload是http://target/?file....//....//....//....//etc/passwd....//经过过滤后变成../四次穿越就变成了标准的../../../../etc/passwd成功读取文件。这层想让你掌握的要点是过滤不等于安全字符串过滤往往可以通过编码、双写、通配符等方式绕过。3.3 第三层伪协议读取源码进入第三层后发现这一层的过滤比第二层更严格不仅过滤了../还过滤了/、.等关键字符常规路径穿越已经行不通了。注意过滤了路径但不能直接走目录穿越不代表漏洞不存在。这时候就要把思路从“读取文件路径”转换到“使用伪协议”上。PHP的php://filter是一个元封装器可以对文件进行过滤处理后再输出。最常用的方式是用php://filter/readconvert.base64-encode/resource目标文件来读取PHP源码。为什么要点convert.base64-encode因为PHP源码里含有?php ?标签如果直接把源码包含进来PHP解析器会把里面的代码执行而不是显示出来。如果源码里没有echo等输出语句你就什么都看不到。用base64编码后源码变成了一串纯字符浏览器原样输出你再解密就能看到完整的PHP源码。这一步很有价值因为在拿到源码之后解题思路就会完全打开。你可以根据源码逻辑去构造精准的payload而不是靠猜。BUU LFI COURSE 1第三层的解法就是在file参数里传http://target/?filephp://filter/readconvert.base64-encode/resource当前页面的文件名响应会返回一段base64字符串。把这段字符串复制到任意在线解码工具或者本地终端里执行echo base64字符串 | base64 -d就能看到完整的PHP源码。源码里通常会包含下一层的提示信息比如过滤规则或者某个特殊文件。3.4 第四层data协议实现代码执行到了最后一层常规LFI的payload基本都被封堵了。这时候的考点转向了PHP伪协议中的data://。data://协议允许把数据流作为文件内容直接封装比如data://text/plain,要输入的数据在PHP中它会被当作文件内容处理。如果配合include函数且PHP配置中allow_url_includeOn就可以直接在数据中写入PHP代码并让服务器执行。我用的payload如下http://target/?filedata://text/plain,?php phpinfo();?如果能看到phpinfo页面说明代码执行成功。但CTF环境下更高效的方式是直接写入一句话木马或者执行命令读取flaghttp://target/?filedata://text/plain,?php system(cat /flag);?这里有一个要注意的坑payload中的特殊字符如、、空格、分号需要URL编码否则可能被服务器端解析出错。把上面的payload做URL编码?php system(cat /flag);?变成%3C%3Fphp%20system%28%27cat%20%2Fflag%27%29%3B%3F%3E再拼接到URL中。有些时候使用data协议不成功原因多半是allow_url_include被设置为Off。这种情况下可以换思路用php://input配合POST请求来注入代码效果类似。这也是为什么说LFI题要多掌握几个伪协议一个不行马上能换下一个。3.5 完整攻击链梳理把这道题实际上考的四层逻辑串起来整个攻击流程是这样的第一层发现file参数直接LFI读/etc/passwd确认漏洞存在第二层触发../过滤用....//双写绕过路径穿越限制第三层路径字符被全面过滤改用php://filter读源码进一步掌握应用逻辑第四层最终利用data://协议注入PHP代码执行系统命令获取flag这个链条的每一环都对应一种LFI防御手段和对应的绕过策略。做完这道题等于把LFI的常见考点都过了一遍。4. 常见报错与排查思路实录4.1 payload没反应的排查路径做这道题时我自己也踩过一些坑把典型问题整理成一个排查表做题遇到同样情况可以直接对着查。现象可能原因排查方法返回空白页面目标文件为大文件导致输出被截断改用php://filter读取或者只读取文件头部分返回Warning: include(...)文件路径不存在或权限不足调整目录穿越深度查看报错信息中暴露的绝对路径读取PHP文件显示乱码PHP代码被解析执行未输出源码使用php://filter/convert.base64-encode读取data协议注入无效果allow_url_include为Off改用php://input或尝试写入文件后再包含页面显示“Flag is not here”目标文件位置不对读取源码查找flag文件路径或隐藏配置过滤了flag关键字关键词过滤规则用fla加通配符、大小写变换、编码等方式绕过4.2 filter伪协议读不出来的原因第三层用php://filter读取源码时最常见的问题是返回内容为空或者base64解码后内容不完整。我遇到过的一种情况是resource后面写的是相对路径导致找不到文件。建议先尝试不同的路径格式php://filter/readconvert.base64-encode/resourceindex.php、resource./index.php、resource/var/www/html/index.php直到拿到明确的base64内容。还有一种情况是payload被某种规则处理了比如php://字符串里的//被过滤导致协议无法被识别。如果遇到这种限制可以试一下php:filter这种少一个斜杠的形式有时候能够绕过正则检查。4.3 include与require的区别对题目的影响在分析源码时注意看代码用的是include还是require。这个区别在漏洞利用时影响不大但在报错处理上不同。include出错只是警告页面其他内容还会输出require出错会直接导致致命错误后面的内容全部中断。如果题目页面上有其他正常的HTML内容当你发现读取某个不存在的文件时页面还有部分输出说明用的是include如果整个页面直接白屏那就可能是require。这个细节可以用来辅助判断后端代码结构。4.4 不要忽视URL编码的细节第四层的data协议payload如果没成功先检查URL编码。?php中的在URL中有时会被服务器解析成标签起始符导致参数被截断。空格会被解析成号。单引号双引号也有可能触发服务器端的过滤规则。所以最稳妥的方式是先在线URL编码工具把payload整体编码然后把编码后的字符串拼到URL里。这里的编码指的是百分号编码Percent-encoding不是base64。编码之后payload就变成了一串纯字符服务器拿到后会自动解码再交给PHP执行。5. 从这道题延伸出的LFI利用面5.1 不只是CTF实战中的LFI同样危险CTF题目与真实漏洞的区别在于前者是刻意搭建的环境后者是你不知道代码逻辑的黑盒。但漏洞原理是相通的。如果你在实战渗透测试中遇到某个请求参数把文件名带了进去比如下载模板、切换语言、加载主题都要下意识地想一下是否存在LFI。实战中LFI的一个典型场景是某个下载功能通过filedownload.php?filenamexxx.pdf这样的形式工作后端直接拼接了文件名。这时候即便不能直接执行命令但读取配置文件、数据库连接信息等敏感数据也已经足够造成严重的风险。5.2 日志注入getshell的通用思路如果某个LFI场景下无法上传文件也不能用data://比如allow_url_includeOff日志注入是保底方案。思路是这样任何Web服务都会记录访问日志。Apache的访问日志通常在/var/log/apache2/access.log或/var/log/httpd/access_log。日志里会记录User-Agent字段。如果你在User-Agent里写一段PHP代码日志文件里就会包含这段代码。然后利用LFI的file参数去包含这个日志文件日志内容就会被PHP解析代码就会执行。原理不复杂实际操作时需要注意日志文件的路径和权限。有些日志文件权限较低web用户无法读取有些日志文件很大包含起来可能会导致页面卡死。这个方法更适合作为LFI无法直接getshell时的兜底思路。5.3 php伪协议清单快速查做LFI题目时php://伪协议系是最常用的这里整理一个快速参考php://filter读取文件内容常用convert.base64-encode可用于读取PHP源码php://input从POST请求体读取数据allow_url_includeOn时可执行代码data://直接把数据当作文件流处理可执行代码php://temp/php://memory临时文件流在部分开发框架中有特殊用途expect://需要特定扩展可以直接执行命令但CTF环境很少启用file://访问本地文件系统效果等同于直接写绝对路径不需要全部背下来但前三项要滚瓜烂熟因为它们是LFI利用时最常出现的三种。5.4 防御视角LFI该怎么防写writeup的时候顺便说说防御因为只有从攻防双方的角度看同一个漏洞理解才会深。LFI的根因是开发者对文件路径的信任。稳健的防御方案有几个对传入的文件名做白名单校验只允许指定文件被包含使用realpath()解析最终路径并校验其是否在允许目录内避免在include语句中使用用户可控的完整路径改用固定目录加文件名拼接关闭allow_url_include这能封堵大部分伪协议利用这道题的四层关卡每一层基础的防御面都不一样做题时你可以思考一下每一层用了哪种防御、为什么这么防是无效的这对理解安全开发和攻击思维都有帮助。6. 写在最后的一点实操体会BUU LFI COURSE 1这道题做下来我的感受是它非常精准地抓住LFI学习的三个关键节点参数无用但包含功能有用、过滤出现时想绕过、绕过走不通时换协议。你做完这道题之后建议自己做一次复盘实验。把file参数分别换成php://filter、data://、php://input观察三种方式在页面上的不同表现。最好把响应包拿到Burp Suite里仔细看一遍重点关注返回长度和状态码的差异。这个实验做完你对LFI的理解会比单纯刷题深刻得多。另外做CTF题目时最重要的一点是不要只看writeup就觉得自己会了。可以在BUUCTF平台上重新开一个环境不参考任何资料从第一层到第四层独立再打一遍。如果卡住了先记下卡在哪里再回来看writeup对应的这部分这样收获最大。再过一遍这道题的核心payload方便你直接抄作业# 第一层直接目录穿越读文件 ?file../../../../etc/passwd # 第二层双写绕过 ../ 过滤 ?file....//....//....//....//etc/passwd # 第三层php://filter 读取源码 ?filephp://filter/readconvert.base64-encode/resourceindex.php # 第四层data:// 协议执行命令 ?filedata://text/plain,%3C%3Fphp%20system%28%27cat%20%2Fflag%27%29%3B%3F%3E最后再分享一个小技巧做LFI题目的时候如果你不确定目标文件在哪先用php://filter把当前页面源码读出来看源码里怎么写的、include了哪些文件、flag文件在哪个路径下。很多LFI题目把flag放在了意想不到的目录里读源码是最快的信息收集方式往往能省下大量盲猜时间。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门