mei said:
So let's assume a class exhibits the design flaw to take a mutable
string as a parameter. Thinking over it, I was wondering how we can make
sure (reasonably) that the thread has a chance to be executed during the
window of vulnerability? Is that a theoretical risk or not?
OK, so we assume that have a third-party class, Victim, which has a bug (any
bug) which we can exploit /if/ we can make our code run during some interval
while the other code is also running. The challenge is to make our own code
run at exactly the right time relative to the execution of Victim's code.
The bug in Victim /might/ give us some way to control its execution. For
instance, imagine that it is passed some object which it uses as a key in some
HashMap during the window of opportunity. If we can supply a malicious object
with a very slow implementation of hash() or equals(), then we can wedge the
window open for as long as we like. Another possibility is that the Victim
code may use a method which is synchronised on some object which we also have
access to; if so then by taking out a lock on that object ourselves, we can
cause the target code to block. Again, that will only work if Victim uses the
synchronised method during the window of opportunity. (As an example, note
that many of the Stream implementations are synchronised internally, so if we
can find a stream that Victim uses during the window then we may be able to
attack). A third way of wedging the window open is if the Victim writes to
some external file, network connection, or stdout stream. If we can take
control of that stream (perhaps by substituting our own stream, or by
interfering with the stream at the operating-system level) then we may be able
to make Victim slow down or even block when it is writing. There are lots of
possibilities if you use your imagination. Perhaps Victim inserts data into a
database in a way that we can cause to block by taking out DB locks. Perhaps
Victim uses some other class which we can replace with a malicious substitute
(maybe using classloaders). Perhaps, if we /really/ want to get exotic, we can
run the code on a custom JVM. Perhaps we can run Victim under a debugger, and
control it that way...
However, if the Victim does not do anything "blockable" during the window of
opportunity, and if we are not allowed to cheat by using debuggers and so on,
then it gets harder. The shorter the time window is open for, the harder it
will be. All we can do is sit in a tight loop (in one thread) trying to attack
the Victim as often as possible and hope that one of our attempts will happen
to run while the window is open. We can make that a bit more likely by running
our thread at the highest possible priority, and the Victim's thread at the
lowest possible. Our loop might then look like:
while (! tryToAttackOnce())
{
Thread.yield();
}
the call to is intended to try to allow the Victim thread a chance to make a
small amount of progress (it has to make /some/ progress or it will never open
the window in the first place) but not so much that it'll be able to open /and/
close the window before our next attempted attack. Depending on the
implementation of the JVM we are running on, we may need to replace
Thread.yield() with Thread.sleep() for some very short interval. Note that all
manipulations of thread priority and yield()/sleep() have
implementation-dependent effects -- what works on one OS/JVM combination may
act completely differently on another one.
Basically, getting our code to run at the right instant is a matter of trusting
to luck. I know of no really good, portable, reliable, way of increasing our
own luck (it's not part of the standard Java libraries, unfortunately ;-) The
only way of boosting our chances are to reduce the adversary's luck -- for
instance we could trick the developers of class Victim into demonstrating their
product to their own top management. If we can't get lucky enough for our own
attack to work during that demo then we probably won't ever manage it at all...
-- chris