diff --git a/Dockerfile b/Dockerfile index 5a0c8a74..f77130a9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ FROM ubuntu:22.04 -MAINTAINER Knownsec 404 Team +LABEL maintainer="Knownsec 404 Team" ARG version -env DEBIAN_FRONTEND=noninteractive +ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update \ && apt-get install -y \ diff --git a/pocsuite3/lib/yaml/nuclei/operators/__init__.py b/pocsuite3/lib/yaml/nuclei/operators/__init__.py index 351b8503..af38c0e7 100644 --- a/pocsuite3/lib/yaml/nuclei/operators/__init__.py +++ b/pocsuite3/lib/yaml/nuclei/operators/__init__.py @@ -11,7 +11,8 @@ match_regex, match_size, match_status_code, - match_words) + match_words, + match_xpath) __all__ = [ "ExtractorType", @@ -29,4 +30,5 @@ "match_regex", "match_binary", "match_dsl", + "match_xpath", ] diff --git a/pocsuite3/lib/yaml/nuclei/operators/extrators/__init__.py b/pocsuite3/lib/yaml/nuclei/operators/extrators/__init__.py index 357684cf..6fd27f68 100644 --- a/pocsuite3/lib/yaml/nuclei/operators/extrators/__init__.py +++ b/pocsuite3/lib/yaml/nuclei/operators/extrators/__init__.py @@ -137,7 +137,7 @@ def extract_xpath(e: Extractor, corpus: str) -> dict: else: doc = etree.HTML(corpus) - if not doc: + if doc is None: return results for x in e.xpath: diff --git a/pocsuite3/lib/yaml/nuclei/operators/matchers/__init__.py b/pocsuite3/lib/yaml/nuclei/operators/matchers/__init__.py index 7badbbba..a84f0363 100644 --- a/pocsuite3/lib/yaml/nuclei/operators/matchers/__init__.py +++ b/pocsuite3/lib/yaml/nuclei/operators/matchers/__init__.py @@ -1,6 +1,7 @@ import binascii import re from dataclasses import dataclass, field +from lxml import html from typing import List from pocsuite3.lib.yaml.nuclei.model import CaseInsensitiveEnum @@ -14,6 +15,7 @@ class MatcherType(CaseInsensitiveEnum): RegexMatcher = "regex" BinaryMatcher = "binary" DSLMatcher = "dsl" + XpathMatcher = "xpath" @dataclass @@ -49,6 +51,9 @@ class Matcher: # Regex contains Regular Expression patterns required to be present in the response part. regex: List[str] = field(default_factory=list) + # Xpath contains xpath patterns required to be present in the response part. + xpath: List[str] = field(default_factory=list) + # Binary are the binary patterns required to be present in the response part. binary: List[str] = field(default_factory=list) @@ -181,3 +186,40 @@ def match_dsl(matcher: Matcher, data: dict) -> bool: if len(matcher.dsl) - 1 == i: return True return False + + +def match_xpath(matcher: Matcher, body: str) -> (bool, list): + """Matches xpath check against a body. + """ + # Convert the body string to etree.HTML object for xpath manipulations + if body is None: + return False + body_tree = html.fromstring(body) + matched_xpaths = [] + + for i, xpath_pattern in enumerate(matcher.xpath): + try: + # Applying xpath on the HTML and capturing the result + result = body_tree.xpath(xpath_pattern) + if not result: + # If result is empty, the xpath expression did not match anything in the HTML body + if matcher.condition == 'and': + return False, [] + elif matcher.condition == 'or': + continue + + if matcher.condition == 'or' and not matcher.match_all: + return True, [result] + + matched_xpaths.append(result) + + if len(matcher.xpath) - 1 == i and not matcher.match_all: + return True, matched_xpaths + + except Exception as e: + print(f"Error while matching with XPath {xpath_pattern}. Error: {str(e)}") + + if len(matched_xpaths) > 0 and matcher.match_all: + return True, matched_xpaths + + return False, [] diff --git a/pocsuite3/lib/yaml/nuclei/protocols/http/__init__.py b/pocsuite3/lib/yaml/nuclei/protocols/http/__init__.py index d3f72e6a..1e670c1b 100644 --- a/pocsuite3/lib/yaml/nuclei/protocols/http/__init__.py +++ b/pocsuite3/lib/yaml/nuclei/protocols/http/__init__.py @@ -16,7 +16,7 @@ extract_xpath, match_binary, match_dsl, match_regex, match_size, match_status_code, - match_words) + match_words, match_xpath) from pocsuite3.lib.yaml.nuclei.protocols.common.generators import AttackType, payload_generator from pocsuite3.lib.yaml.nuclei.protocols.common.interactsh import InteractshClient from pocsuite3.lib.yaml.nuclei.protocols.common.replacer import ( @@ -198,6 +198,9 @@ def http_match(request: HttpRequest, resp_data: dict, interactsh=None): elif matcher.type == MatcherType.DSLMatcher: matcher_res = match_dsl(matcher, resp_data) + elif matcher.type == MatcherType.XpathMatcher: + matcher_res, _ = match_xpath(matcher, item) + if matcher.negative: matcher_res = not matcher_res diff --git a/pocsuite3/lib/yaml/nuclei/protocols/network/__init__.py b/pocsuite3/lib/yaml/nuclei/protocols/network/__init__.py index 953bf95d..3584dcc0 100644 --- a/pocsuite3/lib/yaml/nuclei/protocols/network/__init__.py +++ b/pocsuite3/lib/yaml/nuclei/protocols/network/__init__.py @@ -15,7 +15,7 @@ extract_dsl, extract_kval, extract_regex, match_binary, match_dsl, match_regex, - match_size, match_words) + match_size, match_words, match_xpath) from pocsuite3.lib.yaml.nuclei.protocols.common.generators import AttackType, payload_generator from pocsuite3.lib.yaml.nuclei.protocols.common.interactsh import InteractshClient from pocsuite3.lib.yaml.nuclei.protocols.common.replacer import ( @@ -162,6 +162,9 @@ def network_match(request: NetworkRequest, resp_data: dict, interactsh=None): elif matcher.type == MatcherType.BinaryMatcher: matcher_res, _ = match_binary(matcher, item) + elif matcher.type == MatcherType.XpathMatcher: + matcher_res, _ = match_xpath(matcher, item) + elif matcher.type == MatcherType.DSLMatcher: matcher_res = match_dsl(matcher, resp_data) diff --git a/pocsuite3/modules/httpserver/__init__.py b/pocsuite3/modules/httpserver/__init__.py index 3115b3cc..80aced2b 100644 --- a/pocsuite3/modules/httpserver/__init__.py +++ b/pocsuite3/modules/httpserver/__init__.py @@ -89,7 +89,7 @@ class HTTPServerV4(HTTPServer): class PHTTPServer(threading.Thread, metaclass=PHTTPSingleton): - def __init__(self, bind_ip='0.0.0.0', bind_port=666, is_ipv6=False, use_https=False, + def __init__(self, bind_ip='0.0.0.0', bind_port=6666, is_ipv6=False, use_https=False, certfile=os.path.join(paths.POCSUITE_TMP_PATH, 'cacert.pem'), requestHandler=BaseRequestHandler): threading.Thread.__init__(self)