Security Research & Defense

Information from Microsoft about vulnerabilities, mitigations and workarounds, active attacks, security research, tools and guidance

April, 2008

  • MS08-025: Win32k vulnerabilities

    MS08-025 addresses several vulnerabilities in win32k.sys where you can execute arbitrary code in kernel mode. These bugs can only be exploited locally and there is no remote vector we are aware of.

    One of these vulnerabilities deals on how we can bypass some of the ProbeForWrite and ProbeForRead checks when using user supplied memory pointers.

    ProbeForWrite/Read are functions that will check if a provided address range (base + length) has the following properties (throwing an exception in case it fails):

    ·         The range is inside the user mode virtual memory space.

    ·         ProbeForWrite will check if the range is writable.

    ·         By design, if the length of the range equals to zero, ProbeForRead and ProbeForWrite will not throw an exception and the normal flow of this request will be taken (the range will be validated).

    Find out more information about these functions at: http://msdn2.microsoft.com/en-us/library/ms809962.aspx and http://msdn2.microsoft.com/en-us/library/ms790786.aspx

    In the case of this bulletin, using a specially crafted request to win32k from user mode we can overflow the length variable, which can then take the erroneous value of zero, leading to the probing function being bypassed.

    One of the approaches that we could have taken was to fix these functions and throw an exception when we receive a zero length. This was not a good approach since it will break lots of interfaces. On win32k there are some functions that upon receiving a zero length they will return with the needed length for a correct request. Updating the probe functions to blindly reject zero length values would break these usages.

    Instead we decided to check each of the probes looking for integer overflows that will lead to length zero. These are the cases we and drivers developers need to take care of:

    // lParam and wParam are untrusted DWORDs since they come from user mode
    
    try {
            str.bAnsi = bAnsi;
            str.MaximumLength = (ULONG)wParam;
            if (!bAnsi) {
                str.MaximumLength *= sizeof(WCHAR);   // we can overflow this max length and lead to zero
            }
    
            str.Length = 0;
            str.Buffer = (LPBYTE)lParam;
    
            ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, sizeof(BYTE));
        
        } except (StubExceptionHandler(FALSE)) {
              MSGERROR(0);
        }
    
     [... later write into str.Buffer pointer based on wParam ...]
    

    As you can see we bypass the ProbeForWrite check with the overflow (wParam = 0x80000000 that leads to str.MaximumLength = 0). Once this check has been passed, it depends on the function we are targeting but a ProbeForWrite seems like later we are going to write to the supplied pointer (lPram).

    And these are the cases where we can have a legitimate use of zero length on the probe:

    // lParam and wParam are untrusted DWORDs since they come from user mode
    
    try {
            str.bAnsi = bAnsi;
            str.MaximumLength = (ULONG)wParam;
    
            str.Length = 0;
            str.Buffer = (LPBYTE)lParam;
    
            ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, sizeof(BYTE));
        
        } except (StubExceptionHandler(FALSE)) {
              MSGERROR(0);
        }
    
        if (str.MaximumLength==0) {
                   retval = STATUS_BUFFER_TOO_SMALL;
                  *size_needed= sizeof(struct_to_copy_from);
                  return retval:
        }
    
    [... later checks for the size needed may apply ...]
    

    In this case it is by design on some API that if you pass a zero length the call will fail and you will get back the needed size for this particular API call.

    - Security Vulnerability Research & Defense Bloggers

    *Postings are provided "AS IS" with no warranties, and confers no rights.*

  • MS08-023: Same bug, four different security bulletin ratings

    Security bulletin MS08-023 addressed two ActiveX control vulnerabilities, one in a Visual Studio ActiveX control and another in a Yahoo!’s Music Jukebox ActiveX control.  The security update sets the killbit for both controls.  For more about how the killbit works, see the excellent three-part series (1, 2, 3) from early February in this blog.

    One interesting thing you might notice about this bulletin is the diversity of severity ratings between different platforms.  Windows 2000 and XP are rated Critical.  Windows Vista is rated Important.  Windows Server 2003 is rated Moderate.  And Windows Server 2008 is rated Low.  The same bug on different platforms got four different security bulletin ratings!  We thought this might raise some questions so we decided to explain a little more about how the rating system works for browser-based vulnerabilities.

    We rate browser-based vulnerabilities Critical when they allow drive-by code execution.  Internally, we refer to them as “browse-and-you’re-owned”.  Simply browsing to the website (or being redirected there via iframe) is enough to trigger the vulnerability – no prompts, no gold bar, nothing but browsing is necessary.  In this specific case of MS08-023 on Windows XP SP2, users who have the ActiveX control installed are vulnerable to drive-by attack.  And even if the ActiveX control is not already installed, an attacker can serve it to the browsing user.  Because this control was signed by Microsoft, if a user had previously chosen to always install software from Microsoft, they will not be prompted.  The security warning dialog below shows how a user could choose to always install software from Microsoft.

    IE7 on Vista requires a user to “opt-in” to ActiveX controls they want to run.  If an ActiveX control is not included on the opted-in list, it will not run.  We do not expect users will have opted-in to use this Visual Studio ActiveX control (most of you probably have never even heard of it), so the Vista MS08-023 rating is Important.  You can see what the ActiveX opt-in gold bar looks like below.

    Windows Server 2003 ships with the Enhanced Security Configuration (ESC) enabled. Browsing with the ESC enabled prevents any scripting or ActiveX controls from being run (and also enables other browser hardening suitable on a server).  With the ESC enabled, the MS08-023 vulnerabilities are not reachable.  You’d have to explicitly turn this security setting off, and so we’ve rated this issue Moderate. You can see the Enhanced Security Configuration dialog below.

    Windows Server 2008 includes both the above mitigations.  It ships with IE7 so it gets the IE7 ActiveX opt-in by default.  And it also ships with the Enhanced Security Configuration feature enabled.  The ESC drops the rating from Critical to Moderate.  The IE7 ActiveX opt-in drops it one more notch from Moderate to Low.    

    - Security Vulnerability Research & Defense Bloggers

    *Postings are provided "AS IS" with no warranties, and confers no rights.*

  • MS08-020 : How predictable is the DNS transaction ID?

    Today we released MS08-020 to address a weakness in the Transaction ID (TXID) generation algorithm in the DNS client resolver.  The TXID is a 16-bit entity that is primarily used as a synchronization mechanism between DNS servers/clients; in fact, you can think of it as an Initial Sequence Number (ISN) for DNS query/response exchanges.  Consequently, the TXID is intended to be somewhat random and difficult to predict.  If both the TXID and hostname are predictable, an attacker can forge malicious DNS replies which the DNS client resolver will believe to be from the legitimate DNS server.  The client would then use the spoofed information to make an outbound connection to a (potentially) attacker-controlled IP.

    We wanted to explain a little more about the weakness to help you recognize potential attacks on the wire.  Remember that an attacker needs to match the request TXID exactly in the spoofed response before the legitimate DNS server replies with a valid response.  This was facilitated by our previous implementation of this PRNG algorithm being weak and hence vulnerable to prediction attacks.  Given the previous consecutive TIDs, x_n, x_{n+1}, x_{n+2}, the attacker may be able to determine the PRNG state and predict x_{n+3}, x_{n+4}, … with a high degree of confidence.  The old TXID generation algorithm was as follows (revised pseudo-code for technical accuracy):

          GlobalSeed++;
    SomeNumber = (WORD)GetTickCount()+(SomeRandomAddress>>6)+GlobalSeed;
    SomeNumber = (SomeNumber%487)+1+GlobalLastTXID);
    GlobalLastTXID = SomeNumber;
    XID = SomeNumber^XIDMask;

    Below is a log of sequential TXID’s sent from the old client resolver.  Notice the predictable patterns that develop in bit positions 4,5,6,7 and 8.

    As you can see, attackers cannot predict a guaranteed, known-next TXID exactly even with this weakness.  But limited entropy in those middle bits does cut down the search space substantially to predict the next TXID.  If you are watching for attacks on the wire, continue to look for the same pattern as previous DNS spoofing attacks: a steady flood of DNS “replies” with thousands of different TXID’s targeting a client lookup for a single host. 

    To address this weakness, we simply replaced the algorithm with a cryptographically secure PRNG: CryptGenRandom().  You can read about how it works at http://msdn2.microsoft.com/en-us/library/aa379942(VS.85).aspx.

    Blog Update - April 29: Revised pseudo code above for technical accuracy.

    - Security Vulnerability Research & Defense Bloggers

    *Postings are provided "AS IS" with no warranties, and confers no rights.*