Low
CVE-2022-1040
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
Add References:
CVE-2022-1040
MITRE ATT&CK
Collection
Command and Control
Credential Access
Defense Evasion
Discovery
Execution
Exfiltration
Impact
Initial Access
Lateral Movement
Persistence
Privilege Escalation
Topic Tags
Description
An authentication bypass vulnerability in the User Portal and Webadmin allows a remote attacker to execute code in Sophos Firewall version v18.5 MR3 and older.
Add Assessment
Ratings
-
Attacker ValueLow
-
ExploitabilityLow
Technical Analysis
On March 25, 2022, Sophos published a critical security advisory for Sophos Firewall. The advisory details CVE-2022-1040, an authentication bypass issue affecting the firewall’s User Portal and Webadmin web interfaces. The bypass allows a remote and unauthenticated attacker to execute arbitrary code, resulting in a CVSSv3 score of 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H).
Sophos has reported this vulnerability was “being used to target a small set of specific organizations primarily in the South Asia region.” There is no other public reporting confirming attempted public exploitation of this issue. No public proof of concept currently exists.
Although Sophos Firewall is fairly widely deployed (Shodan fingerprints ~50,000 instances of User Portal and ~1500 Webadmin), wide exploitation of this issue is unlikely. By default, Sophos Firewall automatically updates, and no public proof of concept exists. Both of these factors should keep exploitation down to a minimum.
The Patch
Sophos introduced two changes to address this vulnerability. This first was a change to web.xml
to introduce a new filter on all requests.
albinolobster@ubuntu:~$ diff -u sophos_unpatched/webconsole/WEB-INF/web.xml sophos_patched/webconsole/WEB-INF/web.xml --- sophos_unpatched/webconsole/WEB-INF/web.xml 2022-03-28 10:57:23.841991165 -0700 +++ sophos_patched/webconsole/WEB-INF/web.xml 2022-03-28 10:41:47.757727685 -0700 @@ -12,6 +12,16 @@ </session-config> <filter> + <filter-name>RequestCheckFilter</filter-name> + <filter-class>cyberoam.sessionmanagement.RequestCheckFilter</filter-class> + </filter> + + <filter-mapping> + <filter-name>RequestCheckFilter</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + + <filter> <filter-name>SessionCheckFilter</filter-name> <filter-class>cyberoam.sessionmanagement.SessionCheckFilter</filter-class> </filter>
The second change was the introduction of the new filter RequestCheckFilter.class
. The entire class is a bit long to fit here, but the interesting part for an unauthenticated attacker follows:
JSONObject jsonObject = null; String mode = httpRequest.getParameter("mode"); String operation = httpRequest.getParameter("operation"); String dataGridId = httpRequest.getParameter("datagridid"); try { CyberoamLogger.debug("RequestCheckFilter", "mode: " + mode); CyberoamLogger.debug("RequestCheckFilter", "operation: " + operation); CyberoamLogger.debug("RequestCheckFilter", "dataGridId: " + dataGridId); if (request.getParameter("json") != null && mode != null) { operation = (operation == null) ? "0" : operation; dataGridId = (dataGridId == null) ? "0" : dataGridId; if (ALL_SESSION_CHECK_EXEMPTED_MODES.contains(Integer.valueOf(Integer.parseInt(mode))) || isFilterRequired(Integer.parseInt(mode), Integer.parseInt(operation), Integer.parseInt(dataGridId))) { jsonObject = new JSONObject(httpRequest.getParameter("json")); if (!isvalidJSONKeys(jsonObject)) { redirectToLogin(httpRequest, httpResponse); return; } } } else { CyberoamLogger.debug("RequestCheckFilter", "JSON parameter not found in request payload"); } chain.doFilter((ServletRequest)httpRequest, (ServletResponse)httpResponse);
I’m going to skip over talking about all of the mode, operation, and datagrid values as it just complicates things. Generically, this logic examines the request’s HTTP parameters to determine if it needs to pass the attacker provided JSON into a method called isValidJSONKeys
. Which looks like this:
private boolean isvalidJSONKeys(JSONObject jsonObject) { Iterator<?> jsonkeys = jsonObject.keys(); while (jsonkeys.hasNext()) { String key = (String)jsonkeys.next(); if (!isAsciiPrintable(key)) { CyberoamLogger.info("RequestCheckFilter", "JSON key with non-ASCII printable characters! key = " + key); return false; } } return true; }
This method is obviously looping over the keys in the attacker-provided JSON and validating the keys are made up of printable ASCII characters.
An unauthenticated and remote “attacker” can hit this code path relatively easily with a curl
:
albinolobster@ubuntu:~/sophos_patched$ curl -v --insecure -H "X-Requested-With: XMLHttpRequest" -X POST 'https://10.0.0.19/userportal/Controller?mode=8700&operation=1&datagrid=179&json=\{"🦞":"test"\}' * Trying 10.0.0.19:443... * Connected to 10.0.0.19 (10.0.0.19) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 * ALPN, server did not agree to a protocol * Server certificate: * subject: C=NA; ST=NA; L=NA; O=NA; OU=NA; CN=Appliance_Certificate_n7Rmy46scKRgK16; emailAddress=na@example.com * start date: Aug 1 00:00:00 2015 GMT * expire date: Dec 31 23:59:59 2036 GMT * issuer: C=NA; ST=NA; L=NA; O=NA; OU=NA; CN=Default_CA_n7Rmy46scKRgK16; emailAddress=na@example.com * SSL certificate verify result: self signed certificate in certificate chain (19), continuing anyway. > POST /userportal/Controller?mode=8700&operation=1&datagrid=179&json={"🦞":"test"} HTTP/1.1 > Host: 10.0.0.19 > User-Agent: curl/7.74.0 > Accept: */* > X-Requested-With: XMLHttpRequest > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Date: Fri, 15 Apr 2022 14:59:50 GMT < Server: xxxx < X-Frame-Options: SAMEORIGIN < Strict-Transport-Security: max-age=31536000 < X-Content-Type-Options: nosniff < Content-Length: 15 < Cache-Control: max-age=2592000 < Expires: Sun, 15 May 2022 14:59:50 GMT < Connection: close < {"status":400} * Closing connection 0 * TLSv1.2 (OUT), TLS alert, close notify (256):
Note the {"status":400}
response from the server. An unpatched server will respond a little differently:
albinolobster@ubuntu:~/sophos_patched$ curl --insecure -H "X-Requested-With: XMLHttpRequest" -X POST 'https://10.0.0.12/userportal/Controller?mode=8700&operation=1&datagrid=179&json=\{"🦞":"test"\}' {"status":"Session Expired"}
Since the patch induces a new response from the firewall, we can remotely detect patch status. You can try the same thing on the Webadmin interface and it too generates a slightly different response ({"status":"-2"}
when unpatched).
Finally, it might be useful to know that exploitation attempts on a patched server generate the following log in /log/tomcat.log
.
2022-04-15 15:59:50,877:INFO:RequestCheckFilter - URI: /userportal/Controller 2022-04-15 15:59:50,877:INFO:RequestCheckFilter - JSON key with non-ASCII printable characters! key = 🦞
Summary
In order to address CVE-2022-1040, Sophos introduced a fairly small patch to filter the JSON content of some HTTP requests. Exploitation attempts will have non-ascii characters in the request’s json
parameter’s JSON keys. If your Sophos Firewall is internet facing, it should absolutely have automatic update enabled (the default behavior). If you are in a situation where you can’t do that, you likely shouldn’t be using the internet facing features.
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportCVSS V3 Severity and Metrics
General Information
Vendors
- sophos
Products
- sfos
Exploited in the Wild
Would you like to delete this Exploited in the Wild Report?
Yes, delete this report- Government or Industry Alert (https://www.cyber.gov.au/acsc/view-all-content/alerts/remote-code-execution-vulnerability-present-sophos-firewall-0)
- News Article or Blog (https://securityaffairs.co/wordpress/132377/apt/chinese-driftingcloud-apt-exploited-sophos-firewall-zero-day-before-it-was-fixed.html)
- Other: CISA Known Exploited Vulnerabilities (https://www.cisa.gov/known-exploited-vulnerabilities-catalog)
Would you like to delete this Exploited in the Wild Report?
Yes, delete this reportWould you like to delete this Exploited in the Wild Report?
Yes, delete this reportReferences
Exploit
A PoC added here by the AKB Worker must have at least 2 GitHub stars.
Additional Info
Technical Analysis
Report as Exploited in the Wild
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
PoC code now exists at https://blog.viettelcybersecurity.com/cve-2022-1040-sophos-xg-firewall-authentication-bypass/
I am trying to do some research on sophos firewall and was wondering if anyone have a link to download old version of the product that may vulnerable to CVE-2022-3236
@nam0netime This vulnerability was in Sophos Firewall v18.5 MR3 (18.5.3) and older. I located download links for older versions in a Sophos community forum post titled Download SFOS 18.5.1 MR-1-Build326 HW Installer.
I was able to download the older version but there is no way to turn off automatic updates on a version that still receives an update from Sophos so it really hard to replicate this vulnerability