Home / Vulnerabilities / Bypassing the patch to keep spoofing the Smartscreen/Malware warning (Edge)

Bypassing the patch to keep spoofing the Smartscreen/Malware warning (Edge)

Yesterday, Microsoft pushed a gigantic update where tons of security bugs were fortunately killed, including most ones from this website. Kudos, big kudos to the Edge developers and the ones in charge of its security. Please, convince the ones who want to keep the ridiculous IE policies to change their minds or at least publicly explain why they don’t care about IE, at all. Kill it or protect it.

Bug hunter, if you haven’t seen the original bug, please do so before reading the post below which explains how to bypass the patch.

[ Update: this bug was patched on 2017-05-09 by also bypassed the same day ]

New PoC [2017-05-09]


Super Quick Recap

MS Edge allowed us to load some of its internal resources including html pages like acr_error.htm but it did not not allow us to load BlockSite.htm. Why? Because this last page can be easily used to spoof the internal malware warning message and the address bar. We bypassed that restriction a few months ago by changing a dot from the URL to its escaped counterpart %2e and now it has been patched. Edge developers are decoding (unescaping) our tricky URL before doing the check/string comparison, so, we need to find another way. Come on bug hunter! Close that facebook tab which is distracting you, taking your time for nothing. Close it and let’s dive into this fascinating ocean of super-interesting bits.


No symbols today

Microsoft did not upload many of their public symbols yet so our analysis won’t be as pretty as it could have been in a week (once symbols are up). But no worries because we will try to bypass this anyway, just keep in mind that we will go straight to the point using the attacker’s approach: we just want to bypass the patch and that’s it. I don’t imagine an attacker thinking “oh, I need to take a week off because Microsoft didn’t push the symbols yet“.


Finding the string “blocksite.htm”

We know that somewhere in the gigantic Edge code there has to be a string comparison against BlockSite.htm, so we will attach to Edge, find that string and set a breakpoint on memory access to see which code tries to read it.

The following JavaScript code throws an ACCESS_DENIED without even opening the new window.

Edge is blocking this internal URL for a good reason: this particular error page accepts arguments in the hash/query-string allowing the attacker to spoof the address-bar and content of the page.

Our goal is to open that URL fooling Edge again. However, for this task we will use the following URL (encoded dot and facebook at the end so we can later recognize our own string in memory)

Let’s attach to Edge and find the string BlockSite.htm limiting our search to the EdgeHtml.dll module, where most Edge code resides. It’s just a guess and if we don’t find anything we will try other modules or even grep all Edge files.

Once attached to the correct Edge process, we will need to know the Edge module start/end address so we can do our search only in that memory range.

Now we will feed the search command with that address range and the string that we are interested in. WinDbg syntax is intimidating for me but I can tell you that the instruction below is doing a search s and returning only the addresses [1] of a unicode string u between those ugly 64bit addresses. Ahh! the string is BlockSite.

Nice. It seems WinDbg immediately returned three addresses. Let’s see if it got them right. Du du du. Like Dudú, my friend Eduardo who is nicknamed “Dudú”.

I’m getting excited. We will set a breakpoint on memory access on those three addresses. We want to find out who is accessing that string.

Excellent. Now let’s go to our JavaScript code and try to open our malicious (buuhh!) URL.

Wow! Immediate breakpoint. We are back into WinDbg. Let’s see what we have.

It seems that we are in a kernelbase module right now but our goal is to find out which code of the EdgeHtml module referenced this string. Let’s take a look at the latest 5 calls in the stack trace.

The first two belong to the kernelbase module, but the following one comes from edgehtml. To be clear, a piece of code from the edgehtml has called the function StrStrIW from the kernelbase module/library which seems to be pretty standard. A quick Google search for StrStrIW takes us to the function documentation on MSDN:

The documentation is pretty clear and thanks to the stack-trace, we know that edgehtml is calling this function. Let’s set a breakpoint into the Edge returning address to analyze the code before that point. (By the way, we can arrive to the same point using a “step to next return” twice (pt). Experiment!)

Bang! We immediately break here

But we are just coming back from the string comparison, so let’s look a bit up to see what happened. In WinDbg we can quickly unassemble backward (ub)

Great. Unfortunately we don’t have all the symbols here so everything looks a bit ugly. But no worries, we know we’ve just returned from the call above (the latest line) right? And before that call, there are two arguments being passed, one in rdx and another one in rcx (those two lea). But we have no idea what’s there at this point because the call already executed and those values could have been changed. Let’s examine this closer by setting a breakpoint in the latest call (so it does not execute) and once we are there examine its arguments:

Now we will have a chance to see exactly what’s there before the comparison. Run the same JavaScript statement

Which fires the breakpoint just before doing the string comparison.

Let’s inspect the arguments passed to the StrStrl function:

Aha! We can see here that our %2e (the dot) has already been decoded (it’s a dot instead of our %2e). It seems to me that Edge calls the StrStrl function and then checks if “/assets/errorPages/BlockSite.htm” exists in our URL. Not sure, the following pseudoCode is what I believe at this point:

It is important to remember that we are speculating here, because in reality we haven’ts seen yet any check after this comparison, but because we do have the comparison in front of our eyes, we expect that to happen soon. However, we don’t care too much as long as we can bypass this again, using a similar technique.

The main issue here is that the comparison checks against a hardcoded string but we know URLs can be written in many different ways. Our previous trick was to encode a dot but now we should think of a new one because we know we are being unencoded, and we know the exact string comparison being done.

Many ideas come to my mind like multiple encoding or adding more slashes to the URL. Let’s try by adding a slash in the middle which will fool the string check but hopefully will work as a valid URL. So, we will add a dash after errorPages, just like this:

Wow! It seems a simple double slash bypasses the patch but still, Edge is able to load the URL. Let’s build a better query-string now to completely spoof the malware-page, just as we did before.

Check out the PoC Live on Edge

Bug hunter, there are more bypasses coming! Stay tuned and please don’t waste your precious minutes looking at your friend’s vacation pictures :). Close that Facebook tab.

Have a nice day!