[e-lang] An attack on a mint
Mark Miller
erights at gmail.com
Mon Mar 3 21:33:45 EST 2008
On Mon, Mar 3, 2008 at 9:44 AM, David Wagner <daw at cs.berkeley.edu> wrote:
> Mark Miller writes:
> >However, because JavaScript doesn't have integers, I pulled the
> >addition out into a separate statement to ensure it didn't loose
> >precision.
>
> Oh, gosh, so my fixing this correctly is more subtle than it appears.
> Here was my proposed "fix":
> deposit: function(amount,src) {
> caja.enforceNat(amount);
>
> var box = src.getDecr();
> brand.unseal(box)(amount);
> balance = caja.enforceNat(balance+amount);
> }
> There's a subtle detail here. If balance+amount overflows (i.e., exceeds
> MAXINT, where MAXINT+1 is the smallest non-precisely-representable natural
> number), then enforceNat() will throw an exception -- *after* src.balance
> has been decremented but before this.balance has been incremented.
> Thus this might look like it can violate conservation of currency.
Sigh. Yes, this is probably why, when I "fixed" the += with the
enforceNat, I placed the enforceNat early, and so created the bug you
exploited.
This brings us back to what's so scary about all this: when writing
security code, even if you do write it correctly at first, the amount
of rationale that needs to be captured per line of code is much
greater than I can imagine being captured by any process people can
use. Without capturing this rationale, we need some other form of
cross-check to ensure that security isn't lost under maintenance -- as
I have done here for one of my own most beloved and well examined
examples.
> Fortunately, I think this is not exploitable as long as the total amount
> of money in circulation is representable in a natural number, and I
> believe that assumption is enforced by the Mint.
How? I understand how this is enforced by the IOU mint. I don't think
it is enforced by the simple-money mint.
> Interesting. Does this suffice? One property we want to ensure is
> that if
> enforceNat(x);
> enforceNat(y);
> z = enforceNat(x+y);
> succeeds, then as integers z is the sum of x and y. But what if x is
> MAXINT, and y=1. Is it possible that x+1 rounds down to x?
enforceNat doesn't round or coerce in any other way. If x+y isn't
already an integer in the appropriate range, enforceNat (I hope)
throws. If floating point works as I am counting on, then we should
have the property you state above. enforceNat(MAXINT + 1) should
throw. At least that's the intention. Needs testing on all JavaScript
platforms.
> Similarly
> is it possible that there exists some sum s such that x > MAXINT but
> Math.floor(s-1) === s-1 < s? Are we guaranteed by properties of floating
> point arithmetic that if x > MAXINT, then enforceNat() will throw an
> exception? I just don't know floating point arithmetic well enough to
> reason this through.
I'm not sure I do either, but the properties you state are what I intend.
> What about
> enforceNat(x);
> enforceNat(y);
> z = enforceNat(x*y);
>
> ?
I never count on this property, but I believe it should hold as well.
> This seems to be shaping up to make an interesting case study in
> identifying several kinds of common hazards:
> - exceptions can cause plan interference
> - re-entrancy can cause plan interference
> (or: calling untrusted code while object invariants are
> temporarily broken can introduce security holes)
> - integer overflow can violate expected invariants
> - aliasing can violate expected invariants
Indeed! All this needs to be better understood and well explained.
--
Text by me above is hereby placed in the public domain
Cheers,
--MarkM
More information about the e-lang
mailing list