文章目录
  1. 一点点经验

审计入门之路(一):YzmCMS

上个月把审计扔掉补充渗透的知识了,大概三周左右。我把渗透的常规思路和常用的工具都学了一圈,顺便挣了点点稿费,原文在:http://bobao.360.cn/learning/detail/3683.html ,有错误之处还请师傅们指出^_^ 有新知识学习是最开心的了

渗透入门结束还是回来搞审计,选了一个之前乐清小俊杰师傅搞过的YzmCMS。他审这个CMS的时候说是个同学写的小源码,如今这个CMS已经有官网了,地址是:http://www.yzmcms.com,不过之前审过74cms,Yii和TP都学过一些,所以审MVC不会很费劲,也就当个入门偏向进阶的审计学习CMS了~

1.jpg

加起来看了一天左右,先是摸清了文件夹的结构和功能,然后看了下模块控制器方法的调用方法,这就用了一晚上(新司机经验不够,听柠檬师傅说他们审代码一周都好几套源码,给跪了)。然后半个上午时间审了一圈公共函数,发现几个有问题的函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function grab_image($content, $targeturl = ''){
preg_match_all('/<[img|IMG].*?src=[\\'|\\"](.*?(?:[\\.gif|\\.jpg]))[\\'|\\"].*?[\\/]?>/', $content, $img_array);
$img_array = isset($img_array[1]) ? array_unique($img_array[1]) : array();
if($img_array) {
$path = C('upload_file').'/'.date('Ym/d');
$urlpath = SITE_URL.$path;
$imgpath = YZMPHP_PATH.$path;
if(!is_dir($imgpath)) @mkdir($imgpath, 0777, true);
}
foreach($img_array as $key=>$value){
$val = $value;
if(strpos($value, 'http') === false){
if(!$targeturl) return $content;
$value = $targeturl.$value;
}
$ext = strrchr($value, '.');
if($ext!='.png' && $ext!='.jpg' && $ext!='.gif' && $ext!='.jpeg') return false;
$imgname = date("YmdHis").rand(1,9999).$ext;
$filename = $imgpath.'/'.$imgname;
$urlname = $urlpath.'/'.$imgname;
ob_start();
readfile($value);
$data = ob_get_contents();
ob_end_clean();
file_put_contents($filename, $data);
if(is_file($filename)){
$content = str_replace($val, $urlname, $content);
}else{
return $content;
}
}
return $content;
}

一个读取远程图片保存到本地的函数,图片地址没有验证ip,所以可以读本地图片。一个弱智的SSRF诞生了。不过这也真的没多大的危害,我能想到的就是读一读服务器图片,也再就没啥了。不过值得一提的是,图片地址的验证正则有点问题,不完全是图片格式的代码也可以被匹配到。不过最后他不是直接写入file_put_contents函数,而是先写到缓冲区再把缓冲区的内容写进去。这种写法是第一次看到,学习了。(最后这个没有利用成功)

通用函数读完,就看到控制器了。先从Admin控制器开始看把(因为Admin的模块在最上面),就惊喜的发现了这么一个地方。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public function edit() {
if(isset($_POST['dosubmit'])) {
$catid = isset($_POST['catid']) ? $_POST['catid'] : 0; //这里不能写成intval($_POST['catid'])
if($_POST['parentid']=='0') {
$_POST['arrparentid'] = '0';
}else{
$data = $this->db->field('arrparentid,arrchildid')->where(array('catid'=>$_POST['parentid']))->find();
if(strpos($data['arrparentid'],$catid) !== false || $_POST['parentid']==$catid) return_json(array('status'=>0,'message'=>'不能将类别移动到自己或自己的子类别中!'));
$_POST['arrparentid'] = $data["arrparentid"].','.$_POST['parentid'];
}
//如果有修改分类的动作
if($_POST['arrparentid']!=$_POST['cpath']){
$_POST['cpath'] = safe_replace($_POST['cpath']);
$_POST['arrparentid'] = safe_replace($_POST['arrparentid']);
$cpath = $_POST['cpath'].','.$catid; //和现有的操作的分类id相连
$this->db->query("UPDATE yzmcms_category SET arrparentid=REPLACE(arrparentid, '{$_POST['cpath']}','{$_POST['arrparentid']}') WHERE arrparentid like '{$cpath}%'");
}
if(!isset($_POST['type'])){ //非外部链接,只有外部链接设置了type字段
//如果PC版URL规则为跟随系统
if($_POST['category_urlrule'] == '0'){
$_POST['pclink'] = get_config('url_rule') ? SITE_URL.'list_'.$catid.'.html' : U('index/index/lists','catid='.$catid);
}else{
$urlrule = get_urlrule($_POST['category_urlrule']);
$_POST['pclink'] = SITE_URL.$urlrule['catdir'].'/'; //以URL规则中的catdir为准
}
}
if($this->db->update($_POST, array('catid' => $catid))){
if($_POST['arrparentid']!=$_POST['cpath']) $this->repairs($_POST['arrparentid'], $_POST['cpath']);
delcache('categoryinfo');
return_json(array('status'=>1,'message'=>L('operation_success')));
}else{
return_json();
}
}else{
$type = isset($_GET['type']) ? intval($_GET['type']) : 0;
$catid = isset($_GET['catid']) ? intval($_GET['catid']) : 0;
$modelinfo = get_modelinfo();
$urlrule = get_urlrule();
$tem_style = APP_PATH.'index'.DIRECTORY_SEPARATOR.'view'.DIRECTORY_SEPARATOR.C('site_theme').DIRECTORY_SEPARATOR.'config.php';
if(!is_file($tem_style)) showmsg($tem_style."文件不存在,请检查!", 5);
$templets = require($tem_style);
$category_temp = $templets['category_temp'];
$list_temp = $templets['list_temp'];
$show_temp = $templets['show_temp'];
$data = $this->db->where(array('catid' => $catid))->find();
if($type == 0){
include $this->admin_tpl('category_edit');
}else if($type == 1){
include $this->admin_tpl('category_page_edit');
}else{
include $this->admin_tpl('category_link_edit');
}
}
}

重点在$catid = isset($_POST['catid']) ? $_POST['catid'] : 0; //这里不能写成intval($_POST['catid'])
追一下$catid。

1
2
3
4
5
6
if($_POST['arrparentid']!=$_POST['cpath']){
$_POST['cpath'] = safe_replace($_POST['cpath']);
$_POST['arrparentid'] = safe_replace($_POST['arrparentid']);
$cpath = $_POST['cpath'].','.$catid; //和现有的操作的分类id相连
$this->db->query("UPDATE yzmcms_category SET arrparentid=REPLACE(arrparentid, '{$_POST['cpath']}','{$_POST['arrparentid']}') WHERE arrparentid like '{$cpath}%'");
}

$catid没有走db类的方法,而是用query函数直接写入数据库查询。

1.png

2.png


一点点经验

一段时间的学习找到多少漏洞并不重要,重要的是,我在这个过程学习到了什么。

  1. MVC框架的理清对后面审计控制器帮助很大。
  2. 与数据库交互的地方采用统一的db类入口,只要在db类中做好过滤,就很难找到注入。但是不排除有些db类没有的语句而使用了query()进行数据库交互,产生注入的问题。
  3. 一个控制器全都是与数据库交互的方法,还都用了db类,就不要一个劲盯着看了,找不到注入的。
  4. 这次没有花经验在越权和逻辑漏洞上。我认为这类漏洞在现在的cms上会比注入要多(一个猜测)
  5. api controller 会比 member 或 admin controller 有更多的问题(另一个猜测)

(‘40’,’1.jpg’,’1-jpg’,’1491291832’,’1491291832’,’a:5:{s:4:”name”;s:5:”1.jpg”;s:4:”path”;s:35:”/usr/uploads/2017/04/3299974566.jpg”;s:4:”size”;i:54826;s:4:”type”;s:3:”jpg”;s:4:”mime”;s:10:”image/jpeg”;}’,’3’,’1’,null,’attachment’,’publish’,null,’0’,’1’,’0’,’1’,’39’,’0’),
(‘41’,’1.jpg’,’1-jpg-1’,’1491395174’,’1491395174’,’a:5:{s:4:”name”;s:5:”1.jpg”;s:4:”path”;s:35:”/usr/uploads/2017/04/2242526920.jpg”;s:4:”size”;i:69618;s:4:”type”;s:3:”jpg”;s:4:”mime”;s:10:”image/jpeg”;}’,’1’,’1’,null,’attachment’,’publish’,null,’0’,’1’,’0’,’1’,’45’,’0’),
(‘42’,’2.jpg’,’2-jpg’,’1491396679’,’1491396679’,’a:5:{s:4:”name”;s:5:”2.jpg”;s:4:”path”;s:33:”/usr/uploads/2017/04/86846092.jpg”;s:4:”size”;i:50559;s:4:”type”;s:3:”jpg”;s:4:”mime”;s:10:”image/jpeg”;}’,’2’,’1’,null,’attachment’,’publish’,null,’0’,’1’,’0’,’1’,’45’,’0’),
(‘43’,’3.jpg’,’3-jpg’,’1491396760’,’1491396760’,’a:5:{s:4:”name”;s:5:”3.jpg”;s:4:”path”;s:35:”/usr/uploads/2017/04/4071474630.jpg”;s:4:”size”;i:125896;s:4:”type”;s:3:”jpg”;s:4:”mime”;s:10:”image/jpeg”;}’,’3’,’1’,null,’attachment’,’publish’,null,’0’,’1’,’0’,’1’,’45’,’0’),
(‘44’,’4.jpg’,’4-jpg’,’1491397166’,’1491397166’,’a:5:{s:4:”name”;s:5:”4.jpg”;s:4:”path”;s:35:”/usr/uploads/2017/04/3888413363.jpg”;s:4:”size”;i:97380;s:4:”type”;s:3:”jpg”;s:4:”mime”;s:10:”image/jpeg”;}’,’4’,’1’,null,’attachment’,’publish’,null,’0’,’1’,’0’,’1’,’45’,’0’),
(‘45’,’审计入门之路(二):ourphp’,’45’,’1491401100’,’1493212617’,’

支持一下
扫一扫,支持forsigner