Skip to content

PoC Base Class

In order to simplify the writing of PoC scripts, Pocsuite3 implements the PoC base class: POCBase, where many common code can be placed. When writing PoC, we only need to inherit the base class, and write the core code of the Vulnerability. The commonly used properties and methods are as follows:

Common properties:

self.url # target url
self.scheme # the protocol of the target url
self.rhost # hostname of the target url
self.rport # port of the target url
self.host_ip # WAN ip address

Common method:


# Get the value of the custom command line parameter

# The method to return the result, the parameter is a dictionary,
# it is recommended to use this method to return the result

The self._check() method code is as follows, it will perform port opening check, http/https protocol automatic correction, home page keyword check, honeypot check. It can avoid sending Payload to the honeypot, reducing false positives.

def _check(self, dork='', allow_redirects=False, return_obj=False, is_http=True, honeypot_check=True):
    if conf.get('no_check', False):
        return True

    u = urlparse(self.url)
    # the port closed
    if u.port and not check_port(u.hostname, u.port):
        logger.debug(f'{mosaic(self.url)}, the port is closed.')
        return False

    if is_http is False or self.current_protocol != POC_CATEGORY.PROTOCOL.HTTP:
        return True

    res = None
    # this only covers most cases
    redirect_https_keyword = [
        'request was sent to https port',
        'running in ssl mode. try'
    redirect_https_keyword_found = False
    origin_url = self.url
    netloc = self.url.split('://', 1)[-1]
    urls = OrderedSet()

    # The user has not provided a port in URL, dynamically switching to HTTPS's default port 443
    pr = urlparse(self.url)
    is_ipv6 = pr.netloc.startswith('[')
    if ':' not in'://')[-1] and pr.port == 80:
        pr = pr._replace(scheme='https')
        pr = pr._replace(netloc=f'[{pr.hostname}]:443' if is_ipv6 else f'{pr.hostname}:443')

    for url in urls:
            res = requests.get(url, allow_redirects=allow_redirects)
                - 20x
                - 30x
                - 40x
                - 50x

            # if HTTPS handshake is successful, return directly
            if url.startswith('https://'):

            # if we send an HTTP request to an HTTPS service, but the server may return 20x
            for k in redirect_https_keyword:
                if k.lower() in res.text.lower():
                    redirect_https_keyword_found = True
            if redirect_https_keyword_found:

            # if we send an HTTP request to an HTTPS service, the server may return 30x, 40x, or 50x...
            if not str(res.status_code).startswith('20'):

        except requests.RequestException:

    if not isinstance(res, requests.Response):
        return False

    self.url = res.request.url.rstrip('/')
    if res.history:
        self.url = res.history[0].request.url.rstrip('/')

    if self.url.split('://')[0] != self.scheme:
        self.url = self.build_url(self.url)
        logger.warn(f'auto correct url: {mosaic(origin_url)} -> {mosaic(self.url)}')

    if return_obj:
        return res

    content = str(res.headers).lower() + res.text.lower()
    dork = dork.lower()

    if dork not in content:
        return False

    if not honeypot_check:
        return True

    is_honeypot = False

    # detect honeypot
    keyword = [

    sin = 0
    for k in keyword:
        if k in content:
            sin += 1

    if sin >= 3:
        logger.debug(f'honeypot: sin({sin}) >= 3')
        is_honeypot = True

    # maybe some false positives
    elif len(re.findall('<title>(.*)</title>', content)) > 5:
        logger.debug('honeypot: too many title')
        is_honeypot = True

    elif len(re.findall('basic realm=', content)) > 5:
        logger.debug('honeypot: too many www-auth')
        is_honeypot = True

    elif len(re.findall('server: ', content)) > 5:
        logger.debug('honeypot: too many server')
        is_honeypot = True

    if is_honeypot:
        logger.warn(f'{mosaic(self.url)} is a honeypot.')

    return not is_honeypot

Released under the GPLv2 License.