Sysinternals Freeware - Mark Russinovich & Bryce Cogswell

Mark's Sysinternals Blog

Popup Blocker? What Popup Blocker?

A couple of weeks ago I came across a site in my web wandering and had a popup. This, despite the fact that I’m running either Avant Browser or Maxthon. Avant Browser and Maxthon are applications that wrap Internet Explorer (IE) with all the features considered mandatory of a modern-day web browser, including tabbed browsing, enhanced popup blocking, advertisement blocking, skinning support, and a configurable search engine. So because I’m running Windows XP SP2 I have two popup blockers at work for me: the one built into XP SP2’s version of IE and that of the browser application.

I assumed that the popup was a fluke of some kind, and because I was busy tracking down some piece of information, I dismissed it and forgot about it until a few days ago when I came across another one at a pretty popular Windows information site. Popups are not only annoyances, but they can bait unsuspecting users into visiting “drive-by-download” web sites that try and deploy malware on a system by exploiting unpatched vulnerabilities in the visitor’s browser. I decided to investigate.

Within a short period of time my research took met to a thread in a discussion group where a poster reported that you can see dramatic example of popup blocker ineffectiveness at a particular URL. Before clicking on the link please note that the page only works on IE, there’s no malware posted on the page and you can terminate the demonstration by closing any of the browser windows:

http://www.malware.com/flopup.html

I was stunned (and a little amused). If you look at the source to the page you see the reference to an ActiveX control class ID:

classid="clsid:2D360201-FFF5-11d1-8D03-00A0C959BC0A"

A little more research revealed this is the GUID for the Microsoft DHTML (MSDHTML) Editor ActiveX control that ships with every copy of Windows. The control is considered safe for scripting by Windows, which means that anybody can generate popups that bypass standard popup blockers by invoking its scripting interface. Here’s the invocation of its script interface that references a script on another page that actually creates the popup window and moves it around:

x.DOM.Script.execScript(shellscript.toString());

This control was the source of a major vulnerability related to cross-domain scripting discovered earlier this year and so has been patched. However, Microsoft chose to leave the basic script support in place and to have it ignore the Windows XP popup blocker settings.

While the DHTML Editor ActiveX control might have been the source of at least one of the popups I’ve seen get through the blockers, there’s a web page that will get popups past not only IE, but Firefox as well. You might have to refresh a few times since the popup generation is random:

http://quotes.freerealtime.com/dl/frt/S

This site uses a number of obfuscation techniques to hide what’s happening. First, it references a script on the advertiser’s (Tribalfusion) web page. In the reference it breakups the word "script", most likely to foil browser add-on script blockers. The trail as to what happens when that script executes went cold for me, but when Bryce Cogswell opened the page in his Firefox browser and used Firefox’s feature that let’s you view the objects loaded on a page he saw the Macromedia Flash object. Firefox by default will let popups generated by addons through, but if you disable that in the Firefox options menu it will stop Flash popups. Here’s a Firefox developer’s blog posting about the problem.

There are likely other ways to generate popups, but those are the two that I’ve run into myself. To be fair, both IE and Firefox let you configure them to either prompt you before executing scripts or other active content, or to block such content altogether. I suspect that the default settings let these types of popups through because blocking them would break legitimate sites.

I’m really surprised that we haven’t seen more use of these loopholes by popup-loving sites, including eweek.com and cnn.com, but I’m sure we will over time. But another annoyance I’ve been running into on a regular basis on these sites is the “popover”. These are DHTML scripts that create floating windows and also slip past popup blockers. While not quite as annoying as popups because they’re restricted to the browser frame they live in, they can also be rendered to look like Windows error dialogs that might take someone to a drive-by-download site when dismissed, and they can block the interesting content on a web page until you dismiss them.

While I encourage Microsoft to include popover blocking in the inevitable next IE hotfix, my hopes aren’t high. On one hand Microsoft is telling consumers that it’s on their side against annoying ads that interfere with web productivity and lure people to malware sites, but on the other hand they give the advertisers ways to get their ads through. Not only that, Microsoft itself is guilty of annoying consumers with the same techniques. Last week when I visited the Microsoft TechNet site to read about one of the patches released this past Patch Tuesday I ran into the popover shown below.

Microsoft needs to come up with a policy regarding web advertising, configure the browser to enforce the policy by default, and adhere to it themselves.

posted by Mark Russinovich @ 10:35 AM (31) comments

An Explosion of Audit Records

One of the topics I cover in the security module of the Windows internals seminar that I teach with Dave Solomon is auditing. I demonstrate object access auditing by enabling failure auditing in the Local Security Policy Editor (which you launch by typing secpol.msc in the Run dialog), removing all access to a folder on the system, adding failure auditing to the folder’s System Access Control List (SACL) in Explorer’s permissions editor dialog, and finally, generating failure audits by attempting to navigate into the directory.

In order to verify that audit records generate I open the Security event log in the Event Viewer. Explorer presents an access denied message box exactly once when I try to open the locked-down directory, so when I performed the demonstration for the first time I expected to see one failure audit record. To my amazement and confusion, however, I saw something like this:



I cleared the security event log immediately before causing the error so the 109 events the Event Viewer reports are in the log are all related to one access denied operation in Explorer. Its no wonder auditing is turned off by default! When one user action generates 109 events it’s pretty easy to craft an attack that effectively deletes the useful contents of the security event log.

Every time I’ve performed the demonstration I’ve glossed over the fact that there are far more events than I expect to see and make a mental note that I should investigate what’s going on. When I finally got around to it my first step was to run Filemon and see what’s happening behind the scenes. Filemon confirmed that Explorer is indeed trying to open the file 109 times:



My next question was of course, why? To get the answer to this I first decided to see how Explorer behaves when I navigate into a directory successfully. I created another directory and opened it with Filemon watching:



After trying the experiment a few times I realized that the file access attempts occur when I click on the folder, not when I try and navigate into it. It looks like Explorer checks for the presence of several variants of “summary information” alternate data streams on the directory. Not only that, but it looks like it checks for the same ones over and over. These summary information streams are the same ones that Explorer creates when you enter information on the summary tab of a file’s properties dialog box:



If you watch Explorer query a file when you open a file’s properties with Filemon you’ll see the same alternate data stream queries we saw it execute on the locked-down folder:



Several questions remained open to me at this point. First, why is Explorer even looking for properties on a folder when a user simply selects the folder? Second, Explorer doesn’t present the Summary tab in the properties dialog box for folders, so why does it expect to find properties on a folder? Finally, why does it try to read the same streams repeatedly, even in the face of errors?

A hypothesis that addresses the first two questions is that the distinction between files and folders with respect to displaying summary information tabs on properties dialog is at a higher layer than the code that checks for the presence of the summary information streams. Besides allowing you to configure columns that show summary information in its Details view, Explorer shows the information in the tooltip it pops open if you hover the mouse over a selected item long enough. It must be attempting to gather that information ahead of time.

I figured a look at Explorer’s stack during one of the stream queries might shed some light on the other third question. I couldn’t simply set a breakpoint on CreateFile, the API used to open files, because that’s one of the most commonly used APIs on a system. Instead, I set the breakpoint on SepOpenAuditAlarm, the kernel-mode Security Reference Monitor function that NTFS calls when it wants to write an event to the security event log. Here’s part of the stack trace that I got:



The highlighted frame is the one that shows the name of the function, CPropStgColumns::GetItemData, that kicks off the repeated queries. Its name confirms that it has something to do with the Details view columns and likely the tooltip, but the trace doesn't explain why its querying the same streams repeatedly or why it keeps trying when the access denied errors should cause it to give up.

Anybody from the Shell team out there?

posted by Mark Russinovich @ 5:39 PM (21) comments

Buffer Overflows in Regmon Traces

Last time I talked about buffer overflow errors that you might see in Filemon traces. Now I’ll turn my attention to the same errors, but in Regmon traces. Recall that a buffer overflow error in this context is not a security hole, but a way for the system to tell an application that there’s more data available in response to a query the application has made than can fit in the application’s output buffer. A commenter on the previous post pointed out that a better error for this case would be “buffer too small” or “more data available”, and I agree. There is in fact a STATUS_BUFFER_TOO_SMALL error code, but it’s used in situations where no data is copied to the caller’s buffer, whereas STATUS_BUFFER_OVERFLOW is used when some, but not all, available data has been copied.

Buffer overflow errors in Regmon traces are relatively common. The documentation for RegQueryValueKey says:

If the buffer specified by lpData parameter is not large enough to hold the data, the function returns ERROR_MORE_DATA and stores the required buffer size in the variable pointed to by lpcbData. In this case, the contents of the lpData buffer are undefined.

If lpData is NULL, and lpcbData is non-NULL, the function returns ERROR_SUCCESS and stores the size of the data, in bytes, in the variable pointed to by lpcbData. This enables an application to determine the best way to allocate a buffer for the value's data.


There are two programming approaches commonly taken to reading variable-length Registry data. The first is to simply pass in a NULL pointer on the first call and if the call succeeds to allocate a buffer for a second query. The other approach is for an application to first try and use a static buffer of a size that the programmer expects will usually be large enough to receive the stored data. If the system reports ERROR_MORE_DATA, which is the Windows API equivalent of the native STATUS_BUFFER_OVERFLOW error, the application dynamically allocates a buffer of the required size and re-executes the query. The second approach has the advantage of avoiding a second query in most cases.

Given these approaches you should never see two buffer overflow errors in a row that query the same data. At least that’s what you’d expect, but on many occasions I’ve seen two buffer overflow errors followed by a third query of the same data that succeeds. Here’s an example I see on a Windows XP SP2 system that results when I open My Computer:



I decided to investigate this particular case as I was writing this blog posting. First, I started SoftICE and set a breakpoint on NtQueryValueKey. When the breakpoint triggered I single-stepped in SoftICE to the return instruction, at which point the status of the query is stored in the EAX register. I then cleared the first breakpoint, and set a conditional breakpoint on the return instruction for the case that the result is STATUS_BUFFER_OVERFLOW (0x800000005):

bpx _NtQueryValueKey+0346 IF eax==80000005

Then I opened My Computer and this is the stack at first buffer overflow breakpoint:



A look at the parameters Shlwapi passes into RegQueryValueExA revealed a NULL buffer pointer. I stepped back out into Shlwapi’s code and saw that if RegQueryValueExA returns ERROR_SUCCESS, which is the error code to which RegQueryValueExA translates STATUS_BUFFER_OVERFLOW if the caller uses a NULL buffer pointer, Shlwapi dynamically allocates a buffer of the required size and makes the call again:



Shlwapi makes one call into RegQueryValueExA, but two entries get added to Regmon's trace, one with a buffer overflow and one that's successful. Stepping into Advapi32’s implementation of RegQueryValueExA showed me why the second call results in two Registry queries in the Regmon trace. NtQueryValueKey returns a data structure storing several different pieces of information regarding the Registry value, including its type, length and title index:

typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
ULONG TitleIndex;
ULONG Type;
ULONG DataLength;
UCHAR Data[1]; // Variable size
} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;

However, RegQueryValueExA returns only the actual data into the caller's output buffer. RegQueryValueExA (and RegQueryValueExW) therefore uses a 144-byte stack-allocated buffer to query the value. This is the place in Advapi32 where RegQueryValueExA makes that call:



The first instruction in the disassembly is RegQueryValueExA loading the address of NtQueryValueKey into the ESI register. 144 is represented as 0x90 in hexadecimal, which you can see loaded into the EDI register and then passed as the fifth parameter to NtQueryValueKey, which corresponds to the output buffer size.

The additional value information included in the KEY_VALUE_PARTIAL_INFORMATION structure requires 12 bytes, so if the data being read is larger than 132 bytes NtQueryValueKey returns STATUS_BUFFER_OVERFLOW. If the caller’s buffer is large enough to store the data RegQueryValueExA allocates a buffer large enough to hold it and then executes the call to NtQueryValueKey again. After getting the data RegQueryValueExA copies it to the caller’s buffer.

When I saw the double-buffer overflows in the Regmon trace I thought it was evidence of poorly-written code, but my investigation showed that the pattern will be present in an application that reads Registry values larger than 132 bytes in size. What I don’t know is why the Windows API developers picked 132-bytes as the magical buffer size they expected would hold most Registry data.

On an unrelated node, I’m going to be in Orlando this week speaking at TechEd and delivering a Windows internals seminar with Dave Solomon. If you are attending either please let me know you read the blog. If you can’t make TechEd you can still catch my Understanding and Fighting Malware: Viruses, Spyware and Rootkits presentation the afternoon of Tuesday, June 7, via live web cast. Sign up here: http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032274949&Culture=en-US

posted by Mark Russinovich @ 8:20 PM (6) comments

This page is powered by Blogger. Isn't yours?

RSS Feed

RSS
    2.0

Index

Full Blog Index

Recent Posts

The Power in Power Users
Why Winternals Sued Best Buy
The Case of the Mysterious Driver
Running as Limited User - the Easy Way
Using Rootkits to Defeat Digital Rights Management
Inside the WMF Backdoor
Rootkits in Commercial Software
The Antispyware Conspiracy
Sony Settles
Circumventing Group Policy as a Limited User

Archives

March 2005
April 2005
May 2005
June 2005
July 2005
August 2005
September 2005
October 2005
November 2005
December 2005
January 2006
February 2006
March 2006
April 2006
May 2006

Other Blogs

Raymond Chen
Dana Epp
Aaron Margosis
Wes Miller
Larry Osterman
Bruce Schneier
Larry Seltzer