好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

WordPress中timthumb.php远程文件存储漏洞分析 - 网站

编外:请参考本文: http://www.2cto.com/Article/201108/98870.html

来源:http://xuser.org/read.php?18 作者:xuser@fsafe 今天在微博上看见的关于wordpress出现了漏洞,随即赶紧打开相关页面分析具体原因,发现是timthumb.php远程存储文件时候的验证上不足而产生的漏洞。大概分析过程如下: 该文件对提交的src变量提交并验证后存储到服务器上  

$src = get_request ('src', '');

利用parse_url ($src)将src进行url分割,然后进行验证  

  global $allowedSites;   // work out file details   $filename = 'external_' . md5 ($src);   $local_filepath = DIRECTORY_CACHE . '/' . $filename;      // only do this stuff the file doesn't already exist   if (!file_exists ($local_filepath)) {     if (strpos (strtolower ($src), 'http://') !== false || strpos (strtolower ($src), 'https://') !== false) {       if (!validate_url ($src)) {         display_error ('invalid url');       }       $url_info = parse_url ($src);       if (count (explode ('.', $url_info['path'])) > 2) {         display_error ('source filename invalid');       }             if (($url_info['host'] == 'www.youtube.com' || $url_info['host'] == 'youtube.com') && preg_match ('/v=([^&]+)/i', $url_info['query'], $matches)) {         $v = $matches[1];         $src = 'http://img.youtube.com/vi/' . $v . '/0.jpg';         $url_info['host'] = 'img.youtube.com';        //如果来源是youtube,则修改之前存储的host       }              $isAllowedSite = false;       // check allowed sites (if required)       if (ALLOW_EXTERNAL) {                //ALLOW_EXTERNAL默认为false         $isAllowedSite = true;       } else {         foreach ($allowedSites as $site) {           if (strpos (strtolower ($url_info['host']), $site) !== false)  //在$url_info['host'])查找是否存在$site             $isAllowedSite = true;  //当为true就继续下一步的存储           }         }       }

其中$allowedSites数组在文件头定义如下  

$allowedSites = array (   'flickr.com',   'picasa.com',   'img.youtube.com', );

进过一系列的验证如果$isAllowedSite如果为真就开始存储这个文件到服务器上  

      if ($isAllowedSite) {         if (function_exists ('curl_init')) {           global $fh;           $fh = fopen ($local_filepath, 'w');           $ch = curl_init ($src);           curl_setopt ($ch, CURLOPT_TIMEOUT, CURL_TIMEOUT);           curl_setopt ($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0');           curl_setopt ($ch, CURLOPT_URL, $src);           curl_setopt ($ch, CURLOPT_RETURNTRANSFER, TRUE);           curl_setopt ($ch, CURLOPT_HEADER, 0);           curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, FALSE);           curl_setopt ($ch, CURLOPT_FILE, $fh);           curl_setopt ($ch, CURLOPT_WRITEFUNCTION, 'curl_write');           // error so die           if (curl_exec ($ch) === FALSE) {             unlink ($local_filepath);             touch ($local_filepath);             display_error ('error reading file ' . $src . ' from remote host: ' . curl_error ($ch));           }           curl_close ($ch);           fclose ($fh);                      // check it's actually an image           $file_infos = getimagesize ($local_filepath);           // no mime type or invalid mime type           if (empty ($file_infos['mime']) || !preg_match ("/jpg|jpeg|gif|png/i", $file_infos['mime'])) {             unlink ($local_filepath);             touch ($local_filepath);             display_error ('remote file not a valid image');           }                           } else {           if (!$img = file_get_contents ($src)) {             display_error ('remote file for ' . $src . ' can not be accessed. It is likely that the file permissions are restricted');           }           if (file_put_contents ($local_filepath, $img) == FALSE) {             display_error ('error writing temporary file');           }         }         if (!file_exists ($local_filepath)) {           display_error ('local file for ' . $src . ' can not be created');         }         $src = $local_filepath;       } else {         display_error ('remote host "' . $url_info['host'] . '" not allowed');       }

使用了strpos验证是否匹配列表中的条件应该是考虑到其分域名问题,不过也形成了一些安全隐患,例如picasa.com.yourdomain.com也是符合这个匹配条件的。关于存储文件的位置信息在如下代码中  

  $filename = 'external_' . md5 ($src);   $local_filepath = DIRECTORY_CACHE . '/' . $filename;

不过通过修改这个匹配规则或直接删除$isAllowedSite所有数组元素都可以临时解决该问题。 备注:发现一些timthumb.php版本中$isAllowedSite数组元素和存储文件方式不太一致,不过 漏洞 产生原因与此关系不是很大

查看更多关于WordPress中timthumb.php远程文件存储漏洞分析 - 网站的详细内容...

  阅读:49次