Sadly, you seem to be in a minority position here. I feel comfortable
in assuming that buggy code will be coming from OS vendors for quite
some time to come :-)
> > Regarding guessing the canary value, it is really hard to brute-force a
> > guess at the canary value. The canary is randomly chosen at exec time;
> Unfortunately the current random canary value is quite easy to guess
> at. This is something that should be fairly easy to fix though.
I don't quite understand this claim. What makes a randomly chosen
32-bit value easy to guess at? Especially in light of the fact that
guesses have to be made against the victim machine, and you can't just
go off and make 4 gig of guesses on your idle Alpha workstation?
> Unless you use a cryptographically sound way of generating the
> random numbers, knowing one canary value may be more than enough
> information to allow an attack to proceed. All the canary values
> are related through a deterministic computation that an attacker can
Fair enough. We used the Linux srandom(3) library in this release of
StackGuard, seeded with the time of day. We considered using
/dev/random, but there's some work involved with that. We make NO
claims about the cryptographc strength of these techniques, as we are
not crptography experts. I would be very happy to incorporate a better
source of entropy into a future release.
I don't view this as a really hard crypto problem, because the secret
never has to be transmitted across an open channel, it just has to stay
in a single address space.
> As a second attack (credit to Tom Ptacek who thought of it), you
> can simply trick the program into reusing the same canary value.
> Because there are a finite number of canary values that are reused,
> an attacker can cause the program to make enough function calls to
> reuse the canary value for the procedure that the attacker wishes
> to exploit. For example when processing text there may be a number
> of function calls associated with each character or each line.
> This might be all the leverage that is needed by the attacker.
I don't think I understand this attack. What we do is generate a
vector of canary values at the time the program is exec'd, and then
statically associate each canary with each function call. The canary
value is xor'd with the address of the stack frame (another cheesy
source of entropy) but one could easily argue that the canary value for
a given function will be exactly the same for each invocation of the
function, but *only* for a given execution of the program. If any
activity ever trips a StackGuard alarm, the program exits. When it
re-starts, it will have all new canary values.
> Finally the precomputed canary values may be a target themselves.
> If there is an overflow in the data or bss segments preceeding
> the precomputed canary vector, an attacker can simply overwrite
> all the canary values with a single value of his choosing, effectively
> turning off stack protection.
Excellent point. Initially, the canary vector was allocated by crt0,
placing them below all other memory objects. Currently, the vector is
allocated by libcanary, making it vulnerable to overflow vulnerabilites
in static memory objects linked ahead of libcanary.
I propose to use mprotect(2) to make the canary vector read-only in a
future release. Does that address your concern here?
Crispin Cowan, Research Assistant Professor of Computer Science
Oregon Graduate Institute | Electronically:
Department of Computer Science | analog: 503-690-1265
PO Box 91000 | digital: firstname.lastname@example.org
Portland, OR 97291-1000 | URL: http://www.cse.ogi.edu/~crispin/
Knowledge is to Wisdom as Data is to Code