- MOFI4500-4GXeLTE V2 Firmware 3.6.1-std
- MOFI4500-4GXeLTE V2 Firmware 4.0.8-std
- MOFI4500-4GXeLTE V2 Firmware 4.2.5-std
Multiple critical vulnerabilities have been discovered in the MoFi4500 router, an OpenWRT based wireless router that provides Internet access via LTE.
The initial vulnerabilities were reported to the vendor and patches were made available; however new critical vulnerabilities were subsequently introduced as a result.
Several firmware versions have been released, but some of the vulnerabilities have not been fully patched. The vendor has not communicated with TEAMARES since 6/9/2020.
As of 9/1/2020, the following vulnerabilities remain unpatched by the vendor:
- CVE-2020-15836 Unauthenticated Remote Command Injection
- CVE-2020-15835 Undocumented Backdoor – Authentication Bypass
- CVE-2020-15833 Undocumented Backdoor – SSH Daemon
- CVE-2020-15832 Undocumented Backdoor – Remote Reboot
Most vulnerabilities impact the web management interface, which is accessible by default on all network interfaces. Many Internet Service Providers (ISP) use Carrier Grade NAT to prevent direct access to the management interface from the Internet.
This does not limit an attacker with access to the LAN interface or to the internal ISP network. In some cases, the vulnerability can be triggered indirectly by a user clicking a link or visiting a malicious web site.
On 6/25/2020, Shodan reported that over 14,000 MoFi devices with the management interface were exposed. This number has since dropped to around 7,129 as of 9/1/2020. We suspect this is the result of US-CERT working with ISPs to restrict network access.
Attention Device Owners:
If you own a MoFi device, there is a high chance your device is vulnerable to one or more of these vulnerabilities. We recommend the following steps to secure your router as soon as possible:
- Make a system backup
- Upgrade to the latest available firmware
- Email email@example.com and request the company fix the unresolved vulnerabilities and provide the capability to disable the undocumented backdoors
- Ensure that the SSH service is only listening on the LAN interface (default)
- Disable the inbound HTTP traffic on the WAN/LTE interface
- Understand that if you use the Support Wizard to generate a support file and send this file to MoFi Networks, your wireless network password will be included
- Understand that MoFi Network, your ISP, or anyone with the backdoor secret key may be able to remotely access your router using the root account without your knowledge
I began my research by analyzing the firmware from a static perspective using the Binwalk utility. Several files piqued my interest, so I wanted to test the firmware dynamically.
I attempted to load the firmware with Qemu but failed to get it working in the allotted time. Instead, I opted to purchase the device which I could always re-purpose as a backup Internet connection in the future if needed.
CVE-2020-13859 Authentication Bypass
A format error in /etc/shadow coupled with a logic bug in the LuCI – OpenWrt Configuration Interface framework allows the undocumented system account “mofidev” to login to the management interface without a password.
The MoFi firmware has a built-in feature to assist a device owner with regaining access to the device if the root password is unknown. To accomplish this, visiting the “About” page generates a one-time password for the mofidev system account.
The mofidev Linux account is defined in /etc/passwd. The one-time password displayed on this page is not the actual password. This value is used as part of the calculation which results in a 6-digit numeric password.
A device owner would need to contact Mofi Network’s support for further instructions on how to gain access to the “Setup Wizard”.
I then discovered that you do not need to contact support for the one-time password. Clicking the “Run Setup Wizard” link will load the http://IP/cgi-bin/luci/quick/wizard page and display a login prompt.
Entering mofidev in the username field while leaving the password field blank or set to any string will allow anyone to access the “Quick Wizard”.
At this stage, the root password can be changed along with the network parameters. At the end of the wizard, the changes will be saved, and the router will be rebooted resulting in a complete unauthenticated device takeover.
To understand the root cause of this vulnerability, we must first understand the Predictable One-Time Password vulnerability.
MOFI4500-4GXeLTE – Predictable One Time Password
During static analysis, a script named /usr/bin/otp.sh looked very interesting. This custom script is called when visiting the About page and generates the one-time password code for Mofi support.
It also sets a six-digit password for the “mofidev” account. The code is generated using a static secret resulting in a predictable six-digit password.
The logic shows the following:
- A random PIN (OTP Code) is generated and stored in /etc/config/otppin.
- The PIN is concatenated with the static SECRET removing all spaces to create a TOKEN
- The TOKEN is hashed with MD5 and all letters are removed.
- The mofidev password is reset to the first six digits of the TOKEN
With knowledge of the static SECRET, we can simply generate a TOKEN to reliably determine the password for the mofidev account. The goal was to generate an OTP password and login. When attempting this attack, I generated a six-digit OTP password and it worked on the first try! I was excited but wanted to dig deeper.
Then I attempted to SSH as the mofidev user but was unsuccessful, which was puzzling since I was able to login to the web interface using the code.
I tried to verify by using su from the root account and this also failed, so I downloaded the shadow file and ran it through a numeric wordlist. The password was successfully cracked but was not the same value that I used for the web interface.
I found that the About page automatically refreshes every few seconds which kept resetting the OTP password to a different value. By the time I attempted to SSH as mofidev, the password was already changed to a new random password.
I fixed this issue by turning Burp Intercept on and sending the request through Repeater. This prevented the automatic refresh from changing the password to a new value.
After verifying that only a single request was sent to the About page, I tried to login via SSH, but it failed.
To verify the mofidev password, I copied the shadow file and attempted to crack the hash for mofidev which showed the OTP password was set to the same value used for the web authentication.
Through additional manual testing, I realized I could log in to the web interface as mofidev without a password using the About page. Now I was even more puzzled.
After digging deeper, I found the answer in the check password logic defined in /usr/lib/lua/luci/sys.lua. This logic is not customized by the vendor and is part of the OpenWrt LuCi framework.
The vulnerable logic is highlighted below and results in a “fail open” condition if the password hash is null.
We just demonstrated that the hash was successfully cracked, so how could the password hash be null?
It turns out the number of fields defined in /etc/shadow is important. Notice that the number of fields defined for mofidev is less than the root.
Each entry in the shadow(5) file contains nine fields separated by colons. The mofidev account was missing the last three fields.
- Password hash
- Date of the last password changed
- Minimum password age
- Maximum password age
- Password warning period
- Password inactivity period
- Account expiration date
- Reserved field
Tracing through the function calls shows the reason pwh is nil is because of the call to the nixio.getsp() function fails as a result of the malformed shadow entry. It defaults to nixio.getpw() which returns the second field for the mofidev entry in /etc/passwd which is ‘x‘. The result of pwh is checked and the function returns nil, pwe because pwh is ‘x‘.
Running a simple test with the user.checkpasswd logic snippet confirms this issue.
If pwh is null, the hash is never checked against the nixio.crypt() function. Not calling nixo.crypt() makes sense because the hash is null; however an authentication decision is based on this result, which means the function fails open resulting in any password value being allowed for the mofidev account.
I discovered this issue had already been reported to the OpenWrt LuCi project in 2018. The developer states this is expected behavior when no password is set for the user. A patch was issued, but I reviewed the changeset and this vulnerability was not fixed.
I created pull request #4030 on 5/7/20 to fix this issue; it has not been accepted by the project yet.
My patch prevents the fail-open condition by ensuring that pwh is not null and verifies the hash against the is.crypt() function.
Both vulnerabilities have been fixed by the vendor and the solution was to delete the undocumented mofidev account. Generating an OTP password is no longer possible on MoFi4500 devices with the latest firmware installed.
A similar issue appears to exist in the previous generation MoFi3500 firmware v3.9.2std; however, it is unknown if a fix has been publicly released.
The MoFi3500 otp.sh script does not use a static secret and the format of /etc/shadow for the mofidev account is correct. It is unknown when either of these vulnerabilities were introduced, but it appears to have existed since 2015.
CVE-2020-15836 Unauthenticated Command Injection
The authentication function passes untrusted data to the operating system without proper sanitization. A crafted request can be sent to execute arbitrary commands as root. Technical details are not included at this time because the vendor has not released a patch.
v4.1.5-std – v4.2.8-std
CVE-2020-15835 Undocumented Backdoor – Authentication Bypass
The authentication function contains undocumented code which provides the ability to authenticate as root without having to know the actual root password. An adversary with the private key can remotely authenticate to the management interface as root.
Technical details are not included at this time because the vendor has not released a patch and disclosing this would provide enough details for the unpatched CVE-2020-15836 Unauthenticated Command Injection.
v4.1.5-std – v4.2.8-std
CVE-2020-15833 Undocumented Backdoor – SSH Daemon
The dropbear SSH daemon has been modified to accept an alternate hardcoded path to a public key that allows root access. This key is stored in a location that is not modifiable by the device owner.
v4.1.5-std – v4.2.8-std
CVE-2020-15832 Undocumented Backdoor – Remote Reboot
The poof.cgi script contains undocumented code that provides the ability to remotely reboot the device. An adversary with the private key can remotely reboot the device without having to know the root password.
v4.1.5-std – v4.2.8-std
CVE-2020-13858 Hard-Coded Administrator Accounts
The MOFI4500-4GXeLTE router contains two undocumented administrator accounts. The sftp and mofidev accounts are defined in /etc/passwd and the password is not unique across installations.
CVE-2020-13857 Unauthenticated Reboot
The MOFI4500-4GXeLTE router can be rebooted by sending an unauthenticated HTTP GET request. For devices behind NAT, this can also be triggered as there is no CSRF protection.
CVE-2020-15834 Information Disclosure – WiFi Network Password
The wireless network password is exposed in a QR encoded picture which an unauthenticated adversary can download via the web management interface.
CVE-2020-13856 Information Disclosure
No authentication is required to download the support file that contains sensitive information such as cleartext credentials and password hashes. If the email to Mofi Network support option is used, this file is emailed over a non-encrypted channel.
Steps to Reproduce:
1. Log in as root via the management web interface and access the “Gather Support Logs” page.
2. Enter in a name, email, and problem description and click Next.
3. Click Press Here to Generate Logs.
4. Download http://IP/systemlog.tar.gz using an unauthenticated session.
5. Show a sample of the files included from the /etc directory in the system.log.tar.gz file. Information such as hashed passwords, Wi-Fi configuration including cleartext passwords is included.
It is important to reiterate that some of these vulnerabilities have not been fixed by the vendor as of v4.2.8std released on 8/21/2020. This includes the critical unauthenticated remote command execution vulnerability and several undocumented backdoors.
|CVE||Issue||Affected Product||Approx. Risk Rating||Description|
|2020-13859||Authentication Bypass||MOFI4500-4GXeLTE4.0.8-std||Critical||A format error in /etc/shadow coupled with a logic bug in the LuCI – OpenWrt Configuration Interface framework allows the undocumented system account “mofidev” to login to the management interface without a password|
|2020-13860||Predictable One Time Password||MOFI4500-4GXeLTE4.0.8-std||Critical||The one-time password generation for the undocumented system account “mofidev” generates a predictable six-digit password.|
|2020-13858||Hard-Coded Administrator Accounts||MOFI4500-4GXeLTE4.0.8-std3.6.1-std||Critical||The MOFI4500-4GXeLTE router contains two undocumented administrator accounts. The sftp and mofidev accounts are defined in /etc/passwd and the password is not unique across installations.|
|2020-15836||Unauthenticated Command Injection||MOFI4500-4GXeLTEv4.1.5-std||Critical||The authentication function passes untrusted data to the operating system without proper sanitization. A crafted request can be sent to execute arbitrary commands as root.|
|2020-15835||Undocumented Backdoor –Authentication Bypass||MOFI4500-4GXeLTEv4.1.5-std||Critical||The authentication function contains undocumented code which provides the ability to authenticate as root without having to know the actual root password. An adversary with the private key can remotely authenticate to the management interface as root.|
|2020-15833||Undocumented Backdoor – SSH Daemon||MOFI4500-4GXeLTEv4.1.5-std||Critical||The dropbear SSH daemon has been modified to accept an alternate hardcoded path to a public key that allows root access. This key is stored in a location that is not modifiable by the device owner.|
|2020-13857||Unauthenticated Reboot||MOFI4500-4GXeLTE4.0.8-std3.6.1-std||High||The MOFI4500-4GXeLTE router can be rebooted by sending an unauthenticated HTTP GET request.|
|2020-15834||Information Disclosure – WiFi Network Password||MOFI4500-4GXeLTEv4.1.5-std||High||The wireless network password is exposed in a QR encoded picture which an unauthenticated adversary can download via the web management interface.|
|2020-13856||Information Disclosure||MOFI4500-4GXeLTE4.0.8-std||Medium||No authentication is required to download the support file which contains sensitive information such as cleartext credentials and password hashes.|
|2020-15832||Undocumented Backdoor – Remote Reboot||MOFI4500-4GXeLTEv4.0.9-std – v4.1.5-std||Medium||The poof.cgi script contains undocumented code which provides the ability to remotely reboot the device. An adversary with the private key can remotely reboot the device.|
- 05/05/2020 – Contacted vendor requesting method to report vulnerabilities
- 05/11/2020 – Vulnerabilities reported
- 05/19/2020 – Contacted vendor to verify report was received
- 05/19/2020 – Vendor acknowledged report
- 06/09/2020 – New vulnerabilities reported
- 06/09/2020 – Vendor acknowledged report
- 06/10/2020 – Contacted US-CERT
- 07/09/2020 – Requested a status update – No response
I appreciate Eric Luke for allowing me to independently test his MoFi4500 device and for blindly clicking my rogue links, which temporarily interrupted his Internet access. I appreciate Craig Haskett for assisting with the testing of various MoFi4500 network configurations.
Discovered by Rich Mirch of TEAMARES