Corrupted file causes application to crash; is that a security vulnerability?


A security vulnerability report came in that went something like this:

We have found a vulnerability in the XYZ application when it opens the attached corrupted file. The error message says, "Unhandled exception: System.OverflowException. Value was either too large or too small for an Int16." For a nominal subscription fee, you can learn about similar vulnerabilities in Microsoft products in the future.

Okay, so there is a flaw in the XYZ application where a file that is corrupted in a specific way causes it to suffer an unhandled exception trying to load the file.

That's definitely a bug, and thanks for reporting it, but is it a security vulnerability?

The attack here is that you create one of these corrupted files and you trick somebody into opening it. And then when they open it, the XYZ application crashes. The fact that an Overflow­Exception was raised strongly suggests that the application was diligent enough to do its file parsing under the checked keyword, or that the entire module was compiled with the /checked compiler option, so that any overflow or out-of-range errors raise an exception rather than being ignored. That way, the overflow cannot be used as a vector to another attack.

What is missing from the story is that nobody was set up to catch the overflow exception, so the corrupted file resulted in the entire application crashing rather than some sort of "Sorry, this file is corrupted" error being displayed.

Okay, so let's assess the situation. What have you gained by tricking somebody into opening the file? The program detects that the file is corrupted and crashes instead of using the values in it. There is no code injection because the overflow is detected at the point it occurs, before any decisions are made based on the overflowed value. Consequently, there is no elevation of privilege. All you got was a denial of service against the XYZ application. (The overflow checking did its job and stopped processing as soon as corruption was detected.)

There isn't even data loss, because the problem occurred while loading up the corrupted file. It's not like the XYZ application had any old unsaved data.

At the end of the day, the worst you can do with this crash is annoy somebody.

Here's another way you can annoy somebody: Send them a copy of onestop.mid.

Comments (39)
  1. anonymouscommenter says:

    "At the end of the day, the worst you can do with this crash is annoy somebody."

    Are you sure?  I read a while back that the Firefox team considers any instance in which input can cause an unexpected exception to be raised to be a full pwned-the-system vulnerability, because the exception unwinding can leave the program in an unexpected state which can then be exploited.  (Apparently it's happened a number of times already.)

    Granted, the fact that in this particular case the exception is unhandled and it ends up crashing the whole program makes that appear much less likely, but even so...

  2. anonymouscommenter says:

    Well, there might be data-loss iff that application can have multiple files open at the same time.

    Seems not to be the case here though...

  3. anonymouscommenter says:

    If it were Word I'd be complaining about a DoS bug because it brought down all 8 or so open documents when it crashed.

  4. anonymouscommenter says:

    "unexpected exception"

    I'm struggling with the concept of an expected exception.

  5. @Mason Wheeler: This is true if the exception is caught somewhere and the application decides to just keep going, sure.  Something went wrong and unless you can guarantee your internal structures are still valid, you should terminate.  In this case, the application terminates because it elected not to catch the exception, so there's no chance for this to be exploited.

  6. anonymouscommenter says:

    If exception unwinding leaves the program in an unexpected state, that means the called functions don't even provide the basic guarantee. In that case, Firefox shouldn't be using exceptions in the first place.

    Also, I feel that exceptions in C++ are a whole different beast than exceptions in managed code, anyway.

  7. anonymouscommenter says:

    @Mason Wheeler: Firefox is written in C++, which is a significantly scarier language than C#.  If something unexpected happens, there's a good chance you've invoked UB at some point, and if you're invoking UB, it is entirely possible the system really is pwned.  This is less true of C#.

  8. anonymouscommenter says:

    @Craig: Expected exceptions happen all the time.  For example, a File Not Found (or its network equivalent, the failure to resolve a server from DNS) might easily raise an exception that your code is prepared to deal with.

  9. anonymouscommenter says:

    @Craig & @Mason Wheeler

    Agree with Mason.  When doing any sort of database operation, one truly must expect exceptions (e.g., field has a NULL value even though it is supposed to always have a value).

  10. anonymouscommenter says:

    @12BitSlab: But then such an exception is nothing more than a glorified error code.

  11. anonymouscommenter says:

    @ creaothceann    

    Regardless of terminology, exceptions happen often when dealing with database.  If one is not prepared to deal with them, one will not be developing code for very long.

  12. anonymouscommenter says:

    Back on topic, I don't see this as a security problem.  Even if it was a MDI type of application that can handle multiple documents as a time, the worst thing that could happen is to have some data loss.  There is zero possibility (or at least near zero since we do not know which application it is) of data being exfiltrated or installing code on the host or privilege escalation.

  13. anonymouscommenter says:

    Well, when you're sending out notifications of "vulnerabilities" for a "nominal subscription fee", the validity of the so-called vulnerabilities don't matter as much as how many you report and how scary they sound. After all, most people likely to fall for that probably don't have the expertise to properly evaluate the issue, and they've got to generate plenty of scary-sounding reports to make people feel like they're getting their money's worth from that scam!

  14. anonymouscommenter says:

    "Here's another way you can annoy somebody: Send them a copy of  onestop.mid."

    There's no need, since, you know, everybody running Windows has a copy already. Just the path is enough.

  15. Dave Bacher says:

    That looks like C# to me (or another CLR language), since it's reporting a System.OverflowException on a CLR type.

    Is the app designed to fail secure or to fail open?

    For example -- pretend there's an email client, and it spools all messages to disk and tags them neutral by default.  As each message is received, it spawns a thread that does a DKIM, S/MIME and/or PGP/GPG verification of the message, and then it marks the messages as untrusted if that fails.

    That is a "fail open" scenario -- so pretend this Overflow happens while parsing the security information; the message won't be flagged "untrusted," and the program will termiante.  When the program is restarted, the message will appear in the list -- and won't be (correctly) marked untrusted due to the issue.

    Another typical issue is tombstoning -- the app spools the corrupt file it's been handed to isolated storage, so that it can restore after a tombstone.  The crash happens, and you restart the app -- and it tries to be a good citizen and put you back where you were.  And then crashes again.

    Data loss?  Assume the app is MDI -- and the user has another document open, and you just crashed it.  What happens to the user's data?  Absolutely it could be data loss as well -- ideally you want there to be as few user-initiated actions that can cause a problem

    Anyway -- this "could" be a security issue, it depends on the app's design, implementation and purpose.

  16. anonymouscommenter says:

    @Dave Bacher: Replace all the instances of "application crashed" with "power failed". Does this change any of these scenarios? If not, then it's not a vulnerability in the crash itself.

  17. anonymouscommenter says:

    @Mkie Caron: If somebody could trigger my machine to lose power over the internet I'd be complaining about that too, because there's no good reason for such a thing to exist.

  18. anonymouscommenter says:

    Even if it doesn't cause a C-style arbitrary code execution, there is still potential for a security fault here.

    The fact that there's an OverflowException tells me that there's some value that's probably not validated against a range -- that is, odds are that the valid range for this integer is probably not exactly 32,767. Let's say the actual valid range is 0-100. That means any value between 101 and 32,767 can cause unintended behavior, which may include something like taking document text and executing it as a macro even if macro execution is disabled -- the implication being that a macro may do something like load a web browser with a malicious web site or send a spam email on your behalf.

    In a situation like I just described, the overflow itself is not a security fault, but is evidence that there might be one.

  19. anonymouscommenter says:

    Joshua -- the point isn't about what triggers the power loss. The point is that if an unexpected power loss can leave the application data in an unsecure state, then the application has a security flaw, and the fact that you may be able to force the app to crash isn't itself the security flaw. It's one more route to expose users to the security flaw, but the security flaw exists even if you fix the crash, ergo the crash is not in itself a security hole.

  20. Henri Hein says:

    I think Craig's point is: if an exception is expected executing a statement, why run the statement in the first place?  Take your database example.  If you expect an exception opening the database, why even try opening it?  You open it, expecting it to succeed.  Yes, you should be prepared for failures, and for failures to sometimes throw exceptions, and you should be prepared to handle them.  That's preparing for contingencies, not expecting failure.

    [I think you're saying the same thing. It's just confusion over what "expected exception" means. One definition is "we assume that it will almost always happen"; another is "we are prepared for it (though it may not happen all the time)". We are talking about the latter, which perhaps more precisely should be called a "Not unexpected exception". -Raymond]
  21. anonymouscommenter says:

    @Craig: In one of our company's products, there's even a class called ExpectedException :) It is a specialized GUI framework with deeply nested modal dialogs for industrial use, we throw one subclass of it when the Home button is pressed and catch it at the home screen (of course all dialogs inbetween are disposed of properly).

  22. anonymouscommenter says:

    @alv: We have something like that. We call it LongjumpException.

    Raymond's case happens. See IOException.

  23. Simon says:

    It might be more helpful to talk of "anticipated exceptions", rather than "expected"... the latter kind of has the implication that *not* having an exception is unexpected.

  24. anonymouscommenter says:

    @Gabe - possibly, although the fact this is appearing during document load would make me first check if it was being thrown during base derserialization, before actual bounds checking or clamping.  Or it's part of some other "good enough"/"nobody should need" limit (page count, say).

    From a reporting standpoint, out-of-designated-bounds behavior would be more interesting, but that's not the 'vulnerability' they reported.  Probably something that should be verified as part of this, though.

    @alv, @Joshua - ...you guys know you're not supposed to use exceptions for normal flow control, right?  For one thing, it makes it too easy to forget to clean stuff up in nested dialogs, or even simply not have a handle to some piece of data.

  25. anonymouscommenter says:

    @Clockwork-Muse

    Programmers are supposed to use whatever works well for them.

  26. cheong00 says:

    I remembered that in earlier time of Linux, crashing the shell is considered common technique to gain root access. They have to modify kernel behaviour to fix it.

    But then again this is an application not a shell, and Windows does not use 0 as LocalSystem / Build-in administrator SID.

  27. anonymouscommenter says:

    @Mason Wheeler re Firefox and exceptions

    You failed to make a distinction between language exceptions (of which an OverflowException would be an example) and OS exceptions (such as GPF/SIGSEGV). The latter are an indication that something has broken inside the application machinery, and such breakage can sometimes be exploitable, so there is a valid reason to treat all such exceptions as potential security vulnerabilities (I'm sure MS has a similar policy). The former, on the other hand, are quite safe.

  28. "All you got was a denial of service against the XYZ application".

    Yes. This is a security vulnerability. Such DoS vulnerabilities are classified as security vulnerability.

  29. anonymouscommenter says:

    @Clockwork-Muse: we don't use exceptions for normal flow control, but to break out of normal flow. The cleanup code must be there in case an 'unexpected' exception happens, otherwise we're in serious trouble (there are lots of shared resources and misbehaving third-party stuff), therefore it's an additional bonus that cleanup is a bit more exposed :)

  30. anonymouscommenter says:

    @FleetCommand In a pedantic sense, yes it's a vulnerability because all DoSses are vulnerabilities. It's also an extremely weak vulnerability, so weak that in a less pedantic sense it might as well not be one.

  31. anonymouscommenter says:

    I have a proposal. I think we should start calling expected exceptions "expections". :-)

  32. Joshua Ganes says:

    "Not unexpected exception" *Ugh!*

    I think I prefer the terms anticipated and unanticipated to describe this. Not to mention that expect and except are very similar both visually and phonically.

  33. Monochrome Wench says:

    Really need more details to say for sure if it's a security problem or not, but it's managed code so it's probably ok.

  34. anonymouscommenter says:

    I believe Eric Lippert would call exceptions that you are "expecting" either exogenous or vexing, depending on whether they're avoidable.

    Exogenous exceptions are raised by factors beyond your control (like IOException), while vexing exceptions are those that you could avoid having to catch by using a different design (like using TryParse instead of Parse).

  35. anonymouscommenter says:

    Clearly, not enough people here subscribe to the pythonic philosophy.

  36. anonymouscommenter says:

    @Gabe: Most examples of vexing exceptions are things that can't throw in the context they are called from, even though some other context they could.

    Example: closing a readonly stream can throw IOException (and in Java is declared as such). Exception can only be thrown from a writable stream (under some conditions, writing to a stream is defered to a close() call. This can always be avoided by calling fsync() but that may be overkill).

    Example: constructing a URL from a string constant. Declared to throw MalformedURLException (or is it URI -- don't matter) but cannot throw because it is a constant. This one is particularly egregariuos because almost all the time there's nothing sane that can be done from the parse error.

  37. anonymouscommenter says:

    @Anonymous Cow Herd:  If you don't actually care about using a computer to do things.

  38. anonymouscommenter says:

    creaothceann: "But then such an exception is nothing more than a glorified error code."

    You say that as if its a bad thing.  Functions returning error codes, rather than throwing exceptions on error, are an anti-pattern.  They're the single greatest reason for The Fundamental Failure-Mode Theorem. An unhandled error-code causes your code to run in a state of wrongness.  An unhandled exception causes your code to die immediately.

  39. anonymouscommenter says:

    Joshua: The examples you gave, of having to handle exceptions that you know the callee can never throw, is not what Eric Lippert had in mind when he described vexing exceptions. I'd argue that it's a fifth kind of exception that is specific to Java.

    In the case of MalformedURLException, it's vexing if you can't find out if a URL is malformed by any means other than catching that exception.

Comments are closed.

Skip to main content