{"id":228,"date":"2022-09-25T23:07:10","date_gmt":"2022-09-25T21:07:10","guid":{"rendered":"https:\/\/bergee.it\/blog\/?p=228"},"modified":"2026-04-27T22:18:26","modified_gmt":"2026-04-27T20:18:26","slug":"blind-account-takeover","status":"publish","type":"post","link":"https:\/\/bergee.it\/blog\/blind-account-takeover\/","title":{"rendered":"Blind account takeover"},"content":{"rendered":"<p>In this story, I&#8217;m gonna tell you how I was able to take over an account due to a lack of server-side email verification. To register an account, the user had to enter an email and then got the activation link. This functionality was available on the main site. I entered the email, got the activation link, and played a bit with it however haven&#8217;t found anything special. The format of the link is not important here. I was about to stop playing with this functionality but came up with a really simple idea. What if I enter two email addresses separated by a semicolon? Like this:<\/p>\n<blockquote class=\"wrapped\"><p>account1@mail.com;account2@mail.com<\/p><\/blockquote>\n<p>So I did it and received two identical messages in both mailboxes. I opened up the first link from account1@mail.com, and edited some account details. Then in a private window, I opened the link from the second mail and was taken to the same account seeing all the details I edited a while ago. I thought this behavior could be abused for account takeover when one email would belong to the attacker and the other one to the victim. I noticed the entered email address is encoded with BASE64 format and put into the URL as the value of the &#8220;user&#8221; parameter. Suppose the mail is account@mail.com, the link would be:<\/p>\n<blockquote class=\"wrapped\"><p>https:\/\/target.com\/signup\/?user=YWNjb3VudEBtYWlsLmNvbQ==<\/p><\/blockquote>\n<p>So I need to encode two emails separated by semicolon into BASE64 and give the crafted link to the victim. Suppose we have:<\/p>\n<blockquote class=\"wrapped\"><p>victim@mail.com;attacker@mail.com<\/p><\/blockquote>\n<p>The link will look like this:<\/p>\n<blockquote class=\"wrapped\"><p>https:\/\/target.com\/signup\/?user=dmljdGltQG1haWwuY29tO2F0dGFja2VyQG1haWwuY29t<\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-230\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/09\/2emails.png\" alt=\"\" width=\"1225\" height=\"241\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/09\/2emails.png 1225w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/09\/2emails-300x59.png 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/09\/2emails-1024x201.png 1024w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/09\/2emails-768x151.png 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/09\/2emails-850x167.png 850w\" sizes=\"auto, (max-width: 1225px) 100vw, 1225px\" \/><\/p>\n<p>But now when the victim enters this URL, will see both email addresses in the input form and immediately notice that something is fishy here. I decided to use a simple trick here. I have hidden the attacker email&#8230; just by putting some spaces before the second email which are probably trimmed at the server side anyway. It gives us the following payload:<\/p>\n<blockquote><p>victim@mail.com;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0                                        \u00a0\u00a0\u00a0\u00a0\u00a0attacker@mail.com<\/p><\/blockquote>\n<p>I could probably insert spaces after the first email, so the semicolon would not also be visible to the victim, however, haven&#8217;t tested it back then. This gives us the following URL:<\/p>\n<blockquote class=\"wrapped\"><p>https:\/\/target.com\/signup\/?user=dmljdGltQG1haWwuY29tOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRhY2tlckBtYWlsLmNvbQ==<\/p><\/blockquote>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-231\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/09\/2emails_space.png\" alt=\"\" width=\"1190\" height=\"296\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/09\/2emails_space.png 1190w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/09\/2emails_space-300x75.png 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/09\/2emails_space-1024x255.png 1024w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/09\/2emails_space-768x191.png 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/09\/2emails_space-850x211.png 850w\" sizes=\"auto, (max-width: 1190px) 100vw, 1190px\" \/><\/p>\n<h2>The final attack<\/h2>\n<p>1. The attacker creates the link containing base64 encoded emails as shown above, then delivers this link to the victim<br \/>\n2. The victim opens the link, then submits the form &#8211; the activation link is delivered to both attacker&#8217;s and victim&#8217;s email<br \/>\n3. The activation link is valid for 3 hours, so the attacker must wait as long as possible for the victim to signup and enter personal data<br \/>\n4. The attacker opens the activation link and takes over the victim&#8217;s account<\/p>\n<p>The attack is not perfect because of the following reasons:<br \/>\n&#8211; the attacker doesn&#8217;t know if the victim already signed up and entered the personal data &#8211; if he opens the activation link before the victim, the attack will fail. Hence the title of this post \ud83d\ude42<br \/>\n&#8211; when the victim gets the URL with the crafted GET user parameter, the red error message is visible saying that &#8220;The email is invalid&#8221; just below the input field, so this might trigger an alert in the victim&#8217;s head, users tend not to read messages, however \ud83d\ude42<br \/>\n&#8211; we can only take over the newly created accounts with this method<\/p>\n<p>Because of these reasons, the severity was marked as low and rewarded only 250 USD. Which made me happy anyway.<\/p>\n<h2>Lesson learned<\/h2>\n<p>Do not assume anything upfront while testing things. The bugs might be on the main site even if the program has already dozens of solved reports.<\/p>\n<p>See you next bug \ud83d\ude42<\/p>\n<p>Reward: 250 USD<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this story, I&#8217;m gonna tell you how I was able to take over an account due to a lack of server-side email verification. To register an account, the user had to enter an email and then got the activation link. This functionality was available on the main site. I entered the email, got the&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,32,29],"tags":[18,26,34],"class_list":["post-228","post","type-post","status-publish","format-standard","hentry","category-bez-kategorii","category-bug-bounty","category-write-up","tag-account-takeover","tag-ato","tag-input-validation"],"_links":{"self":[{"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/posts\/228","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/comments?post=228"}],"version-history":[{"count":9,"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/posts\/228\/revisions"}],"predecessor-version":[{"id":239,"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/posts\/228\/revisions\/239"}],"wp:attachment":[{"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/media?parent=228"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/categories?post=228"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/tags?post=228"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}