WP Manifestindependent plugin directory
manifest / social / reclaim-social-media

Reclaim WP Registry grade F. Critical findings · 5 findingsWP RegistryCritical findings · 5 findingsOpen the reportF #10 in Social & Sharing

reclaim your stuff from social media silos

★ 47stars
261release downloads
0.2.4latest · never

Install

Download reclaim.zip From the 0.2.4 release on GitHub, Feb 24, 2014

Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/espresto/reclaim-social-media/releases/download/0.2.4/reclaim.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

Reclaim Social Media version .2, based on Reclaim Social Media version .1 by Felix Schwenzel & Sascha Lobo.

It’s a single WordPress plugin by Remigi Illi at digitaleheimat.de, instead of a collection of proxy-scripts and 3rd party plugins. The code of the early version can be found at GitHub (proxy scripts) and the reclaim.fm site.

The plugin is still pretty raw but should be a good foundation for further development.

What it does

Right now reclaim grabs your tweets, Google+ and Facebook posts, Flickr and Instagram images, YouTube and Vine videos and imports them as WordPress posts. It is written in a modular fashion, which enables anyone to easily write further importer modules for other services.

If reclaim grabs a tweet, it constructs an embed code with clickable hashtags, mentions and real links (unshortened t.co links). To do that, you need to get an API key from Twitter. This is a little complicated, but very much on purpose. We don't want to create a central application, that can be shut down at will by Twitter, but instead many decentralized apps with individual API keys, that can not be shut down easily.

The Twitter embed code is being rendered with Twitter's widget.js, which is a little invasive on users privacy, but looks nice. Also, the embed-code is fully searchable within WordPress. In case an image is attached, it is being saved in the WordPress media library and set as the featured image. Note that with some themes this may cause the image to be shown twice.

The idea is to copy all the relevant data from the services you use and to enable you to keep a copy on your own server.

Demo

http://wirres.net/reclaim/

Installation

Download a release and extract it in your WordPress installation under "wp-content/plugins".

Alternatively you can install the latest version from git. Go to your WordPress installation path and follow these instructions:

cd wp-content/plugins
git clone git://github.com/espresto/reclaim-social-media reclaim
cd reclaim
curl -sS https://getcomposer.org/installer | php
php composer.phar install

Always remember, Reclaim Social Media is still under heavy development and the plugin is not considered stable yet.

Reclaim Social Media requires that you run at least PHP 5.3.2 with CURL support (e.g. php5-curl in Debian).

Releases

4 releases. Each count is every asset in that release; expand a row for the breakdown.

Tag
Published
Assets
Downloads
0.2.4 latest
Feb 24, 2014 12 years ago
reclaim.zip
188
Jan 16, 2014 12 years ago
reclaim.zip
40
Jan 6, 2014 12 years ago
reclaim.zip
19
Jan 2, 2014 12 years ago
reclaim.zip
14
F grade

Security

Reclaim 0.1 · audited by WP Registry

Critical findings.

1 critical 2 high 2 medium
Audited release
0.1
Findings
5
Worst severity
critical
Content hash
7e78103009d255db2c844505…

Findings

  • critical Subscriber-level SSRF in Instagram resync AJAX imports attacker JSON into published posts, giving stored XSS via [embed_code]

    xss_stored

    Each module registers wp_ajax_<mod>_resync_items with no capability check and no nonce, so any logged-in user (Subscriber) can call it. instagram_reclaim_module::ajax_resync_items() takes $_POST['next_url'] verbatim and fetches it with wp_remote_get (SSRF). The JSON response is passed to map_data()/construct_content(), which concatenates $entry['link'] unescaped into an <iframe src="..."> embed_code string. insert_posts() then calls wp_insert_post with post_status 'publish' and saves that string as the 'embed_code' post meta. The [embed_code] shortcode returns get_post_meta(...,'embed_code') with no escaping. Post meta is not kses-filtered, so a link value like '"><script>...</script>' runs on the public front end for every visitor and any admin who views the post. Precondition: the Instagram module is active and has instagram_user_id/instagram_access_token set. Facebook, Flickr, Google+, Moves, Vine and YouTube take the same unvalidated next_url, so the SSRF also applies to them.

    mods/instagram.class.php:224-252, 380-400

    Recommendation

    Require current_user_can('manage_options') and check_ajax_referer() in every ajax_* handler. Never fetch a client-supplied next_url (rebuild pagination server-side or limit it to the provider host). Escape all imported fields (esc_url/esc_attr) and run embed_code through wp_kses before storing or rendering it.

  • high Unauthenticated / CSRF destructive admin actions via is_admin() check in constructor (delete all imported posts, reset, resync)

    missing_auth

    reclaim_core::__construct() runs on init. If is_admin() is true and $_REQUEST['<mod>_remove_posts'], '<mod>_reset' or '<mod>_resync' is set, it immediately calls removePostsMod/resetMod/updateMod. There is no capability check and no nonce. is_admin() is also true for /wp-admin/admin-ajax.php and admin-post.php, including requests from unauthenticated visitors. So anyone can send GET /wp-admin/admin-ajax.php?twitter_remove_posts=1 (or any active module name). remove_posts() force-deletes every post generated by that module, plus their attachments, permanently ($force_delete = true). It can also reset sync state or start expensive remote imports.

    reclaim.php:64-82

    Recommendation

    Move these actions to admin_post_* handlers that require current_user_can('manage_options') and check_admin_referer().

  • high [embed_code] shortcode renders unprotected post meta unescaped (Contributor stored XSS)

    xss_stored

    The embed_code meta key is not underscore-protected. Any user who can edit a post (Contributor and up) can set it through the Custom Fields UI or add_meta, then put [embed_code] in the post. The shortcode returns do_shortcode(get_post_meta($post_id,'embed_code',true)) with no kses or escaping. Script then runs when an editor or admin previews the post, or on the front end once it is published.

    reclaim.php:416-423

    Recommendation

    Store embed codes under a protected key (_reclaim_embed_code) and run output through wp_kses with an iframe allowlist.

  • medium Publicly readable log file in plugin directory records API URLs containing access tokens

    information_disclosure

    reclaim_module::log() appends to RECLAIM_PLUGIN_PATH/reclaim-log.txt inside the web-accessible plugin folder. import_via_curl() logs 'error while loading '.$apiurl on any HTTP error. Those URLs carry instagram_access_token, facebook_oauth_token, foursquare/moves access tokens and the google_api_key. Anyone can fetch /wp-content/plugins/reclaim/reclaim-log.txt and harvest the site owner's social API tokens.

    mod.class.php:220-224, 409-411

    Recommendation

    Write logs outside the web root (or to error_log) and strip tokens and keys from logged URLs.

  • medium Direct-access hybridauth_helper.php is an unauthenticated open redirect

    unsafe_input

    helper/hybridauth/hybridauth_helper.php can be requested directly and does not load WordPress. It takes $_REQUEST['callbackUrl'], urldecodes it, and redirects to it with header('Location: ...') in both the success and failure branches. Nothing validates the URL, so attackers can use the site's domain to bounce victims to phishing pages.

    helper/hybridauth/hybridauth_helper.php:19-37, 67-98

    Recommendation

    Route the OAuth flow through WordPress, validate callbackUrl with wp_validate_redirect() against admin_url(), and block direct access.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.