Contents

测试版本:1.2.6

YXcms的在使用unlink函数删除文件的时候没有考虑到对该参数做一个限制,导致存在很多个任意文件删除的漏洞。漏洞代码也比较直接,比如:

if(!empty($_POST['oldheadpic'])){
    $picpath=$this->uploadpath.$_POST['oldheadpic'];
    if(file_exists($picpath)) @unlink($picpath);

这里是更新头像之后删除旧的头像图片。而旧头像的路径是直接从客户端发送的参数,接受之后仅仅判断了一下文件是否存在,如果存在就删除。从而存在漏洞。

任意文件删除的漏洞有好几个点都存在,官方也进行了一些修复。先看一下官方修复的方式,这里是乌云报过的漏洞。http://wooyun.org/bugs/wooyun-2010-047226 修复前存在问题的代码:

if(!empty($_POST['oldpicture']) && $_POST['oldpicture']!=$this->nopic){

    $picpath=$this->uploadpath.$_POST['oldpicture'];

    echo $picpath;

    if(file_exists($picpath)) @unlink($picpath);//删除文艺文件

修复之后的代码:

if(!empty($_POST['oldpicture']) && $_POST['oldpicture']!=$this->nopic){
        $picpath=$this->uploadpath.$_POST['oldpicture'];
        $lasts=strtolower(substr($_POST['oldpicture'],-3));
        if(file_exists($picpath) && in_array($lasts,array('gif','jpg','png','bmp'))) @unlink($picpath);
    }

这里加入了一个对传入的$_POST[‘oldpicture’]参数的判断,判断这个文件名后缀是否是gif,jpg等。这个修复方案显示是不完善的。之所以存在任意文件删除的问题根源在于传入的文件名$_POST[‘oldpicture’]完全可控,可以使用任意的”.. / \ “字符来遍历任意路径下的文件。所以防御的思路应该是从限制任意路径遍历入手,而不是限制文件类型。限制了文件类型最直接的问题就是可以这个漏洞退化成了一个删除任意图片文件。任何一个注册用户都可以将整个站点的所有图片文件删除。而在php5.3.4以前的版本中,可以使用\0(0x00字节)进行文件操作的截断。所以对布署在php5.3.4以前版本中的应用来说,任意文件删除的漏洞依然没有修复。

最后分析一个最新版中二次操作导致的任意文件删除漏洞。这个漏洞还没有人公开分析过。问题代码存在photoController.php。通过搜索unlink关键字定位到代码:

if(!empty($photos['photolist'])){
    $phoarr=explode(',',$photos['photolist']);
    foreach ($phoarr as $vo){
        if(file_exists($path.$vo))
        unlink($path.$vo);
        if(file_exists($path.'thumb_'.$vo))
        @unlink($path.'thumb_'.$vo);
    }

删除使用的数据来源于$photos[‘photolist’]变量。315行,变量$photo来源于数据库中查询的结果

$photos=model('photo')->find("id='$id'",'photolist,sort,extfield,account');

经过分析,photo表里的数据在新建图集或者编辑图集的时候插入数据库的。数据来源于用户数据。相关代码该文件151行:

if(!empty($_POST['photolist']))
$data['photolist']=implode(',',$_POST['photolist']);
if(!empty($_POST['conlist']))
$data['conlist']=implode(',',in($_POST['conlist']));
if(model('photo')->insert($data))
$this->success('图集添加成功~',url('photo/index'));
else $this->error('图集添加失败');

从$_POST[‘photolist’]中取了数据,插入到了photo表中。所以添加图集的时候,修改post数据中photolist%5B%5D=../../protected/apps/install/install.lock 就可控制目标数据。

data

删除图集的时候就可以看到数据被带入unlink函数中,安装锁定文件被删除。

访问任意页面就会跳到安装页了。

data

Contents