Monday, April 07, 2014

Bypassing the XSS filter using function reassignment

The XSS filter introduced in IE8 is a really powerful defence against XSS. I tested the filter for a number of years and found various bypasses one of which I would like to share with you now. You can read more about the filter and its goal in the following blog post.


There have been numerous public bypasses of the filter however very few within the intended scope of the filter. The filter blocks reflected XSS in HTML context, script, style and event context. It does not support attacks that use multiple parameters or same origin requests. Once you are aware of the intended scope the difficulty of bypassing the filter is very high.

Function reassignment

This bypass was fixed in later versions of Internet Explorer but still works in compatibility mode. You can use the vector in a penetration test by forcing the target site into compatibility mode using an iframe with an EmulateIE7 meta element as shown below.

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

This loads IE in emulate mode and the entire JavaScript engine will revert to an older mode enabling the vector to function. We need to setup a page with the target input inside a function argument in order to demonstrate the bypass. As you can see below the parameter "x" appears inside a string which calls the function "x".

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
function x() {

$x = isset($_GET['x']) ? $_GET['x'] : '';
x('<?php echo $x?&gtl');

In older versions of Internet Explorer it's possible to redefine a function within its calling arguments. This is very useful for bypassing the filter when your XSS hole executes within a function argument. To see how this works we pass a GET request to "x" within a payload that redefines the function "x" to alert and uses an argument before our break out string to pass to the function. The GET request looks like this:

The output of the page now looks like this:

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
function x() {


"1" is inserted at the start of the argument then we break out of the string and redefine the function "x" to alert then finish up by completing the string. The alert function only accepts 1 argument so our other arguments are ignored and alert(1) executes successfully.


As mentioned previously this vector was patched in later versions of IE however it will still work where a target site is in compatibility mode or you can force it into the older mode using iframes. The newer JavaScript engines in IE will not allow you to redefine functions within arguments. To protect against this vector you can force your site into standards mode by specifying a doctype or using the X-UA-Compatible header or meta element in edge mode. Preventing your site from being framed is also a good idea using the X-Frames-Option header and of course fixing the actual XSS hole in the first place is preferred.


Saturday, April 05, 2014

How I Hacked Your Router

Some time ago a friend in infosec asked me to do a strange thing.  He asked me to hack him.  We will call him Bill, for the sake of anonymity.  Other names and places have been changed to protect the innocent.  Vendor names have been kept to incriminate the guilty.

Hacking a large corporation is easy(ish).  They have information assets that may span the globe, and despite investments in various protection technologies, it's just hard to keep track of all that stuff.  It requires Zen-like discipline to rigorously follow the cycle of scan-patch-repeat day after day, on all assets in an organization, without fail.

Hacking a person can be tough.  It's true that blackhats have the advantage in terms of the asymmetric nature of information security.  Sometimes it only takes one bug.  But the attack surface area of a single individual is quite small compared to a corporation.  In addition, most people trust large vendors with their information and the cloud vendors typically do a decent job of protecting people.

I started with basic recon.  I like to use Maltego, along with sites like,, pipl search, and other tools to enumerate online presence.  There's also the classics like Google+, Facebook and Linkedin.  It helps to have a fake profile on Facebook for this kind of work.  A good bait profile should be tuned to your target.  It will help when extracting additional information via social engineering.

In terms of online presence, password reset questions are good low hanging fruit.  I've seen webmail accounts asking for information that you can pull right out of the target's Facebook profile.  I'm sure most people don't even make the connection; they may have written their reset questions 5 years ago.  None of this stuff was going to work in this case though.  My target was an infosec nerd, and he was expecting me.

Time to take the fight to him.  First, I checked to see if he is hosting anything on his home Internet connection.  He may have been doing this and not even know it.  Many apps and devices use UPnP to punch holes in consumer-grade firewalls without much fanfare.  Sometimes all it takes is a NAS or media server to open up a backdoor.  To find his home IP address, I used a Skype resolver, such as  It worked brilliantly, so I scanned his IP address (and a few neighboring IPs) to see if I could find any services.  No dice though… I'm sure he figured I would do this.

Next up, 802.11.  Wireless networks are a great attack vector.  I have two Radeon 6990′s in an i7 rig that chews through WPA hashes.  I use a Markov predictive wordlist generator to feed guesses to oclHashcat.  It can achieve an 80% average crack rate over an 8 hour time frame.

So I set about to Bill's address with various Alfa wifi cards in tow.  While in this case I actually know Bill's address, I may have been able to get this information via recon or social engineering.  It's not exactly a secret.  After successfully capturing a WPA handshake, I ran the cracker for a week.  Still no dice.  This would probably work on most people, but Bill is an infosec guy.  His WPA key is probably >32 characters long.

At this point you're probably wondering why I didn't just spear-phish him with a Java 0-day and go have my victory beer.  The answer is simple — I know my target.  He has mastered the mantra of scan-patch-repeat.  Java isn't even installed.  And if I did have a browser 0-day in my back pocket, I would have used it to win the pwn2own last week.

After my visit to Bill's place, I did come away with one useful piece of information.  The wireless MAC address (BSSID) of his router: 06:A1:51:E3:15:E3.  Since I have the OUI (the first 3 bytes of the MAC), I know that it's a Netgear router.  I also know that Netgear routers have some issues, but Bill was running the latest firmware.  That doesn't mean that all the vulnerabilities were patched in the latest firmware though.  The only way to be sure was to buy a Netgear router and test it myself.

Determining the exact model is probably not possible (not remotely anyway).  Consumer devices may have a lot of variation between different models as the reference platforms come from SoC vendors such as Broadcom and Atheros.  I know that Bill is a bit frugal, so I went with the WNDR3400v3 — the entry level unit.

After reading about some of the vulnerabilities this device has had in the past, I created two Metasploit modules.  In the first module, I would use a CSRF bug to POST to the UPnP interface and punch a hole to access the telnet service of the router itself.  This issue likely exists in numerous other devices and is worth emphasizing:

If you can spoof UPnP requests via CSRF, you can turn the entire network inside-out.

That's an important point.  I was opening up a single port.  You can use Ajax requests from the victim's browser to configure NAT entries for every IP in a subnet, effectively disabling the firewall.  There are hard limits to the number of UPnP NAT entries of course, but most devices will allow enough entries to map a few key ports for a hundred hosts or so.

In order to trick Bill into connecting to my exploit, I sent him an email with an embedded link.  Cobalt Strike has a tool to copy an existing email (headers and all), which makes this basically turn-key.  All you need to do is modify the links.  So what email does everyone always click?  What would work even against an infosec guy?  Linkedin invites.

Now before I sent the email, I needed a follow up payload.  By default, the telnet port is enabled on Netgear routers, but the service is unresponsive.  You have to connect to the port and send a special unlock key.  Public exploits exist for this flaw, but I wrote another MSF modulebecause I love my Ruby (and Metasploit).

Bill clicked the link.  As soon as I saw the callback, I triggered the second module and logged into the router via telnet.  Once I obtained root access to the router, I immediately changed the DNS settings to point to a DNS server that I control.

Controlling DNS is a powerful thing; it effectively provides you with on-demand man-in-the-middle.  There are plenty of MITM attack vectors, but I like Evilgrade for stealth.  Evilgrade has been out for years, and still works great (some modifications necessary).  It took about a week before Bill decided to upgrade notepad++ to the new version.  When he did, he was fed a backdoored version that gave me a Meterpreter shell on his computer.  I immediately emailed him a few screen shots and a keystroke log, and he unplugged his computer a few minutes later.

For my efforts, I was rewarded with a six-pack of Ruby ale.  I do love my Ruby.

Wednesday, March 12, 2014


This page contains a technical description of the back-door found in Samsung Galaxy devices.
For a general description of the issue, please refer to the statement published on the Free Software Foundation's website.

This back-door is present in most proprietary Android systems running on the affected Samsung Galaxy devices, including the ones that are shipped with the devices. However, when Replicant is installed on the device, this back-door is not effective: Replicant does not cooperate with back-doors.


Samsung Galaxy devices running proprietary Android versions come with a back-door that provides remote access to the data stored on the device.
In particular, the proprietary software that is in charge of handling the communications with the modem, using the Samsung IPC protocol, implements a class of requests known as RFS commands, that allows the modem to perform remote I/O operations on the phone's storage. As the modem is running proprietary software, it is likely that it offers over-the-air remote control, that could then be used to issue the incriminated RFS messages and access the phone's file system.

Known affected devices

The following table shows which devices are known to contain this back-door as part of the software they ship with.
Please contact us if you know about some other device that could be concerned by this back-door or have more information on one of the listed devices!

DeviceIncriminated program running as rootSELinux enabledlibsamsung-ipc supportReplicant support
Nexus S (I902x)NoPossible with Android 4.2 and laterYesYes
Galaxy S (I9000)Yes?YesYes
Galaxy S 2 (I9100)No?YesYes
Galaxy Note (N7000)No?YesYes
Galaxy Nexus (I9250)NoPossible with Android 4.2 and laterYesYes
Galaxy Tab 2 7.0 (P31xx)No?YesYes
Galaxy Tab 2 10.1 (P51xx)No?YesYes
Galaxy S 3 (I9300)No?YesYes
Galaxy Note 2 (N7100)No?YesYes

Back-door sample

In order to investigate the back-door and check what it actually lets the modem do, some code was added to the modem kernel driver to make it craft and inject requests using the incriminated messages and check its results.

The following patch: 0001-modem_if-Inject-and-intercept-RFS-I-O-messages-to-pe.patch (to apply to the SMDK4412 Replicant 4.2 kernel) implements a sample use of the back-door that will:
  • open the /data/radio/test file
  • read its content
  • close the file

This demonstrates that the incriminated software will execute these operations upon modem request. Note that the software implementation appends /efs/root/ to the provided path, but it's fairly simple to escape that path and request any file on the file system (using ../../). Note that the files are opened with the incriminated software's user permissions, which may be root on some devices. On other cases, its runs as an unprivileged user that can still access the user's personal data (/sdcard). Finally, some devices may implement SELinux, which considerably restricts the scope of possible files that the modem can access, including the user's personal data (/sdcard/).

The following sample was obtained on a Galaxy Note 2 (N7100) running CyanogenMod 10.1.3.

Sample file

The sample file used for this demonstration (/data/radio/test) is filled with "Hello World!":

root@android:/ # hexdump -C /data/radio/test  00000000  48 65 6c 6c 6f 20 57 6f  72 6c 64 21 0a           |Hello World!.|  0000000d  

Kernel log

<3>[   62.712637] c0 mif: rx_iodev_skb: rx_iodev_skb: Dropping RFS frame  <3>[   62.712808] c0 mif: rfs_craft_start: rfs_craft_start: Crafting open  <3>[   62.712966] c0 mif: rfs_craft_start: rfs_craft_start: Adding SKB to queue  <3>[   62.713122] c0 mif: rx_iodev_skb: rx_iodev_skb: Dropping RFS frame  <3>[   62.744690] c0 mif: misc_write: misc_write: Intercepted RFS response  <3>[   62.744867] c0 mif: rfs_craft_write: rfs_craft_write: Open response: fd=21, errno=0  <3>[   62.745116] c0 mif: rfs_craft_write: rfs_craft_write: Adding SKB to queue  <3>[   62.792888] c0 mif: misc_write: misc_write: Intercepted RFS response  <3>[   62.793026] c0 mif: rfs_craft_write: rfs_craft_write: Read response: 12 bytes read  <3>[   62.793154] c0 mif: mif_print_data: 0000: 48 65 6c 6c  6f 20 57 6f  72 6c 64 21    <3>[   62.793284] c0 mif: rfs_craft_write: rfs_craft_write: Adding SKB to queue  <3>[   62.796168] c0 mif: misc_write: misc_write: Intercepted RFS response  <3>[   62.796269] c0 mif: rfs_craft_write: rfs_craft_write: Rx RFS message with command 0x6 and size 14  <3>[   62.796422] c0 mif: mif_print_data: 0000: 00 00 00 00  00 00 00 00    

The relevant part is the response to the read request:

<3>[   62.793026] c0 mif: rfs_craft_write: rfs_craft_write: Read response: 12 bytes read  <3>[   62.793154] c0 mif: mif_print_data: 0000: 48 65 6c 6c  6f 20 57 6f  72 6c 64 21    

which matches the content of the /data/radio/test file, hence making it obvious that the incriminated software implements the back-door.

Incriminated software log

E/RIL     ( 1927): processRFS: received standalone RFS frame. len 35  E/RIL     ( 1927): ipc_recv_rfs()  E/RIL     ( 1927): get_wakelock: 1. on 1, ril_WakeLock_Mask 0  E/RIL     ( 1927): get_wakelock: 2. on 1, ril_WakeLock_Mask 1  E/RIL     ( 1927): RxRFS_OpenFile:   E/RIL     ( 1927): RxRFS_OpenFile: open file "/efs/root/../../data/radio/test" flag O_RDWR (0x00000002)  E/RIL     ( 1927): check dir '/efs/root/../../data/radio'  E/RIL     ( 1927): A directory already exists.  E/RIL     ( 1927): RxRFS_OpenFile: length 14  E/RIL     ( 1927): TxRFS_CfrmOpenFile()  E/RIL     ( 1927): TxRFS_CfrmOpenFile(): length 14  E/RIL     ( 1927): IPC_send_singleRfsIPC: fd 16 sendto 14 bytes rfs_hdr =6  E/RIL     ( 1927): get_wakelock: 1. on 0, ril_WakeLock_Mask 1  E/RIL     ( 1927): get_wakelock: 2. on 0, ril_WakeLock_Mask 0  E/RIL     ( 1927): set_wakelock: secril_rfs-interface 0  E/RIL     ( 1927): set_wakelock: secril_fmt-interface 1  E/RIL     ( 1927): processIPC: Single IPC plen 23, pkt 23  
E/RIL     ( 1927): processRFS: received standalone RFS frame. len 14  E/RIL     ( 1927): ipc_recv_rfs()  E/RIL     ( 1927): get_wakelock: 1. on 1, ril_WakeLock_Mask 0  E/RIL     ( 1927): get_wakelock: 2. on 1, ril_WakeLock_Mask 1  E/RIL     ( 1927): RxRFS_ReadFile:   E/RIL     ( 1927): RxRFS_ReadFile: length 4110  E/RIL     ( 1927): TxRFS_CfrmReadFile()  E/RIL     ( 1927): TxRFS_CfrmReadFile(): length 4110  E/RIL     ( 1927): IPC_send_singleRfsIPC: fd 16 sendto 4110 bytes rfs_hdr =6  
E/RIL     ( 1927): processRFS: received standalone RFS frame. len 10  E/RIL     ( 1927): get_wakelock: 1. on 0, ril_WakeLock_Mask 1  E/RIL     ( 1927): get_wakelock: 2. on 0, ril_WakeLock_Mask 0  E/RIL     ( 1927): set_wakelock: secril_rfs-interface 0  E/RIL     ( 1927): [EVT]:Req(0), RX(0)  E/RIL     ( 1927): ipc_recv_rfs()  E/RIL     ( 1927): get_wakelock: 1. on 1, ril_WakeLock_Mask 0  E/RIL     ( 1927): get_wakelock: 2. on 1, ril_WakeLock_Mask 1  E/RIL     ( 1927): RxRFS_CloseFile:   E/RIL     ( 1927): RxRFS_CloseFile: length 14  E/RIL     ( 1927): TxRFS_CfrmCloseFile()  E/RIL     ( 1927): TxRFS_CfrmCloseFile(): length 14  E/RIL     ( 1927): IPC_send_singleRfsIPC: fd 16 sendto 14 bytes rfs_hdr =6  


The following analysis was conducted using the binary file (the incriminated proprietary software) as extracted from the CyanogenMod 10.1.3 system zip for the Galaxy S 3 (I9300), from location system/lib/

The developers involved in the present analysis did not ever agree to any sort of End User License Agreement that explicitly prohibited the reverse engineering and decompiling operations of the incriminated binary. The reverse engineering operations that led to these findings originally took place during the development of Samsung-RIL, the free software replacement for the incriminated program. Hence, we believe these operations were conducted for the sole purpose of interoperability and not with the intent of creating a competing product. As the involved developers were based in Europe, we believe the legality of these operations is granted by article 6 of the 1991 EU Computer Programs Directive.

As a first approach, using the strings tool against the incriminated program reveals numerous suspicious command names that appear to be Samsung IPC protocol definitions:


The names of these commands make it obvious that they let the modem perform I/O operations.

The strings utility also reveals matching function names that seem to implement the handling of these commands:

RxRFS_GetFile  RxRFS_CreateFile  RxRFS_ReadDirectory  RxRFS_OpenDirectory  RxRFS_RenameFile  RxRFS_Default  RxRFS_OpenFile  RxRFS_ReadFile  RxRFS_FtruncateFile  RxRFS_WriteFile  RxRFS_GetFileInfoByHandle  RxRFS_GetFileInfo  RxRFS_PutFile  RxRFS_LseekFile  RxRFS_CloseFile  RxRFS_DeleteFile  RxRFS_MakeDirectory  RxRFS_CloseDirectory  RxRFS_RemoveDirectory  TxRFS_CfrmCreateFile  TxRFS_CfrmPutFile  TxRFS_CfrmOpenDirectory  TxRFS_CfrmGetFileInfo  TxRFS_CfrmReadDirectory  TxRFS_CfrmRenameFile  TxRFS_CfrmCloseFile  TxRFS_CfrmFtruncateFile  TxRFS_CfrmGetFileInfoByHandle  TxRFS_CfrmDeleteFile  TxRFS_CfrmCloseDirectory  TxRFS_CfrmRemoveDirectory  TxRFS_CfrmMakeDirectory  TxRFS_CfrmGetFile  TxRFS_CfrmReadFile  TxRFS_CfrmWriteFile  TxRFS_CfrmLseekFile  TxRFS_CfrmOpenFile  

Taking a closer look at these functions, using the objdump decompiler, reveals that they are actually called from the ipc_recv_rfs function, itself called fromprocess_ipc_notify_message, which appears to handle the received messages from the modem. Hence we can deduct that the incriminated functions are actually called upon modem request.

Taking a closer look at one of these functions, e.g. RxRFS_ReadFile reveals multiple calls to the Procedure Linkage Table (PLT). Hence we believe these calls are linked functions from the libc library, especially I/O-related functions such as (in a general manner) openclosereadwrite, etc.

Samsung IPC RFS messages

The following table associates each Samsung IPC RFS message with its hexadecimal command value:

MessageHexadecimal command value


The incriminated RFS messages of the Samsung IPC protocol were not found to have any particular legitimacy nor relevant use-case. However, it is possible that these were added for legitimate purposes, without the intent of doing harm by providing a back-door. Nevertheless, the result is the same and it allows the modem to access the phone's storage.

However, some RFS messages of the Samsung IPC protocol are legitimate (IPC_RFS_NV_READ_ITEM and IPC_RFS_NV_WRITE_ITEM) as they target a very precise file, known as the modem's NV data. There should be no particular security concern about these as both the proprietary implementation and its free software replacement strictly limit actions to that particular file.

Areas of work

Some work could be done in order to handle that back-door:
  • Samsung-RIL could show a message alerting the user when the back-door is being used, including the requested path and asking the user to save logs and contact us.
  • Alternatively, the kernel could block the incriminated RFS requests and keep a trace of them in the logs for the record. That option would work for CyanogenMod, where the incriminated proprietary blob is still used.


Our free software replacement for the incriminated binary is Samsung-RIL which relies on libsamsung-ipc: both are used in Replicant.

The affected devices have modems that use the Samsung IPC protocol, mostly Intel XMM6160 and Intel XMM6260 modems. Note that despite this back-door, the devices using these modems are most likely to have good modem isolation, compared to other devices using Qualcomm platforms. Bear in mind that this back-door is implemented in software and can easily be removed by installing a free replacement for the incriminated software, for instance by installing Replicant. Hence, we don't consider the incriminated devices to be inherently bad targets because of this back-door.

0001-modem_if-Inject-and-intercept-RFS-I-O-messages-to-pe.patch (5.6 kB) Paul Kocialkowski, 02/04/2014 06:57 PM

Tuesday, March 11, 2014

How to Steal WhatsApp database

"Is it possible to upload and read the WhatsApp chats from another Android application?"

With this question my brother and I started an interesting conversation which ended in underneath proof of concept. The tldr answer is: "Yes, that is possible".

The WhatsApp database is saved on the SD card which can be read by any Android application if the user allows it to access the SD card. And since majority of the people allows everything on their Android device, this is not much of a problem.

So what do we need to steal someones Whatsapp database? First we need a place to store the database. I used this webserver with a simple php script.

Make sure you configure you php.ini so that you can upload (large) files.

Next thing we need is an Android application which uploads the WhatsApp database to the website. I created a new default project in Eclipse and made a couple of changes. First of all we need some extra rights to access the SD card and to upload to the internet. To do this I added some lines to the AndroidManifest.xml file.

For the layout I used the default layout which Eclipse creates, but I moved the TextView to the center and increased the text size. The upload magic happens before you see the layout, for this proof of concept this activity_main.xml is good enough.

So far, nothing exciting yet, the real excitement comes in the file. We will try to upload 3 files:

  • /WhatsApp/Databases/msgstore.db
  • /WhatsApp/Databases/wa.db
  • /WhatsApp/Databases/msgstore.db.crypt

In newer versions WhatsApp decided to do some crypto magic on their database (msgstore.db.crypt), so it is more secure. It is still possible to read chats from this database, but more on that later. The msgstore.db and wa.db are the old unencrypted databases of WhatsApp.

During the upload of the WhatsApp database files we will display a simple Loading screen, so people think the application is doing something interesting in the background.

By doing the magic in the loading screen you can also add this code to a real application instead of the Hello World message you see now. Combine it with something like FlappyBird and a description how to install applications from unknown sources and you can harvest a lot of databases.

The WhatsAppp database is a SQLite3 database which can be converted to Excel for easier access. Lately WhatsApp is using encryption to encrypt the database, so it can no longer be opened by SQLite.  But we can simply decrypt this database using a simple python script. This script converts the crypted database to a plain SQLite3 database (got key from Whatsapp Xtract).

So, we can conclude that every application can read the WhatsApp database and it is also possible to read the chats from the encrypted databases. Facebook didn't need to buy WhatsApp to read your chats.