用户
 找回密码
 入住 CI 中国社区
搜索
楼主: visvoy
收起左侧

[讨论/交流] 脆弱的CI缓存系统,1天攻陷你的CI网站

    [复制链接]
发表于 2009-10-29 16:05:26 | 显示全部楼层
hex伤心了 又不是解决不掉
发表于 2009-11-6 16:22:24 | 显示全部楼层
本帖最后由 doom12 于 2009-11-6 16:35 编辑

这样是否可行:
改写Output 的 cache 函数, 将cache的MD5标识从URI改成自定义,cache 完全有 controller 控制,
优点: 自己能控制 cache,有很多情况下uri反映不了问题
缺点: 在controller层,效率差一点。
PHP复制代码
 
<?
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Output extends CI_Output {
        var $id_str='';
        var $c_dir='';
       
        function My_output()
    {
        parent::CI_output();
    }
   
        function _write_cache($output)
        {
                $CI =& get_instance(); 
                $path = $CI->config->item('cache_path');
       
                $cache_path = ($path == '') ? BASEPATH.'cache/' : $path;
               
                if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
                {
                        return;
                }
               
                if($this->c_dir!=='') $cache_path = $cache_path.$this->c_dir."/";
               
                $cache_path .= md5($this->id_str);
 
                if ( ! $fp = @fopen($cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE))
                {
                        log_message('error', "Unable to write cache file: ".$cache_path);
                        return;
                }
               
                $expire = time() + ($this->cache_expiration * 60);
               
                if (flock($fp, LOCK_EX))
                {
                        fwrite($fp, $expire.'TS--->'.$output);
                        flock($fp, LOCK_UN);
                }
                else
                {
                        log_message('error', "Unable to secure a file lock for file at: ".$cache_path);
                        return;
                }
                fclose($fp);
                @chmod($cache_path, DIR_WRITE_MODE);
 
                log_message('debug', "Cache file written: ".$cache_path);
        }
       
  function _display_cache()
  { // don't search cache file by URI
        return FALSE;
  }
 
  function _display_cache_si()
        {   $CI =& get_instance();     
                $path = $CI->config->item('cache_path');
       
                $cache_path = ($path == '') ? BASEPATH.'cache/' : $path;
                if($this->c_dir!=='') $cache_path = $cache_path.$this->c_dir."/";
                       
                if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
                {
                        return FALSE;
                }
               
               
                // Build the file path.  The file name is an MD5 hash of the full URI
               
                                       
                $filepath = $cache_path.md5($this->id_str);
               
                if ( ! @file_exists($filepath))
                {
                        return FALSE;
                }
       
                if ( ! $fp = @fopen($filepath, FOPEN_READ))
                {
                        return FALSE;
                }
                       
                flock($fp, LOCK_SH);
               
                $cache = '';
                if (filesize($filepath) > 0)
                {
                        $cache = fread($fp, filesize($filepath));
                }
       
                flock($fp, LOCK_UN);
                fclose($fp);
                                       
                // Strip out the embedded timestamp            
                if ( ! preg_match("/(\d+TS--->)/", $cache, $match))
                {
                        return FALSE;
                }
               
                // Has the file expired? If so we'll delete it.
                if (time() >= trim(str_replace('TS--->', '', $match['1'])))
                {              
                        @unlink($filepath);
                        log_message('debug', "Cache file has expired. File deleted");
                        return FALSE;
                }
               
        $this->cache_expiration = 0; // set to 0 provent from rewrite cache
       
                // Display the cache
                $this->_display(str_replace($match['0'], '', $cache));
                log_message('debug', "Cache file is current. Sending it to browser.");         
                return TRUE;
        }
 
    function cache($m_id,$time)
        {   $this->id_str=( ! is_string($m_id)) ? '' : $m_id;
                $this->cache_expiration = ( ! is_numeric($time)) ? 0 : $time;
               
                return($this->_display_cache_si());
        }
       
        function cache_dir($m_id,$time,$m_dir)
        {   $this->id_str=( ! is_string($m_id)) ? '' : $m_id;
            $this->c_dir=( ! is_string($m_dir)) ? '' : $m_dir;
                $this->cache_expiration = ( ! is_numeric($time)) ? 0 : $time;
               
                return($this->_display_cache_si());
        }
}
 
复制代码


在 controller 里 的 method 里 开始处加入

if($this->output->cache($cache_id,$expire_time))  return;
或者
if($this->output->cache_dir($cache_id,$expire_time,$cache_dir))  return;

$cache_id 可以用method 的参数+自己赋予的唯一标示串组成
$cache_dir 则是在 系统 cache 里建立的2级目录,用于分散cache文件

评分

参与人数 2威望 +8 收起 理由
BruceWolf + 6 思路很好,确实需要能自定义关联 $filepath.
Hex + 2 原创内容

查看全部评分

发表于 2011-12-15 16:28:13 | 显示全部楼层
本人为 CI初学者 看到这篇“长长”的讨论感觉收益颇丰,在以后用到的时候会再度拿出来看看,谢谢楼主和各位高手的阐述。
发表于 2012-2-28 16:26:16 | 显示全部楼层
看到本帖的讨论,再看了下本帖的主题,发现大家讨论的内容偏了。版主的意思没偏,大伙说偏了。但是从大家的讨论中学习到了不少。继续支持Codeigniter中国论坛。
发表于 2012-3-11 17:33:12 | 显示全部楼层
嗯,要使用的话,可以配合自己的model强制url的检测。
发表于 2012-3-12 09:33:47 | 显示全部楼层
楼主真是细心啊,顶。
发表于 2012-3-12 11:14:47 | 显示全部楼层
mark
发表于 2012-3-12 11:59:27 | 显示全部楼层
Chrome都被攻陷了~~~
发表于 2012-4-15 23:31:16 | 显示全部楼层
visvoy 发表于 2009-4-8 07:57
解决办法:
1. 先扩展URI类

好。。。
发表于 2012-4-16 17:17:49 | 显示全部楼层
2.1了 这个问题还是有哦

本版积分规则