diff --git a/Readme.md b/Readme.md index 226a2b3..1d5526f 100644 --- a/Readme.md +++ b/Readme.md @@ -8,9 +8,9 @@ As a penetration tester I have to deal daily with Oracle DBMS, both via SQL Inje ## Basic Information Most of the times Oracle RDMS run on linux, specifically RedHat or Oracle Linux. The most version I found in the wild were 9 which is extremely old, 10, 11 as most common and 12 in the best cases. Oracle has an official client called `sqlplus`. Sometimes it is extremely useful to have `sqlplus` and the import and export utilities ready in standalone packages. Please see the #Downloads sections for that. -Oracle instances are defined in a file called `tnsmaes.ora` where an instance name is associated to a connection string. +Oracle instances are defined in a file called `tnsnames.ora` where an instance name is associated to a connection string. -Example tnsnames.ora: +Example `tnsnames.ora`: ``` PROD_DB = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP) (HOST = 10.50.50.10) (PORT = 1521)) (CONNECT_DATA = (SID = PROD))) @@ -40,6 +40,13 @@ sqlplus my_user@"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=192.168.1.10)(Port=15 # For a local instance if logged in with the oracle user sqlplus "/ as sysdba" sqlplus "sys as sysdba" +sqlplus my_user/my_password@PROD_DB as sysdba +``` + +Better formatiing: +``` +set pagesize 0; +sel linesize 5000; ``` ## Import/Export @@ -49,7 +56,7 @@ Oracle uses a proprietary format both for storing the actual data on the disk an Both require special privileges: this means that even if you have select privileges on a table that doesn't mean you have the privilege to bulk export it. Please refer to https://docs.oracle.com/database/121/SUTIL/GUID-8B6975D3-3BEC-4584-B416-280125EEC57E.htm -Now the old import export format has been reverse engineered and a python script for decosing the data is provided in the downloads section. You can also find the stabdalone utilities with the required dependencies packed. +Now the old import export format has been reverse engineered and there's a python script available. ## Password hashes Oracle password hashes are both stored inside the database and selectable from a privileged users and stored on disk. @@ -58,10 +65,51 @@ $ORACLE_HOME/dbs/orapw # Unix, %ORACLE_HOME%\database\PWD.ora # Windows ``` ``` -> SELECT * FROM SYS.USER +> SELECT NAME, PASSWORD FROM SYS.USER$; +SYS DCB748A5BC5390F2 +PUBLIC +CONNECT +RESOURCE +DBA +SYSTEM EED9B65CCECDB2E9 +SELECT_CATALOG_ROLE +EXECUTE_CATALOG_ROLE +DELETE_CATALOG_ROLE +EXP_FULL_DATABASE +IMP_FULL_DATABASE +OUTLN 4A3BA55E08595C81 +RECOVERY_CATALOG_OWNER +GATHER_SYSTEM_STATISTICS +LOGSTDBY_ADMINISTRATOR +AQ_ADMINISTRATOR_ROLE +AQ_USER_ROLE +SCHEDULER_ADMIN +DIP CE4A36B8E06CA59C +HS_ADMIN_ROLE +TSMSYS 3DF26A8B17D0F29F +_NEXT_USER +OEM_ADVISOR +OEM_MONITOR +DBSNMP E066D214D5421CCC +PLUSTRACE +CTXSYS D1D21CA56994CAB6 +CTXAPP +XDB E76A6BD999EF9FF1 +ANONYMOUS anonymous +XDBADMIN +AUTHENTICATEDUSER +XDBWEBSERVICES +MDSYS 72979A94BAD2AF80 +HR 4C6D73C3E8B0F0DA +FLOWS_FILES 364B78B9EABB9E56 +FLOWS_020100 16E4C012E98710D0 ``` +Old password format is `3DES(upper($username.$password))` for <12c and an harder custom method for >12. +Both are supported by hashcat as `-m3100` and `-m 12300`. -Fopr more info http://marcel.vandewaters.nl/oracle/security/password-hashes +Fopr more info: + - http://marcel.vandewaters.nl/oracle/security/password-hashes + - https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/changes-in-oracle-database-12c-password-hashes/ ## Recon To begin with Oracle has plenty of system tables and views to keep track of its properties. Some of them have either `all`, `dba` or `user` prefix. What does it mean? @@ -77,7 +125,8 @@ From https://sqljana.wordpress.com/2016/12/21/oracle-data-dictionary-views-user- > DBA* Views > DBA_*: Views that start with DBA_ list all objects unless restricted by the WHERE clause -Most of the time the most useful will be the ones with the `all_` prefix, exceot if we already are dba. +Most of the time the most useful will be the ones with the `all_` prefix, except if we already are dba. +Query to `SYS` tables and to `dba_*` do require high privileges. Oracle default databases to exclude to get cleaner results for custom tables/columns/procedures (from https://github.com/sqlmapproject/sqlmap/blob/master/lib/core/settings.py): @@ -87,33 +136,51 @@ Oracle default databases to exclude to get cleaner results for custom tables/col Check Oracle version: ``` -SELECT * FROM V$VERSION; -SELECT * FROM V$INSTANCE; -SELECT * FROM PRODUCT_COMPONENT_VERSION; +> SELECT BANNER FROM V$VERSION; +Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product +PL/SQL Release 10.2.0.1.0 - Production +CORE 10.2.0.1.0 Production +TNS for Linux: Version 10.2.0.1.0 - Production +NLSRTL Version 10.2. ``` +``` +> SELECT INSTANCE_NAME, HOST_NAME, EDITION, VERSION FROM V$INSTANCE; +INSTANCE_NAME HOST_NAME EDITION VERSION +---------------- ---------------------------------------------------------------- ------- ----------------- +XE oracle.lsd.cat XE 10.2.0.1.0 +``` +``` +> SELECT PRODUCT, VERSION FROM PRODUCT_COMPONENT_VERSION; + +PRODUCT VERSION +---------------------------------------------------------------- ---------------------------------------------------------------- +NLSRTL 10.2.0.1.0 +Oracle Database 10g Express Edition 10.2.0.1.0 +PL/SQL 10.2.0.1.0 +TNS for Linux: 10.2.0.1.0 + +``` + Get the current user: ``` SELECT USER FROM DUAL; -``` -Get the instance name: -``` -SELECT SYS_CONTEXT('USERENV','INSTANCE_NAME') FROM DUAL; -SELECT SYS_CONTEXT('USERENV', 'SID') FROM DUAL; -``` -Check if user is DBA: +SELECT USERNAME FROM USER_USERS; ``` +Get current user privileges: +``` +SELECT * FROM SESSION_PRIVS; ``` Check if Java is available: ``` -SELECT dbms_java.get_ojvm_property(PROPSTRING=>'java.version') FROM DUAL; +SELECT DBMS_JAVA.GET_OJVM_PROPERTY(PROPSTRING=>'java.version') FROM DUAL; ``` List all users ``` -SELECT USER FROM SYS.USER$ -SELECT USER, PASSWORD FROM SYS.USER$; -SELECT USERNAME from DBA_USERS; +SELECT USER, PASSWORD FROM SYS.USER$ +SELECT USERNAME, PASSWORD from DBA_USERS; +SELECT USERNAME FROM ALL_USERS; ``` List all databases @@ -135,19 +202,79 @@ SELECT OWNER, TABLE_NAME, COLUMNS NAME FROM ALL_TAB_COLUMNS; Linked instances ``` SELECT * FROM SYS.LINK$; +SELECT * FROM DBA_DB_LINKS; +SELECT OWNER, USERNAME, HOST, DB_LINK FROM ALL_DB_LINKS; ``` +Password for DB Links may be cleartext, encrypted or non present depending on the version. See #Linked_Instances -Past queries: +It is also possibile to view past queries. This is extremely useful to understand how the database is being used. ``` SELECT SQL_TEXT FROM V$SQL; -SELECT * FROM WRH$_SQLTEXT; +SELECT SQL_TEXT FROM WRH$_SQLTEXT; ``` +List all procedures: +``` +SELECT OWNER, OBJECT_NAME, OBJECT_TYPE FROM ALL_OBJECTS WHERE OBJECT_TYPE IN ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY'); +``` +List user procedures: +``` +SELECT OBJECT_NAME, OBJECT_TYPE FROM ALL_OBJECTS WHERE OBJECT_TYPE IN ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY'); +``` + +Get all non system procedures: +``` +SELECT OWNER, OBJECT_NAME, OBJECT_TYPE FROM ALL_OBJECTS WHERE OBJECT_TYPE IN ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY') AND WHERE OWNER NOT IN ('ANONYMOUS', 'APEX_030200', 'APEX_PUBLIC_USER', 'APPQOSSYS', 'BI', 'CTXSYS', 'DBSNMP', 'DIP', 'EXFSYS', 'FLOWS_%', 'FLOWS_FILES', 'HR', 'IX', 'LBACSYS', 'MDDATA', 'MDSYS', 'MGMT_VIEW', 'OC', 'OE', 'OLAPSYS', 'ORACLE_OCM', 'ORDDATA', 'ORDPLUGINS', 'ORDSYS', 'OUTLN', 'OWBSYS', 'PM', 'SCOTT', 'SH', 'SI_INFORMTN_SCHEMA', 'SPATIAL_CSW_ADMIN_USR', 'SPATIAL_WFS_ADMIN_USR', 'SYS', 'SYSMAN', 'SYSTEM', 'WKPROXY', 'WKSYS', 'WK_TEST', 'WMSYS', 'XDB', 'XS$NULL') + +``` + +Get the source code of an object: +``` +SELECT TEXT FROM ALL_SOURCE WHERE NAME = 'MY_PROCEDURE' ORDER BY LINE; +``` +Somatimes a source code might be obfuscated with a method that Oracle calls 'wrapping'. This is the case of most default procedures. THis format is easily reversible: + - https://github.com/DarkAngelStrike/UnwrapperPLSQL/blob/master/unwrap.py + - https://www.codecrete.net/UnwrapIt/ + + ## Common error based vectors -## Common out of bound channels - ## Linked instances +Linked instances are used very often. They're very useful to an attacker because they extend the attack surface and may even allow to jump to different network. + +Basic Syntax: +``` +SELECT USER FOM DUAL@MY_LINKED_DB; +``` + +Password are stored cleartext or a in a reversible format: +``` +> SELECT PASSWORDX FROM SYS.LINK$; + +PASSWORDX +-------------------------------------------------- +05D3BB995A60D0F7BC8724E1FB001819169BD0818171F28256 +``` +To decode the password look at: + - + - + +It is important to note that the whole recon process might be done in every linked databases. The user in the linked database might have higher privileges, a different Oracle version and different procedures and packages. It might be possibile to gain RCE in a linked database and not in the one used as entry point. + +Queries to linked database may also be nested which means that it is possible to run queries on a database linked to a database linked to the main instance thus making a 'jump' to a third database. +While the following syntax will not work: +``` +SELECT USER FROM DUAL@DB1@DB2; error +``` +It is possible to create a view or a synomin to overcome the syntax problem as described here https://stackoverflow.com/questions/2094843/possible-to-link-to-another-database-link +``` +DB1: +CREATE SYNONYM X FOR MyTable@sqlServerDB + +DB2: +(assumes db link to DB1 connects as owner of synonym) +SELECT * from X@DB1 +``` ## Procedures, packages and functions diff --git a/stuff/Readme.md b/stuff/Readme.md new file mode 100644 index 0000000..7861118 --- /dev/null +++ b/stuff/Readme.md @@ -0,0 +1,8 @@ +## Usage +``` +LD_LIBRARY_PATH=. ORACLE_HOME=./deps ./sqplus user/password@descriptor +``` + +## Files + - x86 version is packed from the files at https://oss.oracle.com/debian/dists/unstable/non-free/binary-i386/ + - x64 version is packed from