How to Efficiently Clean Hidden Link Injections in Your Hacked WordPress Sites

A lightbulb.

Recently I had a very sobering experience that demonstrated just how serious the threat of hacked WordPress sites is. I discovered hidden link injections in some posts on a few of my old sites. These are sites that I no longer actively maintain, they were kind of neglected, and haven’t been updated in a while.

The hack inserted links to drug sites (the viagra and cialis bunch) using “display: none” attribute to hide them from the page. I think Google disregards these hidden type of links, but having them can penalize your site nevertheless.

Creating a Solution

Having assessed the situation, I decided I needed a code snippet that I can run on these sites to find all suspicious posts and later clean them.

I came up with the snippet below. It has two modes, preview and update. In the preview mode (on by default) it will only list suspicious posts which is useful for testing as you can manually inspect the posts to see if they are indeed infected. When you change $preview_only to 0 you activate the update mode where it will also attempt to clean the posts (effectively replacing the link with blank).

The snippet is currently set to look for “display: none” pattern which is commonly used to hide links.

// By default only preview infected posts. Change to 0 to clean posts
$preview_only = 1;

// This is the pattern to search and replace with blank
$pattern = '|
posts where post_content LIKE '%display: none%'"; global $wpdb; $num_cleaned = 0; $posts = $wpdb->get_results($query); echo "Suspicious: ".count($posts)." "; if ($preview_only) echo "Post IDs: "; // go through all suspicious posts foreach ($posts as $post) { if (!$preview_only) { // try the pattern $new_content=preg_replace($pattern, '', $post->post_content); // update the cleaned content if ($new_content!=$post->post_content) { $wpdb->update( $wpdb->posts, array( 'post_content' => $new_content ), array( 'ID' => $post->ID )); $num_cleaned++; } } else echo $post->ID." "; } if (!$preview_only) echo "Cleaned: $num_cleaned";

I loaded the snippet and first run it in the preview mode ($preview_only = 1). Here is how the example output looks like.

Infected
Infected

It basically shows how many posts are suspicious and gives you IDs to these posts so you can manually inspect them (use the Text mode in the editor as you won’t see these links in the Visual editor).

Changing to update mode ($preview_only = 0) the snippet cleans the posts and gives the following output.

Cleaned
Cleaned

Using the ManageWP Code Snippet tool, I was able to run this on a portfolio of 24 sites, and clean the infected sites in less than a minute!

The snippet is now available for your use in the Tools -> Code Snippets screen of your ManageWP dashboard (scroll down to public snippets).

Conclusion

The event is a sobering reminder of hacking threats. I was personally so busy working on ManageWP that I completely forgot about these sites and left them unattended. I have now loaded them into my ManageWP account and used the one click update feature to upgrade the core files, themes and plugins to the latest version (one of these was probably the culprit).

Luckily, after I wrote the code snippet to clean the files, I could use ManageWP to clean all my sites in under a minute, something that could take hours to do manually. I suggest that you run it now, just to check if you have any hidden “surprises” on your sites.

The event also reminded me about the importance of dedicated security tools inside ManageWP (the link injections were unfortunately not detected by the Sucuri checker that we already have integrated). We need tools that will help prevent, warn and clean hacking intrusions. We need them to be a natural extension of the ManageWP dashboard, so you can set it up and not worry about it. Having gone through this experience, I can promise we will be working relentlessly on bringing such tools to ManageWP as soon as possible.

Photo Credit: Sidious Sid

Vladimir Prelovac

Vladimir is the Founder of ManageWP, and is a frequent contributor to the WordPress community - in the form of numerous plug-ins, tools, WordCamp talks and a book by the title WordPress Plugin Development.

20 Comments

  1. Evert Bal

    I can’t get the snippet running. If I leave the PHP opening tag it gives the following error:
    syntax error, unexpected ‘:’ occurred in wp-content/plugins/worker/functions.php(1150) : eval()’d code on line 8

  2. ral

    Hello, I just signed up for managewp. I wanted to try the code snippet to clean up a site, but under tools – code snippet , there is no code? please can you help Regards,

    1. Nevena Tomovic

      Hey Ral,

      Yep we do not provide you with the code, it’s up to you to write it. Here are, however, some great snippets that you can make the most out of. – https://managewp.com/safe-useful-code-snippets

      Regards,

      Nevena

  3. Dnyanesh

    Many Thanks..
    I was looking for this solution. I have many bad links inserted in my post through pingbacks.. This is gonna really helpful

  4. pauliewaulie

    I tried all of this (including paying for the upgrade) but there are still all of the hidden links in my site – http://blog.localdemocracy.org.uk – it keeps saying that there are no suspicious posts but a quick look finds plenty of them.

    The infection that I had has injected loads of hidden links but also lots of visible ones as well. Am I right in guessing that the only way of getting rid of those ones is to do it all manually?

    THanks
    PE

  5. mahajan.344

    Hi

    I am very frustrate with attack.. i have many wordpress sites around 49 and everyday one or more site is being attached by this attack but i have to solve this my going to phpmyadmin of each site then by running below set of query to database

    SELECT * FROM wp_posts WHERE post_content LIKE ‘%%’ and post_status=’publish’ UNION SELECT * FROM wp_posts WHERE post_content LIKE ‘%Ctrl + B%’ and post_status=’publish’

    then remove one by one..

    isn’t there any way i can use managewp to solve this issue ??

    by the way above code is not working. I tried to run it showing 0 result for all sites :(

    1. ManageWP

      There is a code snippet in ManageWP that will allow you to search for any string in posts, including what you need here. Simply use our Code Snippet tool and use this snippet.

  6. Mark

    Hello,

    Your product looks great! To clarify, the Sucuri integration requires a separate account and payments to Sucuri correct?

    Thank you,
    Mark

    1. ManageWP

      It doesn’t. We pay for their scanning API. Cleaning has to be purchased separately though.

  7. Prash

    Hi, I tried it out on a test WP domain which had the default Twenty Twelve. It displayed Zero Infected files. So, after removing the code from the functions.php file, it gives an error which says “Cannot modify header”. Luckily this was a test site. So, how to remove the code safely? Would like to know. Thanks.

  8. Netz

    Hi!

    This is great! Thx (I noticed my DB grew primo this yesr to 2x the size (Could be the new theme with a ton of features?
    But to make sure I wanted to check with this snippet!
    But my Managewp plan is not BIG enuf (PRO).

    Is it possible to install “Code Snippets” by Shea Bunge?
    Copy in this snippet as is (without PHP tags)
    Activate it and just go about… The snippet will be running
    But nothing shows?
    ( I dis change the preview to 0 )??
    After some minutes my DB is still the same size? So if this worked… I’m clean?

    Best regards

    Peter

  9. Peever

    What is this ManageWP you speak of. I have several sites that have had this problem and I have been doing complete re-installs to try and remedy this!

    Sorry for sounding like such a noob but a tool like this would help me tremendously.

    1. Peever

      Oh, you are ManageWP! Sorry I just realized this.

      I will certainly purchase this product and try it out. Which one will I need specifically for this purpose?

      1. ManageWP

        This would be the Professional plan. Please note that when you sign up for the free trial you can use all features for 14 days including the code snippets feature. If you like the service we are happy to have you as our customer!

        1. Peever

          Not sure I can afford the Pro but might opt for the standard when my 14 days are up. Just for the publishing options, bkup, and comment clean up. I will have to start charging my clents more for hosting and maybe I could upgrade next year. Wish I would have heard about your product years ago.

  10. Mathew Porter

    The Sucuri Scanner plugin and online service is a great tool to use.

  11. John

    We will be able to use the code above without using ManageWP? If yes, how?

    Thanks

    1. ManageWP

      Yes you can, it can be used directly in the theme’s funcitons.php file temporarily or transformed into a WordPlugin easilly.

  12. wwip

    Hey Vladimir,

    Thank you for adding this to the code snippets! I had to upgrade to the professional to use it, but I think it’s worth the investment and will help save me some time.

    ~Brett

    1. vprelovac

      Hi Brett

      My pleasure, I hope the repository grows as more people contribute useful snippets.

      Vladimir

Leave a Reply

Your email address will not be published. Required fields are marked *

Over 65,000 WordPress professionals are already using ManageWP

Add as many websites as you want for free, no credit card required. Sign up and start saving time!

Have questions? Get in touch!

Over 65,000 WordPress professionals are already using ManageWP

Add as many websites as you want for free, no credit card required. Sign up and start saving time!



Have questions? Get in touch!

Over 65,000 WordPress professionals are already using ManageWP

Add as many websites as you want for free, no credit card required. Sign up and start saving time!



Have questions? Get in touch!

Over 65,000 WordPress professionals are already using ManageWP

Add as many websites as you want for free, no credit card required. Sign up and start saving time!



Have questions? Get in touch!