This webcast was originally published on June 22nd, 2020
In this video, BB King discusses the security implications and vulnerabilities associated with JSON Web Tokens (JWTs) in web applications. They delve into various attack methods, including the misuse of the ‘none’ algorithm and the potential dangers of poor JWT implementation. The speaker also provides insights on best practices for secure handling and validation of JWTs to prevent exploitation.
- Json Web Tokens (JWT) are crucial in modern web application security, used extensively for authentication and authorization.
- Understanding the intricacies of JWT, including their structure and security vulnerabilities, is essential for effective web application penetration testing.
- Proper handling and validation of JWTs are critical to prevent security breaches, emphasizing the importance of using secure algorithms and managing secrets correctly.
Highlights
Full Video
Transcript
Jason Blanchard
Go ahead and put the word out.
CJ Cox
On good morning, Vietnam.
BB King
Really, CJ? Really?
Jason Blanchard
Today we have intern Madeline with us. She’s one of our content community intern. She’s been with us for a couple months. If, you’ve used backdoors and breaches in the last couple weeks, it’s probably something that Madeline helped work on.
So she’s joined us today.
Madeline
Hello, everybody.
Jason Blanchard
Because I asked her recently in a, like one on one session, I was like, is there anything that you want to do while in this internship? And she’s like, I want to be live during pre show banter.
So we’re here.
BB King
Well, how about that?
Madeline
Ask, and you shall receive, right?
Jason Blanchard
I know.
BB King
If you don’t ask, the answer is always no. That’s what my dad used to say. Yeah. Figured I had to throw it out there at some point. These always look so fun. Thank you.
Yeah. So there’s a million people here helping all this to happen, which is great. Anyhow, I’m here to talk about attacking JSON Web tokens, and I’m going to talk a lot about user input because it’s everywhere, and a lot of times you don’t recognize it as user input in web apps.
This is actually, this is, this is an excerpt from a four day course that I’m doing on modern web app pen testing. The first run, actually, it sold out last night.
I was supposed to have some slots open for you guys, but I don’t. So we’re going to run it again. And it’s, a four day class, for four hour days. So it’s not, overwhelming.
And this is an excerpt from that. So this is the kind of thing that I’ll be covering in that course. So if this is interesting to you, that course is coming up, so let’s just jump right on into it.
JSON Web tokens are these things, they’re not always so conveniently colored for you, but this is what they look like. So you might see why you might overlook them.
They look like gibberish. They often show up in HTTP request headers, in the authorization header bearer tokens. This is where you see them.
So if you’ve ever looked at, HTTP traffic and you’ve seen this kind of gibberish here, maybe it was a JSON web token and maybe there was something you could do with that thing.
We are going to talk about those today because not all input looks like input, and pretty much everything in a web app is input, and those are the things you look at when you’re doing your testing.
So JSON Web tokens are, they’re defined by an RFC 7519 there. I’m not going to read the whole thing to you, but these are kind of important. So it’s a URL safe means of representing claims.
Claims is just what it sounds like. I claim to be somebody, I claim to have some permission, I claim to have an account on your web app.
And URL safe just means that it won’t break, the context of HTTP. The claims are encoded as a JSON object and it’s digitally signed.
The JWT is used as the payload of the whole big thing. So terminology can get confusing. And we use JWT incorrectly twice most of the times that we talk about it.
One, the things that we usually call JWTs are actually JSON web signatures, and even that JSON Web token inside there is only part of it.
so not super critical to know, but it’s a detail. And web app pen testing is all about noticing details, I think. So it’s good to know they look like this when they’re decoded.
Actually they look like this. There’s this Jose header and JavaScript people love, everybody loves to make up acronyms that you can pronounce, right? So Jose is the JSON object signing and encryption standard, which is really cool because the o in JSON stands for object.
So it’s the JavaScript object notation object signing in encryption thing. Fun little aside. Anyhow, so that’s all that’s in the header really. There’s the type, it’s a JWT.
There’s the algorithm, which is the algorithm used for signing. There can be more stuff, but that’s typically most of what’s in there. And then there’s the payload, which is the actual token itself, another JavaScript object that has variables and stuff in it.
But they don’t look like that when I showed you before, right? They look different. They’re base 64 URL encoded. Those two things are concatenated together and then they’re signed, and then the signature is base 64 URL encoded and attached to the end and they’re separated by dots.
So it’s base 64 URL encoded, not base 64 encoded. And again, another detail. This is the kind of thing that if you’re not aware of these, you might miss things in web apps.
Base 64 encoding is just a way of protecting data from whatever transport mechanism you’re using. The transport mechanism, sometimes certain characters mean certain things, and if you have those raw characters there, you might break the communication method or part of your message might get dropped or all kinds of weird things can happen.
So base 64 encoding is a way to make that essentially not happen. It takes any arbitrary data and it turns it into just a big long alphanumeric string. But there are three characters in base 64 encoding that can break URL’s.
One of them is the plus character. And if anybody knows what these things are and why they would break it, that would be an interesting thing to throw into the discord. The plus character can’t be in there, so the plus becomes a dash.
The slash character can’t be in there, so that becomes an underscore. And the equals character at the end that we use for padding that just gets taken out. because if you look at how base 64 is used, the padding characters are actually completely unnecessary.
The purpose of the padding characters is to pad the output to a certain, like, a, I think it’s a four block, four block, four block, four bytes blocks. So it’s determined by how long the last block is, how many equals is you have to add.
So if how long it is, you don’t need the equals signs. So losing them is not a problem. You don’t lose any information, but it does mess up base 64 libraries sometimes.
If they don’t, if the padding’s not there, some of the base 64 routines, we’ll just choke on it. The plus used in get requests, among others. Yes. The plus in a URL is an alternate method of encoding the space character, so it can be a plus or a percent 20 in the URL.
Goodwin cactus. So the clues, how do when you found a JSON web token if they’re just this gibberish? Well, they usually start with one of these two strings, because when you encode this, you get this eyj zero e.
It could also start with ALG because JSON, objects, the sequence of data in there is not important, and most libraries don’t guarantee the sequence either. If you encode the same thing multiple times, it won’t necessarily come out the same way in the same order every time.
I typically see them start with the type. So eyj zero. But this is, just a clue for what you might be looking at when you see those, might be a web token.
So base 64. I was tempted to make the joke about base 64 encryption, but I’m trying not to do that because people who know that base 64 encoding isn’t encryption, they might think it’s funny, but people who don’t know, get confused and they’ll hear, oh, this guy who does the web app stuff, he said it was encryption so it must be okay.
It’s not. And I’m going to try to never make that joke again because it’s confusing for people who are new to it. The only thing basic support encoding does is it makes things safe for their transport mechanism.
That’s all it does. Super useful for that, but that’s it. So in this token we have three things. We have the header and we have the payload and the signature.
The header we saw, it just tells you two main things, that this is a JSON web token and it tells you what signature was used. The payload. There are some standard things that are defined by the RFC that may or may not show up in there.
None of these are required, but they’re defined as short strings because we want these to be small, because they take up space, in an HTTP request and that slows things down.
And there are some limits sometimes to how big a cookie can be, has a limit, so we want to keep them as short as we can. There’s ISS is the issuer, that’s who created this particular JSON web token.
The subject is the person or the entity or the computing system that this JSON web token has information about.
Then there’s three timestamps, there’s IAT, which is issued at, there’s an expires at, and there’s NBF, which is my favorite little abbreviation because it’s not really, you can see how it means not before, but like the f isn’t a separate word.
I just, I thought that was neat. I like that they kept all three characters and those are all epic timestamps. So those are the number of seconds since January 1, 1970.
And those are used to indicate when this thing is valid, when it’s not valid, how long it’s been around for. That’s the header. The payload is the whole reason for sending it, right?
The payload is the interesting stuff. These are the claims in the payload. So it can say absolutely anything you want it to say. It can be any kind of JSON object. The things that I see in these, you see usernames, sometimes you see email addresses.
I saw one recently where it had the users roles were described in there. Permissions they have in your application might be used there. Your password can even be in there. I’ve seen somewhere where that’s the case.
And that’s where the whole base 64 joke causes real problems. Because if people think it’s encrypted, they think it’s safe, a place to put the password, but it’s not, so it’s not.
And then there’s a signature at the end and that’s just a digital signature. Of the two things that happened before, these are most often used.
And I think that the most, the best use case for them is in federated authentication and authorization. So this is where, we have like the sign in with Google or sign in with auth zero or sign in with Okta.
So if you have a web application and you don’t want to deal with all the complexity of managing user identities and everything, you can have someone else do that. So you just have a token in your database that has the user’s permissions and what they’re allowed to do and all their data in there.
But you leave it to Google to decide if this person is who they claim to be. Do they really own that email address? Let Google figure that out and maybe they’ll send you back one of these tokens that says, yeah, yeah, I checked this guy out, he’s good.
When they’re used as that, they’re often used in these request headers like this authorization header as a bearer token.
So this is one line, there’s a space between bearer and the eyj. It’s just wrapped so that you can see it. That’s all one HTTP header.
And this is a good reason for the base 64 stuff. So if we go back real quick, you’ll see that this is line seven and that’s all one line. And then this is line eight down here.
Can you see my mouse? You can’t. Anyway, line seven is followed by line eight and there’s a bunch of stuff in between. That’s actually only one line because in HTTP the request headers, each header is one line.
And when you have a blank line which is two characters for line feeds in a row, that tells the server you’ve gotten all the headers. The rest of this is the body. So JSON, object can have new lines in it.
But if you just put that raw into HTTP headers, you’re going to break them and the server will not receive what you meant to send to it. So that’s one reason why we use basic zero encoding.
You can see the mouse. All right, good. that makes it so much easier.
Jason Blanchard
Hey Bibi.
BB King
Yes?
Jason Blanchard
Quick question, just a level set. Somebody wanted to know what JSON was.
BB King
What is JSON? That’s a really good question. JSON is JavaScript object notation, and it’s a way it is just JavaScript and it’s JavaScript objects.
So it’s like in an HTTP get request you see variables at the end, like username equals Bb and password equals password 123.
Those variables could be in a JSON object and it would be the same information but a different format. It would be in that JSON object inside those braces with colon separated values there’s a colon and then commas in between them.
We’ll get into a little bit of that at the end with a demo maybe remind me and I’ll point out what we’re looking at there. But that’s what JSON is.
So there’s more than one rfc that defines JSON web tokens. There’s at least four. There’s JSON Web tokens, JSON web algorithms, JSON web signatures, and JSON web encryption.
And all of these refer to each other. And it’s kind of a tangled mess of if you want to implement this, you have to read more than one and one will lead to the other.
So I think I mentioned this before, most JSON web tokens are actually JSON web signatures. Technically the token is just the payload, but in other places the token is the whole thing, so it’s a little bit fuzzy.
What exactly means what? But when we say JSON Web token, we’re talking about something that is encoded and not encrypted. What that means is that it’s always readable.
Anybody can decode base 64. That’s what makes it useful for protecting things from network effects. Anybody can decode it. You don’t have to have a secret, you don’t have to make a deal with anybody. Before you share base 64 encoded data, you can just decode it.
So it’s always readable, and that’s a property of, of the technology. It’s supposed to be that way. It can’t be otherwise.
Signature though. The purpose of a signature, a digital signature, is to, detect when something’s been tampered with. Some people will say, well, a signature means you can’t tamper with it.
That’s not true, but signature means if it’s done correctly that if you do tamper with something, your tampering will be detected. And it’s a whole different claim, I think to say you can’t tamper with it is too strong a claim for this.
It just means that if you’re validating signatures correctly, then when you receive a token that has been tampered with, you will be able to know that and then you can respond appropriately.
It doesn’t mean it can’t happen. And the interesting thing about this in the context of this talk is that the signing algorithm is part of the header.
It’s part of that first little thing, I think it said, what HS 256 it said before. There’s different signing algorithms that are defined by the rfcs and the header tells you which one you’re supposed to use.
So the way that works then is if you receive this JSON web token and you want to make sure it hasn’t been tampered with, you will look at the header and you’ll say okay, it used the HS 256 signing algorithm, so I’m going to look up in my little library how to do that and then I’m going to calculate that signature on the token that you gave me, and I’m going to compare that signature to the signature that was on the token as I received it.
And if those signatures match, then it means you haven’t changed anything in the header or the payload. So that means I can trust that it hasn’t been modified since it was created.
Jason Blanchard
Stevie, quick question.
BB King
Yeah.
Jason Blanchard
Do we have to intercept these or steal them? And if so, how?
BB King
Well, intercepting and stealing is always good when you’re doing the web app pen testing. Yeah, for a web app pen test, if these are used in the application you’re testing, it’s going to be part of the HTTP traffic.
So you’re using burp suite. Maybe, maybe you’re just using the developer tools in your browser, but you’re seeing that traffic. So these will be visible to you in that traffic and then you can use those, you can do some of these attacks, I’ll show you later, and submit those in place of a legitimate token and see what happens with it.
So yeah, you do have to get at them and you do have to take some steps to make that happen. So like if you’re signed into the web application under your account, it’s going to be very difficult for me to get your JSON web token.
But if I sign m as myself, then I can see my own and I can pull it apart and see how it’s built and maybe I can use that to my advantage in the pen test.
So the signing algorithm is in the header, so the attacker can replace that, they can just decode this and they can say hey, use this other signing algorithm instead and the server may or may not be able to detect that it may not expect a certain signature, it may be flexible, it may want to just take whatever you give me and I’ll do my best with it.
And that’s where you get into functional based security problems in web applications when the server tries to be too kind.
there’s a saying, I, think it comes from the rfcs. It’s about you should be, strict in what you emit. What you put out there should be well formed, and you should be liberal or open in what you receive.
You should try to interpret things and do the best you can to make sense of it. And that’s a great way to be interoperable, but it’s also a great way to cause security problems. If you’re accepting things that aren’t formed correctly, there might be a reason it’s not formed correctly.
Maybe someone’s trying to pull something over on you. So the servers need to be skeptical of these things when they receive this JSON web token. They shouldn’t just accept that everything’s cool about it.
They should be strict. I think more of, looking for problems and rejecting rather than trying to make it work. Hey, CJ, you’re muted.
CJ Cox
Yeah, protects you guys. How long does a JWT live?
BB King
It lives until the expiration date. That’s part of the, payload. Usually that’s, exp time stamp. That’s when it dies.
CJ Cox
If you steal a JWT and they have credentials, can they impersonate that person?
BB King
Absolutely. If you have username and password in the claims there, then you have the username and password and all you have to do is decode it. So it would be bad for people to create JWTs with credentials in them.
CJ Cox
Excellent. Hey, go ahead, Marcello.
BB King
Marcello is muted now just because CJ did it.
CJ Cox
Monkey see, monkey dude, it’s going around.
Marcello
All right, so two quick questions from discord. Is there any other way other than changing algorithm to none? to bypass the signature check?
BB King
To bypass it? That’s the only way I know of.
Marcello
Okay, m. And also, we had another question. Why is JWT token so popular?
BB King
Why? Oh boy. It’s a why question. And it’s about JavaScript because that’s how they did it really well. It’s a super handy way of doing federated authentication, like I talked about earlier.
So if you don’t want to have to manage your users identities and you don’t want to have to manage their passwords and make sure that they’re good passwords and all that kind of stuff, which is complicated and difficult and easy to mess up.
Let somebody else do it. Let somebody else handle your authentication. That’s the most common reason for it. Awesome.
Marcello
There’s a couple other ones, but I’ll let you finish, I’ll ask you.
CJ Cox
Go ahead.
BB King
All right, cool. So I have one red slide because this is the most important thing. Whenever you’re testing web apps, the bottom line rule is don’t trust user input.
Then the thing that follows on that is absolutely everything is user input. You might not think about it that way, but everything is user input. It’s not necessarily something people typed in.
Not everything is their password or the first line of their address, but everything about that request is controllable by the person sending that request, who may not be your customer, he may be some kind of an attacker, and everything about that request is under that person’s control.
So your application has to detect bad situations and react appropriately. And I could spend a whole other talk on this one, but just, I want to throw this out that the OWas top ten issues, there’s really only three most.
Seven of them are about unexpected input or poor input validation, or not handling input correctly, and then there are two others. So everything is a user input problem.
So about the signatures. one of the rfcs defines the algorithms that are allowed. One, of them is HS 256, which is HMAC, with SHA 256, which I don’t want to get into the cryptography part of this, but basically there’s a secret that you have, that you share with whoever’s creating this token.
So you would share this secret with Google or with Okta or with whoever’s doing that. They would use that to create the signature. So that secret is something that an attacker won’t know, so they can’t.
That secret is what prevents them from forging it. And that’s required. You have to support the HS 256 algorithm. There’s an RS 256 which uses public key cryptography.
So you don’t have to share a secret, you share certificates and that’s a different one. That’s recommended but not required. And then none, which means there is no signature, which means there is no protection of any kind on this thing.
Not only is it not protected against people viewing it, because it’s just base 64 and you can decode it, it’s also not protected against forgery because there’s no secret involved. Anyone can create one.
That sounds bad, but it’s optional, so that’s good. The reason this one sounds bad is this is again from the, from the RFC JWTs may be created that don’t provide integrity protection, which I would say is resistance to tampering.
And that’s called an unsecured jWs. So they’re very blatant about it. One that uses the none algorithm, it’s unsecured, they call it that in the RFC. So they’re warning you that this is not a thing that you want to be able to rely on.
Right. So it’s great that they said it’s optional. It would be better if they said it doesn’t exist. It’s not possible, but optional. All right, that’s the next best thing.
A lot of times in things that involve cryptography or keeping secrets or like layers of encoding, you’ll see that those layers in the specs are often optional.
And that’s horrible for security because people will use them that way and they’ll skip some of these things that should be required. But the reason they do it is it’s not because they’re dumb, it’s not because they’re not thinking, it’s because it’s so much easier to test if you can turn off layers one at a time.
So if I can just make sure that I’m following the right syntax, I’m using the right encoding for my string, maybe I’m using UTF eight or UTF 16, and maybe that’s important and maybe only one of those works.
So if I encode this string that it shows up finding my text editor. Maybe your system won’t handle it because I used an encoding that you didn’t expect. It’s way easier to troubleshoot that if that’s the only thing that can be wrong.
But if I could also have gotten one of the algorithms wrong, or if I could also have messed up the private key I’m using, or if I could also have, I don’t know, sent things too fast, there’s too many variables and it’s hard to troubleshoot.
So whenever you see one of these things about security that offers a way to disable all the security. People like to pick on that, but it makes it so much easier to implement things.
You just have to be careful about what you live with afterwards.
another RFC, this is not the same one, this was one of the four. This one says that the none algorithm must be implemented.
So one of them says it’s optional and one of them says you have to do it. This is where looking into rfcs can be a form of pen testing itself. Really look at these things and put yourself in the shoes of somebody who’s building something described by this RFC.
And the things that must be done, assume you do those, the things that are recommended, maybe you do those, maybe you don’t do those things that are optional. Maybe you do that, maybe you don’t do that.
There are sometimes conflicts between all those different options, and there might be more than one way to interpret correctly what is described in the RFC.
So if there’s a way to interpret it that’s more secure and a way to interpret that that’s less secure, you can be pretty sure that both of those options exist out there in the world. Somebody has chosen one, somebody has chosen the other.
So this is where you can find ways to attack things. And this is where the attack using the none algorithm came from, right? Someone read the RFC and said hey wait a second, we could disable all the protections.
I bet somebody built that and that’s all it took. That’s the security side of things. The privacy side of things is a little bit different. Privacy is different from security.
They’re related, but they’re different. Privacy is about, I don’t want you to see what I’m up to. And JWTs may contain privacy sensitive information.
This is from the RFC again, and it says when this is the case, measures must be taken. We don’t define any of those measures in JWT. There aren’t any specific things in this spec that do that.
They say there’s a couple paragraphs, I think it’s literally a couple paragraphs that basically say encrypt the entire token or use TL’s, use SSL. So it’s not disclosed over the wire as it’s being transmitted from your browser to the web server.
And then at the end it says at the bottom hey, by the way, the best way to keep these safe is don’t put privacy stuff in there. So this is kind of a hand wave. This is kind of the use tor use signal of JWTs.
So again, mister Snowden is not incorrect. If you’re doing things that you want to keep secret, using Tor and using signal are good ways to make that happen.
The best way to protect secrets is not to share them at all. If you have to share them, then maybe use Tor, maybe use signal, maybe use an encrypted JWT, maybe don’t put them in the JWT, that’s the privacy.
And then on security they talk about the key entropy and random values. So when you have that key, that’s part of your HMAC, or part of the public key signing algorithm that you use, you want to make sure that it’s a good securely random value, that is not something someone could guess is what that means.
And then key protection is keep it safe. And once youve come up with a good secret keep it somewhere and then all the rest of it is all the same stuff you see in every crypto thing.
Cryptography is hard, theres so many things you can get wrong and thats what the rest of those covers. So we’ve read the rfcs and we maybe want to use one of these or maybe we want to attack these.
So that leaves us with, there are no privacy protections, the none algorithm disables signing completely and the none algorithm is, we’re not quite sure if it’s required or not.
So the attacks then for those there’s no privacy. So information disclosure is that attack and we just decode the payload and we can read it. And if there’s something secret that shouldn’t have been in there, that’s a finding in itself.
Maybe you can use it for a further attack, but that in itself would be a finding. Hey, your credit card number is stored in plain text inside your JWT.
The none algorithm which disables signing completely means that the JWTs don’t have to have a signature, which means anybody in the world can create one. So anybody can create one. So you have the potential for forgery.
If your system supports the none algorithm and accepts JWTs that use that, and then there’s also cracking that password, that secret is subject to attack, right.
So you could guess, you could guess at what that secret might be and use that secret to do the signature and see if the signatures match. And if they do, you found the secret. And now we’re back to number two.
And even though it’s signed you can still forge them. I don’t cover the cracking aspect very much because it’s the same as any other cracking aspect, any other cracking attack.
You get this JSON web token and you can do all of this testing offline on your own system. You just sign and sign and sign and sign and sign and check your signature to see if it matches the one that was already on there.
And when you get a match you have found the key. This is an interesting attack for JSON Web tokens because the examples that you see out there for how to build JSON Web tokens pretty routinely use horrible horrible secrets.
This one here, the secret is this string with the s and the four or five h’s that is the key. There’s nothing done with this. This isn’t subjected to any sort of manipulation or computationally intensive things that might slow down guessing.
It’s literally those, what, five, six characters? That’s the password. If you want to try JSON web token password cracking, just go around to all of the, different libraries out there that implement JSON web tokens and look for the passwords they use in their example code.
I guarantee you somebody has copied and pasted that into their code while they were learning this, and maybe they never fixed it. Anyhow, hashcat supports those now, has supported them for quite some time.
So where do you want to practice this? You want to practice where you have permission. And this is one thing I love about web apps, is it’s so easy to find places where you can do this with permission. Juice shop.
I use juice shop a lot in the course that I’m teaching for two reasons. Several reasons, actually. One reason is that it’s because it’s so complete, it has so many different things that you can attack and different ways of exposing similar issues.
The other is, that’s why it’s built. That’s what Owasp, and Bjorn built it for, is to use as a teaching platform.
And the other is, it’s something you keep after the class is over. So after we’ve done everything that we do in the class, you still have the same thing. You’ve gotten a foothold, you’ve done a few things during the class, and now you have a comfortable, familiar application that you can keep practicing against.
Another great place is, digit ninja. He’s, one of the friends of Bhis. he gives away a lot of tools. He has a lot of things on his website, Digininja, and he’s got a section called authentication labs.
There’s maybe ten or so different vulnerabilities he’s intentionally coded and he’s got on his website. They’re just up there. You can play with them.
JSON Web tokens is one of them. So this is where I’m going to get into taking some risks, trying to do some demos, some of the stuff that’s in the class, and some of the ways to use to our advantage, some of these things that we’ve talked about.
Do you have any questions, any questions before I jump into those helpers? Anything showed up.
CJ Cox
So many questions. So many questions.
BB King
All right, give me just a couple and then I’ll do the demos and then we’ll do some more. Yeah.
CJ Cox
Are JWT secrets the same server wide, session wide or other.
BB King
Other, they’re generally going to be the same between from a given provider. So if you have a secret, if, auth Zero does your authentication for you, you’re going to have a secret between you and Auth Zero.
And how often you change that secret is up to the two of you.
CJ Cox
You said it.
BB King
Yep.
CJ Cox
Can somebody steal JBWT tokens if they’re trafficking over TL’s?
BB King
not like out of the TL’s tunnel itself, but there might be ways to get a web app to disclose them in another way. So, if you’ve got cross site scripting in the application, you could write a cross site scripting attack that would read the JSON web token and ship it off to you some other way.
Absolutely.
CJ Cox
What is the best tool for JWT?
BB King
Testing? Pen testing. The best tool depends on your goals and what you’re comfortable with. I’m going to show you a couple of tools and you can pick which one works the best for you.
CJ Cox
Marcello, take a couple here.
Marcello
Yeah, I got a bunch of them too. So what if we were to modify the GWT’s algorithm from rs 256 to HS 256?
Is this considered another avenue of attack since we’re changing from asymmetric to symmetric? from an asymmetric to a symmetric.
BB King
Algorithm, it is, it’s less likely to be effective than if none is supported, because none’s just so obviously dead. But there is another type of attack that’s in some of the references here in the end of the slide deck, where if the implementation has changed, if at one point it used the public key version of signing, and then it decided to change over to the shared secret way of signing, it’s possible that it could still accept, the public key as the literal secret for the signature.
So if you don’t make that change correctly, it’s possible that somebody could send in the previous public key, which is public and not a secret at all, and your system will use that as the password, as what you typed in for the H vac.
That’s possible. I haven’t seen that myself in real applications, but it’s a possibility.
Marcello
Also, another interesting was can we compile all the test cases and share with everybody? I thought that would be useful.
BB King
yeah, actually, I’ll show you some of them. There are some that are already built into a, plugin for burp suite or an extension for burp suite. Awesome.
Marcello
There are a bunch of others, but I’ll let you continue because otherwise you’d.
BB King
Run out of time. Thank you.
CJ Cox
Try not to dos you bb.
BB King
Right, right. Cool. Well no, this is good timing. I think we’re going to be able to get through some of these. So we’re going to use Juiceop to look at some of these JSON web tokens. So the prerequisites for this, you register an account at Juicehop and you notice while you’re just exploring to look around before you start your real testing, you notice that there’s a user called administrator and there’s a review on one of the products that has that email address in it.
And then you notice in the traffic that there is a call to this who am I function in. the traffic. And inside that thing there is a JSON web token.
I open up burstmite, I log in as a normal user. I’m going to send that who am I request to repeater and then I’m going to resend that to make sure that it still works. That’s something I always do in virtually.
So here’s the review and see admin. So we know that this user is a user and I look at this traffic and I hope this is big enough that you can read it.
This is way bigger than I’m normally comfortable with, but I want you to be able to read it. So this request gives this response which is shoot.
304 not modified. So anyway we’re going to send this to repeater and we’re going to send it again and see what happens.
304 not modified. So that means that it’s checking to see if this is cached. So we’re going to delete that line and send it again. And ok, this time it worked and it gave me my user id and this is who I’m logged in as and the profile image and I’ve got this JSON web token.
There’s Let me go back to the proxy and we’ll start with the we’re going to start with the tool that will identify these for you.
So I’m going to send this to Joseph which is the JSON web token attacker tool. And the type here is, because my font is so gigantic, type is JWT algorithm by default is rs 256.
So I’m going to try the signature exclusion attack which is changing the algorithm to none and omitting the signature. And then I’m going to click attack. That’s kind of all you do.
And I get back this, I get oh it’s a 304 again. All right, so I’m going to go back to repeater because I fixed that here and I’m going to send it from here.
Go back to Joseph. There’s a new tab, I want signature exclusion. Load it and attack it. And now we get different length. So what happened?
So this response, it’s the same response but you can see it used algorithm of none and these all have the same length so they’re all probably the same response.
So it accepted the word none, in all different capitalizations as the signature algorithm. So this is vulnerable to that attack.
But if you notice this request, the web token shows up twice. It’s here in the bearer token and it’s also here as a cookie. So which one did it use?
Well, the one that’s in the cookie ends with a dot which means that the signature would be after that and it’s gone. So this is the one that Joseph was playing with. If you look up here, here’s that same dot.
So this is the signature. So this burp extension only messed with the one in the cookie and didn’t touch the one in the authorization header because it worked.
Well we don’t know, we don’t know why it worked. Right. Maybe it worked because this one is the one the server read and it just ignored the one in the cookie.
Don’t really know. So let us take this request.
Jason Blanchard
And.
BB King
We’Ll go back to repeater. Actually no, all I need is where’d it go? All I need is this part. This is the new header with the none algorithm in it.
So I take that back to repeater and I change this. Yes.
Jason Blanchard
Quick question, where can you find Joseph? I do not, the person says I do not see it in the burp extender store.
BB King
right, because it’s not called Joseph there. It’s called shoot, let me go back to etcetera. It’s called JSON web token attacker.
I don’t know why they have different names for it.
Jason Blanchard
Thank you.
CJ Cox
Real quick, is it correct to say that JWT is used in API authentication?
BB King
Yes, very often they’re using API authentication.
CJ Cox
Awesome, thanks.
BB King
So here I think I’ve changed the, this is the one that has signature none. I’m not quite sure if I did that or not. So I’m going to send that to the decoder, decode, that as base 64.
Nope, that has the rs 256. So I’m going to make it none and then I’m going to re encode it as base 64. And remember that little guy is going to cause us trouble.
So go back to repeater, delete that and paste that in. So now if I leave that in there, let’s see what happens. Oh, it still worked. So it must not be using that one because that would have caused a parsing error.
So what I’m going to do next is I’m going to just delete all of the extra stuff so that there’s fewer variables and then I’m going to put my modified thing in there with that equal sign in there because that’s going to break it and I get back at kind of nothing.
So maybe it just died on that. Nope, it’s still not working. Oh, that’s right. There’s still a signature on it. So I got to get rid of that signature and now it comes back and it works.
So now I’ve got a request that has the none algorithm in it and it has all this other stuff which is whatever is in that JSON web token. And I can mess with that later if I want to.
That’s the next thing I will show you. But I want to show you how, you can manually do what Joseph did. So if I go back to the first request here, second request, okay, this is the one that is signed.
This is the normal request. I’m going to send this to intruder this time and I’m going to get rid of the things I know aren’t necessary to make it easier to mess with.
I’m going to clear all the payload positions and I want to mess with the header. Right. And for payloads I want to try none.
none and none and none. But if I just put those payloads into that position it’s just going to be the word none and it’s not going to be a valid JSON web token anymore.
Right. So I need to do an extra step. I’m going to send this to, I’m going to copy this, I guess, and go back to decoder, paste that in and I am going to copy this because that’s what that is.
After it’s base 64 decoded, I go back to intruder and payloads. I’m going to add payload processing. I want to put the word none in place of the other signature algorithm.
So I’m going to add a prefix and my prefix is going to be everything but that. And then I’m going to add, guess what, a suffix and my suffix is going to be everything after that.
And then m, I need to base 64 encode it. So I’m going to base 64 encode it. So now I will have recreated that header but with none as the algorithm in the token.
And I’m getting 200. That’s good. Oh, but my user’s gone. So what’s wrong with my request? So I’ve got. The signature is still on there. I got to get rid of that guy.
And here percent 3d is a h. It’s a, URL encoded equals sign. So I didn’t take care of everything I needed to take care of. So back to positions.
Find that last dot. Get rid of that. Make sure I still have two blank lines in the payloads. I’m going to say don’t URL encode things.
But the equal sign is still going to be there, which is going to cause trouble. So let’s do one more rule. Let’s match and replace. Let’s find an equal sign and replace it with nothing.
So we got rid of the signature, we got rid of the equal sign and we encoded everything correctly. So maybe it’ll work this time.
That thing that pops up is just, a limitation of the free version of burp suite. The intruder is throttled. But I’m only doing five requests here, so it still works.
Here’s my request. Here’s my response. Hey, it worked. I got back what I was expecting to get back, but the token I sent in said none.
What I just did here manually is exactly what the Joseph plugin does automatically. But now I know how I did it and I know how it worked. That’s a little more interesting to me.
I like tools that save me time, but I like to understand what they’re doing. Yes.
Jason Blanchard
I’m not sure how much content you have left, but do you have time to walk through that one more time and now that you’ve shown everyone and just do it slowly, step by step, or do we do that during the post show banter?
BB King
I have one more demo I’m going to do that builds on this one and repeats some of the same steps. Let me do that. And if that doesn’t answer the question, I’ll do this one again.
Jason Blanchard
Sounds good.
BB King
All right, so that’s the first attack. This is the secrecy thing. Well, the secrecy thing is just, we just decoded it, right? And we found in the whoops.
In that token we found that we had, we had the username, email address. There was a user id in there also that maybe was all that looked interesting.
let’s see. We, can also do this on the command line. Let me save that for the next one too. We’ll do command line version if we can get time after that.
This is interesting. So now all I know right now, I haven’t attacked anything, I haven’t done anything. All I’ve learned is that I can create a token that the server will accept and that’s a finding. But now what? Now what do I do from here?
Now I need to show what the impact of that is. Why is that a bad thing? Apart from people can forge it, it’s not necessarily obvious to everyone why that’s bad. So we’re going to use the non algorithm to forge a token.
So I showed you this advanced payload processing, I showed you what that looks like. And Joseph did the same thing.
But it didn’t, didn’t forge anything yet. Well it did, but it forged the same thing that was in the original token. So once we found that none works, we’re going to look and see what else might be interesting to do with it so I can close this attack and I can go back to my positions.
So what, actually let me do that again so I can get a good header. The response, did it work? Yes.
So I want this now because that’s the head that has the none algorithm in it. And I’m going to go replace this thing with the one that I know works.
And now I want to see what’s in here. So if I copy this and send this to decoder, it’s already decoding as base 64.
So you can see what’s in here. Success data has all this stuff. This is not just what came back in the response. There’s password crazy.
There’s a role, the role as a customer. There’s a thing called deluxe token that has a null value. So it’s not a deluxe token. Profile image secret for multifactor authentication.
That’s a crazy thing to put in there. Maybe.
CJ Cox
Can you maximize your window?
BB King
It won’t help. This is the best I can do with burp suite.
CJ Cox
Thank you, sir.
BB King
So I know there’s an admin user, his name was admin op, like that.
So what if I, instead of sending my own email address, what if I send in this other guy’s email address? I’m going to encode that as base 64, select all that and copy it and go back to intruder.
I don’t need intruder for this. I was back on the other thing. I want repeater for this one actually. because I’m only testing one thing at a time here. If I had a whole list of email addresses I wanted to try, I would use intruder.
But as I don’t, let’s go back to this trimmed.
Want to make sure that it still works. Okay. So it hasn’t timed out. So that’s good. And then I’ve got, that’s the whole thing with, this was the one where I put in my other address.
Right. I did not go back to decoder.
and see what I did wrong. I didn’t copy the right one.
Back to repeater, delete that, paste that in place, get rid of the equals sign. And now it thinks I’m admin.
My id number hasn’t changed. I wonder if I could change that. Maybe the id number has something to do with my privileges. So now you just go back to decoder here.
And let’s change the id number to one because one is usually admin. Right.
And back to computer. Now is delete first and then paste just to make sure I’m actually pasting. There’s two equal signs.
Don’t need those. Send that, cannot read property of null. Something is broken up.
there’s an equal sign there. Where’d that come from? Let’s go back to decoder control.
A control circle repeater. And I’m replacing just the middle bit, not the equal signs.
There we go. Now I’m user id one and I’m admin at juice shop. So this is showing the effects of why it’s bad to allow someone to give you a none token. Because now I can be whoever I want.
And by using, by using intruder in the way I did, I was able to see how that actually works and to recreate that manually.
So now if, for example, I didn’t know that admin had an account on this system, but I had a bunch of email addresses of people who use this system, I could have used intruder in the exact same way.
But instead of using different values for the word none, I would use different values for email addresses and send those, I could send 1000 of them at once and see which one of those returned with hits. So I would be discovering who has accounts on the system and possibly depending on how the server processes this, possibly just impersonating all of them right now.
So that is the walkthrough I had planned for you in the class. I go through, doing the same things with cybershef and on the command line.
So there are always different ways of doing it. Someone asked earlier, what’s the best tool for this? The best tool is the one that works for where you’re at. The best tool to me is one that’s the most flexible. So command line is super flexible, but sometimes hard to remember what to type.
so there’s a bunch of options out there to mess with these things. I got a couple of further study slides at the end, and if you picked up the slide deck, you have these.
There’s a great blog at medium that talks about all different kinds of JWT attacks. Digineja’s auth lab. There’s a best practices thing from just February of this year. So if you’re on the blue side and you want to not make these mistakes, there’s an RFC for you.
Auth zero uses. JWt’s quite a bit. And they’ve got JWT IO, which is a great place to play with them. It’s an online decoder. So everything I just did, now you can do that on their website.
And there’s a fun talk by Randall Deggies, I think is how you say his name. I saw this talk at Codemash a couple years ago, and Randall doesn’t like JSON web tokens. And he tells you all about why.
So it’s a good thing to watch and disagree with the things you disagree with, understand why he thinks they’re so horrible, and maybe you can solve some of those problems in the way that you use them.
And then the RFCs and all the other stuff that I have talked about here. So, for further study. So are there any other questions?
CJ and Marshall?
CJ Cox
Nope. You covered them all.
BB King
Be I am so on it. No. What’s up? I got a bunch of.
Marcello
Oh, sorry. I got a bunch of other questions. Is there a way to know the id numbers used by a web app? No, it’s usually one for admin.
BB King
I said it’s usually one for admin because that’s something that pentesters say. If you create users and if you assign their identifiers sequentially, which is the obvious thing to do, it’s not always the best thing to do, but it’s the obvious thing to do.
Then the first one you create is going to be number one or number zero. And the first one you create is probably the one that you use to create other ones with. So it’s probably admin. That’s why pentesters like to say id one is a good one to go after.
Awesome.
CJ Cox
Is a WAF effective against these bb?
BB King
A waf? No, I don’t think so. Well, think about what the WAF would have to do.
The WAF is going to have to know what kind of jwts to expect it’s going to have to see that it’s a JWT and decode it and do some analysis of what it decodes and make some decision based on that.
I don’t see a WaF doing that effectively without adding a bunch of overhead and a bunch of potential failure modes.
Marcello
Does sign jWt with ETF’s? Break your joy too?
BB King
Signed JWT’s with ad fs I’m not sure that I’ve seen well, oh, oh, so active directory using these. I’ve not, can’t remember seeing that in a real web app, but I imagine that it would be done correctly there.
And yes it would. So it wouldn’t let me forge them, but it would let me see what’s in that payload and that could be interesting still, even though I can’t just completely make up my own, maybe there’s some disclosure that’s interesting and worth knowing about.
Awesome.
Marcello
can a token be refreshed just like a session?
BB King
Kind of. The tokens are completely divorced from either system once they’re created. The receiving system doesn’t know what tokens have been created and the token is meant to be self contained.
So if you decode it and check the signature and that’s all good, and the expiry timestamp hasn’t passed yet, then that token is still good. You as the server are using that token like this one is as a session cookie.
You could just keep updating that expires at time and regenerating, reissuing that token with every request. It’s a little bit iffy whether you want to do that or not, because there’s no way to kill one of these things.
There’s like a session that’s actually maintained on the server. The server can decide at any moment that something happened. I need to kill all my sessions and make nothing valid anymore, make people log back in again.
You can’t do that with JSON Web tokens because you don’t know they exist until they come in. So if you’re constantly refreshing it, then you’re constantly defeating the value of having an expiration in the first place.
CJ Cox
Are there known vulnerabilities in JWT libraries that people should be aware of?
BB King
I don’t know of any current ones. I know that there used to be some. This whole none thing was built into a bunch of the libraries early on, back in like 20 1617 when JSON web tokens were new.
One of them just resurfaced, actually. I don’t know, sometime earlier this year. This is what prompted Digiminja to add his tests was that we all thought that this whole none thing was a solved problem.
And I did too. And I ran into this actual problem. The none algorithm was accepted on a real pen test for a real customer in production recently. So we all kind of thought that this had been solved and people stopped doing the whole none thing.
But things revert sometimes and you see old problems again.
CJ Cox
What version of Linux are you using in your vm?
BB King
That is Ubuntu 2004. It’s the one with the dog. It’s a new one. It’s a new lts version.
Nice.
CJ Cox
A lot of people asking about how to fix these things and I think your references kind of pointed the way. You’re talking about another session, right, to talk about fixes.
BB King
Yeah, the current best practices thing is kind of it. So the fix is conceptually the fix is it’s all user input.
Don’t trust it. So that means don’t just accept whatever signing algorithm is attached to these random JSON web tokens that come to you.
You decide what signing algorithm you’re going to support and that’s the only one you use. So if you see a token coming with a different signature it’s invalid. A different type of signature it’s invalid.
And if you’re using the secrets rather the HMac rather than the digital signatures, make sure that that secret you use is a good secret. And a good secret is when people say it’s random.
Well no, it’s not random. It’s unpredictable. It’s unguessable because there’s that XKCD comic that the number four was randomly chosen or can be random, but it’s not hard to guess.
So what you want is hard to guess. You want a big, long cryptographically secure 128 bits of entropy type secrets. No way those things, you’re as good as you’re going to be.
Jason Blanchard
We’re going to wrap it up for the webcast and then we’re going to do pre show badger.
CJ Cox
I just want to say that we were dossed by the volume of questions. This kind of thing fans out. There were 1 million questions.
We just couldn’t get to them all. So apologies, folks.
BB King
Yeah, all right.
Jason Blanchard
thank you for being here today for this Black Hills information security webcast. We will be sticking around. So we’re just going to kill the recording. So this is just to tell the editor. That’s it.
We do these for an hour, but for the people who show up live we do a lot of extra q and a, so thanks for being here. If you need a pen test, where to find us. And with that, thanks for being here.
feel free to leave, but we’re going to do q and a at this point.
Hey, Bb. Good job. All right, thank you.