WordPress Online Store arbitrary file disclosure


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


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


Secunia Advisory SA51346

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:


WordPress Zingiri Forums arbitrary file disclosure


Secunia Advisory SA50833

Analysis of vulnerability

The Zingiri Web Forums for WordPress writes our a header for the forum in forum.php through adding an action to wp_head.

So on each load of the WordPress blog it will call into zing_forum_header. The first call it makes it into zing_forum_output, which is rather long. I’ve highlighted two areas:

We can affect the value of $zing_forum_to_include through the zforum GET variable. This is then used in a big else if statement. Here is the block of code that is executed if we set that to css:

If we don’t set anything expect the “url” get variable, we can cause it to be fed into the file_get_contents call on line 554. We can abuse this to disclose the contents of the wp-config.php file like this:


WordPress Google Document Embedder arbitrary file disclosure


Secunia Advisory SA50832

Analysis of vulnerability

Google Document Embedder offers a proxy for forcing a PDF to download rather than use the default browser handler. It implements this through /libs/pdf.php:

First it will check if allow_url_fopen is enabled. Then it checks the two variables we need to provide, the “fn”(Filename) and “file” GET parameters. If both are provided it will verify that the filename ends in .pdf. From there, it goes onto deicing how to fetch the file, and eventually call into file_get_contents by passing the file GET parameter straight into the call. Note that the filename is only used to determine the filename returned on line 45. Because it will use file_get_contents if at all possible, we can provide a local path to include. We can for instance fetch the wp-config.php file like this:


WordPress Duplicator plugin arbitrary file disclosure

Analysis of vulnerability

In version 0.3.0 of WordPress duplicator the file /files/installer.rescue.php and /files/installer.template.php which were added for security reasons. The file was made to download an installer file. They both start with this snippet of code::

If the “get” querystring parameter is set, it will read the file specified by the “file” querystring parameter and read that into the response as installer.php. But because this file is deployed by default to all installations and it does not sanitize the “file” variable, we can use it to read any arbitrary file by making a request like this:


WordPress Advanced Custom Fields remote file inclusion vulnerability


Secunia Advisory SA 51037

Analysis of vulnerability
A Remote File Inclusion vulnerability exists in the Advanced Custom Fields plugin for WordPress. By exploiting an unsafe use of array_merge which takes user-input in /core/actions/export.php, it is possible to override a value used for an include:

By posting another value for acf_abspath to the script, we can overwrite the value which is used for the two require_once calls. For instance, we can make a request like this which will request /wp-load.php and /wp-admin/admin.php from myevilsite.com:


WordPress All Video Gallery Plugin SQL injection vulnerability


Secunia Advisory SA50874

Analysis of vulnerability

The All Video Gallery Plugin has two pages, playlist.php and /xml/playlist.php, which both takes a “vid” ID and outputs the result from the query into XML format.

Note however that the “vid” GET parameter is never sanitized, which means that we can inject SQL into it and disclose information from the database by making a simple request to either of the pages like this:


WordPress FireStorm Professional Real Estate Plugin SQL Injection vulnerability


Secunia Advisory SA 50873

Analysis of vulnerability

The FireStorm Professional Real Estate Plugin for WordPress offers functionality for an user to search for real estate based on a province or country. It is implemented in the file search.php:

By either providing a ProvinceID or CountryID, we can make the application pass the value into two SQL queries. Note however that in both cases, the value is taken directly from the GET parameter without sanitazion, which opens it up to a SQL injection attack where we can select arbitrary data from the database. For instance, we can select the password hash for an user like this: