2018-02-23 18:58:03 +00:00
|
|
|
|
---
|
|
|
|
|
created_at: '2015-01-09T21:14:13.000Z'
|
|
|
|
|
title: Typing the Letters A-E-S Into Your Code (2009)
|
|
|
|
|
url: http://chargen.matasano.com/chargen/2009/7/22/if-youre-typing-the-letters-a-e-s-into-your-code-youre-doing.html
|
|
|
|
|
author: zorked
|
|
|
|
|
points: 168
|
|
|
|
|
story_text: ''
|
|
|
|
|
comment_text:
|
|
|
|
|
num_comments: 63
|
|
|
|
|
story_id:
|
|
|
|
|
story_title:
|
|
|
|
|
story_url:
|
|
|
|
|
parent_id:
|
|
|
|
|
created_at_i: 1420838053
|
|
|
|
|
_tags:
|
|
|
|
|
- story
|
|
|
|
|
- author_zorked
|
|
|
|
|
- story_8864555
|
|
|
|
|
objectID: '8864555'
|
2018-06-08 12:05:27 +00:00
|
|
|
|
year: 2009
|
2018-02-23 18:58:03 +00:00
|
|
|
|
|
|
|
|
|
---
|
2018-03-03 09:35:28 +00:00
|
|
|
|
# If You’re Typing the Letters A-E-S Into Your Code You’re Doing It Wrong
|
2018-02-23 18:19:40 +00:00
|
|
|
|
|
2018-03-03 09:35:28 +00:00
|
|
|
|
## 1\. INT. COFFEE SHOP, MORNING
|
2018-02-23 18:19:40 +00:00
|
|
|
|
|
2018-03-03 09:35:28 +00:00
|
|
|
|
**DISCUSSING AN INTERVIEW**
|
2018-02-23 18:19:40 +00:00
|
|
|
|
|
2018-03-03 09:35:28 +00:00
|
|
|
|
A “young, cool-people’s” coffee shop on the first floor of an old office
|
|
|
|
|
building in downtown Chicago. “My band is playing” notices line the
|
|
|
|
|
wall. A hipster in a tight t-shirt hands a cappucino to MIKE TRACY while
|
|
|
|
|
THOMAS PTACEK waits impatiently. The coffee shop is loud; Mike and
|
|
|
|
|
Thomas raise their voices to be heard over the noise.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Did you see that? He worked so hard on my coffee.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
What? Right. Whatever. Let’s get…
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
He got all those little beans and put them in the thing and tamped them
|
|
|
|
|
down and
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Whatever. Ok. We’ve gotta get ready for this interview
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY (CONT’D)**
|
|
|
|
|
|
|
|
|
|
and he clickity-clack clickity-clacked with the machine and
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Mike\! I get it\! He made the shit out of your coffee. What are we going
|
|
|
|
|
to ask this guy?
|
|
|
|
|
|
|
|
|
|
Mike walks to a table at the side of the shop, grabbing a lid and a
|
|
|
|
|
sleeve for his coffee.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Miffed
|
|
|
|
|
|
|
|
|
|
I don’t know. It’s your interview. Single signon cookies?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Why SSO?
|
|
|
|
|
|
|
|
|
|
Mike is maneuvering around people entering the shop through a door
|
|
|
|
|
leading out to the hallway.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
It’s got crypto in it. Everyone always fucks it up.
|
|
|
|
|
|
|
|
|
|
### INT. HALLWAY - CONTINUOUS
|
|
|
|
|
|
|
|
|
|
Thomas follows Mike, walking towards the elevators.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Yeah, that could work. We’ll have two apps. User logged into one of
|
|
|
|
|
them, needs the other app to do something without making them log in.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Print an invoice.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Yeah, this will work. We’ll see if he comes up with the industry
|
|
|
|
|
standard answer; the cookie both apps honor to let you in, encrypted so
|
|
|
|
|
users can’t change their account to someone else’s.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
So, a base64 blob AES encrypted with a key both servers share? That’s
|
|
|
|
|
pretty easy, isn’t it? Are we sure this isn’t a layup?
|
|
|
|
|
|
|
|
|
|
DING. An elevator opens. Thomas and Mike step inside.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
You’ll be surprised.
|
|
|
|
|
|
|
|
|
|
## 2\. INT. OFFICE - LATER THAT MORNING
|
|
|
|
|
|
|
|
|
|
An unadorned off-white office lined with Ikea desks, piled with books,
|
|
|
|
|
papers, and in one case a pile of random electronics tools (soldering
|
|
|
|
|
iron, multi, etc). An EASEL PAD stands next to a large window looking
|
|
|
|
|
out on a brick wall. Thomas and Mike sit office chairs with THE
|
|
|
|
|
CANDIDATE.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
So you’d have app ‘A’ set a cookie with your account ID in it, right,
|
|
|
|
|
but how would you keep the user from switching their account by messing
|
|
|
|
|
with the cookie?
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Uh, I’d encrypt the cookie?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Show us how on the pad? \* Thomas hands THE CANDIDATE a dry erase
|
|
|
|
|
marker, as THE CANDIDATE walks to the easel pad.\*
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Does it matter what language I write it in?
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Whatever you’re comfortable with.
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Writing awkwardly, addressing the easel
|
|
|
|
|
|
|
|
|
|
Ok, so in C\#, I’d use `Response.Cookies`, and
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
You can just do the part where you encrypt the cookies.
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Oh, ok.
|
|
|
|
|
|
|
|
|
|
THE CANDIDATE writes on the pad, slowly
|
|
|
|
|
|
|
|
|
|
``` line-numbers
|
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
|
3
|
|
|
|
|
4
|
|
|
|
|
5
|
|
|
|
|
6
|
|
|
|
|
7
|
|
|
|
|
8
|
|
|
|
|
9
|
|
|
|
|
10
|
|
|
|
|
11
|
|
|
|
|
12
|
|
|
|
|
13
|
|
|
|
|
14
|
|
|
|
|
15
|
|
|
|
|
16
|
|
|
|
|
17
|
|
|
|
|
18
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
public static string Encrypt(string toEncrypt, string key, bool useHashing)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
|
|
|
|
|
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
|
|
|
|
|
|
|
|
|
|
if (useHashing)
|
|
|
|
|
keyArray = new MD5CryptoServiceProvider().ComputeHash(keyArray);
|
|
|
|
|
|
|
|
|
|
var tdes = new TripleDESCryptoServiceProvider()
|
|
|
|
|
{ Key = keyArray, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };
|
|
|
|
|
|
|
|
|
|
ICryptoTransform cTransform = tdes.CreateEncryptor();
|
|
|
|
|
byte[] resultArray = cTransform.TransformFinalBlock(
|
|
|
|
|
toEncryptArray, 0, toEncryptArray.Length);
|
|
|
|
|
|
|
|
|
|
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Sorry.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
No worries, writing code during interviews sucks.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Can you walk us through what that code is doing?
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Sure. So I’m Triple-DES encrypting the cookie, which is
|
|
|
|
|
the `toEncrypt` function argument.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Triple DES? Seriously?
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Ah, yeah, you’re right, in my last job we had to use Triple DES for
|
|
|
|
|
campatibility, but I’d use AES now.
|
|
|
|
|
|
|
|
|
|
THE CANDIDATE starts correcting the text on the pad.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Don’t worry about it, keep going. But yeah, don’t use Triple DES for
|
|
|
|
|
anything. It has a bunch of problems, but also an 8 byte block size,
|
|
|
|
|
which is tiny.
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Ok, so, I take the key and I turn it into an AES key by MD5’ing it.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
You know MD5 is broken, right?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Yeah, that’s not really the problem there though.
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Oh, I could just use SHA-1.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
SHA-1 is really fast. Can you see why that’s a problem here?
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Haltingly
|
|
|
|
|
|
|
|
|
|
Um. Not really? Don’t I want this to be fast?
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
What’s in the cookie you’re encrypting again?
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
A string of URL arguments…
|
|
|
|
|
|
|
|
|
|
THE CANDIDATE starts writing on the
|
|
|
|
|
pad `userId=39493&role=user×tamp=1414919`
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
So what’s to stop me from just running a dictionary through MD5,
|
|
|
|
|
generating a key, and trying to decrypt the cookie? I’ll know I won when
|
|
|
|
|
I get clean ASCII.
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
And how do I keep that from happening? You should use strong passwords
|
|
|
|
|
anyways. And I use a salt with the key anyways.
|
|
|
|
|
|
|
|
|
|
Mike vomits onto the floor.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Gross.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Wiping mouth
|
|
|
|
|
|
|
|
|
|
A salt doesn’t do anything here\!
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Just put a `for` loop around SHA-1 and run it 1000 times to generate the
|
|
|
|
|
key; that’ll at least slow down a brute force attack. SHA-1 is lightning
|
|
|
|
|
fast. By itself, it’s a crappy way to generate a key.
|
|
|
|
|
|
|
|
|
|
To Mike
|
|
|
|
|
|
|
|
|
|
Clean that up?
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Well, I guess. Wait, why should we use a password here at all? I could
|
|
|
|
|
just use a random string of bytes…
|
|
|
|
|
|
|
|
|
|
THE CANDIDATE writes again on the whiteboard
|
|
|
|
|
|
|
|
|
|
``` line-numbers
|
|
|
|
|
1
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
new RNGCryptoServiceProvider().GetBytes(keyArray);
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
That is much better. Sometimes it’s a lot more convenient to use a
|
|
|
|
|
readable string. If you do, the loop around SHA-1 is similar to what
|
|
|
|
|
PBKDF does, which is I guess a best practice here. But if you can keep
|
|
|
|
|
structure out of your crypto keys, that’s much better.
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Ok. Should I keep going?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Your encryption function. Do you know what the `ECB` thing there means?
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Oh, fuck\! You’re right, that should be `CBC`.
|
|
|
|
|
|
|
|
|
|
Pausing
|
|
|
|
|
|
|
|
|
|
Sorry for swearing.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
S’okay. You’ll fit right in.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
You know the difference between `ECB` and `CBC`?
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Yeah, like, each block feeds into the next one?
|
|
|
|
|
|
|
|
|
|
THE CANDIDATE draws on the easel
|
|
|
|
|
|
|
|
|
|
![](/globalassets/newsroom/us/blog/images/2009/07/cbc1.png)
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Why’s that a win?
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
Because if any of the blocks repeat, you can see them repeat?
|
|
|
|
|
|
|
|
|
|
Mike has opened his laptop and is typing.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
To the laptop
|
|
|
|
|
|
|
|
|
|
We have a picture of that somewhere. Oh, here.
|
|
|
|
|
|
|
|
|
|
Mike raises the laptop up to show THE CANDIDATE
|
|
|
|
|
|
|
|
|
|
![](/globalassets/newsroom/us/blog/images/2009/07/ecb.jpg)
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY (CONT’D)**
|
|
|
|
|
|
|
|
|
|
The top part is unencrypted. The bottom part is encrypted ECB. You’re
|
|
|
|
|
like Jack from Heat Vision and Jack.
|
|
|
|
|
|
|
|
|
|
**THE CANDIDATE**
|
|
|
|
|
|
|
|
|
|
I know EVERYTHING\! Right, because one bunch of 16 “black” bytes is the
|
|
|
|
|
same as the next, so they show up the same in the picture. Neat. Also,
|
|
|
|
|
in ECB mode you can cut and paste the blocks, right? He could take
|
|
|
|
|
the `userid`out of your cookie and put it in his own?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Sure. That’s a good answer. Let’s move on. Say you’re implementing a web
|
|
|
|
|
server. What do you think, processes or threads?
|
|
|
|
|
|
|
|
|
|
## 3\. INT. OFFICE CONFERENCE ROOM - AFTERNOON
|
|
|
|
|
|
|
|
|
|
A room in the same office, roughly the same size, with an oversized
|
|
|
|
|
brown kitchen table in the middle, littered with paper and McDonalds
|
|
|
|
|
wrappers. Thomas and Mike sit at the table, talking to a CONFERENCE
|
|
|
|
|
PHONE.
|
|
|
|
|
|
|
|
|
|
**CONFERENCE PHONE**
|
|
|
|
|
|
|
|
|
|
So how’d he do?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Pretty much aced it.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
What? He bombed the cookie part. He used ECB, MD5, and Triple DES\!
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
I’m impressed that he could spell ECB, MD5, or Triple DES. And it
|
|
|
|
|
wouldn’t have mattered if he had used CBC, SHA-256, and AES-256. His
|
|
|
|
|
code still would have been broken.
|
|
|
|
|
|
|
|
|
|
**CONFERENCE PHONE**
|
|
|
|
|
|
|
|
|
|
How so?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
He didn’t authenticate the message. Encryption isn’t —
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Chanting
|
|
|
|
|
|
|
|
|
|
Encryption - isn’t - authentication.
|
|
|
|
|
|
|
|
|
|
**CONFERENCE PHONE**
|
|
|
|
|
|
|
|
|
|
Don’t you mean integrity?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
No, Dave, I mean authentication. They’re called message authentication
|
|
|
|
|
codes.
|
|
|
|
|
|
|
|
|
|
**CONFERENCE PHONE**
|
|
|
|
|
|
|
|
|
|
Ok, Tom. But he screwed that up?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Yeah, but who cares? I’m surprised he even knew what CBC was. But we
|
|
|
|
|
just asked that to see how he thinks. We’re never going to let him
|
|
|
|
|
implement crypto code anyways.
|
|
|
|
|
|
|
|
|
|
**CONFERENCE PHONE**
|
|
|
|
|
|
|
|
|
|
I guess we don’t even let you write crypto code.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Sure, and when I asked him about processes and threads…
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Can I stop you both here for a second?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Yeah?
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
This room is pretty fucking boring. We’re in a screenplay, right?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Oh, yeah, you’re right. Let’s fix that.
|
|
|
|
|
|
|
|
|
|
Shouting
|
|
|
|
|
|
|
|
|
|
**Wings of silver\!**
|
|
|
|
|
|
|
|
|
|
**CONFERENCE PHONE**
|
|
|
|
|
|
|
|
|
|
**Nerves of steel\!**
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
**Thundercats go\!**
|
|
|
|
|
|
|
|
|
|
### EXT. HURTLING THROUGH SPACE - CONTINUOUS
|
|
|
|
|
|
|
|
|
|
The office melts away around them, revealing a starfield hurtling past
|
|
|
|
|
as if moving at awesome speed. Meanwhile, the CONFERENCE PHONE
|
|
|
|
|
transforms into a UNICORN WITH LASER HORN.
|
|
|
|
|
|
|
|
|
|
**DAVE THE LASER UNICORN**
|
|
|
|
|
|
|
|
|
|
It’s “Silverhawks”, jackass.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Where were we?
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Authentication?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Oh yeah. Even if he had done AES-256-CBC. His code is still busted. I
|
|
|
|
|
can make his messages say whatever I want them to.
|
|
|
|
|
|
|
|
|
|
**DAVE THE LASER UNICORN**
|
|
|
|
|
|
|
|
|
|
How do you do that? Isn’t that the point of CBC mode? Anything you
|
|
|
|
|
change in the ciphertext randomizes the output. What can an attacker do
|
|
|
|
|
with that?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
First of all, sometimes randomizing the output is all you need. If one
|
|
|
|
|
of the key-value pairs in the cookie is your role, and the default role
|
|
|
|
|
is `admin`, but the server always generates a `role=user` field…
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Yikes. Yeah, that’s bad. Have you ever seen that bug in the wild?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Garbling a block to confuse an app? I found a similar problem recently.
|
|
|
|
|
Login generates an encrypted cookie. Inside the cookie, comma-seperated
|
|
|
|
|
key-value pairs. If you put a comma in your user name, the server
|
|
|
|
|
doesn’t want you to inject your own key-value pairs, like “bob comma
|
|
|
|
|
admin equals yes”. So it quotes the commas. You can mess up a block to
|
|
|
|
|
eat the quote character.
|
|
|
|
|
|
|
|
|
|
**DAVE THE LASER UNICORN**
|
|
|
|
|
|
|
|
|
|
How do you know what block to mess up?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
It’s a cookie. You get unlimited tries. Each time, you add another ‘A’
|
|
|
|
|
to the login name, or mess with a different block. Eventually you line
|
|
|
|
|
things up just right so that you’ve garbled the quote character but not
|
|
|
|
|
the comma. Here, let me show you.
|
|
|
|
|
|
|
|
|
|
Thomas puts his hand to his forehead, and a beam of light emerges from
|
|
|
|
|
his forehead, projecting a picture, because it’s my script dammit.
|
|
|
|
|
|
|
|
|
|
![](/globalassets/newsroom/us/blog/images/2009/07/cbc2.png)
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Top hexdump. The plaintext of the cookie. Nothing’s been done to it.
|
|
|
|
|
Second hexdump. The encrypted cookie. Key doesn’t matter. Third hexdump.
|
|
|
|
|
I’ve flipped a bit in the second AES block.
|
|
|
|
|
|
|
|
|
|
**DAVE THE LASER UNICORN**
|
|
|
|
|
|
|
|
|
|
Convenient how AES blocks and hexdump lines are the same width.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Fourth hexdump. The decrypted output, after flipping that bit in the
|
|
|
|
|
ciphertext. Notice that flipping one bit totally garbled the second
|
|
|
|
|
block — and ate my quote character.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Doesn’t the app reject the cookie because of the garbled stuff in the
|
|
|
|
|
middle of it?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Probably not. Why would it? C\# and Java and Ruby and Python don’t care
|
|
|
|
|
what go in your strings. And hey, if it does reject them, flip a
|
|
|
|
|
different bit. Totally different output. You get 2128 tries.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Good point. What’s with the red “B” in the decrypted hexdump?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Getting to that. Turns out, I can make the cookie say whatever I want.
|
|
|
|
|
It’s a property of CBC.
|
|
|
|
|
|
|
|
|
|
The property is this: take a ciphertext block and flip bit 0 (or 2, or
|
|
|
|
|
N). The resulting plaintext for that block? Garbage. But the next block
|
|
|
|
|
is normal… except has that bit flipped. Not good\!
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
So you sacrifice one block and flip bits in the second block?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Yeah. Although let’s stop calling it “flipping bits” and call it
|
|
|
|
|
“rewriting”, because that’s what you’re doing.
|
|
|
|
|
|
|
|
|
|
**DAVE THE LASER UNICORN**
|
|
|
|
|
|
|
|
|
|
If you know what bits to flip.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
You always know what the bits are.
|
|
|
|
|
|
|
|
|
|
**DAVE THE LASER UNICORN**
|
|
|
|
|
|
|
|
|
|
How?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Because the bits are always 0x41414141.
|
|
|
|
|
|
|
|
|
|
**DAVE THE LASER UNICORN**
|
|
|
|
|
|
|
|
|
|
Huh?
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Because that’s what he stuffed them with. He logged in as bob
|
|
|
|
|
A-A-A-A-A-A-A-A-A.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Right. An SSO cookie is usually, what, 100 bytes? If I stuff 1000 A’s
|
|
|
|
|
after my login name, and the cookie grows to 1100 bytes? Almost all of
|
|
|
|
|
those bytes are known to me. Here.
|
|
|
|
|
|
|
|
|
|
Again with the forehead beam thing.
|
|
|
|
|
|
|
|
|
|
![](/globalassets/newsroom/us/blog/images/2009/07/cbc3.png)
|
|
|
|
|
|
|
|
|
|
AES encrypt something that I partially control. Doesn’t matter what the
|
|
|
|
|
key is. Now XOR that block into the ciphertext. Decrypt it, and
|
|
|
|
|
somewhere in it you get a random block and `&admin=yes&x=AAAAA`.
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Not good.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
If you’re encrypting something it’s usually somehow user-controlled.
|
|
|
|
|
I’ll find that by plugging 100 A’s into each form field and waiting
|
|
|
|
|
for the cookie to grow.
|
|
|
|
|
|
|
|
|
|
**DAVE THE LASER UNICORN**
|
|
|
|
|
|
|
|
|
|
How will you know if the cookie is AES?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Same way Chris Eng said to. Add A’s one at a time, see what increments
|
|
|
|
|
the cookie grows in. 16 bytes at a time? AES.
|
|
|
|
|
|
|
|
|
|
**DAVE THE LASER UNICORN**
|
|
|
|
|
|
|
|
|
|
And CBC?
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
If you’re encrypting all A’s, the ciphertext blocks will repeat.
|
|
|
|
|
|
|
|
|
|
**DAVE THE LASER UNICORN**
|
|
|
|
|
|
|
|
|
|
And how do you know the format to write into the cookie?
|
|
|
|
|
|
|
|
|
|
**MIKE TRACY**
|
|
|
|
|
|
|
|
|
|
Who cares? Trial and error.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Yeah. Point is, you thought encryption protected the contents of the
|
|
|
|
|
cookie. It doesn’t. Oh look, we’re almost there.
|
|
|
|
|
|
|
|
|
|
Thomas, Mike, and Dave hurtle towards a star system, a solar system, a
|
|
|
|
|
planet, powers-of-ten-style, towards the Michigan shore, converging
|
|
|
|
|
eventually on an office building, and then…
|
|
|
|
|
|
|
|
|
|
### INT. OFFICE CONFERENCE ROOM - AFTERNOON
|
|
|
|
|
|
|
|
|
|
**CONFERENCE PHONE**
|
|
|
|
|
|
|
|
|
|
That was really fucking anticlimactic.
|
|
|
|
|
|
|
|
|
|
### EXT. PARKING GARAGE - EARLY EVENING
|
|
|
|
|
|
|
|
|
|
Thomas stands next to his car, a black Volvo 850 held together with duct
|
|
|
|
|
tape, talking on a cell phone to NATE LAWSON.
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
You know this scene is a really bad setup for a movie, right?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Yeah yeah, whatever. Shut up before I turn you into a claymation
|
|
|
|
|
character. So yeah, it’s amazing how you can be a top tier vuln
|
|
|
|
|
researcher for over a decade and not really get how bad it is not to
|
|
|
|
|
have a MAC.
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
A MAC doesn’t necessarily save you either.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
How so?
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
There’s still a bunch of things you can do wrong. Like I was just
|
|
|
|
|
saying, Google Keyczar did almost everything right, but compared the MAC
|
|
|
|
|
using a timeable comparison function. You could tell how many bytes of
|
|
|
|
|
the MAC matched by watching how long the function took. People make that
|
|
|
|
|
mistake all the time. An even more common mistake is to generate an
|
|
|
|
|
error message when your padding is wrong. If you do that, you can
|
|
|
|
|
decrypt messages.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
I’ve heard about that. The Bleichenbacher PKCS thing, and the Vaudenay
|
|
|
|
|
paper.
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
This was a major TLS finding too.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
I’ve never really been all that clear on how this works.
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
Well you know how PKCS 7 padding works, right?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Yeah, you have 2 bytes, you need to fill 16 bytes for an AES block, so
|
|
|
|
|
you fill the remaining 14 bytes with 0xe.
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
So if you tack a random block onto a CBC message, what happens when the
|
|
|
|
|
receiver decrypts it?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
It comes out random.
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
And the padding?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Broken.
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
Right. And if you send an error when that happens, you know the padding
|
|
|
|
|
failed. Now if you keep trying different random blocks, what’s
|
|
|
|
|
eventually going to happen?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Uh…
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
You’ll get a message with valid padding. Valid padding might be 0x3 0x3
|
|
|
|
|
0x3. Or it might be 0x4 0x4 0x4 0x4. But if you’re basically generating
|
|
|
|
|
random blocks, what’s the mostly likely padding you’re going to get that
|
|
|
|
|
will pass the check?
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
0x1.
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
Right. And you’re randomizing the output by tacking a random block in
|
|
|
|
|
front of real ciphertext, which gets XOR’d during decryption. So you
|
|
|
|
|
know the last byte of your random block…
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
And the 0x1 that you know the padding is, and so that random byte XOR
|
|
|
|
|
the last byte of the plaintext is 0x1, and so you know the last byte of
|
|
|
|
|
the plaintext.
|
|
|
|
|
|
|
|
|
|
Pausing
|
|
|
|
|
|
|
|
|
|
And now that you know the last byte of the plaintext, you can make the
|
|
|
|
|
padding come out to 0x2 and try randomizing the other 15 bytes to find
|
|
|
|
|
out the next byte, and so on?
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
Close enough.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
That is fucked up. All you did wrong was show me the exception your
|
|
|
|
|
library generated when you decrypted the block, and I could decrypt a
|
|
|
|
|
block. You got to reason byte by byte instead of block by block.
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
You can decrypt whole messages that way. It’s called an error oracle.
|
|
|
|
|
You can’t show clients discernable errors. You can’t even take different
|
|
|
|
|
amounts of time to do things\! You can watch the system with random
|
|
|
|
|
inputs and measure how much time things take.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
There’s no way any programmer is ever going to get this stuff right.
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
Professional crypto people don’t even get this stuff right. But if you
|
|
|
|
|
have to encrypt something, you might as well use something that has
|
|
|
|
|
already been tested.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
GPG for data at rest. TLS for data in motion.
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
You can also use Guttman’s cryptlib, which has a sane API. Or Google
|
|
|
|
|
Keyczar. They both have really simple interfaces, and they try to make
|
|
|
|
|
it hard to do the wrong thing. What we need are fewer libraries with
|
|
|
|
|
higher level interfaces. But we also need more testing for those
|
|
|
|
|
libraries.
|
|
|
|
|
|
|
|
|
|
**THOMAS PTACEK**
|
|
|
|
|
|
|
|
|
|
Like I’ve been saying, if you have to type the letters “A-E-S” into your
|
|
|
|
|
source code, you’re doing it wrong.
|
|
|
|
|
|
|
|
|
|
**NATE LAWSON**
|
|
|
|
|
|
|
|
|
|
Uh. Ok. Whatever you say, Tom.
|
|
|
|
|
|
|
|
|
|
## 5\. FADE TO BLACK
|
|
|
|
|
|
|
|
|
|
Fade in epilogue
|
|
|
|
|
|
|
|
|
|
The next day, Thomas’ planet was destroyed. Have you guessed the name of
|
|
|
|
|
his planet? It was EARTH\! DON’T DATE ROBOTS.
|
|
|
|
|
|
|
|
|
|
**Published date:**\  22 July 2009
|
|
|
|
|
|
|
|
|
|
**Written by:**\  Thomas Ptacek
|