Hey folks, I want to talk about a False Positive Issue that I was troubleshooting on our community Discord. A couple of users had notified us of some false positives with the rule ET INFO PE EXE or DLL Windows file download HTTP (2018959)
.
Before we go on about the FPs this rule produced, let’s talk about its overall purpose.
This is an informational, almost-but-not-quite-hunting rule, that is designed to inform analysts of when a webserver responds back with a windows PE executable in its response body. In this day and age, its not that common anymore, and is therefore probably not normal.
“Does this ever fire on modern networks?”
There are a lot of threat actors out there who just stand up plaintext HTTP servers to just serve out a payload. That’s their only purpose. Even some nation-state actors do this. Especially if their tradecraft involves ‘smash and grab’ tactics (e.g. “I’ll take what I want, I don’t care about leaving network evidence, so long as my goals are met”), or they’re fast enough to set up multiple persistence points when they gain access to a target network so that if the initial access attempt is discovered, it doesn’t matter, because by the time that initial access has been remediated, they’re probably set up multiple redundant beachheads.
It’s the hacker mantra to use the path of least resistance, so why bother with encryption if the company’s security contacts aren’t watching the logs anyway? That’s why I recommend using our rules that monitor for stuff like this over plain HTTP: the bad guys use what is effective, and this is still effective.
…At least that’s the theory behind the rule. But then there’s Microsoft, and Windows Update, serving executables over plain HTTP. So it’s not too uncommon, except its the most common thing happening for the update mechanism of the most common operating system out there.
So, how do we address this issue? There are multiple ways to handle this, but we at Emerging Threats have chosen to use flowbits
as a method of working around this.
Go with the flow(bits)
Flowbits are a feature of both Snort and Suricata that allows rule writers to create rules that, if the criteria are met, will tag network flows. Rule writers can create additional rules that piggyback off that tag. You can configure the rule to conditionally alert if a flow bit is set, is not set, or even unset the flowbit tag from a previous rule that triggered in the stream. This is for things that are happening in the same network flow in which the original flowbit(s) has been set. In our use case, the same TCP (http) stream.
Suricata documentation here.
Snort documentation here.
On a somewhat related note, and another reason why Suricata is awesome, you should check out xbits
. To summarize, its the ability to set a flowbit-like tag for connectivity between two IP addresses for a set amount of time. You can use it for malware that might do its C2 comms across different flows/TCP sessions. Or maybe C2 commands are received from one IP address, but output is sent to another IP address. More about that here.
So, here is a rule that we use for saying “If the http host is *.windowsupdate.com
, set the flowbit ET.INFO.WindowsUpdate
”:
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"ET INFO Windows Update/Microsoft FP Flowbit"; flow:established,to_server; flowbits:set,ET.INFO.WindowsUpdate; flowbits:noalert; http.host; content:".windowsupdate.com"; endswith; classtype:not-suspicious; sid:2023818; rev:4; metadata:affected_product Windows_XP_Vista_7_8_10_Server_32_64_Bit, attack_target Client_Endpoint, created_at 2017_02_01, deployment Perimeter, performance_impact Low, confidence High, signature_severity Major, updated_at 2023_04_14;)
So with that bit set we can then use the logic: flowbits:isnotset,ET.INFO.WindowsUpdate;
to make sure that this is NOT the HTTP Host we’re talking to. Oh, one more nice thing about flowbits
is that multiple rules are allowed to set the same flowbit.
Windows Update and its Massive Network Footprint
As time has marched on, Windows Update infrastructure has spread. There are a multitude of Microsoft hosts your systems have to talk to in order to pull down updates. Yes, that includes your WSUS/SCCM/BigFix servers – something has to download the updates from the internet, before your users refuse to download those updates for 15 days in a row before the update is enforced at the worst possible time.
Here’s something from Microsoft that provides a list of hosts WSUS wants to talk to.
None of those are covered by the rule that sets the flowbit. On top of that, if a host is just talking to windowsupdate.com, and not a subdomain of that, then that also results in that flowbit not being set.
For suricata, we can add the dotprefix
transformation to the original windowsupdate.com
rule (ET INFO Windows Update/Microsoft FP Flowbit" (2023818)
) and call it a day:
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"ET INFO Windows Update/Microsoft FP Flowbit M1"; flow:established,to_server; flowbits:set,ET.INFO.WindowsUpdate; flowbits:noalert; http.host; dotprefix; content:".windowsupdate.com"; endswith; sid:1; rev:1;)
For Snort, however, we don’t have an http.host
sticky buffer or modifier. We don’t have a dotprefix
transform, and we don’t have endswith
. What we do have is pcre
:
alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"ET INFO Windows Update/Microsoft FP Flowbit M1"; flow:established,to_server; flowbits:set,ET.INFO.WindowsUpdate; flowbits:noalert; content:"windowsupdate.com"; http_header; pcre:"/(?:\x3a\x20|\x2e)windowsupdate\x2ecom\r?$/Hmi"; sid:1; rev:1;)
The PCRE is looking for a colon (\x3a
) and a space (\x20
) OR a period (\x2e
) followed by windowsupdate.com
and the end of a line (\r?$
) in the HTTP header, case insensitive (/Hmi
). In this way we’re kind of emulating http.host
, dotprefix
, and endswith
from the Suricata rule. It’s not pretty, but it does work.
So we souped up this old rule to be able to account for subdomains. I also added in the domains (and their subdomains):
delivery.mp.microsoft.com
update.microsoft.com
Those rules were posted today in the daily rule update. Check out:
2059284 - ET INFO Windows Update/Microsoft FP Flowbit M2 (info.rules)
2059285 - ET INFO Windows Update/Microsoft FP Flowbit M3 (info.rules)
Microsoft Connected Cache aka “Delivery Optimization”
Okay so this is all well and good if you’re getting your updates directly from an official Microsoft source. What happens when you’re not?
“Don’t you have to get your updates from an official Microsoft Source?”
Well… yes and no.
Microsoft Connected Cache allows other systems who have downloaded their updates operate as a sort of distributed CDN. By default (on Windows 10 22H2 at least), Delivery Optimization is configured to share update files with peers on the same local network. Buuut there is the ability to download/share updates from other peers over the internet.
Here is a link to a blogpost affiliated with Microsoft on how this can be enabled on the ISP-level. It gives a pretty good introduction on how MCC works in general.
Your patches can come from non-microsoft hosts, so our rules looking at HTTP Host headers and trying to prevent false positives are useless for executables downloaded via MCC. So, how do we work around this?
MCC connections will usually be in the form of a GET
request. The URI will contain the parameter cacheHostOrigin=
followed by the name of a legitimate Windows host that the destination is acting as a proxy for, to download the patch executable or whatever content. with just this information, we can craft another rule that sets the ET.INFO.WindowsUpdate
flowbit.
Suricata:
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"ET INFO Windows Update/Microsoft FP Flowbit M4"; flow:established,to_server; flowbits:set,ET.INFO.WindowsUpdate; flowbits:noalert; http.method; content:"GET"; http.uri; content:"cacheHostOrigin="; fast_pattern; pcre:"/(?:^|\x2e)(?:windowsupdate\x2ecom|update\x2emicrosoft\x2ecom|delivery\x2emp\x2emicrosoft\x2ecom)$/R"; reference:url,techcommunity.microsoft.com/blog/windows-itpro-blog/microsoft-connected-cache-for-isps-microsoft%E2%80%99s-distributed-cdn/3891604; classtype:not-suspicious; sid:4; rev:1;)
Snort:
alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"ET INFO Windows Update/Microsoft FP Flowbit M4"; flow:established,to_server; flowbits:set,ET.INFO.WindowsUpdate; flowbits:noalert; content:"GET"; http_method; content:"cacheHostOrigin="; fast_pattern; http_uri; pcre:"/cacheHostOrigin(?:\x3d|\x3d.+\x2e)(?:windowsupdate\x2ecom|update\x2emicrosoft\x2ecom|delivery\x2emp\x2emicrosoft\x2ecom)$/U"; reference:url,techcommunity.microsoft.com/blog/windows-itpro-blog/microsoft-connected-cache-for-isps-microsoft%E2%80%99s-distributed-cdn/3891604; classtype:not-suspicious; sid:4; rev:1;)
In both instances here, we key off of the cacheHostOrigin parameter in the http uri. Then we use PCRE to kind of emulate the dotprefix
transform for both Snort and Suricata. The reason we can’t use dotprefix
for Suricata here easily, is that dotprefix
transforms the whole sticky buffer, not just the one content match we’re looking for.
That rule also dropped in today’s daily ruleset update. Check out:
2059288 - ET INFO Windows Update/Microsoft FP Flowbit M4 (info.rules)
This false positive was found thanks to our User Community. Its thanks to you reporting to us about your real-world problems that enables us to make rules that are more relevant to your interests, and result in less false positives to sift through.
To submit feedback on our rules, or report problems (False Positives, False Negatives, and everything else therein), join our community forum here or feel free to join us on our Discord channel: EmergingThreats
Sidenote: Of course, these aren’t the only domains your Windows system will talk to to get updates on Microsoft applications. I came across a Microsoft Learning link in the past that describes the multitude of Connection Endpoints that Windows 10 and Windows 11 will connect to for a variety of services.
I had to do a little bit of digging (and rely on colleagues on social media for help finding it again), and wanted to share it here with you, as a point of reference, because its extremely helpful:
Manage Connection Endpoints for Windows 10 Enterprise, Version 21H2