代码审计-YXcms1.4.7
题外: 今天是上班第一天,全都在做准备工作,明天开始正式实战做事。
看着周围稍年长的同事和老大做事,自己的感觉就是自己还是差的很多很多,自己只能算个废物。
学无止境,我这样的垃圾废物就该多练,保持战斗的欲望,嗯。
今晚回来了没什么事,跟着网上的师傅复现审计一套awd的源码吧。
看了下也是很简单的一套源码,不过在某的小地方可能不容易发现,所以这篇自己把过程写的尽可能详细、对新手友好。
0x01 前台储存型XSS
在留言板处存在储存型XSS
来看看代码 存储xss,首先是前台接收数据没有过滤,然后是后台存储后输出的时候也没有过滤,两个点,一个输入,一个输出 ,都没过滤造成xss存储漏洞。
首先是前台接收:
提交留言的时候我们请求的地址是:
POST /YXCMS_v1.4.7/index.php?r=default/column/index&col=guestbook HTTP/1.1
对应文件的地址:
default模块中column控制器的index()方法.快速审计我们只用找到接收插入数据的地方即可:
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'];
这里$sortinfo=model('sort')->find("ename='{$ename}'",'id,name,ename,path,url,type,deep,method,tplist,keywords,description,extendid');
这里其实很简单,不过有的新手朋友看不懂一些细节,这里就记录的细一些:
先看这个model('sort') 追踪到函数:
function model($model){ static $objArray = array(); $className = $model . 'Model'; if( !is_object($objArray[$className]) ){ if( !class_exists($className) ) { throw new Exception(config('_APP_NAME'). '/' . $className . '.php 模型类不存在'); } $objArray[$className] = new $className(); } return $objArray[$className]; }
这个函数就是找到对应的model文件,如果存在该model的类就新建对象,mvc都是这个套路,这里就是sortModel,
然后是:调用这个函数的find("ename='{$ename}'",'id,name,ename,path,url,type,deep,method,tplist,keywords,description,extendid');函数,我们继续来看看find(),
追踪到model的基类(protected\base\model\model.php):
public function find($condition = '', $field = '', $order = ''){ return $this->model->table($this->table, $this->ignoreTablePrefix)->field($field)->where($condition)->order($order)->find(); }
这里其实非常非常明显了,table方法指定操作的表名,field操作指定的字段,where是指定条件,order是排序,
这里->find()函数是cpModel的find函数,内部调用的select函数,将封装在options数组中的信息进行拼接查询。
//查询多条信息,返回数组 public function select() { $table = $this->options['table']; //当前表 $field = $this->options['field']; //查询的字段 $where = $this->_parseCondition(); //条件 return $this->query("SELECT $field FROM $table $where", array(), true); }
关于这里如果 知道model是cpModel和相应函数的作用,写了下追踪过程:
这里调用了自己的model属性的table方法,我们再转到构造函数来看,虽然有点绕,但是别晕,mvc都是这样,清楚了后一点不难。
public function __construct( $database= 'DB', $force = false){ $this->model = self::connect( config($database), $force); $this->db = $this->model->db; }
这里model属性是自己connect函数的返回值,看看connect函数;
static public function connect($config, $force=false){ static $model = NULL; if( $force==true || empty($model) ){ $model = new cpModel($config); } return $model; }
不用追求细节末枝,我们只需要看到这里新建了cpModel,接着看
$model = new cpModel($config);
ok回到我们这里:
public function find($condition = '', $field = '', $order = ''){ return $this->model->table($this->table, $this->ignoreTablePrefix)->field($field)->where($condition)->order($order)->find(); }
调用了model对象的table方法,这里model对象我们已经知道是cpModel这个对象了,来看看它的table方法:
public function table($table, $ignorePre = false) { if ( $ignorePre ) { $this->options['table'] = $table; } else { $this->options['table'] = $this->config['DB_PREFIX'] . $table; } return $this; }
这里我们是走到:
$this->options['table'] = $this->config['DB_PREFIX'] . $table;
注意这里是调用model对象的table方法,也就是cpModel这个对象,而不是基类model,这里容易搞混淆哦~~~
而这里就大致知道我们插到哪个数据库了,config方法是定义数据库前缀,表前缀也就是我们当初传入的sort,操作的表也就是yx_sort,其他的函数追踪也大同小异 ,我们再回到当初的:
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; }
这里根据不同的type值调用不同的方法,我们来看看我们留言板的数据库是插在哪个表的。
而这个type是查询返回的字典,我们提交的col的值是guestbook,对应的type是6,所以我们执行的是
case 6://表单 $this->extend($sortinfo,$path,$deep); break;
看到这里的extend()函数,我们跟踪:
到这里我们只关注插入相关的操作:
$list=model('extend')->Extselect($tablename,"ispass='1'",'','id desc',$limit);
又是和上面新建model对象一样,这次是extendModel的extselect,我们跟踪看看是否是插入操作:
这里还是最后调用的cpModel的insert方法,中间没有任何过滤。到这里前台接收的代码就分析完成,我们再来看看后台从数据库读取数据的代码.
然后是后台读取:
http://192.168.5.149/YXCMS_v1.4.7/index.php?r=admin/index/login
admin 123456
来看看代码部分
文件位置protected/apps/admin/controller/extendfieldController.php:
//自定义表中信息编辑 public function mesedit() { $tableid=intval($_GET['tabid']); if(!$this->checkConPower('extend',$tableid)) $this->error('您没有权限管理此独立表内容~'); $id=intval($_GET['id']);//信息id if(empty($tableid) || empty($id) ) $this->error('参数错误~'); $tableinfo = model('extend')->select("id='{$tableid}' OR pid='{$tableid}'",'id,tableinfo,name,type,defvalue','pid,norder DESC'); if(empty($tableinfo)) $this->error('自定义表不存在~'); if (!$this->isPost()) { $info=model('extend')->Extfind($tableinfo[0]['tableinfo'],"id='{$id}'"); $this->info=$info; $this->tableid=$tableid; $this->id=$id; $this->tableinfo=$tableinfo; $this->display(); }else{ for($i=1;$i<count($tableinfo);$i++){ if(is_array($_POST[$tableinfo[$i]['tableinfo']])) $data[$tableinfo[$i]['tableinfo']]=implode(',',$_POST[$tableinfo[$i]['tableinfo']]); else $data[$tableinfo[$i]['tableinfo']]=html_in($_POST[$tableinfo[$i]['tableinfo']]); } if(model('extend')->Extup($tableinfo[0]['tableinfo'],"id='{$id}'",$data)) $this->success('修改成功~',url('extendfield/meslist',array('id'=>$tableid))); else $this->error('信息修改失败~'); } }
发现读取数据也没有任何过滤和转移。造成存储xss。
0x02 后台模版getshell
这里可以直接对php文件进行操作。。
并且没有任何过滤措施:
0x03 任意文件删除
文件位置protected/apps/admin/controller/photoController.php
:
public function delpic() { if(empty($_POST['picname'])) $this->error('参数错误~'); $picname=$_POST['picname']; $path=$this->uploadpath; if(file_exists($path.$picname)) @unlink($path.$picname); else{echo '图片不存在~';return;} if(file_exists($path.'thumb_'.$picname)) @unlink($path.'thumb_'.$picname); else {echo '缩略图不存在~';return;} echo '原图以及缩略图删除成功~'; }
代码首先判断是否含有POST参数picname
,然后赋给$picname
,获取路径uploadpath=ROOT_PATH.'upload/photos/'
,使用file_exists()
函数判断文件是否存在,然后再unlink()
进行删除。参数$picname
完全可控,导致任意文件删除:
yxcms代码不是很绕,主要还是心细
代码审计-YXcms1.4.7的更多相关文章
- PHP代码审计中你不知道的牛叉技术点
一.前言 php代码审计如字面意思,对php源代码进行审查,理解代码的逻辑,发现其中的安全漏洞.如审计代码中是否存在sql注入,则检查代码中sql语句到数据库的传输 和调用过程. 入门php代码审计实 ...
- 技术专题-PHP代码审计
作者:坏蛋链接:https://zhuanlan.zhihu.com/p/24472674来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 一.前言 php代码审计如字面 ...
- 关于PHP代码审计和漏洞挖掘的一点思考
这里对PHP的代码审计和漏洞挖掘的思路做一下总结,都是个人观点,有不对的地方请多多指出. PHP的漏洞有很大一部分是来自于程序员本身的经验不足,当然和服务器的配置有关,但那属于系统安全范畴了,我不太懂 ...
- Kindeditor 代码审计
<?php /** * KindEditor PHP * * 本PHP程序是演示程序,建议不要直接在实际项目中使用. * 如果您确定直接使用本程序,使用之前请仔细确认相关安全设置. * */ r ...
- 一个CMS案例实战讲解PHP代码审计入门
前言 php代码审计介绍:顾名思义就是检查php源代码中的缺点和错误信息,分析并找到这些问题引发的安全漏洞. 1.环境搭建: 工欲善其事必先利其器,先介绍代码审计必要的环境搭建 审计环境 window ...
- php代码审计基础笔记
出处: 九零SEC连接:http://forum.90sec.org/forum.php?mod=viewthread&tid=8059 --------------------------- ...
- 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 3.全局防护Bypass之Base64Decode
0x01 背景 现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号.同上一篇,我 ...
- 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 2.全局防护Bypass之UrlDecode
0x01 背景 现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号.遇到这种情况 ...
- PHP代码审计】 那些年我们一起挖掘SQL注入 - 1.什么都没过滤的入门情况
0x01 背景 首先恭喜Seay法师的力作<代码审计:企业级web代码安全架构>,读了两天后深有感触.想了想自己也做审计有2年了,决定写个PHP代码审计实例教程的系列,希望能够帮助到新人更 ...
随机推荐
- HTML5为什么只需要写<!DOCTYPE HTML>?
HTML4.01中的doctype需要对DTD进行引用,因为HTML4.01基于SGML.而HTML5不基于SGML,因此不需要对DTD进行引用,但是需要doctype来规范浏览器的行为.其中,SGM ...
- centos开启nginx服务成功,却无法访问。没有开启80端口。centos配置防火墙 开启80端口
Linux配置防火墙 开启80端口 编辑配置文件/etc/sysconfig/iptables [root@weixinht ~]# vim /etc/sysconfig/iptables 1 # F ...
- C#将数据导入到excel文件
最近在做C#对excel的操作程序,简单的与datagridview的交互如下 using System;using System.Collections.Generic;using System.C ...
- 转换地图 (康托展开+预处理+BFS)
Problem Description 在小白成功的通过了第一轮面试后,他来到了第二轮面试.面试的题目有点难度了,为了考核你的思维能量,面试官给你一副(2x4)的初态地图,然后在给你一副(2x4)的终 ...
- 在64系统里执行32位程序出现/lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
安装下glic即可 sudo yum install glibc.i686
- 实现一个正则表达式引擎in Python(一)
前言 项目地址:Regex in Python 开学摸鱼了几个礼拜,最近几天用Python造了一个正则表达式引擎的轮子,在这里记录分享一下. 实现目标 实现了所有基本语法 st = 'AS342abc ...
- vim编辑python脚本时Tab补全
所属分类:成长之路 使用Linux写python脚本的时候,初期最痛苦的是什么?当然是各种库的不熟悉,知道了库,里面的方法还要挨个看,挨个记. 所以这时候,很多小伙伴使用了ipython,最强大的功能 ...
- [Leetcode][动态规划] 买卖股票的最佳时机IV
一.题目描述 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 k 笔交易. 注意: 你不能同时参与多笔交易(你必须在再次购 ...
- php 循环从数据库分页取数据批量修改数据
//批量修改email重复 public function getEmail() { $this->model = app::get('shop')->model('manage'); / ...
- linux系统下开发环境安装与配置
安装系统环境 CentOS 6.8 64位 jdk版本 7u80 64位 Tomcat版本 Tomcat7 maven版本 Apache Maven 3.6.0 vsftpd版本 vsftpd-2.2 ...