<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[attack ships on fire]]></title><description><![CDATA[The unbridled ramblings of a security dinosaur.]]></description><link>https://attackshipsonfi.re</link><image><url>https://attackshipsonfi.re/img/substack.png</url><title>attack ships on fire</title><link>https://attackshipsonfi.re</link></image><generator>Substack</generator><lastBuildDate>Tue, 07 Apr 2026 06:50:29 GMT</lastBuildDate><atom:link href="https://attackshipsonfi.re/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[attack ships on fire]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[jhsfddfg@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[jhsfddfg@substack.com]]></itunes:email><itunes:name><![CDATA[attack ships on fire]]></itunes:name></itunes:owner><itunes:author><![CDATA[attack ships on fire]]></itunes:author><googleplay:owner><![CDATA[jhsfddfg@substack.com]]></googleplay:owner><googleplay:email><![CDATA[jhsfddfg@substack.com]]></googleplay:email><googleplay:author><![CDATA[attack ships on fire]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Exploiting Reflected Input Via the Range Header]]></title><description><![CDATA[TL;DR Reflected input is often unexploitable because the attack ends up in a place which stops it working, such as inside a quoted attribute.]]></description><link>https://attackshipsonfi.re/p/exploiting-reflected-input-via-the</link><guid isPermaLink="false">https://attackshipsonfi.re/p/exploiting-reflected-input-via-the</guid><dc:creator><![CDATA[attack ships on fire]]></dc:creator><pubDate>Thu, 19 Dec 2024 09:37:11 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!IGLj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2f3ff51-9e1a-47e7-80bf-3ab236de2da0_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IGLj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2f3ff51-9e1a-47e7-80bf-3ab236de2da0_1024x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IGLj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2f3ff51-9e1a-47e7-80bf-3ab236de2da0_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!IGLj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2f3ff51-9e1a-47e7-80bf-3ab236de2da0_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!IGLj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2f3ff51-9e1a-47e7-80bf-3ab236de2da0_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!IGLj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2f3ff51-9e1a-47e7-80bf-3ab236de2da0_1024x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IGLj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2f3ff51-9e1a-47e7-80bf-3ab236de2da0_1024x1024.png" width="340" height="340" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b2f3ff51-9e1a-47e7-80bf-3ab236de2da0_1024x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:340,&quot;bytes&quot;:1257447,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IGLj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2f3ff51-9e1a-47e7-80bf-3ab236de2da0_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!IGLj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2f3ff51-9e1a-47e7-80bf-3ab236de2da0_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!IGLj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2f3ff51-9e1a-47e7-80bf-3ab236de2da0_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!IGLj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2f3ff51-9e1a-47e7-80bf-3ab236de2da0_1024x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1>TL;DR</h1><p>Reflected input is often unexploitable because the attack ends up in a place which stops it working, such as inside a quoted attribute. However, the <em>Range </em>header can be used to force the server to send only the attack section from the document, making it fully-exploitable in the process.</p><p>&nbsp;</p><h1>Background</h1><p>In recent months I&#8217;ve been doing quite a lot of research around improving my ability to detect desync and header injection vectors, and then make them fully exploitable. And as part of this, even though they are generally quite effective on their own, I also wanted to find better ways to insert XSS attacks into the responses which were sent back to the victims. Because, after all, there&#8217;s nothing quite like a bit of instant gratification to warm even the blackest of hearts, right?</p><p>Now, as I&#8217;m sure you know, one of the pleasing things about desync and header injection is that unlike anything delivered through a browser, you aren&#8217;t restricted by the limitations of CORS and fetch. Which means that you can pretty much put whatever you like into the requests.</p><p>As part of this, I allocated some time to looking at the <em>Range </em>header, and noticed a few useful things:</p><ul><li><p>all of the main browsers will happily accept an unsolicited <em>Range </em>response (<em>206 Partial Content</em>). Yay!</p></li><li><p>and something like 30-40% of all endpoints will respond to a <em>Range </em>request</p></li></ul><p>&nbsp;</p><h1>In the Red Corner</h1><p>From an offensive perspective, this should be interesting as it lets you take an unexploitable vector, glue it together with desync or header-injection, and make it fully exploitable.</p><p>There are two bits you&#8217;re looking for. The first is endpoints with reflected input which ends up being incorporated into the response verbatim, but alas somewhere unexploitable (like inside quotes in an attribute). Then the second bit is whether the same endpoint will respond to the <em>Range </em>header.</p><p>To test for the latter, just add the following header to the request and look for a <em>206 Partial Content</em> response:</p><pre><code>Range: bytes=0-0</code></pre><p>&nbsp;</p><h3>Putting it all Together</h3><p>In practice (once you&#8217;ve found a target that meets all the requirements), the actual delivery ends up being straightforward. </p><p>Just remember to also strip the <em>Accept-Encoding</em> header from the request, so you get back the raw document, not an unusable chunk of binary noise. </p><pre><code>GET /api/v1/web-cookie-privacy/config?locale=en&amp;appId=(console.log(`XSS`));//&amp;theme=default&amp;tea=1 HTTP/1.1
Host: www.tiktok.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Cache-Control: no-cache
Connection: keep-alive
Range: bytes=80-99
</code></pre><pre><code>HTTP/1.1 206 Partial Content
Content-Type: application/json; charset=utf-8
Server: TLB
Content-Range: bytes 80-99/105
Content-Length: 20

(console.log(`XSS`))</code></pre><p>(no tiktok streamers were harmed in the making of this blog)</p><p>&nbsp;</p><h1>In the Blue Corner</h1><p>This is actually pretty tough to defend against, as all the individual steps in the attack chain are relatively benign. Unexploitable reflected content, and an endpoint that responds to the Range header, don&#8217;t even warrant an informational note in a report.</p><p>The only way to spot this is to understand how the individual issues can be assembled into a working attack chain, and then keep an eye out for the combinations.</p><p>&nbsp;</p><h1>Additional Information</h1><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range">https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range</a></p><p>&nbsp;</p><h1>&#8220;Thanks&#8221;</h1><p>I just wanted to say a big &#8220;thanks&#8221; to my inability to say no to intrusive thoughts. It&#8217;s the little things, right?</p><p></p>]]></content:encoded></item><item><title><![CDATA[Exploiting CSP Wildcards for Google Domains]]></title><description><![CDATA[TL;DR The Google developer documentation includes CSP examples which use domain wildcards (which have been widely cut & pasted), and additionally there are numerous endpoints within the Google eTLDs which are vulnerable to Javascript XSS.]]></description><link>https://attackshipsonfi.re/p/exploiting-csp-wildcards-for-google</link><guid isPermaLink="false">https://attackshipsonfi.re/p/exploiting-csp-wildcards-for-google</guid><dc:creator><![CDATA[attack ships on fire]]></dc:creator><pubDate>Thu, 29 Feb 2024 11:35:28 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!_QLP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff03c581b-bb7b-480d-95d1-8b332bfc2faa_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_QLP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff03c581b-bb7b-480d-95d1-8b332bfc2faa_1024x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_QLP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff03c581b-bb7b-480d-95d1-8b332bfc2faa_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!_QLP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff03c581b-bb7b-480d-95d1-8b332bfc2faa_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!_QLP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff03c581b-bb7b-480d-95d1-8b332bfc2faa_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!_QLP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff03c581b-bb7b-480d-95d1-8b332bfc2faa_1024x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_QLP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff03c581b-bb7b-480d-95d1-8b332bfc2faa_1024x1024.png" width="353" height="353" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f03c581b-bb7b-480d-95d1-8b332bfc2faa_1024x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:353,&quot;bytes&quot;:1068101,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_QLP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff03c581b-bb7b-480d-95d1-8b332bfc2faa_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!_QLP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff03c581b-bb7b-480d-95d1-8b332bfc2faa_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!_QLP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff03c581b-bb7b-480d-95d1-8b332bfc2faa_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!_QLP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff03c581b-bb7b-480d-95d1-8b332bfc2faa_1024x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1>TL;DR</h1><p>The Google developer documentation includes CSP examples which use domain wildcards (which have been widely cut &amp; pasted), and additionally there are numerous endpoints within the Google eTLDs which are vulnerable to Javascript XSS. These can be combined into an effective attack against any domain with an HTML injection vector that would be otherwise unexploitable.</p><p>&nbsp;</p><h1>Background</h1><p>Whilst researching ways to make HTML injection vectors exploitable, I noticed that many of the vulnerable endpoints included similar CSP headers, which often had wildcards for the google eTLDs. It soon became obvious that the reason for this, was that they had been cut &amp; pasted straight from the Google developer documentation. Oh dear.</p><p>So then I took a quick sweep through the Google eTLDs, to see if I could find any endpoints which were vulnerable to javascript XSS that I could use, and to my obvious delight I found that there were actually plenty to choose from. </p><p>It&#8217;s worth noting at this point that I did do the responsible thing, and flagged the issues to the Google security team, but as far as they were concerned this was &#8220;by design&#8221; and not a security problem. Though to their credit, they have updated the CSP documentation so that it no longer has the wildcards. Small victories.</p><p>&nbsp;</p><h1>In the Red Corner</h1><p>From an attack point of view, the reason that you should be interested is that you can take an otherwise unexploitable HTML injection vector, and work it up into a full XSS.</p><p>But before we go any further, if you&#8217;re not already familiar with the way that CSP works, then I&#8217;d recommend reading the Mozilla <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP">CSP</a><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"> </a>guide first, which is a good primer.</p><p>&nbsp;</p><h3>Content-Security-Policy</h3><p>What you are looking for is an endpoint that is vulnerable to HTML injection, but with a CSP that blocks the full XSS. However, if the CSP has the wildcard google eTLDs in the script-src or default-src sections, then you are on to a winner. </p><pre><code><code>Content-Security-Policy: default-src 'self' *.google.com *.googleapis.com</code></code></pre><p>&nbsp;</p><h3>Javascript XSS</h3><p>The easiest way of getting javascript from the google domains is to simply upload it to one of the containers (like storage.<code>googleapis.com or firebasestorage.googleapis.com). However, if this isn&#8217;t possible for some reason, then there is currently a broken JSONP library that is widely used across the Google estate, which you can leverage too. You just need to add a callback query parameter containing your payload. Easy as cake.</code></p><p>&nbsp;</p><h3>Putting it all Together</h3><p>In practice (once you&#8217;ve found a target that meets all the requirements), the actual delivery ends up being really simple. </p><pre><code><code>&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Security-Policy" content="default-src https://*.google.com"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;script src=https://clients6.google.com/discovery/v1/apis?callback=%28alert%28%27XSS%27%29%29&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></code></pre><p>&nbsp;</p><h1>In the Blue Corner</h1><p>The first thing to look at is to make sure that your CSPs are effective. As a general rule, avoiding inline code and any wildcard domains is a good place to start.</p><p>Google actually provide a CSP analyser tool which is useful (would have been nice if they&#8217;d used it to generate their developer examples ;)</p><p>&nbsp;</p><h1>Additional Information</h1><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP">https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP</a></p><p><a href="https://bughunters.google.com/learn/invalid-reports/web-platform/xss/6619189462433792/xss-in-sandbox-domains">https://bughunters.google.com/learn/invalid-reports/web-platform/xss/6619189462433792/xss-in-sandbox-domains</a></p><p><a href="https://csp-evaluator.withgoogle.com/">https://csp-evaluator.withgoogle.com/</a></p><p>&nbsp;</p><h1>&#8220;Thanks&#8221;</h1><p>I just wanted to say a big &#8220;thanks&#8221; to the Google security team, who were efficient, professional and a complete pleasure to work with. Love you long-time!</p>]]></content:encoded></item><item><title><![CDATA[Exploiting Cacheable Responses]]></title><description><![CDATA[TL;DR The main browsers share their cache between Fetch requests and normal navigation.]]></description><link>https://attackshipsonfi.re/p/exploiting-cacheable-responses</link><guid isPermaLink="false">https://attackshipsonfi.re/p/exploiting-cacheable-responses</guid><dc:creator><![CDATA[attack ships on fire]]></dc:creator><pubDate>Tue, 20 Feb 2024 15:29:14 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!g-qG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd9b5dd2-0277-4ab2-8718-2efaa1e100f1_1053x1407.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!g-qG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd9b5dd2-0277-4ab2-8718-2efaa1e100f1_1053x1407.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!g-qG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd9b5dd2-0277-4ab2-8718-2efaa1e100f1_1053x1407.jpeg 424w, https://substackcdn.com/image/fetch/$s_!g-qG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd9b5dd2-0277-4ab2-8718-2efaa1e100f1_1053x1407.jpeg 848w, https://substackcdn.com/image/fetch/$s_!g-qG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd9b5dd2-0277-4ab2-8718-2efaa1e100f1_1053x1407.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!g-qG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd9b5dd2-0277-4ab2-8718-2efaa1e100f1_1053x1407.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!g-qG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd9b5dd2-0277-4ab2-8718-2efaa1e100f1_1053x1407.jpeg" width="380" height="507.74928774928776" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dd9b5dd2-0277-4ab2-8718-2efaa1e100f1_1053x1407.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1407,&quot;width&quot;:1053,&quot;resizeWidth&quot;:380,&quot;bytes&quot;:199303,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!g-qG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd9b5dd2-0277-4ab2-8718-2efaa1e100f1_1053x1407.jpeg 424w, https://substackcdn.com/image/fetch/$s_!g-qG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd9b5dd2-0277-4ab2-8718-2efaa1e100f1_1053x1407.jpeg 848w, https://substackcdn.com/image/fetch/$s_!g-qG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd9b5dd2-0277-4ab2-8718-2efaa1e100f1_1053x1407.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!g-qG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd9b5dd2-0277-4ab2-8718-2efaa1e100f1_1053x1407.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1>TL;DR</h1><p>The main browsers share their cache between Fetch requests and normal navigation. This means that any request that can be made with Fetch, which produces a cacheable response, can also be used to poison the browser navigation too. Given the right set of circumstances, this approach can unlock a raft of unexploitable vulnerabilities, and make them practical.</p><p>&nbsp;</p><h1>Background</h1><p>The idea for this research came about after sitting through lots of penetration test washups, where the &#8220;Cacheable Response&#8221; finding was skipped over as irrelevant. However, you may have noticed that I find it really satisfying to chain a bunch of low impact issues into something more substantial, so I added browser caching to my never-ending research list. </p><p>The result was that I noticed that Fetch shares the same cache as the regular navigation, with the cache key being based upon the URI and originating state. However, because Fetch is able to add headers to the request that can change the response (but which are not included in the cache key), an attacker can pre-request resources to poison the private cache, then force the browser to navigate to the page, which activates the attack.</p><p>To make this work requires two things:</p><ul><li><p>the target endpoint must pass a pre-flight check, as adding headers to a Fetch request requires CORS; and</p></li><li><p>the Fetch response (or if a redirect, then both the redirect and response) must be cacheable by the browser, either explicitly (cache-control, pragma or expires headers), or implicitly (301/308 status code, or last-modified header).</p></li></ul><p>As an interesting observation, the response does not always have to be made available to Fetch for the browser cache to be updated. For example, if the pre-flight passes, but the actual response does not have an access-control-allow-origin header, then it will be blocked due to CORS. But even so, the cache will still be updated successfully.</p><p>&nbsp;</p><h1>In the Red Corner</h1><p>From an attack point of view, the reason that you should be interested in poisoning the browser cache, is that you can use it to leverage vectors that would otherwise be unexploitable, and even better, to use them to pivot laterally between sites that share the same eTLD.</p><p>However, before we go any further, if you&#8217;re not already familiar with the way that caching and CORS work, then I&#8217;d recommend reading the Mozilla <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching">caching </a>and <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">CORS </a>guides first, which are good primers.</p><p>You may also be thinking that this is exactly the kind of situation that browser <a href="https://developer.mozilla.org/en-US/docs/Web/Privacy/State_Partitioning">state partitioning</a> should prevent. And you&#8217;d be partially right. Originally it was introduced as a privacy measure, to stop information leaking between states. And in the same way that it broke shared CDNs, it should also have stopped a lot of the cache poisoning too. However, it only partially mitigates it. There are some browser implementation bugs that mean that different states are incorrectly treated as the same, but the biggest issue is that the null state is universally equal. So, if the attack can be delivered from the null origin, then it can be happily poisoned and exploited cross-site. Yay!</p><p>&nbsp;</p><h3>Pre-request with Fetch</h3><p>The crux of the issue is that Fetch and the normal navigation share the same cache, but requests made with Fetch can include headers which change the response, but not the cache key. Ooops.</p><p>For the pre-request step to work, any useful Fetch request (which typically triggers an exploit using headers), will first need to pass the CORS preflight check. After this, the actual response will need to be cacheable. However, if the response itself does not pass CORS, then it will end up being cached anyway (after all it was successful at the HTTP layer). The detail varies per browser brand, so you&#8217;ll need to verify this manually.</p><p>And that&#8217;s it. All you need is to follow-up with a normal navigation to load the content from cache and activate it within the target DOM. Pow!</p><p>&nbsp;</p><h3>Putting it all Together</h3><p>In practice (once you&#8217;ve found a target that meets all the requirements), the actual delivery ends up being really simple. For some browsers, you&#8217;ll need to wrap the below in an iframe, to force the state partition check to work.</p><pre><code>           
      window.nonce = Math.random( ).toString( 36 ).substr( 2, 5 )

      fetch( 'http://a.gvj.io/200?n=' + window.nonce, {
            method: 'GET',
            mode: 'cors',
            cache: 'reload',
            redirect: 'follow',
            credentials: 'include',
            headers: {
                  'x-original-url': '/poisoned'
            }
      } )
      .catch( ( ) =&gt; { } )
      .then( ( ) =&gt; { 

        setTimeout( function( ) { 

            window.location.replace( 'http://a.gvj.io/200?n=' + window.nonce );

        }, 200 );

      } );</code></pre><p>&nbsp;</p><h3>Browser Test Cases</h3><p>Although it seems like there are a lot of browsers to choose from, there are basically three: the Chromium variants, Firefox, and Safari. Obviously, they all implemented state partitioning slightly differently, and so also respond differently to cache poisoning. On top of that, in the months since I first notified the vendors of this bug, the teams have also been merging patches that subtly change the caching behaviour. </p><p>So, if you want to know if a particular version of a browser is vulnerable, the test cases below should give you a definitive answer. These are divided by direct and iframe (forcing a null origin), then further subdivided by same-origin, same-site and cross-site states:</p><p><a href="http://a.gvj.io/direct">http://a.gvj.io/direct</a></p><p><a href="http://a.gvj.io/iframe">http://a.gvj.io/iframe</a></p><p>&nbsp;</p><h1>In the Blue Corner</h1><p>As all the magic is happening in the browser, it might seem that there isn&#8217;t a lot you can do to prevent this kind of attack. However, there are a few things you can try.</p><p>The first is to ensure that dynamically generated content isn&#8217;t being cached when it shouldn&#8217;t be (remember that &#8220;cacheable response&#8221; finding in the report? It&#8217;s time to triage those). Then if a response really must be cached, you can explore the use of the vary header, which will force the cache key to include any headers of your choosing. Using this approach, you can effectively make Fetch and the normal navigation use separate cache keys. </p><p>Then from a detection perspective, for an attacker to find a vulnerable target typically requires scanning for broken CORS, which you can detect in your SIEM (look out for large volumes of failed OPTIONS requests).</p><p>&nbsp;</p><h1>Additional Information</h1><p><a href="https://fetch.spec.whatwg.org/#http-cache-partitions">https://fetch.spec.whatwg.org/#http-cache-partitions</a></p><p><a href="https://developer.mozilla.org/en-US/docs/Web/Privacy/State_Partitioning">https://developer.mozilla.org/en-US/docs/Web/Privacy/State_Partitioning</a></p><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching">https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching</a></p><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS</a> <br><br><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-1554">https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-1554</a></p><p>&nbsp;</p><h1>&#8220;Thanks&#8221;</h1><p>I just wanted to say a big &#8220;thanks&#8221; to the teams from Firefox, Google and Apple, who were efficient, professional and a complete pleasure to work with. Love you long-time!</p><p></p>]]></content:encoded></item><item><title><![CDATA[Exploiting Unsynchronised Clocks]]></title><description><![CDATA[TL;DR According to data from RIPE, over 40% of computers attached to the Internet have a few seconds of clock drift, which with the right combination of headers, will make an HTTP response unintentionally cacheable.]]></description><link>https://attackshipsonfi.re/p/exploiting-unsynchonised-clocks</link><guid isPermaLink="false">https://attackshipsonfi.re/p/exploiting-unsynchonised-clocks</guid><dc:creator><![CDATA[attack ships on fire]]></dc:creator><pubDate>Sun, 11 Feb 2024 13:46:43 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!3arp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6086dfc9-5f5c-4b0e-a7c1-95510a9a9d12_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3arp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6086dfc9-5f5c-4b0e-a7c1-95510a9a9d12_1024x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3arp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6086dfc9-5f5c-4b0e-a7c1-95510a9a9d12_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!3arp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6086dfc9-5f5c-4b0e-a7c1-95510a9a9d12_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!3arp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6086dfc9-5f5c-4b0e-a7c1-95510a9a9d12_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!3arp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6086dfc9-5f5c-4b0e-a7c1-95510a9a9d12_1024x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3arp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6086dfc9-5f5c-4b0e-a7c1-95510a9a9d12_1024x1024.png" width="376" height="376" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6086dfc9-5f5c-4b0e-a7c1-95510a9a9d12_1024x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:376,&quot;bytes&quot;:1304751,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3arp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6086dfc9-5f5c-4b0e-a7c1-95510a9a9d12_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!3arp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6086dfc9-5f5c-4b0e-a7c1-95510a9a9d12_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!3arp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6086dfc9-5f5c-4b0e-a7c1-95510a9a9d12_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!3arp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6086dfc9-5f5c-4b0e-a7c1-95510a9a9d12_1024x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1>TL;DR</h1><p>According to data from RIPE, over 40% of computers attached to the Internet have a few seconds of clock drift, which with the right combination of headers, will make an HTTP response unintentionally cacheable.</p><p>&nbsp;</p><h1>Background</h1><p>Like many parts of the HTTP model, caching has been extended and revised multiple times over the years. The result is a confusing set of response header values, which affect the way that the browser may or may-not cache the response.</p><p>If you are not already familiar with the browser caching model, I&#8217;d recommend reading the Mozilla <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching">caching</a> guide, which is a good primer.</p><p>For this article, the two interesting bits are the <em><strong>expires</strong></em> header (which explicitly directs the browser to cache), and the <em><strong>last-modified</strong></em> header (which implicitly triggers heuristic caching). Both of these use a standard HTTP date format response.</p><p>So, as long as a response does not have a pragma or cache-control header, then the browser will use expires and last-modified if they are present.</p><p>&nbsp;</p><h1>In the Red Corner</h1><p>From an attack point of view, the reason that you should be interested in responses that are unintenionally cacheable, is that you can use them with cache poisoning to leverage vectors that would otherwise be unexploitable.</p><p>&nbsp;</p><h3>Expires</h3><p>The expires header normally works by setting the value to a point in the future, which tells the browser it can cache the response until that time. The potential for unintentional caching is introduced when the application attempts to signal that the resource should not be cached, by setting the expires value to the current time (&#8220;now&#8221;). That&#8217;s because, if the server clock is fast, or the browser clock is slow, then &#8220;now&#8221; is actually a point in the future, and the browser will cache the response. Ooops.</p><p>&nbsp;</p><h3>Last-Modified</h3><p>The last-modified header works in a similar way. If the last-modified value is in the past, then the heuristic caching algorithm in the browser may add the response to the cache.</p><p>&nbsp;</p><h3>Putting it all Together</h3><p>What you are looking for are responses that:</p><ul><li><p>do not contain a cache-control or pragma header that explicitly stops the browser caching the response (so cache-control could contain the private parameter, but not the no-store parameter); and</p></li><li><p>do contain an expires or last-modified header that is set to the same value as the date header. </p></li></ul><pre><code><code>HTTP/1.1 200 OK
Date: Sat, 10 Feb 2024 07:08:02 GMT
Content-Type: text/html; charset=utf-8
Connection: close
Expires: Sat, 10 Feb 2024 07:08:02 GMT
Content-Language: en</code></code></pre><p>&nbsp;</p><h1>In the Blue Corner</h1><p>The expires and last-modified headers are only used by the browser when the cache-control and pragma headers are not present:</p><ul><li><p>always set the cache-control header on every response, to explicitly control whether you want the browser to cache it or not;</p></li><li><p>if you absolutely must use an expires header to signal that a response should not be cached, set it to a value waaaay in the past; and</p></li><li><p>do not rely on last-modified alone to signal caching behaviour to the browser, as the heuristic model varies between browsers, and you may not get what you expected.</p></li></ul><p>&nbsp;</p><h1>Additional Information</h1><p><a href="https://labs.ripe.net/author/gih/is-the-internet-running-late/">https://labs.ripe.net/author/gih/is-the-internet-running-late/</a></p><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching">https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching</a></p><p>&nbsp;</p><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Exploiting TRACE]]></title><description><![CDATA[TL;DR The presence of the TRACE method is generally considered to be at best an informational finding (and in isolation, I wouldn&#8217;t disagree with that).]]></description><link>https://attackshipsonfi.re/p/exploiting-trace</link><guid isPermaLink="false">https://attackshipsonfi.re/p/exploiting-trace</guid><dc:creator><![CDATA[attack ships on fire]]></dc:creator><pubDate>Fri, 04 Aug 2023 11:17:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!9lbA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220e9d79-8742-44c8-894a-60b1971a2f63_1598x1226.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9lbA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220e9d79-8742-44c8-894a-60b1971a2f63_1598x1226.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9lbA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220e9d79-8742-44c8-894a-60b1971a2f63_1598x1226.jpeg 424w, https://substackcdn.com/image/fetch/$s_!9lbA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220e9d79-8742-44c8-894a-60b1971a2f63_1598x1226.jpeg 848w, https://substackcdn.com/image/fetch/$s_!9lbA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220e9d79-8742-44c8-894a-60b1971a2f63_1598x1226.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!9lbA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220e9d79-8742-44c8-894a-60b1971a2f63_1598x1226.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9lbA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220e9d79-8742-44c8-894a-60b1971a2f63_1598x1226.jpeg" width="548" height="420.40934065934067" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/220e9d79-8742-44c8-894a-60b1971a2f63_1598x1226.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1117,&quot;width&quot;:1456,&quot;resizeWidth&quot;:548,&quot;bytes&quot;:248382,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!9lbA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220e9d79-8742-44c8-894a-60b1971a2f63_1598x1226.jpeg 424w, https://substackcdn.com/image/fetch/$s_!9lbA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220e9d79-8742-44c8-894a-60b1971a2f63_1598x1226.jpeg 848w, https://substackcdn.com/image/fetch/$s_!9lbA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220e9d79-8742-44c8-894a-60b1971a2f63_1598x1226.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!9lbA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220e9d79-8742-44c8-894a-60b1971a2f63_1598x1226.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1>TL;DR</h1><p>The presence of the TRACE method is generally considered to be at best an informational finding (and in isolation, I wouldn&#8217;t disagree with that). But before you deploy your <em>meh</em>, if you know what to look for, the TRACE method (and any other mechanism that reflect requests) can be added to a practical attack chain, and will dramatically increase the impact of an exploit.</p><p>&nbsp;</p><h1>Background</h1><p>The TRACE method was originally introduced as a diagnostic tool, to reflect back the request that was received by the server. But as is the way, it didn&#8217;t take too long before enterprising individuals realised that it could be combined with any old XSS, to provide a practical way of getting around the HttpOnly cookie flag (which is intended to stop sensitive cookies being accessible to javascript). </p><p>At this point, you&#8217;ll probably be thinking &#8220;yeah, but changes to the XMLHttpRequest and fetch standards mean that you can&#8217;t send the TRACE method anymore&#8221;, and you&#8217;d be right. <br><br>But don&#8217;t you think it would be cool if you could bypass those restrictions, or there were other ways to achieve the same, reflected request? Well, you&#8217;ve come to the right place!</p><p>&nbsp;</p><h1>In the Red Corner</h1><p>From an offensive point of view, this should be interesting as it enables two useful things:</p><ul><li><p>firstly, the diagnostic response itself often contains sensitive information from the app stack, like keys and tokens that have been added by internal systems, along with evidence of hidden issues, like missing encryption on internal connections etc. Scrutinise carefully!</p></li><li><p>and secondly, it allows you to dramatically increase the impact of other exploits, turning a hum-drum XSS into a full account takeover etc.</p></li></ul><p>&nbsp;</p><h3>Override headers</h3><p>Although it is true that changes to the XMLHttpRequest and fetch standards have stopped the direct use of the TRACE method, up until last year you could still use the standard override headers (<em>x-http-method-override</em> etc.) to deliver the same attack. And even better, with the right set of CORS misconfigurations, you didn&#8217;t even need to chain it to anything else to deliver the attack.</p><p>That said, only the most common override headers are blocked by the standard, so it is still possible to find and exploit the less common ones in the wild (like <em>_method</em>, <em>x-method</em> and <em>x-tunneled-method</em>).</p><pre><code>GET /path.html HTTP/1.1
Host: yomama.com
_method: TRACE</code></pre><p>&nbsp;&nbsp;</p><h3>Query and body parameters</h3><p>A collection of the common app stacks will accept a method override parameter by default, which functions the same as the TRACE method. You&#8217;ll need to deploy your google-fu and tweak your approach to match the target environment (I&#8217;ve included a handful of references at the end of this blog to get you started). And once again, check for CORS misconfigurations, as if present, these are fully exploitable all on their own.</p><pre><code>GET /path.html?_method=TRACE HTTP/1.1
Host: yomama.com</code></pre><p>&nbsp;&nbsp;</p><h3>Weird shit</h3><p>There are a lot of app instrumentation products around now, which gather user statistics at a low level, by passing the raw request on to an instrumentation stack for analysis. Usually this happens via a collection of client-side javascript plugins, but I&#8217;ve seen some really awful implementations that put the raw request into a JSON blob embedded within the main page, which in-turn gets sent on to the instrumentation.</p><p>Gaining access to the reflected request obviously works just fine in a chain with XSS, but if you can combine it with something else, like cache deception, this is a really elegant way of gaining access to a user&#8217;s session tokens, which can often be leveraged into a full account takeover.</p><p>&nbsp;</p><h1>In the Blue Corner</h1><p>There are two things you can immediately do to defend against these kinds of reflected request attacks.</p><p>Firstly, add signatures to your IDS/SIEM that trigger on the main override headers and parameters (this should be as early in your app stack as possible, so it catches headers entering your environment, not those added by any of your internal components). Monitor the output closely, as you may find that you have apps deployed that depend on some of these headers.</p><p>Secondly, strip (or reject) any of the headers and parameters that your apps don&#8217;t need as early as possible in your app stack.</p><p>&nbsp;</p><h1>References</h1><p><a href="https://www.rfc-editor.org/rfc/rfc2068#section-9.8">https://www.rfc-editor.org/rfc/rfc2068#section-9.8</a></p><p><a href="https://owasp.org/www-community/attacks/Cross_Site_Tracing">https://owasp.org/www-community/attacks/Cross_Site_Tracing</a></p><p><a href="https://developer.wordpress.org/rest-api/using-the-rest-api/global-parameters/#_method-or-x-http-method-override-header">https://developer.wordpress.org/rest-api/using-the-rest-api/global-parameters/#_method-or-x-http-method-override-header</a></p><p><a href="https://docs.spring.io/spring-framework/docs/5.0.2.RELEASE/kdoc-api/spring-framework/org.springframework.web.filter/-hidden-http-method-filter/">https://docs.spring.io/spring-framework/docs/5.0.2.RELEASE/kdoc-api/spring-framework/org.springframework.web.filter/-hidden-http-method-filter/</a></p>]]></content:encoded></item><item><title><![CDATA[Exploiting API Framework Flexibility]]></title><description><![CDATA[TL;DR The modern frameworks are often very flexible with what they accept, and will happily treat a POST with a JSON body as interchangeable with a URL encoded body, or even with query parameters.]]></description><link>https://attackshipsonfi.re/p/exploiting-api-framework-flexibility</link><guid isPermaLink="false">https://attackshipsonfi.re/p/exploiting-api-framework-flexibility</guid><dc:creator><![CDATA[attack ships on fire]]></dc:creator><pubDate>Sat, 17 Dec 2022 10:22:21 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!1vsW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F589ad231-d347-46b1-8e9a-b5a497a602e3_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1vsW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F589ad231-d347-46b1-8e9a-b5a497a602e3_1024x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1vsW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F589ad231-d347-46b1-8e9a-b5a497a602e3_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!1vsW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F589ad231-d347-46b1-8e9a-b5a497a602e3_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!1vsW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F589ad231-d347-46b1-8e9a-b5a497a602e3_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!1vsW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F589ad231-d347-46b1-8e9a-b5a497a602e3_1024x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1vsW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F589ad231-d347-46b1-8e9a-b5a497a602e3_1024x1024.png" width="356" height="356" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/589ad231-d347-46b1-8e9a-b5a497a602e3_1024x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:356,&quot;bytes&quot;:1294259,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1vsW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F589ad231-d347-46b1-8e9a-b5a497a602e3_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!1vsW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F589ad231-d347-46b1-8e9a-b5a497a602e3_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!1vsW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F589ad231-d347-46b1-8e9a-b5a497a602e3_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!1vsW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F589ad231-d347-46b1-8e9a-b5a497a602e3_1024x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1>TL;DR</h1><p>The modern frameworks are often very flexible with what they accept, and will happily treat a POST with a JSON body as interchangeable with a URL encoded body, or even with query parameters. Due to this, an unexploitable JSON XSS vector can sometimes be made exploitable by flipping it to one of these alternative approaches.</p><p>&nbsp;&nbsp;</p><h1>Background</h1><p>In the dim and distant past, most web apps were almost entirely bespoke creations, and they were often riddled with vulnerabilities that were unique to that particular site. These days, a lot of the generic issues have been addressed through the use of the modern app frameworks, which take care of a lot of the heavy lifting when it comes to generating HTML and providing database access etc.</p><p>However, those same app frameworks are also very flexible by default when it comes to the ways that they accept data, and they will happily take parameters, whether they are in a JSON body, URL encoded body, or a query string. Yay!</p><p>&nbsp;&nbsp;</p><h1>In the Red Corner</h1><p>From an offensive point of view, this should be interesting as it allows you to take a vector that is otherwise unexploitable, and make it useable. </p><p>For example, a POST with a JSON body that returns an HTML response with an XSS payload. It&#8217;s a good find, but as it stands, it can&#8217;t be practically exploited. However, if you can swap the JSON body to URL encoded (or a query) then you can happily use a self-submitting form to make the XSS work without any interaction at all (no CORS, and the HTML response is rendered).</p><p>As if this wasn&#8217;t enough, you&#8217;ll often also find that the encoding/decoding sequence is different for a parameter that is received from JSON as opposed to the alternatives: this may be enough to enable an attack to work when it otherwise wouldn&#8217;t.</p><p>&nbsp;&nbsp;</p><h3>Simple</h3><p>For a simple JSON object, the transposition is really straight forward: you just flip the attribute/value pairs between encoding styles.</p><pre><code>{"attribute1":"value1","attribute2":"value2"} </code></pre><p>becomes </p><pre><code>attribute1=value1&amp;attribute2=value2</code></pre><p>&nbsp;&nbsp;</p><h3>Nested</h3><p>For nested JSON objects/arrays there are a bunch of competing (and incompatible, obviously) approaches. Mostly though, this just means serialising the object into a set of paths. </p><p>The main standards for the transposition are Rack, Spring and Stripe. I&#8217;ve included a few references to get you started at the end of this blog, but beyond that, you&#8217;ll need to deploy your google-fu and tweak your approach to match the target environment.</p><pre><code><code>{"object":{"attribute1":"value1","attribute2":"value2"}}</code></code></pre><p>&nbsp;&nbsp;becomes</p><pre><code><code>object[attribute1]=value1&amp;object[attribute2]=value2</code></code></pre><p>&nbsp;&nbsp;</p><h3>Weird Shit</h3><p>I have also seen some weird endpoints in the wild, that ignore the <em>content-type</em> altogether, and will instead dynamically detect the data in the body. For these, you can try making the entire JSON request into a text/plain or URL encoded attribute and it may parse just fine.</p><pre><code><code>{"object":{"attribute1":"value1","attribute2":"value2"}}</code></code></pre><p>becomes for text/plain (note the JSON comment suffix to stop the equals sign tripping up the parser) </p><pre><code><code>{"object":{"attribute1":"value1","attribute2":"value2"}}//=</code></code></pre><p>which becomes for URL encoded</p><pre><code><code>%7B%22object%22%3A%7B%22attribute1%22%3A%22value1%22%2C%22attribute2%22%3A%22value2%22%7D%7D%2F%2F=</code>&nbsp;&nbsp;</code></pre><p>&nbsp;&nbsp;</p><h3>Self-Submitting Form</h3><p>And obviously, once you get the transposition working, you&#8217;ll want to be able to practically exploit it. A URL encoded POST is treated as a CORS simple request, and so it&#8217;ll happily work cross-origin, and will also include the authentication cookies too. Whoop!</p><pre><code>&lt;body onload=document.getElementsByTagName('form')[0].submit();&gt;

    &lt;form method=post action=https://yo.mama&gt;

        &lt;input type=hidden name=attribute1 value=value1&gt;
        &lt;input type=hidden name=attribute2 value=value2&gt;

    &lt;/form&gt;

&lt;/body&gt;</code></pre><p>&nbsp;&nbsp;</p><h1>In the Blue Corner</h1><p>The thorough way to defend against this is to hunt out all your endpoints that accept JSON by default, and if they also accept URL encoded and queries (which aren&#8217;t used by your apps) then disable the functionality. </p><p>However, if you&#8217;re in a rush and need to monkey-patch an active attack, then you can always use your WAF to block content-types other than application/json. It&#8217;s not pretty, but it&#8217;ll get the job done.</p><p>&nbsp;&nbsp;</p><h1>References</h1><p><a href="https://brandur.org/fragments/application-x-wwww-form-urlencoded">https://brandur.org/fragments/application-x-wwww-form-urlencoded</a></p><p>&nbsp;&nbsp;</p>]]></content:encoded></item><item><title><![CDATA[Exploiting CORS Misconfigurations]]></title><description><![CDATA[TL;DR If you can find an unrestricted CORS endpoint, that also responds to the HTTP override headers, then potentially you can use it to access endpoints that aren&#8217;t enabled for CORS, bypass CSRF protections, and also deliver an XST (which will give you access to cookies protected by the httpOnly attribute).]]></description><link>https://attackshipsonfi.re/p/exploiting-cors-misconfigurations</link><guid isPermaLink="false">https://attackshipsonfi.re/p/exploiting-cors-misconfigurations</guid><dc:creator><![CDATA[attack ships on fire]]></dc:creator><pubDate>Sat, 26 Nov 2022 08:16:40 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!fgYu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F40910ab0-40b9-4abc-88bb-f26b354118cd_1179x1437.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fgYu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F40910ab0-40b9-4abc-88bb-f26b354118cd_1179x1437.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fgYu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F40910ab0-40b9-4abc-88bb-f26b354118cd_1179x1437.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fgYu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F40910ab0-40b9-4abc-88bb-f26b354118cd_1179x1437.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fgYu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F40910ab0-40b9-4abc-88bb-f26b354118cd_1179x1437.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fgYu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F40910ab0-40b9-4abc-88bb-f26b354118cd_1179x1437.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fgYu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F40910ab0-40b9-4abc-88bb-f26b354118cd_1179x1437.jpeg" width="304" height="370.52417302798983" data-attrs="{&quot;src&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/40910ab0-40b9-4abc-88bb-f26b354118cd_1179x1437.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1437,&quot;width&quot;:1179,&quot;resizeWidth&quot;:304,&quot;bytes&quot;:194273,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fgYu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F40910ab0-40b9-4abc-88bb-f26b354118cd_1179x1437.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fgYu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F40910ab0-40b9-4abc-88bb-f26b354118cd_1179x1437.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fgYu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F40910ab0-40b9-4abc-88bb-f26b354118cd_1179x1437.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fgYu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F40910ab0-40b9-4abc-88bb-f26b354118cd_1179x1437.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1>TL;DR</h1><p>If you can find an unrestricted CORS endpoint, that also responds to the HTTP override headers, then potentially you can use it to access endpoints that aren&#8217;t enabled for CORS, bypass CSRF protections, and also deliver an XST (which will give you access to cookies protected by the httpOnly attribute).</p><p>&nbsp;&nbsp;</p><h1>Background</h1><p>The idea for this research came about after repeatedly hearing people say that CORS issues are irrelevant (which to be fair, the generic <em>&#8220;allows any origin&#8221;</em> alert you get from many scanners mostly is). </p><p>But I really don&#8217;t like being told something isn&#8217;t possible, so instead I set out to have a proper rummage and see what I could actually do with CORS. Apart from being fun, along the way I found a quirk that affected all the main browsers, and also some web platform zero-days too. What&#8217;s not to like about that?</p><p>Anyway, back in the Dark Ages, before CORS existed, we just had the same-origin policy, which limited the types of requests that could be sent between sites. The introduction of CORS brought a huge amount of flexibility to cross-origin requests, and made the web the rich experience that it is today. But it is also a bit fiddly to setup, and because of that, is easy to get wrong. Which is a bad thing, if you&#8217;re looking to secure your site.</p><p>It&#8217;s a bit like the classic firewalling problem. The engineer spends the morning trying to make a fiddly rule work well, then just gives up, clicks the <em>any </em>button, and makes a mental note to come back and fix it properly sometime (i.e. when hell freezes over).</p><p>CORS is the same. Out in the real world, there are a lot of sites configured with a * for methods, origins and headers. Either because that is the default the platform ships with, or because someone gave up and clicked the <em>any </em>button.</p><p>&nbsp;</p><h1>In the Red Corner</h1><p>From an attack point of view, the reason that you should be interested in CORS is that you can get a request to fire within a user&#8217;s session, and in doing so leverage their credentials and network access.</p><p>However, before we go any further, if you&#8217;re not already familiar with the way CORS works (and CORS Preflight in particular), then I&#8217;d recommend reading the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">Mozilla CORS guide</a> which is a good primer.</p><p>&nbsp;&nbsp;</p><h3>Override Headers</h3><p>Once upon a time, an engineer (let&#8217;s call her Karren) was struggling to make an application work through a firewall, when she had an epiphany. She would fix the problem by implementing a shadow set of <em>method</em>, <em>host </em>and <em>URI </em>headers that the firewall didn&#8217;t know about. And in that moment, she created dozens of possible combinations for accessing an app through a restrictive firewall. And even better, she then told the rest of her engineer buddies, who spawned similar abominations. Love you Karren!</p><p>Anyway, wouldn&#8217;t it be cool if you could take an unrestricted CORS configuration, and use these override headers to basically ignore CORS and access whatever part of the app stack you wanted to? Well, as it turns out, that&#8217;s exactly what you can do. Yay!</p><p>The reason that this works is that any useful CORS request will generate two separate HTTP requests. The first is the Preflight (which has minimal headers, and no overrides) and then the second is the actual CORS request (which has your override headers). That means that each HTTP request will get a response from a different part of the app stack. The Preflight will be answered by the unrestricted CORS endpoint, but the actual request goes elsewhere. OooOOoooh!</p><p>&nbsp;&nbsp;</p><h3>Recon</h3><p>To make this work in practice, you will need to do your recon thoroughly, then glue all the separate bits together into a workable attack.</p><p>The first thing to do is to find the unrestricted CORS endpoints: the ones which allow authentication plus the override headers. In practice, this means making a lot of CORS Preflight requests, to enumerate the possible origin, method and header combinations (because when authentication is enabled, a * in the response is treated as a literal, not a wildcard). </p><p>It&#8217;s also worth noting that some CORS endpoints will take an <em>access-control-request-headers</em> populated with all the desired headers, then respond with an <em>access-control-allow-headers </em>that contains the subset of allowed headers. You can use this to cut the number of requests you need to send. However, some other CORS endpoints will reject the request outright if they do not support one of the requested headers. These you will need to enumerate empirically.</p><p>The second thing to do is to check whether these unrestricted CORS endpoints also respond to one of the override headers too. If this isn&#8217;t something you are already familiar with, then it is time to deploy your google-fu. What am I, your mother?</p><p>&nbsp;&nbsp;</p><h3>Putting It All Together</h3><p>Ok, so you&#8217;ve found an unrestricted CORS endpoint that also accepts the override headers, now what? Well, the actual detail depends on the app stack in use, and what you want to achieve.</p><p>Let&#8217;s say that your target responds to one of the host override headers (forwarded, x-forwarded-host, x-forwarded-server, x-host and x-http-host-override). Because the typical app stack has a common set of load balancers and reverse-proxies, you can often use these headers to redirect your request between servers. </p><p>Then there are the URI override headers (x-original-url, x-rewrite-url and x-url), which allow you to redirect your request to other endpoints on the same host.</p><p>And finally, the method override headers (x-http-method, x-http-method-override, x-method and x-method-override), which allow you to swap methods.</p><p>It&#8217;s worth noting that any combination of overrides that redirect the request to a non-CORS endpoint may not return the correct CORS headers, and so will &#8220;fail&#8221; from the perspective of the browser (and block access to the response). However, that will not stop the request from working.</p><p>&nbsp;&nbsp;</p><h3>CSRF</h3><p>This is where it gets fun. A lot of CSRF protection mechanisms rely on the token only being available from an endpoint that doesn&#8217;t allow CORS requests. However, that isn&#8217;t strictly true, is it ;) </p><p>&nbsp;&nbsp;</p><h3>XST</h3><p>XST hasn&#8217;t been a thing for years now, because the browsers have blocked direct access to the TRACE method. However, again, that isn&#8217;t strictly true.</p><p>Also, because this is CORS, all it takes is the right combination of misconfigurations on a site, and you can use XST to completely compromise the user accounts with one fetch call (bypassing any cookie httpOnly restrictions). Full account compromise, and all from a CORS misconfiguration. Boom!</p><p>I had a lot of fun with this in the last few months, whilst the main browsers were busy implementing fixes. However, as of now, this shouldn&#8217;t be possible with the latest browser code (though there will of course be vulnerable versions hanging around for years to come).</p><p>&nbsp;</p><h1>In the Blue Corner</h1><p>There are three things you can immediately do to defend against these kinds of request header issues in general, and the CORS issues specifically.</p><p>Firstly, add signatures to your IDS/SIEM that trigger on the main override headers (this should be as early in your app stack as possible, so it catches headers entering your environment, not those added by any of your internal components). Monitor the output closely, as you may find that you have apps deployed that depend on some of these headers:</p><ul><li><p>forwarded</p></li><li><p>x-forwarded-host</p></li><li><p>x-forwarded-server</p></li><li><p>x-host</p></li><li><p>x-http-host-override</p></li><li><p>x-http-method</p></li><li><p>x-http-method-override</p></li><li><p>x-method</p></li><li><p>x-method-override</p></li><li><p>x-original-url</p></li><li><p>x-rewrite-url</p></li><li><p>x-url</p></li></ul><p>Secondly, strip (or reject) any of these headers that your apps don&#8217;t need as early as possible in your app stack. </p><p>And finally, find all your endpoints that respond to CORS Preflight requests, and ensure that they accept the minimum set of headers required to make the app work. Pay special attention to the <em>access-control-allow-headers</em> response (which should not be a * and also should not simply reflect back the request either).</p><p>&nbsp;&nbsp;</p><h1>XST PoC Site</h1><p>If you want to see it work for real, then there is an XST PoC site available that you can experiment with&nbsp;here: <a href="https://xst.scarlet.ae">https://xst.scarlet.ae</a>&nbsp;</p><p>&nbsp;&nbsp;</p><h1>Additional Information</h1><p><a href="https://fetch.spec.whatwg.org/">https://fetch.spec.whatwg.org/</a></p><p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS</a></p><p><a href="https://www.mozilla.org/en-US/security/advisories/mfsa2022-47/#CVE-2022-45411">https://www.mozilla.org/en-US/security/advisories/mfsa2022-47/#CVE-2022-45411</a></p><p>&nbsp;&nbsp;</p><h1>&#8220;Thanks&#8221;</h1><p>I just wanted to say a big &#8220;thanks&#8221; to the teams from whatwg, Firefox, Google and Apple, who were efficient, professional and a complete pleasure to work with. Love you long-time!</p><p>&nbsp;</p>]]></content:encoded></item></channel></rss>