{"id":26043,"date":"2015-09-02T15:53:04","date_gmt":"2015-09-02T10:23:04","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=26043"},"modified":"2022-01-11T12:10:43","modified_gmt":"2022-01-11T06:40:43","slug":"abusing-password-reset-part-1","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/abusing-password-reset-part-1\/","title":{"rendered":"Abusing Password reset functionality to steal user data (Part &#8211; I)"},"content":{"rendered":"<p>For every developer, implementing a password reset feature is a very interesting part. This is where he develops a logic and then implements it in the code. There is no well-defined industry standard on how to implement a secure password reset functionality in your application. So, the result is that every application has a different way of doing the same, starting from emails, unique URLs, temporary passwords, security questions, OTP etc.<\/p>\n<p>Because every developer has a different (in a way) method of implementing such feature, every time the hacker has to think of a newer way to hack. At <a href=\"http:\/\/www.tothenew.com\">TO THE NEW Digital<\/a>, we audit numerous applications with such feature.\u00a0In this series of blogs, I will analyse common implementations of the password reset functionality in web applications.<\/p>\n<p>We are talking about the applications, which authenticate users with username\/email and password combinations. Let\u2019s list the most commonly used ways to implement the password reset feature:<\/p>\n<p>\u2022 Email sent with a unique URL to reset the password<br \/>\n\u2022 Email sent with a temporary password or current password<br \/>\n\u2022 Secret questions asked and then given the option to reset the password<br \/>\n\u2022 Use of OTP (One-time passwords) or multi-factor authentication<\/p>\n<p>In this first part of the series, we will look into the first method of implementing this feature. Subsequently we will analyse each of these and will recommend the best practice.<\/p>\n<p>&nbsp;<\/p>\n<h3><span style=\"text-decoration: underline;\">Password reset with unique URL sent over email<\/span><\/h3>\n<p>This is the most common method of the password reset. The steps involved are below:<\/p>\n<p>\u2022 User visits forgot password page and submit the email address\/username<br \/>\n\u2022 The application generates a URL with a unique token and sends to the registered email address of that account<br \/>\n\u2022 User logs in to the email account and clicks the URL in forgot password email<br \/>\n\u2022 Now, the user is redirected to a page where he is asked to choose a new password for the account<\/p>\n<p>In all this, there are multiple things that need to be validated at the server end; failing which will lead to a vulnerability in the application. Let me present a case to you. Think of an application that gives the same option of resetting the password. Below screenshot shows an automated email received.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-26053\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/09\/1.png\" alt=\"1\" width=\"399\" height=\"173\" \/><\/p>\n<p>Now when the user click\u2019s this link, he gets redirected to the password reset page of the application. This page gives the option to choose a new password.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-26054\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/09\/2.png\" alt=\"2\" width=\"404\" height=\"249\" \/><\/p>\n<p style=\"text-align: left;\">Now, when the user fills the new password and clicks Change button, a request like the one shown below is sent.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-26124\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/09\/Screenshot-from-2015-09-02-161059.png\" alt=\"Screenshot from 2015-09-02 16:10:59\" width=\"700\" height=\"259\" \/><\/p>\n<p>The catch is to capture this request, and change the value of \u201cemail\u201d to a different one and send the request. Doing that might change the password for a different email account if the application does not validate the token and account combination.<\/p>\n<p>So, let\u2019s see what all hacks can be possible in such a case:<\/p>\n<p>1. Changing the email address in the final request<br \/>\n\u2022 This is happening because the application does not validate the email address and random token combination to be valid. Before completing the request, the application should check if the token is generated for associated email address only or not.<\/p>\n<p>2. Using the same URL for multiple times<br \/>\n\u2022 This might be possible if the application does not ensure that the URL expires after use. If an attacker gets access to such an email once, it can be used to hack an account any number of times.<\/p>\n<p>3. Generating the URL token<br \/>\n\u2022 The randomness of the URL token should be very good, else an attacker might use several such URLs and can predict the randomness. For example, the below password reset URL looks fine at first, but let\u2019s see the magic.<\/p>\n<h6><\/h6>\n<p>But let\u2019s look deeper, this is basically a combination of the email address of the user and date \u2026 Base64 encoded twice and then the ASCII Hex.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-26055\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/09\/3.png\" alt=\"3\" width=\"540\" height=\"339\" \/><\/p>\n<p>4. Executing password resets for numerous accounts.<br \/>\n\u2022 Though this may seem to be a less severe issue, but if your password reset page does not imply any restriction on the number of requests that can be sent from a device\/IP\/account, then an attacker may start an automated script and will send numerous requests for password reset.<\/p>\n<p>5. Username enumeration.<br \/>\n\u2022 What does the application say, if someone enters an email\/username which does not exist in the database? Many applications respond with a response like; \u201cUsername is not in the database, please make sure you entered the correct email address\/username\u201d or a similar message. But the catch is that this tells an attacker if the email account is registered with the application or not. This will lead to username enumeration.<\/p>\n<p>One more interesting issue can be due to Host header validation. If the application generates the reset password link by taking the Host header value in the request, then modifying the same will result in a forged reset link generation. For example; if the request is modified to change the Host header, as below:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-26127\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/09\/31.png\" alt=\"3\" width=\"684\" height=\"251\" \/><\/p>\n<p>This will send a crafted password reset email to victim account (test@email.com) from the application server. Though this issue is very specific to certain type of application, but this can be used as a phishing attempt. The email will look like:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-26071\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/09\/gallery_email.png\" alt=\"gallery_email\" width=\"772\" height=\"343\" \/><\/p>\n<p>So finally let me list down some of the recommendations if you are using the above method.<\/p>\n<p>\u2022 The application should validate the random token and email associated combination before executing the request<br \/>\n\u2022 The password reset URL should have expiry time and can only be used once<br \/>\n\u2022 Always ask the user to provide some data before sending an automated password reset email The data can be something like username and date of birth combination<br \/>\n\u2022 Implement restriction to avoid automated requests through programs. This can be done by implementing human checks, like captcha<br \/>\n\u2022 Implement restriction on the number of requests that can be generated from and IP\/device\/account within a period of time<\/p>\n<p>Thus, it is important to assess the level of security of your application at regular intervals. This is as simple as answering a 5-minute questionnaire like the one below \u2013<\/p>\n<p>Please follow my next blog in this series, for a detailed analysis of the next methods of implementing password reset feature.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For every developer, implementing a password reset feature is a very interesting part. This is where he develops a logic and then implements it in the code. There is no well-defined industry standard on how to implement a secure password reset functionality in your application. So, the result is that every application has a different [&hellip;]<\/p>\n","protected":false},"author":234,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":34},"categories":[2026],"tags":[2274,2270,2273,2271,2268,2275,2267,2269,2276,2265,2272],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/26043"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/234"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=26043"}],"version-history":[{"count":1,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/26043\/revisions"}],"predecessor-version":[{"id":54524,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/26043\/revisions\/54524"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=26043"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=26043"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=26043"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}