It rather involved being on the other side of this airtight hatchway: Invalid parameters from one security level crashing code at the same security level (doesn’t get old)


We received a very professional security vulnerability report from a video driver manufacturer which reported a security vulnerability in DirectX. You can tell it's a professional operation because the vulnerability report took the form of a neatly-formatted PowerPoint presentation with corporate logos in every corner. Unfortunately, you'll have to make do with my distillation into boring text.

An attacker program can pass intentionally invalid buffers to various DirectX functions, resulting in a number of identified vulnerabilities, of which the !exploitable debugger extension classifies several as high severity.

The root cause of all of the vulnerabilities is that the functions in question are passed buffers and sizes which are not validated. The functions read from or write to these improperly-sized buffers, which can result in memory corruption and potential remote code execution, information disclosure, data tampering, denial of service, and the collapse of Western civilization.

For example, the IDirect3D­Resource9::­Set­Private­Data method does not verify that the SizeOfData is correct. If SizeOfData is larger than the actual size of the data, then DirectX will perform an invalid pointer read beyond the end of the buffer. This can be used to extract information from memory managed by DirectX, resulting in information disclosure.

Similarly, the IDirect3D­Resource9::­Get­Private­Data method does not verify that the *pSizeOfData is correct. If *pSizeOfData is larger than the actual size of the data, then DirectX will perform an invalid pointer write beyond the end of the buffer. This can be used to corrupt memory managed by DirectX, leading to further exploits.

There is no vulnerability here yet because there is no elevation. I mean, sure, the attacker can pass bogus buffers and trick DirectX but let's take a closer look at who the attacker is and who the victim is.

The attacker is a rogue program that is intentionally passing invalid buffers to DirectX. DirectX runs in-process and tries to read data from or write results to those buffers. The attacker can trick DirectX into reading or writing past the end of the buffer by lying about the buffer size.

void UseDirectXToReadPastEndOfBuffer()
{
  direct3dResource9->SetPrivateData(
    GUID_Attack,
    buffer,
    incorrectSize,
    0);
}

void UseDirectXToWritePastEndOfBuffer()
{
  DWORD size = incorrectSize;
  direct3dResource9->GetPrivateData(
    GUID_Attack,
    buffer,
    &size);
}

But so what? The attacker can already do that without needing to trick DirectX into doing anything.

void JustReadPastEndOfBuffer()
{
  memcmp(buffer, buffer, incorrectSize);
}

void JustWritePastEndOfBuffer()
{
  memset(buffer, 0, incorrectSize);
}

Using DirectX to read memory from within your process is just adding style points. You aren't doing you can't already do. You're just going through a middle man and then blaming the middle man.

Of course, one must verify that corruption or exposure of data within the process causes no damage beyond the process. If the corrupted data crosses a security boundary (e.g., gets passed to a kernel mode video driver), the recipient of the data must be resilient to intentionally invalid parameters.

The !exploitable debugger extension classifies these failures as high severity because it is looking at the world through data fuzzing-colored glasses. It's assuming that all the data upon which the program is operating is potentially untrusted, and it's assessing how bad it would be if an attacker could trigger this crash by giving your application an intentionally corrupted file. In other words, the !exploitable debugger extension assumes that the program is trusted but it is operating on untrusted data. Any crashes are assumed to the result of the trusted program mishandling the untrusted data.

From that standpoint, these are indeed severe errors if a corrupted file can trick your application into passing incorrect buffer sizes to DirectX. And that's the bug you need to fix in the program: Make sure your program passes correct buffer sizes regardless of the contents of the file being parsed.

But if the program itself is the attacker, then we have another instance of MS07-052: Code execution results in code execution.

Previous discussion:

Comments (25)
  1. Darran Rowe says:

    This interestingly shows how confusing all of this stuff around security can be, if even large companies can do it.

  2. Joshua says:

    /me takes note

    I think I just found a way out of the WinRT sandbox that the auto-analyzer can’t find.

    1. Myria says:

      I don’t understand. WinRT applications really *are* in a sandbox enforced by the NT kernel (“lowbox token”), so if you can escape the WinRT sandbox, you would be crossing a security boundary with a real exploit.

      1. Joshua says:

        Modern UI is unusable to me. The bug filed against Windows 8 stands yet unfixed. Unless I find a solution that allows CreateWindowEx(…, HWND_DESKTOP, …) to succeed RT might as well not exist at all.

        1. Anon says:

          If you want to write a desktop app, write a desktop app. If the “bug” is that you can’t escape the WinRT sandbox, that’s not a bug. That’s literally the only purpose of the sandbox.

          1. Joshua says:

            The bug is a font rendering flaw in Modern UI.

            Can you write a desktop app for RT without using an exploit yet?

        2. DWalker says:

          Your messages are confusing. If the Modern UI is “unusable” to you, that’s fine. Don’t use it.

          I have no idea what you mean by “the bug filed against Windows 8 stands yet unfixed”. Which bug? If you mean the font rendering flaw that you mentioned later, I predict that a font rendering flaw in Windows 8 is not high on Microsoft’s list of things to fix right now, in late spring 2016. Windows 8 likely won’t get much attention.

          “A way out of the WinRT sandbox that the auto-analyzer can’t find” is also confusing. If you can get out of the WinRT sandbox under running code, that’s noteworthy. If the auto-analyzer doesn’t point it out, then that’s perhaps a problem in the auto-analyzer.

          “Can you write a desktop app for RT without using an exploit”. Who is “you”? Do you mean ANYONE? Do people generally use exploits to write desktop apps “for RT”?

          Maybe I shouldn’t feed you….

        3. Klimax says:

          I see you mentioned later “font rendering” bug, but what is the nature, what is repro of it and how does it manifest.. Does it affect Windows 8.1 or not (aka Windows 8.0 only) and does it repro on Windows 10? I got few projects for WinRT, Universal Apps, so I am curious what are you talking about.

          1. Joshua says:

            Try turning off anti-aliasing altogether. It doesn’t work. But I must turn it off.

          2. Klimax says:

            Pretty sure not a bug. (aka by design) Second, why? You are still leaving many questions unanswered. I hope you reported design oversight far better then that.

  3. Nico says:

    Isn’t the usual concern these days about remote attacks, usually proxied by a web browser? So for example:

    IE^H^HEdge gets a webpage from evil.com with Javascript that creates a canvas element. Edge uses Direct2D for canvas. The Javascript somehow gets Edge to pass the wrong buffer size which causes DirectX to read past the array and into SekritMemoryData[]. This is returned to the browser as a bag of bytes, and returned to the server via an async call.

    Combine this with memory pressure (http://www.theregister.co.uk/2015/04/21/cache_creeps_can_spy_on_web_histories_for_80_of_net_users/) or something and maybe you can get the data you want. Or execute code. Or something.

    Or not.

    1. pc says:

      And if Edge does pass the wrong buffer to DirectX, that’s a security bug in Edge, not in DirectX.

      1. Falcon says:

        Exactly – Edge (or its Javascript interpreter) is the one operating with untrusted data. The Javascript code presumably doesn’t even have access to the DirectX API – otherwise it wouldn’t work on platforms without DirectX.

  4. henke37 says:

    There isn’t a tag for these posts yet?

  5. Alan says:

    My experience that when someone sends you an unsolicited PowerPoint deck to read, one can safely delete it unread.

    1. Anon says:

      If your job is to read unsolicited documents sent by customers, that’s also a great way to get fired.

  6. Falcon says:

    Maybe they could share some wisdom with us on how to validate the size of a (void *)?

  7. Scarlet Manuka says:

    “You can tell it’s a professional operation because the vulnerability report took the form of a neatly-formatted PowerPoint presentation with corporate logos in every corner. Unfortunately, you’ll have to make do with my distillation into boring text.”

    But you’re so good with the HTML fake images and such! Couldn’t you have rigged up at least a few pretend logos? I really feel like I’m missing out now.

    Not even bullet points on the list? C’mon, throw us a bone here.

    (no, not really)

  8. Mason Wheeler says:

    So basically you’re saying that vulnerabilities that don’t involve privilege escalation aren’t real vulnerabilities?

    Out of curiosity, have you seen http://www.xkcd.com/1200/ ?

    1. Kemp says:

      Bad program behaviour != security vulnerability. In general, without elevation all you’re doing is finding a novel way to do something that your program could already do anyway. Remember, “security vulnerability” doesn’t mean the program gives out your gmail password, it means that the program allows your machine to be compromised in a way that your user account permissions should prevent.

    2. ChDF T says:

      I think Raymonds point is, that the caller of the DirectX API can do the same things directly, without calling DirectX APIs at all. Therefore this behavior isn’t a vulnerability *in DirectX*. The post isn’t about whether this is a security vulnerability, but where the vulnerability is.

      1. smf says:

        I’m not sure this even counts as a security vulnerability, they are passing the wrong size for a buffer. It’s only a vulnerability if a user of the software has control over the size of the buffer, this is just a bug.

    3. Aurora says:

      Basically, yeah. Raymond is saying that trusted code causing a crash in the same “security context” is not a security issue, because that doesn’t cross any security boundaries.

      That xkcd is completely irrelevant. Privilege escalation isn’t only from a user account to an admin account. Something like Javascript code in a browser getting the full permissions of the user account also counts would be an actual exploit, because then the Javascript code can do something it’s not supposed to be able to do. In this case, the program is using an “exploit” to do something it was already supposed to be able to do (read/write to its own process’ memory), something which is not very interesting at all.

  9. Joop says:

    “MS07-052: Code execution results in code execution” is such a great and funny summary! :D And nice that you linked to the original author’s comment.

    1. Brian says:

      And as the original author of that comment (nine years ago!) I still get a chuckle when I read Raymond’s deconstruction of these dubious vulnerabilities… doubly so when he drops the MS07-052 on them.

Comments are closed.

Skip to main content