Credit card numbers, third parties and you

One part of the preparation for my upcoming talk at BSides RI involved shuffling some cash from my bank account to make it available on my credit card. While in this process, something struck me as rather odd, as seen on the following Burp output:

Request containing credit card number

Request containing credit card number

As we can see, the URL query string contains a parameter identified as “KortNo”. And this just so happens to contain what is in fact my credit card number. So the question becomes, is this a big deal? Well, this had me wondering and looking at it from a PCI perspective; I think there may be some cause for concern.

Access logs, browser history

It’s of course common practice for companies to keep access logs for all HTTP servers in the event of a system breach for forensic purposes. PCI has a mandate for companies to retain at least 1 year worth of “logs”. Because PCI mandates logs are kept, you are 99% likely as a bank to keep your HTTP logs, including the URL requested. In this instance, we make a request with data that PCI has a strong view upon the storage of, including the very explicit requirement of encrypting the PAN(Primary account number), CVV2, expiration date, and any other personally identifiable information if you store the 3 former.

So what happens when you make a HTTP GET request containing data which PCI mandates the encryption of, and it goes into a standard IIS log? Well, you are storing data in violation of PCI compliance. You will only need to get your hands on the access logs from the server to now access a lot of credit card data. This is rather unfortunate.

Even more likely, is that your personal browser history will now contain your credit card number and hang on to it. Of course, this requires some social engineering to be relevant. However, if this is not made known to the user, then this is a cause for concern.

Third parties

Of course, when you run a web site, you like to track user behavior on your site. Who doesn’t? Banks do, and in this case, the above concerns are amplified when I noticed this request having been made by my browser at the same time:

Request to google analytics

Request to google analytics

What you see here is a standard Google analytics callback. We see that our query string containing data that PCI mandates that you must ensure is stored correctly is now sent off to a third-party. That is Google in this case. Ok, we may trust Google, but it also means that anybody with access to the Google analytics account now can view this credit card data. That means that this bank will now have to explicitly have made a contract with Google to verify that they will safe-keep this PCI data.

Is that likely? Not really. This is just an unfortunate side-effect of the bad practice of using the straight up PAN(Credit card number) as a part of the request through a query-string.

Putting it into perspective

When I discovered this, I rushed over to my other bank account(with a different back) to check if a similar problem existed over there. I observed that they had made the seemingly explicit design decision of not using the credit card number. Rather, they used a hash and a GUID to identify my credit card. While they were using a third-party analytics service, it did not contain personal information to the extent the above did as a result, which mitigates potential concerns in this regard.

Timeline

  • 13/05/2013 – Advisory sent to CERT
  • 13/05/2013 – CERT confirms receipt of advisory, promises to provide contact at vendor
  • 14/05/2013 – CERT still searching for appropriate vendor point of contact
  • 15/05/2013 – CERT provides point of contact
  • 15/05/2013 – Advisory sent to vendor
  • 15/05/2013 – Vendor response confirming issue
  • 15/05/2013 – Vendor deploys fix
  • 16/05/2013 – Advisory published

It should be noted that the bank in question was quick to respond and fix the privacy concern in a professional manner. I’ve redacted the name of the bank as the goal of this was to highlight a potential pitfall that others may fall into, and hopefully this may encourage other banks to ensure that this is not a concern in their systems as well.

CVE-2013-2692 – Or when your OpenVPN is a bit too open

Advisories

OpenVPN

Secunia

Details

When analyzing the OpenVPN Access Server, it quickly became apparent that the administration interface lacked any basic level of CSRF protection, which was easily demonstrated with a CSRF form like this, which will add a new user with admin privileges, using the username “csrfaccount” and password “qweasd”:

For this to be effective, we need to ensure that the server is configured to use “Local” authentication. This means OpenVPN controls the authentication, rather than using PAM/RADIUS/LDAP. We can do this with these two simple requests:

When we have changed the authentication method, we need to commit the change:

If we do a CSRF attack against a target using these 3 requests(Which can be done with the method described in my post about multi-stage CSRF attacks), we can then authenticate to the OpenVPN AS admin interface using the account details csrfaccount/qweasd. This further allows us to take over the server.

Conditional CSRF – Or how to spray without praying

A part of the goal of my latest project, WordPress CSRF Exploit kit – A novel approach to exploiting WordPress plugins, was to show some novel techniques that I’ve been picking up on in terms of exploitation of web applications and delivering payloads in neat ways. One goal specifically was to deliver an array of different potential payloads depending on specific conditions and not spray and pray. The one that is the most obvious, is whether or not the target has a specific plugin installed. My approach ended up being a somewhat obscure but neat one that others have documented before. Specifically, the onload/onerror attribute on certain HTML elements that pull in outside resources. Lets deconstruct a landing page as you’d see it from the above project:

What we can observe here is a bunch of different image/script tags all pointing to a potential file existing on a remote system which belong to a specific WordPress plugin. In the event that the plugin is not installed on the host, nothing happens. We’re not loading them for display as I’m sure you guessed. Rather, we’re hoping to get the onload attribute invoked, which contains some convenient javascript of ours.

In the event that the vulnerable plugin is detected, in this case we redirect to a page that contains our actual exploit payload. This means we don’t have to send all possible payloads at once, but can have some obscurity until we know we can hit something interesting. Or in other words, you can spray a target and not have to pray that your exploits work, because they won’t trigger unless a target has the plugin you’re targeting.

This approach is not new, as it has been used in the past for things like trying to resolve different host-names/ip/port ranges on an internal network through a hooked browser to scan for other web applications to target. In this case, we’re using this approach to detect the presence of a vulnerable plugin on a, granted that it’s a pre-determined, target. By being able to not have to do up-front poking at a running system, we’re able to achieve a lower turn-around time on delivering a payload that either hits a target or simply just does nothing.

So there you have it. This is probably not an useful approach to take in all cases where you exploit a CSRF vulnerability. But it’s still an interesting approach and hopefully will inspire others to consider thinking about being more sneaky(Don’t spray and pray!) in their exploitation attempts and make full use of the wonderful things HTML and javascript offer you!

WordPress CSRF Exploit kit – A novel approach to exploiting WordPress plugins

Over the last few weeks I’ve been on roll with finding CSRF vulnerabilities in WordPress plugins. That’s all nice and good, but when you’ve got 30 of them, it’s a shame to not take it a step further and show the dangers of them! This project is solely designed to show off a few random thoughts of mine, and most importantly to hopefully inspire others to think along these lines. This project is solely meant for educational purposes, not attack against running services or people.

https://github.com/CharlieEriksen/WP-CSRF-POC

The project shows a few basic concepts in regards to the process of pulling off a CSRF attack against a large number of WordPress sites. Some things worth pointing out:

  • It’s not designed to simply spray and pray. You define the target URLs you want to hit and then you have an unique URL for each blog you can go phishing with.
  • Then it will use the onload function of an img or script tag to detect the presence of the vulnerable plugin on the target blog on request through the unique URL pre-defined
  • We generate the payload on request with an uniquely identifying URL to ensure it’s not easy to extract the exploits.
  • You get max 2 requests to the script per IP. That is all a compromise needs. After that, you get nothing back. Makes it harder for researchers life
  • We deliver a beef hook. Because beef is cool and god damn tasty

I want to stress especially the “novel” use of the onload function of img/script tags. People in the past have used it to detect the presence of different host-names/”port scanning” internal systems by vectoring through a hooked browser. I say that’s cool and all, but you can take that further and use it to detect the presence of a plugin on a target on demand, making you able to be much more sneaky. When the markup detects a plugin present on the target, it redirects the browser to the exploit, and no further requests can be made by that IP to the script.

A normal series of events would be:

  1. An attacker sets up this script with pre-defined targets(targets variable) with an unique URL for each target blog
  2. The attacker then spams out a link to the running script with the unique URL for each target blog
  3. When a target clicks the link to this script, we validate that the URL contains the unique identifier that resolves to a blog URL
  4. The script the generates a random URL for each exploit we have with the target blog URL put in that can then be requested
  5. We output to the user a series of img/script tags with onload attributes that redirect to the unique URL generated in step 4. These tags look for specific plugins on the targeted blog
  6. If none of the plugins are detected on the blog, we redirect to google
  7. If any of the plugins are detected, we redirect to the uniquely generated URL made in step 4
  8. The exploit is now written out to the user, submitting the CSRF with a XSS payload pointing to our beef instance
  9. We now delete all cached exploits made for the requesting IP

There’s a number of improvements that could be made to this. It could be designed to spray and pray through iframes, but that is much much dirtier, and not the goal of this proof of concept. I urge anybody who finds the concept to be useful to run with it if they so desire. I’ll be adding more exploits as advisories are published. Otherwise, I’m curious to hear people’s thoughts on this.

AMD Catalyst driver update vulnerability

Description of vulnerability

The AMD Catalyst driver auto update feature enables users to automatically update the AMD Catalyst driver on their machine through a single click when the driver determines that it is out of date.

However a vulnerability exists in this mechanism as a result of:

  1. The download URL and binary download is done over HTTP
  2. The binary is not verified as having been signed by AMD before execution

This means that a MITM can intercept the requests to the AMD support site and redirect the auto-update feature to download and execute a binary of the attacker’s choice without the user knowing any better when they decide to auto-update.

Proof of concept

By pointing  amd.comwww.amd.comwww.ati.com and www2.ati.com at this script, you’ll observe that the Catalyst update feature will prompt you to update the driver, and download and execute calc.exe.

Time table

23.11.2012 – Sent a request for security contact details
23.11.2012 – Vendor informs that they will only coordinate issues through their support ticket system
23.11.2012 – Sent details as per request including proof of concept
26.11.2012 – Vendor acknowledges receipt of details and request further contact details
29.11.2012 – Vendor confirms that the team is working with their web team to address the issue
10.12.2012 – Mail sent asking for a rough timeline
14.12.2012 – Vendor replies informing that the driver team is still working on the issue, and that their legal team is also involved
19.12.2012 – Vendor publishes advisory: http://support.amd.com/us/kbarticles/Pages/AMDauto-updatenotification.aspx
17.01.2013 – Vendor releases AMD Catalyst 13.1, removing the update feature

WordPress Online Store local file inclusion vulnerability

Advisory

Secunia Advisory SA50836

Analysis of vulnerability

The WP Online Store exposes a shortcode for displaying the store, which is declared in core.php:

If the “slug” request parameter isn’t defined, it will load the index page of the store. But if it is defined, it will load the relevant page which the user requests. It however does not sanitize that the “slug” is a WP Online Store file, which allows for a local file inclusion vulnerability if we create a post/page with the text “[WP_online_store]“, and submit a request with the slug set like this:

 

WordPress Online Store arbitrary file disclosure

Advisory

Secunia Advisory SA50836

Analysis of vulnerability

The plugin hooks two functions as a part of its core functionality in core.php by adding an action for init and admin_init.

The first line calls into osc_session_init_fend whenever a WordPress page is loaded, in order to set up a session.

The interesting thing is that on line 136 is checks the “force” request variable to see if it matches to “downloadnow”. If it is set, it will change the content type of the response to be a download, and then read the file set by the request variables “turl” and “file” and write that to the response. These variables are however not sanitized, which leads to an arbitrary file disclosure. We can exploit this by making a request to any page with following querystring, which will force the browser to download a page containing the contents of the wp-config.php file at the top of the file:

 

WP Symposium multiple SQL injection vulnerabilities

Advisory

Secunia Advisory SA50674

Analysis of groups get_user_list SQL injection vulnerability

This first vulnerability in the /ajax/symposium_groups_functions.php file makes use of the functionality for people to view the users of a group. It accepts a groupID(gid) which it inserts without validation into a query and then spits out the result, even if you are not authenticated.

Because it uses multiple line, we have to do a bit more work than the other ones. We can craft an union select which fits in and uses the rest of the query without a problem like this, and dump a list of usernames and password hashes:

Analysis of get_album_item.php SQL injection vulnerability

This SQL injection vulnerability is practically as simple as it gets. And it even makes it simple for us in get_album_item.php.

It reads in 2 variables from $_REQUEST, which can be either GET or POST parameters. That’s very handy. It then proceeds to stuff the size into the SELECT part of the query using plain concatenation without previous sanitization, and then uses the wordpress prepare method of passing in content to a query safely using a printf syntax, which is safe.

Because we have control over the SELECT part of the query, we can easily select out a single piece of data at a time, which is sufficient to dump the whole database as needed. Here we can pull out a password from the users table, for instance, using a very simple request, no authentication required:

Analysis of symposium_show_profile SQL injection vulnerability

This vulnerability relies on the way which profiles are shown in Symposium. It calls into the symposium_show_profile method in symposium_profile.php file, which finds out what ID to show information for like this, assuming you are authenticated:

Note that the last line takes the $uid variable as determined on the first block of code, and simply puts it straight into the query without any sort of input sanitation. So by creating a page with the “[symposium-profile-menu]” short-tag, we can inject into the page with a simple URL like this:

Analysis of forum updateEditDetail blind SQL injection vulnerability

This vulnerability is actually more like 2. We can see that in this standard ajax call in /ajax/symposium_forum_functions.php file that there is a total of 4 SQL queries executed, 2 updates and 2 selects. Notice that the $_POST parameters aren’t sanitized before use, yet all but the 3rd query uses concatenation to create the SQL query, which creates SQL injection conditions if you are logged in.

We can exploit it like this with an appropriate set of cookies:

 Analysis of profile addFriend blind SQL injection vulnerability

A similar lack of input validation can be seen in the /ajax/symposium_profile_functions.php file in the addFriend action handling code. It takes in an ID for a friend to add and then starts putting together some SQL like this:

Notice that it simply concatenates the $friend_to variable into the query. While this query is not used for output, we can still do a blind SQL injection if we’re logged in.

 

Vulnerability chaining, magic quotes bypass with hexadecimal literals and data exfiltration

I have a pet peeve. It’s when people argue that vulnerabilities that exist in an administrator interface, though not inherently critical, does not need to be fixed. Many administrator interfaces assume that if a user has access to it, the user can be explicitly trusted. And that leaves entire applications at a risk that’s easily fixable, yet developers refuse to acknowledge this.

A such example is what I’m going to talk about in this blog post more in depth. I already showed an example of a similar issue over here. But what happens when you take this sort of triple-joy attack further to its logical conclusion? First though, let’s take a look at the WP Easy Gallery plugin!

SQL Injection analysis
I first came across this issue through some tools I coded to discover extremely obvious vulnerabilities, which exist all over. It alerted me to the fact that there was a good likelihood of a SQL injection condition existing in the /admin/add-images.php file. Let’s look!

It pulls either the “select_gallery” or “galleryId” POST parameter. That’s then passed to two SQL queries without being cast to integers. That’s clue 1 right there that this is something we need to dig a bit deeper into. The file name is a clue that these pages are most likely not publicly accessible, as well as that there’s a check at the top of the file to ensure the file isn’t called directly. So this relies on somebody having access to the admin interface. And the admin needs to be silly enough to insert SQL into a query string parameter, but only blindly. We need to now establish whether or not the SQLi is blind or not.

A good clue is to grep the file for echo statements. Here are some examples:

Bingo! Our injection vector is not blind. And what is more, keep in mind for later that no output encoding is done. This is important.

CSRF vector
Without access to the WordPress administration interface directly, there’s a few means which we can achieve the delivery of a payload to exploit the SQL Injection vulnerability. Given that we need to deliver the items through the POST variables, we have to evaluate the application for the absence of any mitigation against CSRF attacks. In theory, a CSRF attack should be impossible. In reality though, many WordPress plugins do not CSRF protect their admin interfaces despite WordPress offering a very easy way of mitigating the attack.

Evaluating this for this attack vector can either be done by sampling a request with Burp Suite Pro and have it do the boring work of generating the appropriate form(Can be done by hand easily), or reading the code and see if there’s any actual CSRF tokens being inserted and validated anywhere that could be a kill joy for us. As it turns out, there’s a complete absence of this. So we now have a delivery method for a payload that could execute some arbitrary SQL and show the result to the user. But just outputting the list of users and their password to the admin user is rather boring. We need to find some way of exfiltration this data to us.

Data exfiltration through XSS and magic quotes bypass
Remember back how we determined that the SQL results was in no way output encoded. It’s presumed of course that any data in the database was input by the admin, and as such completely not dangerous. What dangerous content can you possibly get from an integer column that auto-increments automagically? As it turns out, this is critical for turning this vulnerability into a beast.

We can’t possibly hope for the admin user to email us the result of the SQL injection output. So we need to somehow use the fact that we control the output of the SQL query to our advantage, and the fact that we can mostly unhindered write anything to the rendered page of the admin is a good start. So if we were able to put in either some JavaScript that’d infiltrate data for us, or a simple img tag which causes an external request, we can achieve our goal. Of course, the one thing that stops us is this pesky thing called magic quotes. We could try and put in some HTML into our SQL query, but if we have to use characters like quotes, magic quotes will make that a no-go. But what we can however do, is use the hex-literals feature that MySQL kindly offers us.

If you’ve never encountered hexadecimal literals before, you can try and neat little experiment in MySQL like this: SELECT CONCAT(“foo”, 0×626172). This will output the string “foobar”. You can check out why by playing with the HEX and UNHEX methods, which will give you the hexadecimal values of different values. But slapping 0x in front of those values, it’ll act as if a string or integer for all intents and purposes. This offers us the wonderful ability to input arbitrary characters into a query using only hexadecimal digits(0-9 and A-F).

Putting it all together
So far, we’ve determined:

  • The plugin has a SQL injection vulnerability in the administrator interface
  • The SQLi is not blind
  • The output from the query is not output encoded
  • The plugin does not protect against CSRF attacks

So we need to create a CSRF request which contains an image tag which contains an URL to a server we own, where the output of the SQL injection is in the src of the tag as a part of the query string. A bit of stitching together a CONCAT statement by encoding the HTML we need using HEX(), we end up with this result:

With that, we end up with valid rows of “images” in the $imageResults query. When the ID parameter now gets output onto the page, we now have a HTML tag for each user on the site, like this:

When the page then renders, the image tags will try and fetch each of these URLs. Given that you own the domain contained in the injection, you can now fetch the HTTP logs and now you have a full set of hashes for the WordPress installation. Game over!

WordPress Floating Social Media Link Plugins Remote File Inclusion

Advisory

Secunia Advisory SA51346

Analysis
The fsml-admin.js.php and fsml-hideshow.js.php both require a get parameter to specify the path for the wp-load.php file, used to initialize the WordPress backend.
However the wpp parameter is used without validation that it does not contain a malicious input. We can thus provide an url to malicious PHP code, which will be executed by the remote host, like this: