(MS16-104, MS16-105, CVE-2016-3325)
A specially crafted HTTP response can cause the
CHttpHeaderParser::
method in WININET to read data beyond the
end of a buffer. The size of the read can be controlled through the HTTP
response. An attacker that is able to get any application that uses WININET to
make a request to a server under his/her control may be able to disclose
information stored after this memory block. This includes Microsoft Internet
Explorer, Microsoft Edge and Microsoft Windows Media Player. As far as I can
tell WININET is widely used by Microsoft applications to handle HTTP requests,
and probably be all third-party applications that use Windows APIs to make HTTP
requests. All these applications may be vulnerable to the issue, though it
may be hard to exploit in most (if not all, see below).
WININET.
The issue was first discovered in pre-release Windows 10
fbl_release.
Microsoft Internet Explorer
XMLHttpRequest can be used to trigger this issue - I have not tried other vectors. To exploit the vulnerability, Javascript is most likely required, so disabling Javascript should mitigate it.
Microsoft Edge
XMLHttpRequest can be used to trigger this issue - I have not tried other vectors. To exploit the vulnerability, Javascript is most likely required, so disabling Javascript should mitigate it.
Microsoft Windows Media Player
Opening a link to a media file on a malicious server can be used to trigger the issue.
Microsoft has released two bulletins to address this issue, one for Microsoft Internet Explorer and one for Microsoft Edge. I do not know why Microsoft did not mention other applications in their bulletins, nor why they have two fixes for these specific applications, rather than one fix for a component of the Windows Operating System.
One wonders what would happen on a system where you have previously uninstalled both MSIE and Edge: do neither of the fixes apply and will your system be left vulnerable? Let me know if you found out!
The below repro consists of two parts: an HTML file that constructs an
XMLHttpRequest
in order to trigger the issue and a raw HTTP response that
actually triggers it.
When WININET is processing a HTTP 100
response, it expects another HTTP
response to follow. WININET stores all data received from the server into a
buffer, uses a variable to store an index into this buffer to track where it is
currently processing data, and uses another variable to store the length of the
remaining data in the buffer.
When processing the headers of the HTTP 100
request, the code updates the
index correctly, but does not decrement the length variable. When the code
processes the next request, the length variable is too large, which can cause
the code to read beyond the end of the data received from the server. This may
cause it to parse data stored in the buffer that was previously received as
part of the current HTTP response, and can even cause it to do the same for
data read beyond the end of the buffer. This can potentially lead to
information disclosure.
The larger the HTTP 100
response is, the more bytes the code reads beyond the
end of the data. Here are some example responses and their effect:
"HTTP 100\r\n\r\nX" (12 bytes in HTTP 100 response)
=> read "X" and the next 11 bytes in memory as the next response.
"HTTP 100\r\n\r\nXXXX" (12 bytes in HTTP 100 response)
=> read "XXXX" and the next 8 bytes in memory as the next response.
"HTTP 100XXX\r\n\r\nX" (15 bytes in HTTP 100 response)
=> read "X" and the next 14 bytes in memory as the next response.
"HTTP 100XXX........XXX\r\n\r\nX..." (N bytes in HTTP 100 response)
=> read "X" and the next (N-1) bytes in memory as the next response.
This issue is remarkably similar to an issue in HTTP 1xx response handling I found in Google Chrome a while back. That issue allowed disclosure of information from the main process' memory through response headers. I attempted to leak some data using this vulnerability by using the following response:
"HTTP 100XXX........XXX\r\nHTTP 200 X"
I was hoping this would cause the OOB read to save data from beyond the end of
the HTTP 200
reponse in the statusText
property of the XMLHttpRequest
,
but I did not immediately see this happen; all I got was "OK" or an empty
string.
Unfortunately, I did not have time to reverse the code and investigate further myself. All VCPs I submitted the issue to rejected it because they though it was not practically exploitable.
Id: | AVR:OOB[0xAB]+0x5 microsoftedgecp. |
Description: | Access violation while reading memory at 0x6989000; 0x5 bytes beyond a 0xAB byte memory block at 0x6988F50 |
Process binary: | microsoftedgecp. |
Location: | WININET. |
Security impact: | Potentially exploitable security issue |
Id: | AVR:OOB+4*N 917. |
Description: | Access violation while reading memory at 0x1F55E205000; 0/0x0 bytes beyond a 512/0x200 byte memory block at 0x1F55E204E00 |
Location: | microsoftedgecp. |
Security impact: | Potentially exploitable security issue |