コード例 #1
0
 def init_bruteforce(self, domain, dict_user, dict_password):
     self.logger = Logger().get_logger()
     self.target = Target()
     self.request = Request()
     self.domain = domain
     self.dict_user = dict_user
     self.dict_password = dict_password
     self.logger.debug("init_bruteforce")
コード例 #2
0
class Request:
    _instance = None
    session = None
    logger = None

    def __new__(cls, domain=None, username=None, password=None):
        # Creating Logger as a Singleton and init the colored output
        if cls._instance is None:
            cls._instance = super(Request, cls).__new__(cls)
            cls._instance.init_requests(domain, username, password)
        return cls._instance

    def init_requests(self, domain, username, password):
        self.logger = Logger().get_logger()
        # create the sessions object for the requests
        self.session = requests.Session()
        self.session.verify = False

        # update the ua flag
        self.session.headers.update({'User-Agent': constants.USER_AGENT})

        # check if we have to add the auth to our requests
        if username and password:
            if domain:
                username = '******' % (domain, username)
            self.session.auth = HttpNtlmAuth(username, password)

    def request_get(self, url):
        self.logger.debug("request_get")
        try:
            r = self.session.get(url, timeout=constants.REQUESTS_TIMEOUT)

            # close the connection
            r.close()
        except requests.exceptions.Timeout:
            raise ValueError("Request timed out, server is unreachable.")

        return r

    def request_post(self, url, json):
        self.logger.debug("request_post")
        try:
            r = self.session.post(url,
                                  timeout=constants.REQUESTS_TIMEOUT,
                                  json=json)

            # close the connection
            r.close()
        except requests.exceptions.Timeout:
            raise ValueError("Request timed out, server is unreachable.")

        return r
コード例 #3
0
    def init_requests(self, domain, username, password):
        self.logger = Logger().get_logger()
        # create the sessions object for the requests
        self.session = requests.Session()
        self.session.verify = False

        # update the ua flag
        self.session.headers.update({'User-Agent': constants.USER_AGENT})

        # check if we have to add the auth to our requests
        if username and password:
            if domain:
                username = '******' % (domain, username)
            self.session.auth = HttpNtlmAuth(username, password)
コード例 #4
0
class UserEnum:

    _instance = None
    logger = None
    target = None
    request = None

    def __new__(cls):
        # Creating Logger as a Singleton and init the colored output
        if cls._instance is None:
            cls._instance = super(UserEnum, cls).__new__(cls)
            cls._instance.init_userenum()
        return cls._instance

    def init_userenum(self):
        self.logger = Logger().get_logger()
        self.target = Target()
        self.request = Request()

    def user_enumeration(self):
        self.logger.debug("user_enumeration")
        url = "%s%s" % (self.target.url, constants.SHAREPOINT_SITEUSER_API_URL)

        # Starting User Enumeration
        try:
            r = self.request.request_get(url)
            if r.status_code != '200':
                self.logger.warning(
                    "User enumeration API is unreachable or current account is not authorized :("
                )
            else:
                xml = BeautifulSoup(r.text.encode("utf-8"), "lxml")
                for child in xml.find_all("m:properties"):

                    info_sid_issuer = child.find("d:userid")
                    found_user = {}
                    found_user["login name"] = child.find("d:loginname").text
                    found_user["title"] = child.find("d:title").text
                    found_user["isSiteAdmin"] = child.find(
                        "d:issiteadmin").text
                    if [t_child for t_child in info_sid_issuer.children]:
                        found_user["sid"] = info_sid_issuer.find(
                            "d:nameid").text
                        found_user["issuer"] = info_sid_issuer.find(
                            "d:nameidissuer").text
                    self.target.found_users.append(found_user)
                    self.logger.info("#################")
                    for key in found_user:
                        logger.info("%s : %s" (key, found_user[key]))
                    self.logger.info("#################")

        except Exception:
            raise ValueError("Unhandled exception in user_enumeration.")
コード例 #5
0
class Database:
    _instance = None
    logger = None

    def __new__(cls):
        # Creating Logger as a Singleton and init the colored output
        if cls._instance is None:
            cls._instance = super(Database, cls).__new__(cls)
            cls._instance.init_database()
        return cls._instance

    def init_database(self):
        self.logger = Logger().get_logger()

    def verify_installation(self):
        self.logger.debug("Check if the constants.DATABASE_FOLDER exist.")
        if not os.path.exists(constants.DATABASE_FOLDER):
            raise ValueError(
                "Please run the update flag in order to create the folder db.")

        # check if our database exist
        if not os.path.exists('%s%sversions.csv' %
                              (constants.DATABASE_FOLDER, os.path.sep)):
            raise ValueError(
                'Please run the update flag in order to create the version db.'
            )

        # check if our database exist
        if not os.path.exists('%s%scves.csv' %
                              (constants.DATABASE_FOLDER, os.path.sep)):
            raise ValueError(
                'Please run the update flag in order to create the CVE db.')

    def update(self):
        self.logger.info("Running database update.")
        try:
            r = requests.get(constants.DB_VERSION_URL,
                             timeout=constants.REQUESTS_TIMEOUT)
            with open(
                    '%s%scves.csv' % (constants.DATABASE_FOLDER, os.path.sep),
                    'wb') as f:
                f.write(r.content)
        except Exception:
            raise ValueError("Error while retrieving versions file.")

        try:
            r = requests.get(constants.DB_CVE_URL,
                             timeout=constants.REQUESTS_TIMEOUT)
            with open(
                    '%s%sversions.csv' %
                (constants.DATABASE_FOLDER, os.path.sep), 'wb') as f:
                f.write(r.content)
        except Exception:
            raise ValueError("Error while retrieving versions file.")
        self.logger.info("Database updated.")
コード例 #6
0
class BruteForce:
    
    _instance = None
    logger = None
    target = None
    request = None
    domain = None
    dict_user = None
    dict_password = None

    def __new__(cls, domain, dict_user, dict_password):
        # Creating Logger as a Singleton and init the colored output
        if cls._instance is None:
            cls._instance = super(BruteForce, cls).__new__(cls)
            cls._instance.init_bruteforce(domain, dict_user, dict_password)
        return cls._instance

    def init_bruteforce(self, domain, dict_user, dict_password):
        self.logger = Logger().get_logger()
        self.target = Target()
        self.request = Request()
        self.domain = domain
        self.dict_user = dict_user
        self.dict_password = dict_password
        self.logger.debug("init_bruteforce")

    def bruteforce(self):
        self.logger.debug("Starting bruteforce")

        url = "%s%s" % (self.target.url,constants.SHAREPOINT_DEFAULT_URL)
        if not path.exists(self.dict_user):
            raise ValueError("User file does not exists (wrong path?)")
        if not path.exists(self.dict_password):
            raise ValueError("Password file does not exists (wrong path?)")

        file_user = open(self.dict_user, "r")
        file_password = open(self.dict_password, "r")

        # save the current session
        tmp = self.request.session

        # Starting bruteforce
        for user in file_user:
            user = user.rstrip()
            for passwd in file_password:
                passwd = passwd.rstrip()

                # create a new session for each request
                self.request.init_requests(self.domain, user, passwd)

                try:
                    r = self.request.request_get(url)
                    if str(r.status_code)[0] != '4':
                        self.logger.debug("Found user and password: %s - %s" % (user, passwd))
                        self.target.credentials.append({"username":user,"password":passwd})
                except Exception as e:
                    raise ValueError("Unhandled error during running the brute force.")

            # restore the index of the file
            file_password.seek(0)

        # restore the old session
        self.request.session = tmp

        file_user.close()
        file_password.close()
コード例 #7
0
 def init_userenum(self):
     self.logger = Logger().get_logger()
     self.target = Target()
     self.request = Request()
コード例 #8
0
 def init_sharepoint(self):
     self.logger = Logger().get_logger()
     self.target = Target()
     self.request = Request()
コード例 #9
0
class Sharepoint:
    _instance = None
    logger = None
    target = None
    request = None

    def __new__(cls):
        # Creating Logger as a Singleton and init the colored output
        if cls._instance is None:
            cls._instance = super(Sharepoint, cls).__new__(cls)
            cls._instance.init_sharepoint()
        return cls._instance

    def init_sharepoint(self):
        self.logger = Logger().get_logger()
        self.target = Target()
        self.request = Request()

    def check_availability(self):
        self.logger.debug("check_availability")
        try:
            r = self.request.request_get(self.target.url)

            if r.status_code != 200:
                self.logger.warning("Please take attention, the target answered with %i code." % r.status_code)

        except Exception:
            raise ValueError("Unhandled error on check_availability().")

        return r

    def check_iis_target(self, headers):
        self.logger.debug("check_iis_target")
        # Detection by header parse
        detected_version_iis = detect_server_by_headers(headers)
        if detected_version_iis:
            self.target.server = detected_version_iis
            self.logger.debug("Server version Detected (headers parse): {}".format(detected_version_iis))

        # detect the technology if present
        detected_tec = detect_tec_by_headers(headers)
        if detected_tec:
            self.target.technology = detected_tec
            self.logger.debug("Technology detected (headers parse): {}".format(detected_tec))

    def check_share_point(self, headers):
        self.logger.debug("check_share_point")
        # Detection by header parse
        detected_version_share_point = self.detect_sharepoint_by_headers(headers)
        if detected_version_share_point:
            self.logger.debug("SharePoint version Detected (headers parse): {}".format(detected_version_share_point))

        # Detection by conf file parse #
        if not detected_version_share_point:
            detected_version_share_point = self.detect_sharepoint_by_servicefile()
            if detected_version_share_point:
                self.logger.debug(
                    "SharePoint version Detected (service.cnf parse): {}".format(detected_version_share_point))

        self.get_version(detected_version_share_point)



    def detect_sharepoint_by_headers(self, headers):
        self.logger.debug("detect_sharepoint_by_headers")
        useful_headers = [header for header in headers if "sharepoint" in header.lower()]
        if "MicrosoftSharePointTeamServices" in headers.keys():
            version = headers["MicrosoftSharePointTeamServices"].split(";")[0].split(":")[0]
            return version
        elif len(useful_headers) > 0:
            self.logger.warning(
                "Header %s was found, it may not bring the exact version." % headers[useful_headers[0]].replace("\r\n",
                                                                                                                ""))
        return None

    def detect_sharepoint_by_servicefile(self):
        self.logger.debug("detect_sharepoint_by_servicefile")
        version = None
        for service_url in constants.SHAREPOINT_SERVICE_URLS:
            try:

                # request the url and save the data into the session variable
                r = self.request.request_get(self.target.url + service_url)

                if r.status_code == 200:
                    if "vti_extenderversion" in r.text:
                        version = r.text.split("vti_extenderversion:SR|")[1].replace("\n", "")
                        break
                    if "vti_buildversion" in r.text:
                        version = r.text.split("vti_extenderversion:SR|")[1].replace("\n", "")
                        break

            except Exception:
                raise ValueError("Unhandled error detect_sharepoint_by_servicefile().")

        return version

    def get_version(self,patch_number):


        _patch_tokens = patch_number.split(".")
        _major_version = int(_patch_tokens[0])
        _minor_version = int(_patch_tokens[1])
        _build_version = int(_patch_tokens[3])
        _patch_number = "%s.%s.%s" % (_major_version,_minor_version,_build_version)
        _last_version = ""
        _last_date = ""
        db_version = {
            "version": "",
            "date": ""
        }



        with open('%s%sversions.csv' % (constants.DATABASE_FOLDER, os.path.sep),"r") as file_versions:

            for line in file_versions:

                _line_tokens = line.split(",")
                _checked_version = _line_tokens[0].split(".")
                _checked_version_date = _line_tokens[2]

                #### if there are not enough tokens, we skip it #######

                if(len(_checked_version)<4):
                    continue

                #### Extract major, minor and build version #######

                _checked_version_major = int(_checked_version[0])
                _checked_version_minor = int(_checked_version[1])
                _checked_version_build = int(_checked_version[2])

                #### reformat checked version date #######

                if(_checked_version_date!="N/A"):
                    _checked_version_date = datetime.strptime(_checked_version_date, "%Y %B %d")

                #### reformat checked version structure #######

                _checked_version = "%s.%s.%s" % (_checked_version_major,_checked_version_minor,_checked_version_build)

                #### check if we found a version #######

                if(_checked_version == _patch_number):
                    db_version["version"] = _checked_version
                    db_version["date"] = _checked_version_date
                    self.logger.info("Version details found.")
                    break

                #### if not a suitable version is found, we return the closer one (since they are ordered) #######

                if((_major_version > _checked_version_major) or (_major_version == _checked_version_major and _build_version > _checked_version_build)):

                    db_version["version"] = _checked_version
                    db_version["date"] = _checked_version_date
                    self.logger.info("Version could not be found, performing best guess.")
                    break

        self.target.sharepoint = db_version
コード例 #10
0
ファイル: unsharepoint.py プロジェクト: CYS4srl/unSharePoint
def main():
    # print banner
    print_banner()

    # init logger
    logger_instance = Logger()
    logger = logger_instance.get_logger()

    try:

        # init options and parse the arguments
        args = gen_cli_args()

        # set the verbose level if flagged
        if args.verbose:
            logger_instance.enable_debug()

        # init request and their auth if needed
        Request(args.domain, args.username, args.password)

        # init target
        tg = Target(args.url)

        # check if we need to update the database an verify the installation
        db = Database()
        if args.update:
            db.update()

        db.verify_installation()

        # check if the target is online
        sh = Sharepoint()

        # verify if the target is online or not
        response_obj = sh.check_availability()

        # check the headers in order to look into the technology and the server
        sh.check_iis_target(response_obj.headers)

        # check if we have a sharepoint or something else
        sh.check_share_point(response_obj.headers)

        # check cve based on the build number
        if tg.sharepoint:
            check_cve = CheckCVE()
            check_cve.get_cve()

        # verify if we have to to other checks
        if args.type != 'i':

            if args.type == 'a' or args.type == 'ad':
                # Api scan, checking SOAP stuff
                detailed = args.type == 'ad'
                soap_api = CheckSoapApi()
                soap_api.check_soap_api(detailed)


        if args.bruteforce:
            bt = BruteForce(args.domain, args.username_file, args.password_file)
            bt.bruteforce()

        if args.enum_users:
            ue = UserEnum()
            ue.user_enumeration()

        logger.info("Scan completed!")
        logger.info("Results:")
        logger.info(tg.to_string())



    except (KeyboardInterrupt, SystemExit):
        sys.exit(2)
    except Exception as e:
        logger.error(e)
        sys.exit(1)
コード例 #11
0
ファイル: check_cve.py プロジェクト: CYS4srl/unSharePoint
    def init_checkcve(self):

        self.logger = Logger().get_logger()
        self.target = Target()
        self.db = Database()
コード例 #12
0
 def init_database(self):
     self.logger = Logger().get_logger()
コード例 #13
0
 def init_soap_api(self):
     self.logger = Logger().get_logger()
     self.target = Target()
     self.request = Request()
コード例 #14
0
class CheckSoapApi:

    _instance = None
    logger = None
    target = None
    request = None

    def __new__(cls):
        # Creating Logger as a Singleton and init the colored output
        if cls._instance is None:
            cls._instance = super(CheckSoapApi, cls).__new__(cls)
            cls._instance.init_soap_api()
        return cls._instance

    def init_soap_api(self):
        self.logger = Logger().get_logger()
        self.target = Target()
        self.request = Request()

    def check_soap_api(self, detailed):
        self.logger.debug("starting check_soap_api")
        url = self.target.url
        # TODO check more https://docs.microsoft.com/en-us/previous-versions/office/developer/sharepoint-2010/ms467069
        for path in constants.SHAREPOINT_ASMX_PATHS:
            self.check_soap_availability(
                constants.SHAREPOINT_ASMX_START_PATH % (url, path), detailed)
        for path in constants.SHAREPOINT_SVC_PATHS:
            self.check_soap_availability(
                constants.SHAREPOINT_SVC_START_PATH % (url, path), detailed)

    def check_soap_availability(self, url, detailed):
        self.logger.debug("starting check_soap_availability")
        try:
            # request the url and save the data into the session variable
            r = self.request.request_get(url)

            if r.status_code == 200:
                self.logger.info("%s is reachable :)." % url)
            elif r.status_code == 401:
                self.logger.warning("%s unauthorized :(." % url)
                return False
        except Exception:
            raise ValueError("Unhandled error check_soap_availability().")

        if detailed:
            client = Client(url,
                            transport=Transport(session=self.request.session))
            for service in client.wsdl.services.values():
                for port in service.ports.values():
                    for operation in port.binding._operations.values():
                        parameters = {}
                        if operation.input.body:
                            for parameter in operation.input.body.type.elements:
                                parameters[parameter[0]] = xsd.SkipValue
                            with client.settings(raw_response=True):
                                response = client.service[operation.name](
                                    **parameters)
                                if str(response.status_code)[0] == "2":
                                    self.logger.info(
                                        "--- Available method: %s" %
                                        operation.name)
                                if str(response.status_code)[0] == "5":
                                    self.logger.info(
                                        "--- Maybe available (double check) method: %s"
                                        % operation.name)