By Ben Reardon, Corelight Security Researcher
In this blog we aim to provide a little insight into part of the lifecycle of Corelight Lab’s response to a critical HTTP vulnerability. We’ve open-sourced many such responses over the last year (see Appendix A), and this one is a good demonstration of the evolving nature of the threat landscape. It also serves to highlight some issues we track through development of these packages.
- How would you know if your enterprise may be running a vulnerable system ?
- How would you know if an adversary is probing for this exploit ?
In May’s Patch Tuesday, Microsoft released a critical patch to systems running a vulnerable version of a function in HTTP.sys. The vulnerability is unauthenticated, trivial, wormable, and is rated as a 9.8 CVE score.
You can read up on the underlying details of the vulnerability here. The essence of the vulnerability lies in the way the code handles the Accept-Encoding HTTP header. The Accept-Encoding header is simply a header sent by the client to inform the server of the compression algorithms the client can understand. If the client can accept more than one algorithm, these are separated by commas, and this is where the CVE-2021-31166 vulnerability lies. The exploit is triggered simply if there is whitespace (or nothing at all) between the commas in the Accept-Encoding header.
A working proof-of-concept (POC) of the DoS exploit became publicly available a few days after the patch was released. This is when myself and fellow Corelighters Anthony Kasza, Alex Kirk, Aaron Soto and Paul Dokas kicked into gear, with the aim of rapidly producing both a Zeek package and a Suricata rule to aid defenders. We developed an initial solution within hours of the POC release, and then continued to test and fine-tune before then open sourcing the content. You can find our Zeek and Suricata content here https://github.com/corelight/CVE-2021-31166.
To give a sense of the various facets we look at during development of these responses, here are some considerations:
Does the detection logic produce an acceptable number of false positive results?
Our experience has shown that without testing detections in real-world large-scale networks, even highly specific detection logic may trigger false positives in surprising ways. Not many detections are 100% guaranteed not to create false positives, but we aim to bring the number of false positives down to the absolute minimum level we can.
Does it detect subtle variants of the POC?
Here we aim to decrease the false negative case to zero, that is we don’t want to miss detections because the logic is too specific and brittle to account for small variations in the attack vector. To attain this goal, we take the POC into a lab test environment where we test several subtle variations of the exploit and launch them at a vulnerable system. We then check that our content still provides the expected notices/alerts for all of these variations. The challenge in this process is that widening a detection to include more working variations also opens up the possibility of more false positives. Tuning for false negatives vs false positives involves taming opposing forces, and getting this balance within the acceptable limits can sometimes be as much an art as it is a science.
What are the performance characteristics of the detection?
This is where experience comes to the fore. The key aspect is to ensure that the resources consumed by the detection logic are within expectations. We spend significant energy here, as with both the Zeek and Suricata content there are often subtleties that make or break a detection strategy. We covered some examples of practical Zeek performance tips in a recent blog.
Getting back to the lifecycle of the exploit, a few days after the release of the exploit POC (which largely focused on IIS server) it became known that the vulnerable Accept-Encoding parsing function is also used by the Windows Remote Management (WinRM) Service. What is WinRM you ask? For the purpose of this blog we’ll stick to a brief explanation, but you can read more about it here. Windows Remote Management (WinRM) runs by default on TCP port 5985. It can run on both servers and desktops and is a SOAP driven API designed so that Windows systems can be managed using scripts such as Powershell.
Note: WinRM can also potentially be used by attackers for lateral movement, as per https://attack.mitre.org/techniques/T1021/006/. This is an effective tactic and sometimes referred to as “living off the land” – in that the tool that is used for lateral movement (WinRM) already exists natively on the system.
The content of the WinRM traffic is encrypted outside of the HTTP session, however the API endpoint itself operates over HTTP cleartext. Most importantly, if it runs the vulnerable version of HTTP.sys on port 5985 it is also exploitable.
It wasn’t long after the possibility of winRM using the vulnerable code in HTTP.sys was reported that the existing exploit was adapted to the WinRM service. Researchers also used shodan.io to gauge how many systems on the internet are exposing WinRM:
Note that not all of these systems will have the vulnerable version of HTTP.sys, but this does serve to quantify the extent of exposure of WinRM itself. It’s certainly enough context for us to want to ensure that our detection logic holds up with WinRM as compared to IIS, so we set back to work on this new development.
Firstly, we checked the Server headers from port 5985 on our lab victim machine, to make sure the port is open and serving the expected headers from WinRM:
Next, we tested several variations of the exploit against WinRM on the victim machine and found that both the Zeek and Suricata content we’d already published days ago also detected the WinRM scenario. This is largely due to Zeek’s ability to detect and parse HTTP traffic on any port.
The following graphic shows how trivial the exploit is, the resulting reboot of the Windows machine, and the notices and alerts provided by our Zeek package and Suricata rule.
If you’ve read this far, you may be interested in discovering how much WinRM activity you have on your corporate network. Regardless of the existence of the exploit, it is still valuable to understand the extent of management protocols, especially when they could be used by adversaries for lateral movement. If you have Zeek logs, you can check http.log for some common WinRM artifacts. Note that while there are other ways to discover WinRM activity, these simple indicators are provided by Zeek by default.
Corelight Labs will continue to monitor this vulnerability, particularly for any developments involving a Remote Code Exploit or new attack vector. If/when these occur we will re-test and amend our content as required. In the meantime, if you have any suggestions or feedback please get in touch!
Appendix A: previously Open Sourced Detection packages
Pingback C2 Detection published 05/07/2021
Linux Malware C2 ‘RedXOR’ published 04/20/2021
‘Bad Neighbour’ Microsoft Remote Code Execution – CVE-2020-16898 published 10/15/2020
ZeroLogon – CVE-2020-1472 published 09/16/2020
F5 Big IP – CVE-2020-5902 published 07/01/2020
SIGRed – CVE-2020-1350 published 07/14/2020
Ripple20 (Trek) 19 vulnerabilities published 06/17/20
GnuTLS – CVE-2020-13777 published 06/04/20
Call Stranger – CVE-2020-12695 published 06/08/20
Curveball – CVE-2020-0601 published 01/17/20
Detecting OpenBSD CVE-2019-19521 SSH exploit attempts published 01/06/19