抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

实验环境为 Linux x64 + MySQL 5.2.23

实验环境为 Linux x64 + MySQL 5.2.23

Webshell排查

into outfile 排查

通过使用 into outfile 来模拟 SQL 注入并写入 Webshell

1
2
mysql> SELECT 'webshell_test' INTO OUTFILE '/var/www/html/test1.php';
Query OK, 1 row affected (0.00 sec)

在执行以上 SQL 查询后,日志中明显出现了恶意文件的路径和内容,我们可以直接删除这个 WebShell 文件

1
2
mysql> \! cat /var/lib/mysql/14ab6e4fe4be.log
240508 8:15:21 6 Query SELECT 'webshell_test' INTO OUTFILE '/var/www/html/test1.php'

通过日志写入 WebShell 排查

在排查时,如果发现日志路径被篡改,可判断由日志写入的 Webshell

1
2
3
4
5
6
7
mysql> show VARIABLES LIKE "general_log%";
+------------------+----------------------------+
| Variable_name | Value |
+------------------+----------------------------+
| general_log | ON |
| general_log_file | /var/www/html/shell.php |
+------------------+----------------------------+

删除恶意文件/var/www/html/shell.php,同时将数据库日志路径恢复原状

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
root@14ab6e4fe4be:/# ls -al /var/lib/mysql/
total 28700
drwx------ 5 mysql mysql 4096 May 8 07:52 .
drwxr-xr-x 1 root root 4096 Feb 15 2016 ..
-rw-rw---- 1 mysql mysql 393 May 8 07:52 14ab6e4fe4be.log
-rw-rw---- 1 mysql mysql 5242880 May 8 03:13 ib_logfile0
-rw-rw---- 1 mysql mysql 5242880 May 8 03:13 ib_logfile1
-rw-rw---- 1 mysql mysql 18874368 May 8 03:13 ibdata1
drwx------ 2 mysql root 4096 May 8 03:13 mysql
drwx------ 2 mysql mysql 4096 May 8 03:13 performance_schema
drwx------ 2 mysql mysql 4096 May 8 03:23 testdb

mysql> SET GLOBAL general_log_file='/var/lib/mysql/14ab6e4fe4be.log';
Query OK, 0 rows affected (0.00 sec)

mysql> show VARIABLES LIKE "general_log%";
+------------------+----------------------------------------+
| Variable_name | Value |
+------------------+----------------------------------------+
| general_log | ON |
| general_log_file | /usr/local/mysql/data/9956ee9aa191.log |
+------------------+----------------------------------------+
2 rows in set (0.00 sec)

UDF提权排查

查看 MySQL 版本,判断 UDF 提权文件的导出路径

1
2
3
select version();

// 5.5.23

在 MySQL 版本高于或等于5.1的情况下,请检查plugin目录,可能存在恶意的.so文件

1
2
3
show variables like '%plugin%';

// 路径为:/usr/local/mysql/lib/plugin/

检查日志是否开启,默认为关闭状态

1
2
3
4
5
6
7
8
mysql> show VARIABLES LIKE "general_log%";

+------------------+----------------------------------------+
| Variable_name | Value |
+------------------+----------------------------------------+
| general_log | ON |
| general_log_file | /usr/local/mysql/data/9956ee9aa191.log |
+------------------+----------------------------------------+

日志开启情况下排查

若日志文件启用,可以检索其中的记录,查看是否存在 create function 的记录。若存在,则可发现创建的恶意函数名,在此处是 sys_eval

1
2
root@9956ee9aa191:/# cat /usr/local/mysql/data/9956ee9aa191.log | grep "create function"
7 Query create function sys_eval returns string soname 'udf.so'

跟踪恶意函数,检查其执行的敏感操作。通常,管理员不会创建一个用于执行命令的函数并查看自身权限,因此可以基本确认这是攻击者的行为

1
2
3
root@9956ee9aa191:/# cat /usr/local/mysql/data/9956ee9aa191.log | grep "sys_eval"
7 Query create function sys_eval returns string soname 'udf.so'
7 Query select sys_eval("id")

日志未开启情况下排查

直接检查 plugin 目录是否存在异常文件,可以根据文件的创建时间来进行判断。发现最新创建的文件是udf.so,应将异常文件上传至安全威胁平台进行分析或反编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
root@9956ee9aa191:/# ls -al /usr/local/mysql/lib/plugin/
total 1512
drwxr-xr-x 1 mysql mysql 4096 May 7 09:38 .
drwxr-xr-x 1 mysql mysql 4096 Mar 23 2018 ..
-rw-r--r-- 1 mysql mysql 13920 Mar 23 2018 adt_null.so
-rw-r--r-- 1 mysql mysql 29992 Mar 23 2018 auth.so
-rw-r--r-- 1 mysql mysql 14456 Mar 23 2018 auth_socket.so
-rw-r--r-- 1 mysql mysql 27976 Mar 23 2018 auth_test_plugin.so
-rw-r--r-- 1 mysql mysql 227 Mar 29 2012 daemon_example.ini
drwxr-xr-x 1 mysql mysql 4096 Mar 23 2018 debug
-rw-r--r-- 1 mysql mysql 271184 Mar 23 2018 ha_archive.so
-rw-r--r-- 1 mysql mysql 219064 Mar 23 2018 ha_blackhole.so
-rw-r--r-- 1 mysql mysql 175272 Mar 23 2018 ha_example.so
-rw-r--r-- 1 mysql mysql 340712 Mar 23 2018 ha_federated.so
-rw-r--r-- 1 mysql mysql 36440 Mar 23 2018 libdaemon_example.so
-rw-r--r-- 1 mysql mysql 20816 Mar 23 2018 mypluglib.so
-rw-r--r-- 1 mysql mysql 19512 Mar 23 2018 qa_auth_client.so
-rw-r--r-- 1 mysql mysql 30568 Mar 23 2018 qa_auth_interface.so
-rw-r--r-- 1 mysql mysql 15600 Mar 23 2018 qa_auth_server.so
-rw-r--r-- 1 mysql mysql 182336 Mar 23 2018 semisync_master.so
-rw-r--r-- 1 mysql mysql 91000 Mar 23 2018 semisync_slave.so
-rw-rw-rw- 1 mysql mysql 8040 May 7 09:38 udf.so

在 MySQL 数据库中的 func 表中存在恶意函数记录

1
2
3
4
5
6
7
select * from mysql.func

+-----------+---------+---------------+-----+
| name | dl | type | ret |
+-----------+---------+---------------+-----+
| sys_eval | udf.so | function | 0 |
+-----------+---------+---------------+-----+

应急操作

  1. 将恶意的 .so 文件备份至本地,并删除 plugin 目录下的恶意文件
  2. 删除恶意函数:DROP FUNCTION sys_eval;
  3. 将备份的恶意文件上传至威胁情报平台进行分析或者反编译

CVE-2012-2122

通过查看日志文件发现短时间内存在大量的登陆记录,类似于爆破密码的过程,但与爆破密码不同的是中间会存在多条登录成功的日志记录

1
2
3
4
5
6
7
8
9
662 Connect   root@localhost on 
662 Connect Access denied for user 'root'@'localhost' (using password: YES)
663 Connect root@localhost on
663 Query select @@version_comment limit 1
240508 1:58:37 663 Quit
664 Connect root@localhost on
664 Connect Access denied for user 'root'@'localhost' (using password: YES)
665 Connect root@localhost on
665 Connect Access denied for user 'root'@'localhost' (using password: YES)

若使用 MSF 进行攻击,只有150行左右的日志记录,登录成功后的会导出 MySQL 所有用户的哈希值,可以在日志中看到如下语句

1
2
3
4
5
142 Connect   root@172.18.0.1 on 
142 Connect Access denied for user 'root'@'172.18.0.1' (using password: YES)
145 Connect root@172.18.0.1 on
145 Connect Access denied for user 'root'@'172.18.0.1' (using password: YES)
136 Query SELECT user,password from mysql.user

CVE-2016-6663 & CVE-2016-6664

这两个漏洞一般用作组合拳,CVE-2016-6663 用于从 webshell 拿到 www-data 权限后提权至 MySQL 用户,再使用 CVE-2016-6664 将 MySQL提权至 Root权限。

利用版本:MySQL<5.5.51 或 MySQL<5.6.32 或 MySQL<5.7.14

CVE-2016-6663

CVE-2016-6663 涉及一个需要具备创建、删除、插入和查询权限的数据库账号。使用该账号进行攻击会在数据库中留下被攻击后的表格,但这些表格无法打开,提示已损坏,且无法修复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| testdb |
+--------------------+
4 rows in set (0.00 sec)

mysql> use testdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW TABLES;
+------------------+
| Tables_in_testdb |
+------------------+
| exploit_table |
| mysql_suid_shell |
+------------------+
2 rows in set (0.00 sec)

以下是截取部分日志代表性信息:

1
2
3
4
5
240508  3:53:37     9 Query     CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/mysql_privesc_exploit'
240508 3:53:38 9 Query REPAIR TABLE exploit_table EXTENDED
240508 3:59:41 9 Quit
240508 4:00:47 10 Connect test@localhost on testdb
240508 4:00:49 10 Query DROP TABLE IF EXISTS exploit_table

特征点:

  1. 日志中频繁出现了对 exploit_table 表的创建和删除操作,并显示了使用了 MyISAM 存储引擎
  2. 恶意数据文件存放在目录:/tmp/mysql_privesc_exploit

排查与响应:

  1. 排查网站目录下的 Webshell,判断攻击者是通过 www-data 进行提权至 MySQL 权限,还是通过 MySQL 权限提升至 ROOT 权限
  2. 排查 MySQL 数据库是否泄露用户名和密码导致被攻击者利用,例如 Web 站点被拿下,攻击者读取配置文件发现 MySQL 账号密码
  3. 删除已经创建的恶意数据表,并清理/tmp目录下的 mysql_privesc_exploit 目录及其内容

CVE-2016-6664

漏洞是利用了 MySQL 的自启动权限来进行提权的。攻击者通过将error.log文件软链接至恶意文件,当 MySQL 自启动时,权限被授予给了error.log文件,实际上也就是授予了恶意文件

该漏洞需要获取到 MySQL 权限后才能提权至 ROOT 权限。其可能更改的配置文件为:

  1. /etc/mysql/conf.d/mysqld_safe_syslog.cnf可能会被更改,攻击者会将删除syslog
1
2
3
4
// 初始mysqld_safe_syslog.cnf文件内容
root@14ab6e4fe4be:/tmp# cat /etc/mysql/conf.d/mysqld_safe_syslog.cnf
[mysqld_safe]
syslog
  1. tmp 下会出现提权共享库privesclib.c和privesclib.so文件
1
rm -rf privesclib.c privesclib.so
  1. tmp 下会存在低权限后门mysqlrootsh
1
rm -rf mysqlrootsh
  1. 创建恶意的连接符(软链接),将恶意内容写入至ld.so.preload
1
2
3
4
5
6
7
8
// 恶意连接符
/var/log/mysql/error.log -> /etc/ld.so.preload

// 查看特定目录下的所有连接符
ls -l /path/to/directory/*

// 删除连接符,如下命令不会删除目标文件或目录
rm /var/log/mysql/error.log

后门用户排查

查看是否存在攻击者创建的恶意账户

1
2
3
4
5
6
7
8
9
10
11
12
13
// 查看MySQL中所有用户
mysql> SELECT User, Host FROM mysql.user;
+-------+--------------+
| User | Host |
+-------+--------------+
| admin | % |
| test | % |
| root | 127.0.0.1 |
| root | 14ab6e4fe4be |
| root | ::1 |
| root | localhost |
+-------+--------------+
6 rows in set (0.00 sec)

排查用户的权限时,需要注意权限分配情况,尤其要关注是否存在滥用权限的账号。只有拥有 CREATE USER 权限的账号才能创建用户

1
2
3
4
5
6
7
8
9
10
11
12
13
// 排查创建用户的权限
mysql> SELECT User, Host, Create_user_priv FROM mysql.user;
+-------+--------------+------------------+
| User | Host | Create_user_priv |
+-------+--------------+------------------+
| root | localhost | Y |
| root | 14ab6e4fe4be | Y |
| root | 127.0.0.1 | Y |
| root | ::1 | Y |
| admin | % | Y |
| test | % | N |
+-------+--------------+------------------+
6 rows in set (0.00 sec)

排查拥有 EXECUTE 权限的用户,因为只有拥有该权限的用户才能调用存储过程

1
2
3
4
5
6
7
8
9
10
11
12
mysql> SELECT User, Host, Execute_priv FROM mysql.user;
+-------+--------------+--------------+
| User | Host | Execute_priv |
+-------+--------------+--------------+
| root | localhost | Y |
| root | 14ab6e4fe4be | Y |
| root | 127.0.0.1 | Y |
| root | ::1 | Y |
| admin | % | Y |
| test | % | N |
+-------+--------------+--------------+
6 rows in set (0.00 sec)

MySQL启动项提权排查

该技巧只能在 Windows 中使用,且需要服务器重启

排查方法:

  1. 排查 Windows 开始菜单栏中是否有恶意的 VBS 提权脚本
  2. MySQL 日志中会存在如下的恶意 SQL 语句
1
2
3
4
5
2024-05-08T08:28:39.234957Z           13 Query        create table secist(cmd text)
2024-05-08T08:28:46.097512Z 13 Query insert into secist values("set wshshell=createobject(""wscript.shell"")")
2024-05-08T08:28:55.592555Z 13 Query insert into secist values("a=wshshell.run(""cmd.exe /c net user secist secist.com /add"",0)")
2024-05-08T08:29:01.858967Z 13 Query insert into secist values("b=wshshell.run(""cmd.exe /c net localgroup administrators secist /add"",0)")
2024-05-08T08:29:36.139032Z 13 Query select * from secist into dumpfile "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\1.vbs"

存储过程利用排查

拥有 EXECUTE****权限才可以调用存储过程

通过日志排查

排查日志,可通过排查 procedure 关键字发现其创建的存储过程,在此处为 readf

1
2
root@14ab6e4fe4be:/# cat /var/lib/mysql/14ab6e4fe4be.log | grep "procedure"
240508 10:20:11 1 Query create procedure readf(f varchar (100))

通过追踪存储过程的名称,来查看其执行的操作,可以发现其查看了敏感文件

1
2
3
4
root@14ab6e4fe4be:/# cat /var/lib/mysql/14ab6e4fe4be.log | grep "readf"
240508 10:20:11 1 Query create procedure readf(f varchar (100))
240508 10:21:59 4 Query call testdb.readf('/etc/passwd')
240508 10:22:15 4 Query call testdb.readf('/etc/shadow')

通过数据库排查

查询已有存储过程

1
2
3
4
5
6
7
mysql> SHOW PROCEDURE STATUS;
+--------+-------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| Db | Name | Type | Definer | Modified | Created | Security_type | Comment | character_set_client | collation_connection | Database Collation |
+--------+-------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| testdb | readf | PROCEDURE | root@localhost | 2024-05-08 09:47:42 | 2024-05-08 09:47:42 | DEFINER | | latin1 | latin1_swedish_ci | latin1_swedish_ci |
+--------+-------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
1 row in set (0.00 sec)

查询已有存储过程的详细信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mysql> SHOW CREATE PROCEDURE testdb.readf;                                                                                                                                                                                                                                                  
+-----------+----------+-------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
| Procedure | sql_mode | Create Procedure | character_set_client | collation_connection | Database Collation |
+-----------+----------+-------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
| readf | | CREATE DEFINER=`root`@`localhost` PROCEDURE `readf`(f varchar (100))
begin
select load_file(f);
end | latin1 | latin1_swedish_ci | latin1_swedish_ci |
+-----------+----------+-------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
1 row in set (0.00 sec)



// 上述的实际内容为:
CREATE DEFINER=`root`@`localhost` PROCEDURE `readf`(f VARCHAR(100))
BEGIN
SELECT LOAD_FILE(f);
END

应急操作

1
2
// 将存储过程删除
DROP PROCEDURE IF EXISTS testdb.readf;

小技巧

判断攻击者是否登录成功

登陆成功的日志文件

1
2
240507 10:46:22    17 Connect   root@localhost on 
17 Query select @@version_comment limit 1

登录失败的日志文件

1
2
240507 10:41:37    14 Connect   root@192.168.96.1 on 
14 Connect Access denied for user 'root'@'192.168.96.1' (using password: YES)

登录失败会有很明显的提示,而登录成功则执行后续的操作

判断攻击者登录方式

Navicat 执行恶意操作的日志:

1
2
3
4
5
root@9956ee9aa191:/# cat /usr/local/mysql/data/9956ee9aa191.log | grep "sys_eval"
7 Query create function sys_eval returns string soname 'udf.so'
7 Query select sys_eval("id")
8 Query select sys_eval("id")
8 Query select sys_eval("id")

命令行执行恶意操作的日志:

1
2
3
4
5
6
7
root@9956ee9aa191:/# cat /usr/local/mysql/data/9956ee9aa191.log | grep "sys_eval"
9 Query create function sys_eval returns string soname 'udf.so'
9 Query select sys_eval("whoami")
240507 9:38:50 11 Query select sys_eval("id")
240507 9:38:52 11 Query select sys_eval("id")
11 Query select sys_eval("id")
240507 9:38:53 11 Query select sys_eval("id")

MDUT执行恶意操作的日志

1
2
3
4
5
6
7
8
9
10
11
root@9956ee9aa191:/# cat /usr/local/mysql/data/9956ee9aa191.log | grep "sys_eval"
240507 10:13:47 8 Query drop function if exists sys_eval
8 Query create function sys_eval returns string soname '3fe6a354251823f6.temp'
240507 10:13:51 8 Query select sys_eval('id') as s
240507 10:13:57 8 Query select sys_eval('id') as s
8 Query select sys_eval('id') as s
8 Query select sys_eval('id') as s
8 Query select sys_eval('id') as s
8 Query select sys_eval('id') as s
240507 10:13:58 8 Query select sys_eval('id') as s
8 Query select sys_eval('id') as s

查看当前连接数据库的活跃用户

1
2
3
4
5
6
7
8
9
10
11
12
mysql> SHOW PROCESSLIST;
+----+------+--------------------+------+---------+-------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+--------------------+------+---------+-------+-------+------------------+
| 5 | root | 192.168.96.1:4814 | NULL | Sleep | 66100 | | NULL |
| 6 | root | 192.168.96.1:22537 | NULL | Sleep | 66128 | | NULL |
| 7 | root | 192.168.96.1:56755 | NULL | Sleep | 2 | | NULL |
| 9 | root | 172.18.0.1:41538 | NULL | Sleep | 294 | | NULL |
| 10 | root | 192.168.96.1:37797 | NULL | Sleep | 2 | | NULL |
| 12 | root | localhost | NULL | Query | 0 | NULL | SHOW PROCESSLIST |
+----+------+--------------------+------+---------+-------+-------+------------------+
6 rows in set (0.00 sec)