• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

代码审计——YXCMS

大数据 开发技术 3周前 (05-12) 19次浏览

前言

YXcms是一个代码审计入门级的cms,比较适合想我这样的小白玩家进行操作。。。

我一直想尝试审计一个cms,但是因为各种原因,一直搁置了。

尝试分析一下 YXCMS 。。。

相关环境

源码信息 : Yxcms php建站系统 1.4.7

本地环境 : phpstudy2018

下载地址 : 175.6.244.211:88/uploads/userup/1596/YXcmsApp1.4.7.zip

安装环境

具体的安装和使用的详细可以上官网查看 https://www.kancloud.cn/yongheng/yxcms

YXcms代码审计

YXcms目录结构

YXcms目录结构
data 存放备份数据
protected 网站程序核心文件夹
public 存放css、images、js、swf等模板公用文件
upload 存放上传文件
.htaccess apache伪静态规则文件
httpd.ini iis伪静态规则文件
index.php 网站入口
robots.txt robots协议
升级日志.txt 详细升级日志记录文件
protected文件夹一些重要的路径:
protected/base 控制器、模型以及接口的父类
protected/cache 数据库缓存、模板缓存等
protected/include canphp核心
protected/config.php 系统全局配置
protected/core.php 系统核心函数
protected/apps 存放应用
protected/apps/admin 后台
protected/apps/default 前台
protected/apps/member 会员中心
protected/apps/install 系统安装

YXcms1.4.7是mvc路由模式开发的。。。

这个版本后台有好几个严重漏洞,

前台有一个储存型XSS,要利用也需与管理员交互。

我们一个一个来进行分析。。。

前台存储型XSS

漏洞复现

前台有留言板的功能,进行测试:

当管理员在后台查看留言的时候,就能触发xss:

可以通过这个 xss 来获取管理员的 cookie ,从而进入网站后台。。

代码分析

让我们看一下代码的实现:

首先前台留言板的代码:

前台的文件源码 protected/apps/default/controller/columnController.php

public function index() { $ename=in($_GET['col']); if(empty($ename)) throw new Exception('栏目名不能为空~', 404); $sortinfo=model('sort')->find("ename='{$ename}'",'id,name,ename,path,url,type,deep,method,tplist,keywords,description,extendid'); $path=$sortinfo['path'].','.$sortinfo['id']; $deep=$sortinfo['deep']+1; $this->col=$ename; switch ($sortinfo['type']) { case 1://文章 $this->newslist($sortinfo,$path,$deep); break; case 2://图集 $this->photolist($sortinfo,$path,$deep); break; case 3://单页 $this->page($sortinfo,$path,$deep); break; case 4://应用 break; case 5://自定义 break; case 6://表单 $this->extend($sortinfo,$path,$deep); break; default: throw new Exception('未知的栏目类型~', 404); break; } } ... protected function extend($sortinfo,$path,$deep) { $tableid=$sortinfo['extendid']; if(empty($tableid)) $this->error('表单栏目不存在~'); $tableinfo = model('extend')->select("id='{$tableid}' OR pid='{$tableid}'",'id,tableinfo,name,type,defvalue','pid,norder DESC'); if(empty($tableinfo)) $this->error('自定义表不存在~'); $urls=explode('|', $sortinfo['url']); // var_dump($tableinfo); // var_dump($urls); // exit(); if (!$this->isPost()) { ... }else{ session_starts(); $verify=session('verify'); session('verify',null); if(empty($verify) || $_POST['checkcode']!=$verify) $this->error('验证码错误,请重新输入'); for($i=1;$i<count($tableinfo);$i++){ if(is_array($_POST[$tableinfo[$i]['tableinfo']])){ $data[$tableinfo[$i]['tableinfo']]=in(deletehtml(implode(',',$_POST[$tableinfo[$i]['tableinfo']]))); $data[$tableinfo[$i]['tableinfo']]=$data[$tableinfo[$i]['tableinfo']]?in(deletehtml($data[$tableinfo[$i]['tableinfo']])):''; }else{ if(strlen($_POST[$tableinfo[$i]['tableinfo']])>65535) $this->error('提交内容超过限制长度~'); $data[$tableinfo[$i]['tableinfo']]=html_in($_POST[$tableinfo[$i]['tableinfo']],true); } } $data['ip']=get_client_ip(); $data['ispass']=0; $data['addtime']=time(); if(empty($urls[1])) $jump=$_SERVER['HTTP_REFERER']; else{ $jurl=explode(',',$urls[1]); if(!empty($jurl[1])){ $arr=explode('/',$jurl[1]); if(!empty($arr)){ $canshu=array(); foreach ($arr as $vo) { $val=explode('=',$vo); $canshu[$val[0]]=$val[1]; } } } $jump=url($jurl[0],$canshu); } $mes=$urls[2]?$urls[2]:'提交成功请等待审核~'; if(model('extend')->Extin($tableinfo[0]['tableinfo'],$data)) $this->success($mes,$jump); else $this->error('提交失败~'); } }

这里前端对xss过滤不完善。。

只对 tname 参数进行了验证 deletehtmlhtml_in

deletehtml 函数

/protected/include/lib/common.function.php

//去除html js标签 function deletehtml($document) { $document = trim($document); if (strlen($document) <= 0) { return $document; } $search = array ("'<script[^>]*?>.*?</script>'si",  // 去掉 javascript "'<[/!]*?[^<>]*?>'si",          // 去掉 HTML 标记 "'([rn])[s]+'",                // 去掉空白字符 "'&(quot|#34);'i",                // 替换 HTML 实体 "'&(amp|#38);'i", "'&(lt|#60);'i", "'&(gt|#62);'i", "'&(nbsp|#160);'i" );                    // 作为 PHP 代码运行 $replace = array ("", "", "1", """, "&", "<", ">", " " ); return @preg_replace ($search, $replace, $document); }

html_in 函数 对html代码进行xss识别,看是否存在危险的html标签对,并进行过滤

使用htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。:

/protected/include/lib/common.function.php

//html代码输入 function html_in($str,$filter=false){ if($filter){ $str=RemoveXSS($str); } $str=htmlspecialchars($str); if(!get_magic_quotes_gpc()) { $str = addslashes($str); } return $str; }

RemoveXSS 函数 对一些危险的标签对 进行了过滤,使其不能进行正常的xss功能,:

function RemoveXSS($val) { // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed // this prevents some character re-spacing such as <javascript> // note that you have to handle splits with n, r, and t later since they *are* allowed in some inputs $val = preg_replace('/([x00-x08,x0b-x0c,x0e-x19])/', '', $val); // straight replacements, the user should never need these since they're normal characters // this prevents like <IMG SRC=@avascript:alert('XSS')> $search = 'abcdefghijklmnopqrstuvwxyz'; $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $search .= '1234567890!@#$%^&*()'; $search .= '~`";:?+/={}[]-_|''; for ($i = 0; $i < strlen($search); $i++) { // ;? matches the ;, which is optional // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars // @ @ search for the hex values $val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ; // @ @ 0{0,7} matches '0' zero to seven times $val = preg_replace('/(


程序员灯塔 , 版权所有
转载请注明原文链接:https://www.wangt.cc/2020/05/%e4%bb%a3%e7%a0%81%e5%ae%a1%e8%ae%a1-yxcms/
喜欢 (0)