wp-time-capsule < 1.17.0 Unrestricted File Upload vulnerability

Yesterday, one of my customers had their WordPress website hacked. An out-of-date plugin had allowed uploading an arbitrary PHP file, and someone had used this to drop a few files on serveral locations on the website. Luckily the IDS picked up on this quickly, and we could remove the infection and fix the hole.

What happened?

If we just restore the website, and do not plug the hole, the website will be hacked again in no time. So how did they gain access?

According to the webserver logs, a POST was performed to /wp-content/plugins/wp-time-capsule/wp-tcapsule-bridge/upload/php/index.php. That index.php file is just including /wp-content/plugins/wp-time-capsule/wp-tcapsule-bridge/upload/php/UploadHandler.php and instantiating the UploadHandler class. After sending the POST request to index.php, a webshell was created on the server, which was then used to drop the other files.

There was a .htaccess file in /wp-content/plugins/wp-time-capsule/wp-tcapsule-bridge that could have prevented this, but not every webserver even supports .htaccess files.

First thing I did was compare UploadHandler.php to the most recent version of the file. Apart from a few empty lines, the difference between UploadHandler.php in 1.16.3 and 1.17.0 is:

@@ -377,10 +379,21 @@
             return false;
         }

-        if (!in_array($file->type, $this->options['accept_file_types'])) {
+
+
+        $allowed_extensions = array('.sql', '.gz', '.crypt');
+        $found = false;
+        foreach ($allowed_extensions as $extension) {
+            if(strrpos($file->name, $extension) + strlen($extension) === strlen($file->name)){
+                $found = true;
+            }
+        }
+
+        if (!$found) {
             $file-&>error = $this->get_error_message('accept_file_types');
             return false;
         }
+
         if ($uploaded_file && is_uploaded_file($uploaded_file)) {
             $file_size = $this->get_file_size($uploaded_file);
         } else {

The version 1.16.3 used content-type (a untrusted field) to check for file type, the new version checks the actual file extension. If you can modify the headers of the HTTP-request to spoof a application/sql type of file, you can basically upload anything you like.

Lets just make a proof of concept here. First create a file test.php with some malicious code. Then upload it using:

curl -H Expect: -F "files=@test.php;type=application/sql" http://www.example.com/wp-content/plugins/wp-time-capsule/wp-tcapsule-bridge/upload/php/index.php

Now your file is available through http://www.example.com/wp-content/plugins/wp-time-capsule/wp-tcapsule-bridge/upload/php/text.php

Version 1.17.0 of the wp-time-capsule plugin patches the vulnerability by implementing a file extension check, but the changelog does not mention this at all. I believe making a coding error could happen, but covering it up is unpermissible. I prefer to stay away from software developers that don't report on their security problems.

Had this vulnerability been reported transparently, then the WP management software this customer uses would probably have flagged this update as necessary.

Why?

Why was wp-time-capsule out of date in the first place? Because the customer installed a plugin to defer and hide updates... They install updates through some central WordPress management platform like InfiniteWP or ManageWP.

© GeekLabInfo wp-time-capsule < 1.17.0 Unrestricted File Upload vulnerability is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to http://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

Reusing WordPress components: L10n

Personally, I'm a big fan of WordPress. Although it can be bloated sometimes, it uses smart programming techniques and high quality libraries. (Unlike some of the plugins.)

Today, I sorted out how to use the Localization (l10n) libraries of WordPress in another project. And it was a lot simpler than I could have hoped for.

Step 1: Copy some files

From the WordPress distribution, we're gonna need /wp-includes/l10n.php and the directory /wp-includes/pomo/*.php. Copy l10n and the whole directory pomo to your own includes directory.

Step 2: Compatibility

WordPress extensively uses apply_filters and do_action for filtering data and triggering events. We're not gonna use those now, but unless we want to rewrite half of l10n.php, we better make something for compatibility. I entered these simple statements in a new file named wordpress-compat.php:

Continue Reading…

© GeekLabInfo Reusing WordPress components: L10n is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to http://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

Making broken link checker work with Woocommerce external products

I'm working on a new project to bring together all high quality WordPress themes on one website. Today I tried to make broken link checker work with Woocommerce external products.

When you configure the broken link checker to look for urls in the custom field named _product_url, BLC would find all these links. Unfortunately, this only works for posts and pages, but Woocommerce stores its products as product.

So, in order to make these plugins work together, you should add the post_type 'product' to both line 441 and 478 of broken-link-checker/modules/containers/custom_field.php

Guess it would be better if the plugin asked you which post_types should be included.

© GeekLabInfo Making broken link checker work with Woocommerce external products is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to http://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

WordPress: Posting images using XML-RPC

The following code uploads a file using xmlrpc... and without using all kinds of libs, you just need the regular php-xmlrpc module.

$rpcurl='http://www.enter-your-domain-name-he.re/xmlrpc.php';
$username='admin';
$password='your-password';
$blogid=1; //Post ID
 
$file=file_get_contents('file.jpg');
$filetype = "image/jpeg";
$filename = "remote_filename.jpg";
 
xmlrpc_set_type($file,'base64'); // <-- required!
$params = array($blogid,$username,$password,
            array('name'=>$filename,'type'=>$filetype,'bits'=>$file,'overwrite'=>false));
$request = xmlrpc_encode_request('wp.uploadFile',$params);
 
$result = go($request,$rpcurl);
print_r($result);
 
function go($request,$rpcurl){
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_POST,1);
    curl_setopt($ch,CURLOPT_URL,$rpcurl);
    curl_setopt($ch,CURLOPT_POSTFIELDS,$request );
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
    $result = curl_exec($ch);
    return $result;
}
© GeekLabInfo WordPress: Posting images using XML-RPC is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to http://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 4.50 out of 5)
Loading...

My little SEO project (part 2)

Last week I built a site for rental of sinterklaas, a figure in Dutch holiday tradition.

I set up a WordPress blog with Woothemes Inspire. I used a few plugins to do SEO and to speed up the site:
Contact Form 7
Google Analyticator
Google XML Sitemaps
My Page Order
W3 Total Cache
WordPress SEO (yoast)
WP to Twitter
Yoast Breadcrumbs

Within 24 hours, we made it to the first page for relevant keywords. I got a first response in about 20 hours from launch. Then the ranking dropped. Anyway, I'm still pretty impressed.

© GeekLabInfo My little SEO project (part 2) is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to http://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

My little SEO project

Last week I built a site for my motorcycle driving instructor, partly for him, partly for myself to see what I can do with SEO.

I set up a WordPress blog with Woothemes Inspire. I used a few plugins to do SEO and to speed up the site:
Contact Form 7
Google Analyticator
Google XML Sitemaps
My Page Order
W3 Total Cache
WordPress SEO (yoast)
WP to Twitter
Yoast Breadcrumbs

Within 24 hours, we made it to the first page for relevant keywords. I got a first response in about 20 hours from launch. Then the ranking dropped. Anyway, I'm still pretty impressed.

© GeekLabInfo My little SEO project is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to http://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

WordPress: custom links on plugin page

Since WordPress 2.8, you can easily add your own links to the plugin page. This can be useful to jump right to the settings of the plugin. Example code:

function set_plugin_meta($plugin_meta, $plugin_file, $plugin_data, $status){
if (plugin_basename(__FILE__)!=$plugin_file) return $plugin_meta;
return array_merge( $plugin_meta, array( sprintf( '&lt;a href="options-general.php?page=%s"&gt;%s&lt;/a&gt;', $plugin, __('Settings') ) ));
}
add_filter( 'plugin_row_meta', 'set_plugin_meta', 10, 2 );

Two other interesting plugin hooks are:

do_action( 'after_plugin_row', $plugin_file, $plugin_data, $status );
do_action( "after_plugin_row_$plugin_file", $plugin_file, $plugin_data, $status );

These are both run after the row was printed.

© GeekLabInfo WordPress: custom links on plugin page is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to http://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...