The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding...

23
T P O A Fionn Fitzmaurice [redacted] --

Transcript of The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding...

Page 1: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

The Padding Oracle Attack

Fionn Fitzmaurice

[redacted]

2018-11-01

Page 2: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

ECB Mode

Enc

p0

k

c0

Enc

p1

k

c1

Enc

p2

k

c2

· · · Enc

pn

k

cn

Dec

c0

k

p0

Dec

c1

k

p1

Dec

c2

k

p2

· · · Dec

cn

k

pn

Page 3: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

CBC Encryption

Enc

p0

k

c0

Enc

p1

k

c1

Enc

p2

k

c2

IV

· · · Enc

pn

k

cn

· · · Enc

pn

k

cn

Page 4: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

CBC Decryption

Dec

p0

k

c0

Dec

p1

k

c1

Dec

p2

k

c2

IV

· · · Dec

pn

k

cn

· · · Dec

pn

k

cn

Page 5: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

Padding Blocks (PKCS#7)

Assume blocksize k. (k < 256.)

[x1, x2, ... , xk−l]→ [x1, x2, ... , xk−l, l, l, ... , l︸ ︷︷ ︸l

].

E.g.[x1, x2, ... , xk−4]→ [x1, x2, ... , xk−4, 4, 4, 4, 4]

(where 4 is the byte \x04).

If the data is already of length k, append a block.

[x1, x2, ... , xk]→ [x1, x2, ... , xk] + [k, k, ... , k︸ ︷︷ ︸k

].

Page 6: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

Padding Blocks (PKCS#7)

Assume blocksize k. (k < 256.)

[x1, x2, ... , xk−l]→ [x1, x2, ... , xk−l, l, l, ... , l︸ ︷︷ ︸l

].

E.g.[x1, x2, ... , xk−4]→ [x1, x2, ... , xk−4, 4, 4, 4, 4]

(where 4 is the byte \x04).

If the data is already of length k, append a block.

[x1, x2, ... , xk]→ [x1, x2, ... , xk] + [k, k, ... , k︸ ︷︷ ︸k

].

Page 7: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

The Padding Oracle

O(c) ={1 if p has valid padding,0 otherwise.

Page 8: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

Malicious Cyphertext

Let there be n blocks of plaintext, each of blocksize k. Fori ∈ [1,n],

ci = E(pi ⊕ ci−1),pi = D(ci)⊕ ci−1

where ci is the ith cyphertext block, pi the ith plaintext blockand c0 the initialisation vector.

Page 9: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

Construct some block c′ and concatonate with cn. Thecorresponding plaintext is c′|cn ↔ p′1|p′2.

p′1 = D(c′)⊕ c0, p′2 = D(cn)⊕ c′

= D(E(pn ⊕ cn−1))⊕ c′

= pn ⊕ cn−1 ⊕ c′

givingpn = p′2 ⊕ c′ ⊕ cn−1.

p′2 is at the end of our plaintext block so must have validpadding. This constrains c′!

If only there was some way to tell if the plaintext had validpadding. . .

Page 10: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

Construct some block c′ and concatonate with cn. Thecorresponding plaintext is c′|cn ↔ p′1|p′2.

p′1 = D(c′)⊕ c0, p′2 = D(cn)⊕ c′

= D(E(pn ⊕ cn−1))⊕ c′

= pn ⊕ cn−1 ⊕ c′

givingpn = p′2 ⊕ c′ ⊕ cn−1.

p′2 is at the end of our plaintext block so must have validpadding. This constrains c′!

If only there was some way to tell if the plaintext had validpadding. . .

Page 11: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

Construct some block c′ and concatonate with cn. Thecorresponding plaintext is c′|cn ↔ p′1|p′2.

p′1 = D(c′)⊕ c0, p′2 = D(cn)⊕ c′

= D(E(pn ⊕ cn−1))⊕ c′

= pn ⊕ cn−1 ⊕ c′

givingpn = p′2 ⊕ c′ ⊕ cn−1.

p′2 is at the end of our plaintext block so must have validpadding. This constrains c′!

If only there was some way to tell if the plaintext had validpadding. . .

Page 12: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

How to construct c′ such that p′2 = D(cn)⊕ c′ has valid padding?

By submitting c′|cn to the oracle!

O(c) ={1 if p has valid padding,0 otherwise.

O(c′|cn) = 1 ⇒ p′2 has valid padding.

Page 13: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

The Last Byte

Take pn = p′2 ⊕ c′ ⊕ cn−1 and consider only the last byte. If weconstrain p′2[k] = 1, p′2 has valid padding.

Construct c′ = c′k such that this is true. Then

pn[k] = p′2[k]⊕ c′k[k]⊕ cn−1[k]= 1⊕ c′k[k]⊕ cn−1[k].

We only care about p′2[k] = D(cn)[k]⊕ c′k[k], so let

c′k = [0, 0, ... , 0︸ ︷︷ ︸(anything)

,b].

Iterate over all values of b until O(c′k|cn) = 1 and, viapn[k] = 1⊕ b⊕ cn−1[k], you’ve found the last byte.

Page 14: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

The Last Byte

Take pn = p′2 ⊕ c′ ⊕ cn−1 and consider only the last byte. If weconstrain p′2[k] = 1, p′2 has valid padding.

Construct c′ = c′k such that this is true. Then

pn[k] = p′2[k]⊕ c′k[k]⊕ cn−1[k]= 1⊕ c′k[k]⊕ cn−1[k].

We only care about p′2[k] = D(cn)[k]⊕ c′k[k], so let

c′k = [0, 0, ... , 0︸ ︷︷ ︸(anything)

,b].

Iterate over all values of b until O(c′k|cn) = 1 and, viapn[k] = 1⊕ b⊕ cn−1[k], you’ve found the last byte.

Page 15: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

The Second-Last Byte

Another valid plaintext would be p′2[k] = p′2[k− 1] = 2.

∴ pn[k− 1] = 2⊕ c′k−1[k− 1]⊕ cn−1[k− 1]

andc′k−1[k] = c

′k[k]⊕ 1⊕ 2.

Page 16: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

All the Bytes!

pn[k] = 1⊕ c′k[k]⊕ cn−1[k],pn[k− 1] = 2⊕ c′k−1[k− 1]⊕ cn−1[k− 1],

...pn[k− i] = (i + 1)⊕ c′k−i[k− i]⊕ cn−1[k− i]

for i ∈ [0, k) and

c′k−i[k− j] = c′k−i+1[k− j]⊕ i⊕ (i + 1)

where j < i.

Page 17: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

All the Blocks!

Just repeat this for every block (except the �rst one).

Page 18: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

Caveats

To �nd pn[k] we iterate over possible values of c′k[k] = b andwhen O(c′k|cn) = 1 we conclude that the corresponding p

′2[k] = 1.

But there’s a chance that p′2[k− 1] = 2 and we found c′k[k]corresponding to p′2[k] = 2.

Similarly, if p′2[k− 2] = p′2[k− 1] = 3.

Page 19: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

Solution 1

Take cn−1|cn ↔ pn−1|pn and vary cn−1 from left to right. When

O(c′n−1|cn) = 0

on the ith byte, the remaining k− i bytes are all k− i.

Page 20: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

Solution 2

For the last byte, c′[k], check if it really corresponds to p′j[k] = 1by varying c′[k− 1].

If O(c′′|cj) = 0, we were wrong about the last byte.

This only needs to be checked once per block.

Page 21: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

This is Real

I SSL,

I IPSec,

I lots of web applications,

I Steam,

I &tc.

Page 22: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

def attack_block(block , c=cbc_oracle ()):c = [c[i:i+16] for i in range(0, len(c), 16)]c_prime , p = bytearray (16), bytearray (16)for i in range (15, -1, -1):

for b in range (256):c_prime[i] = bif padding_oracle(bytes(c_prime) + c[block]):

if i == 15:c_test = c_primec_test[i - 1] ^= c_prime[i]if padding_oracle(bytes(c_test) + c[block]):

breakelse:

breakp[i] = (16 - i) ^ c_prime[i] ^ c[block - 1][i]for j in range(i, 16):

c_prime[j] = c_prime[j] ^ (16 - i) ^ (16 - i + 1)return bytes(p)

def attack(c=cbc_oracle ()):p = [attack_block(i, c) for i in range(len(c) // 16 - 1, 0,

-1)]return de_pkcs7(b''.join(p[:: -1]))

Page 23: The Padding Oracle Attack - maths.tcd.iefionn/misc/padding_oracle/padding_oracl… · The Padding Oracle Attack Fionn Fitzmaurice [redacted] 2018-11-01. ECB Mode Enc p 0 k c 0 Enc

https://asciinema.org/a/81051