Mastadon's Misconfigured Rack_Attack.rb Does Not Appropriately Protect Against Brute Force Attacks in mastodon/mastodon
Reported on
Jun 20th 2022
Description
Mastadon relies on the Rack_Attack.rb file to manage API throttling in the application through the declaration of absolute paths (i.e., /auth/sign_in). By appending random strings of characters to the end of the directory in a POST request it is possible to bypass brute force protections. Tester attempted to file this finding through Intigriti as requested on Github, however it's noted that Intigriti is phasing this project out. Tester utilized the staging.mastodon.social demo application, and also a local installation of the application to confirm the vulnerability.
Tester was able to bypass sign-in restrictions by appending .json behind the directory, however any string is viable. It was possible to identify valid passwords based on a 406 response from the server, versus invalid responses containing a 401 error. Rack_Attack declares a 300 request per 5 minute limit, which appears to be the only appropriate restriction. Provided an attacker maintains less than 300 requests in 5 minutes it is possible to completely bypass all restrictions.
Note that the tester has a proof of concept fix for the issue already and is happy to work with the maintainer to fix it. Tester would ask that a comparable bounty amount be applied by the maintainer as it would be with Intigriti, where the low-end of a valid finding is 1,000 pounds, and a high end finding is 20,000 pounds. Tester would have submitted through Intigriti had it not been for the pending closure of the program unfortunately. Tester does realize that the prize pot is depleted on this platform, and it would be at the discretion of the maintainer to honor a payment or not. Either way, CVE status will be requested due to the severity of the finding.
Proof of Concept
POST /auth/sign_in.json HTTP/1.1
Host: staging.mastodon.social
Cookie: _mastodon_session=wM5JZ5uFbag8V81Jk2jWsVES1Gl8dkukxjZdaN%2FnNNHh9UFamiUn62zY8Mh9nR8zu82pD%2FddQndPV8rJTgIiMPppVybkaJ3ULzMmawkADNUvx7q9Lz8vmT0svrnKDfL9MqnQ5YhKEvIq6c3LPBM8O1U%2FT4qQk2FZIoyjc1S1O8kbBBj6eYztCHLDdC25PnZ9%2Fd0IOB2fEW9qDnvNrNzxw77UcgRHjt9GWCw%2BPTh1aBS6J8a9f94ZXf%2BlgE2dCubsH7V5PL8Ijuq1bsePt27q1Pb8TbXzCBaO%2FA%3D%3D--JIrYMu6fwlXhF3%2FU--cSi5lAMp4z2IyeM1WfCzdQ%3D%3D
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,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: 187
Origin: https://staging.mastodon.social
Dnt: 1
Referer: https://staging.mastodon.social/auth/sign_in
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Te: trailers
Connection: close
authenticity_token=1ItjuEy9z3KwYRBwjKswfJWvwnGXIrnLvn7AT2czIG1jYpaN193lao-RldsgPydOi06hRmp12FXs6zK0jd6sZA&user%5Bemail%5D=themayor%40intigriti.me&user%5Bpassword%5D=§testpasswordhere§&button=
None of the API endpoints noted in the Rack_Attack configuration appear to have appropriate constraints, which would allow comparable brute force attempts against each.
See following link for screenshot with bypass responses and times. https://www.notion.so/themayor/Mastadon-Rack-Attack-7e665d571f4f407286480409594ef916
Impact
The impact of this vulnerability is that an attacker can brute force logins or other API calls in the application without threat of throttling or IP blocking.
Remediation
Tester has a tested proof of concept locally that they are willing to share and provide with the maintainer once conversation has taken place on an appropriate bounty payment, if applicable.
Occurrences
Hi @maintainer. Any thoughts on a possible bounty being as you were recently on Intigriti?
Also, I have some code updates to help fix the issue if you and your team are interested. Thanks!
Hi Joe, the Intigriti program was funded by the European Commission. We on our own do not have the means to award such high bounties.
Regarding the fix, I have an idea on how it could be fixed, but if you want to have a go at submitting one to collect a huntr.dev bounty (if there is such a thing) I'm open to it.
Understood, and no worries at all. Looks like the bounty pot is gone for your organization here on the platform, so that's really the only reason I was asking if your organization was able to honor something like was offered on Intigriti. Not sure if @admin makes case by case determinations on things when pots are depleted.
I can fork the repository and submit the fix through here for your review on your Github. In short, your rack_attack.rb file is configured to use specific, declared paths. As an example, req.remote_ip if req.post && req.path == '/api/v1/accounts'. The issue is with "req.path ==" rather than something like req.path.starts_with?('/api/v1/accounts'). I have the fix tested on my end and I'll get the fix to you soon.
Thank you for following up!
I've submitted the patch for your review. Please let me know if you have any questions.
I suspect the patch is not sufficient as there are many API paths that start with /api/v1/accounts
. For the /auth
paths that approach is probably fine though...
I've tested it against the attacks listed and it is sufficient. All of the directories that could receive those requests in the rack_attack file have been changed to starts_with? rather than req ==.
In the end it's your application, however from my end the modifications prevent the actions.
@Joe - great work on the report and thanks @Eugen for your diligence in responding to this, as ever! ♥️
Unfortunately, we can only reward bounties when the prize pot has funds or it is being sponsored by an organisation.
To clarify why I think the submitted fix is insufficient is that it affects all API endpoints that start with /api/v1/accounts
, of which there is a non-neglibile amount. So while it fixes the one reported bug, it introduces another bug, which rate-limits a lot of APIs the wrong way. The real fix is likely to disable the ability to append the desired format to API paths (since all APIs only ever return JSON).
@eugen By no means do you have to accept my suggested fix. More or less just wondering if there was an update on your end so we can move towards the final disclosure.
You're welcome to gently follow up with the maintainer @dievus, it's not up to us
@eugen @maintainer Hello. Any updates here? Now that your platform is getting more popular it'd be nice to get this thing wrapped up and out the door.
@eugen thanks! Can you click the button to make the report public?