Week 12, Comp [34]49, Nov 13 ============================================================================ There's nothing wrong with RC4, per se, and 5-byte keys take a VERY long time to brute-force, if they really have 40 bits of entropy. Review: Purpose of IV: so IV ^ SecretKey is the session key, different from SecretKey Some problems: Problem 1. WEP starts a new keystream with EVERY PACKET Problem 2. Not enough bits in IV to prevent reuse Problem 3. If you *do* break IV^SecretKey, you've found SecretKey as well. Fix 1: don't start new keystream on every packet; keep existing keystream and include a position indicator. Problem: what if a packet arrives late, needing keystream position 1,000,000,000, and we're already at 1,000,100,000? How do we BACK UP that far? Fix 2: have SessionKey = IV XOR SecretKey, use 5-byte (or more) IV We now have enough IV's to avoid reuse, though problem 3 is still there. Fix 3: Have SessionKey = MD5(IV + SecretKey). Now we've fixed both 2 and 3. There remains Problem 4: starting the keystream from 0 all the time introduces the FMS vulnerability ====================================================================== Another approach to session keys: Diffie-Hellman Diffie-Hellman Key Exchange: Both sides agree publicly to a prime p and a base g (typically g=2 or 5) p must have more bits than the desired keylength. Alice picks a, and sends Bob g^a mod p. Alice does *not* share a. Bob picks b, and sends Alice g^b mod p. Bob does *not* share b. Both sides can now compute k = g^(ab) = (g^a)^b = (g^b)^a However, Diffie-Hellman is vulnerable to a man-in-the-middle attack. In other words, the shared-key is really all about authentication Safe D-H: use some kind of secure signature MD-5 signatures: Both parties have a key "secretkey" To sign a message, add a field MD5(message^secretkey). This could only have been done by someone with the key. using SecretKey to encrypt SessionKey ======================================================================= outline of RC4 ============== key-scheduling step for (i = 0; i<256; i++) S[i] = i; j = 0; for (i=0; i<256; i++) { j = (j + S[i] + key[i % keylength]) swap(S[i], S[j]); } byte-generation step (start with i=j=0) i = i+1; j = j + S[i]; swap(S[i], S[j]); return S[ S[i] + S[j] ]; Do example, 1st 5 steps with KEY = 3, -1, 5, 4, -14, 3 i=0, j=0 S_0: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 i=0, j=0+3 S_1: 3 1 2 0 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 i=1, j=3+1+(-1) = 3 S_2: 3 0 2 1 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 i=2, j=3+2+5=10 S_3: 3 0 10 1 4 5 6 7 8 9 2 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 i=3, j=10+1+4=15 S_4: 3 0 10 15 4 5 6 7 8 9 2 11 12 13 14 3 16 17 18 19 20 21 22 23 24 25 i=4, j=15+4+(-14) = 5 S_5: 3 0 10 15 5 4 6 7 8 9 2 11 12 13 14 3 16 17 18 19 20 21 22 23 24 25 i=5, j=5+4+3=12 S_6: 3 0 10 15 5 12 6 7 8 9 2 11 4 13 14 3 16 17 18 19 20 21 22 23 24 25 Fluhrer, Mantin, & Shamir WEP vulnerability: The very first byte of the keystream gives us some information! Each packet is encrypted "from scratch" in WEP, and the first byte of data payload is known, so we get LOTS of first bytes of the keystream! 1st byte is S[ S[1] + S[S[1]] ] (verify) ============================================================================== discussion of rc4.java; some demos Note need for posify() brute-force demo ============================================================================== FMS attack What the initial three steps of the key-scheduler does IV: <3,-1,X>: if 1st byte of keystream is Y, then we guess key[3] = Y-X-6 What are the odds that the packet won't be further messed up beyond the first 3 stages? 255 chances odds of one chance messing things up: 3/255 P(no messup) = (1-3/255)^255 = e^-3 = 0.04978 4-step version General version: precompute S_n (that is, run KSA for i=0 up through i=n-1) S[n] *might* have been tweaked, might not. We have i_n = n-1, j_n = whatever Now, the next step is to do j = j_n + S_n[n] + key[n] swap(S[i], S[j]) IF we get lucky, IF IF IF, future swaps will not affect S[0] through S[n]. Furthermore, we will have S[1] = 0, S[0] = n The first byte of the keystream is S[ S[1] + S[S[1]] ] if we're LUCKY, this is S [ S[0] ] = S[n] This in turn is S_n[j], with j as above. How to figure out key[n]? Let OUT be the value above, S[n] * work out S_n * figure out j: easiest way is to find j so OUT = S_n[j]; in other words j = inverse-of-S_n ( OUT ) * key[n] = j - j_n - S_n[n] The rc4 library has a method to run ksa for n stages. It also has methods inverse(byte b) the_j() S(byte n) to give the pieces above. DO AN EXAMPLE ON THE BOARD! Weak IV's are of the form This gives (if we're lucky) S[1]=0, S[0]=N, and S[N]= what we want BUT there are other helpful IVs too: See FMS , last paragraph of ยง7.1 ============================================================================== WEP authentication ... boy, did this plan fail This is a WEP-key-based authentication protocol, used BEFORE WEP encryption takes over. 1. STA --> AP: request for authentication 2. AP --> STA: challenge text, randomly selected 3. STA --> AP: response: station encrypts challenge text 4. AP --> STA: yes/no (note that the AP also needs to authenticate itself to the STA, to prevent rogue-AP attacks, but there the STA doesn't have to do anything) How to break this We (the bad guy) capture two packets corresponding to stages 2 and 3 above. This gives us the challenge text and its encrypted version. We can then figure out the ENTIRE plaintext of the encrypted part; the challenge text we sniffed, the rest of the data fields are standard, and we can calculate the CRC. Now it's our turn to request authentication. The AP will send a different challenge text. We simply encrypt our response by XORing with the keystream found above, specifying the same IV and same key. The AP accepts it. The AP *should* notice that we're reusing a keystream, but they DO NOT. Note that this only gets us as far as authentication. ============================================================================== Message modification (BGW) The theory was that there's nothing a bad guy can do to modify the message **and preserve the CRC checksum**. But CRC isn't strong enough; achieving such message modification is in fact trivial! Problem: CRC(m1 xor m2) = CRC(m1) xor CRC(m2). This is trivial as "xor" translates to addition-as-polynomials, and CRC is just the remainder; it becomes: (m1 + m2) mod P = (m1 mod p) + (m2 mod p) Now, suppose we have encrypted message e = (m ^ CRC(m)) xor keystream Assume for the moment that we do not know m, but we DO know how to tweak a few bytes by XORing: m' = m xor delta. We want to generate e' = (m' ^ CRC(m'). The body is easy: m' xor keystream = (m xor keystream) xor delta But how do we fix the CRC? Alas, CRC(m') = CRC(m) xor CRC(delta), so the encrypted CRC, CRC(m') xor keystream, is just (CRC(m) xor keystream) xor CRC(delta) In other words, e' = e xor (delta ^ CRC(delta)) ============== IP-address modification Goal: capture a packet, and modify the IP address (within the WEP-protected payload) to have the packet sent to our own IP address. It will arrive decrypted by the AP, and we will have another keystream piece. XORing to modify the IP address is trivial, assuming we know (or can guess, in a reasonable number of tries) the original IP address. What turns out to be nontrivial is updating the IP-header checksum. And our packet won't be routed if that isn't correct. We know what fudge factor to ADD (IPnew - IPold), but we don't know what to XOR (for the embedded IP header checksum) (The entire-packet CRC is handled as above.) Easiest attack: just tweak OTHER header fields until we get a packet with the SAME checksum. IP checksum is simple addition. =========================================================================== Newsham: 21-bit problem Key-generation algorithm in hardware throws entropy away! Newsham obviously did some work to figure out how the values were being generated. Linear congruential PRNG: X(n+1) = (a*X(n) + c) mod m Typically m = 2^32 (or 2^16). From three successive values, X2, X1, and X0 (and m), we can figure out a and c. (At least if X1-X0 is relatively prime to m; that is, is odd if m is a power of 2) X2 = aX1 + c mod m X1 = aX0 + c mod m X2-X1 = a(X1-X0) mod m Now do mod-m division of both sides by (X1-X0) (this is where we need this relatively prime to m) Moral: LCGs are TRIVIAL to "break". Who are you trying to fool: the universe, or your enemies? Einstein: God is subtle, but he is not malicious ============================================================================= ============================================================================= WPA: First pass: WPA-1, or TKIP 802.11i + 802.1X (X is *not* a placeholder here!) 128-bit key session key: hash of (base key, MAC addr, serial # of packet) Part of the header includes a 48-bit packet serial number, incremented for each packet The base key is rebuilt each time the STA associates to an AP, using the secret key only for this purpose. 802.1X: "port-based authentication" EAP/RADIUS server acts as "authenticator" Extensible Authentication Protocol Remote Authentication Dial In User Service Michael (MIC) 64-bit checksum that is NOT XOR-linear; that is, MIC(m1 xor m2) != MIC(m1) xor MIC(m2) in fact, no plausible replacement for the RHS xor is known. Packets must be in sequence 60-second rule MIC failure: good ICV, bad MIC 2 in 60 seconds: shut down for 60 seconds and then renegotiate all keys