Beispiel #1
0
    def addDomainInDb(self, checkDomain=True):
        """
        Add this scope domain in database.

        Args:
            checkDomain: boolean. If true (Default), checks that the domain IP is in scope

        Returns: a tuple with :
                * bool for success
                * mongo ObjectId : already existing object if duplicate, create object id otherwise 
        """
        # Checking unicity
        base = self.getDbKey()
        mongoInstance = MongoCalendar.getInstance()
        existing = mongoInstance.find("scopes", base, False)
        if existing is not None:
            return 0, None
        # Check if domain's ip fit in one of the Scope of the wave
        if checkDomain:
            if not Scope.checkDomainFit(self.wave, self.scope):
                return -1, None
        # insert the domains in the scopes
        parent = self.getParent()
        res_insert = mongoInstance.insert("scopes", base, parent)
        ret = res_insert.inserted_id
        self._id = ret
        # Adding appropriate tools for this scopes
        wave = mongoInstance.find("waves", {"wave": self.wave}, False)
        commands = wave["wave_commands"]
        for commName in commands:
            comm = mongoInstance.findInDb("pollenisator", "commands", {
                "name": commName,
                "lvl": "network"
            }, False)
            if comm is not None:
                newTool = Tool()
                newTool.initialize(comm["name"], self.wave, self.scope, "", "",
                                   "", "network")
                newTool.addInDb()
            else:
                comm = mongoInstance.findInDb("pollenisator", "commands", {
                    "name": commName,
                    "lvl": "domain"
                }, False)
                if comm is not None:
                    newTool = Tool()
                    newTool.initialize(comm["name"], self.wave, self.scope, "",
                                       "", "", "domain")
                    newTool.addInDb()
        # Testing this scope against every ips
        ips = Ip.fetchObjects({})
        for ip in ips:
            if self._id not in ip.in_scopes:
                if ip.fitInScope(self.scope):
                    ip.addScopeFitting(self.getId())
        ipToInsert = Ip()
        ipToInsert.initialize(self.scope)
        ipToInsert.addInDb()
        return 1, ret
Beispiel #2
0
 def Parse(self, file_opened, **_kwargs):
     """
     Parse a opened file to extract information
     Args:
         file_opened: the open file
         _kwargs: not used
     Returns:
         a tuple with 4 values (All set to None if Parsing wrong file): 
             0. notes: notes to be inserted in tool giving direct info to pentester
             1. tags: a list of tags to be added to tool 
             2. lvl: the level of the command executed to assign to given targets
             3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
     """
     notes = ""
     tags = []
     targets = {}
     result_socket = file_opened.read()
     domain, ip = parse_reverse_python(result_socket)
     if domain is None:
         return None, None, None, None
     Ip().initialize(domain).addInDb()
     ip_m = Ip().initialize(ip)
     res, iid = ip_m.addInDb()
     if not res:
         ip_m = Ip.fetchObject({"_id": iid})
     hostnames = list(set(ip_m.infos.get("hostname", []) + [domain]))
     ip_m.updateInfos({"hostname": hostnames})
     targets["ip"] = {"ip": ip}
     notes += "Domain found :" + domain + "\n"
     if notes == "":
         notes = "No domain found\n"
     return notes, tags, "ip", targets
Beispiel #3
0
    def doInsert(self, values):
        """
        Insert the Ip represented by this model in the database with the given values.

        Args:
            values: A dictionary crafted by MultipleIpView or IpView containg all form fields values needed.

        Returns:
            {
                '_id': The mongo ObjectId _id of the inserted command document.
                'nbErrors': The number of objects that has not been inserted in database due to errors.
            }
        """
        # Only multi insert exists at the moment for IP
        try:
            multi = True
        except KeyError:
            multi = False

        if multi:
            # Get form values
            ret = []
            total = 0
            accepted = 0
            for line in values["IPs"].split("\n"):
                if line != "":
                    # Insert in database
                    model = Ip().initialize(line)
                    inserted, iid = model.addInDb()
                    if inserted:
                        ret.append(iid)
                        accepted += 1
                    total += 1
            return ret, total - accepted  # nb errors = total - accepted
Beispiel #4
0
    def Parse(self, file_opened, **_kwargs):
        """
        Parse a opened file to extract information

        foe.test.fr.	801	IN	A	18.19.20.21
        blog.test.fr.	10800	IN	CNAME	22.33.44.55
        Args:
            file_opened: the open file
            _kwargs: not used
        Returns:
            a tuple with 4 values (All set to None if Parsing wrong file): 
                0. notes: notes to be inserted in tool giving direct info to pentester
                1. tags: a list of tags to be added to tool 
                2. lvl: the level of the command executed to assign to given targets
                3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
        """
        notes = ""
        tags = []
        countInserted = 0
        for line in file_opened:
            domain, _record_type, ip = parse_crtsh_line(line)
            if domain is not None:
                # a domain has been found
                infosToAdd = {"hostname": ip}
                ip_m = Ip().initialize(domain, infos=infosToAdd)
                res, iid = ip_m.addInDb()
                # failed, domain is out of scope
                if not res:
                    notes += domain + " exists but already added.\n"
                    ip_m = Ip.fetchObject({"_id": iid})
                    infosToAdd = {
                        "hostname":
                        list(set([ip] + ip_m.infos.get("hostname", [])))
                    }
                    ip_m.updateInfos(infosToAdd)
                else:
                    countInserted += 1
                    notes += domain + " inserted.\n"
        if notes.strip() == "":
            return None, None, None, None
        elif countInserted != 0:
            tags.append("todo")
        return notes, tags, "wave", {"wave": None}
Beispiel #5
0
def editScopeIPs(hostsInfos):
    """
    Add all the ips and theirs ports found after parsing the file to the scope object in database.
    Args:
        hostsInfos: the dictionnary with ips as keys and a list of dictionnary containing ports informations as value.
    """
    # Check if any ip has been found.
    if hostsInfos is not None:
        for infos in hostsInfos:
            tags = []
            if infos.get("powned", False):
                tags.append("P0wned!")
            infosToAdd = {}
            OS = infos.get("OS", "")
            if OS != "":
                infosToAdd["OS"] = OS
            creds = infos.get("creds", "")
            if creds != "":
                infosToAdd["creds"] = creds
            powned = infos.get("powned", False)
            if powned:
                infosToAdd["powned"] = "True"
            ip_m = Ip().initialize(str(infos["ip"]))
            res, iid = ip_m.addInDb()
            if not res:
                ip_m = Ip.fetchObject({"_id": iid})
            infosToAdd["hostname"] = list(
                set(ip_m.infos.get("hostname", []) + [infos["hostname"]]))
            ip_m.notes = "hostname:" + \
                infos["hostname"] + "\n"+infos.get("OS", "")
            ip_m.tags = tags
            ip_m.update()
            port_m = Port().initialize(str(infos["ip"]), str(infos["port"]),
                                       "tcp", "netbios-ssn")
            res, iid = port_m.addInDb()
            if not res:
                port_m = Port.fetchObject({"_id": iid})
            port_m.updateInfos(infosToAdd)
            port_m.tags = tags
            port_m.update()
Beispiel #6
0
def getIpPortsNmap(nmapFile):
    """
    Read the given nmap .nmap file results and return a dictionnary with ips and a list of their open ports.
        Args:
            nmapFile:  the path to the .nmap file generated by an nmap scan

        Returns:
            notes about inseted ip and ports
    """
    notes = ""
    countOpen = 0
    all_text = nmapFile.read().strip()
    lines = all_text.split("\n")
    if len(lines) <= 3:
        # print("Not enough lines to be nmap")
        return None
    if not lines[0].startswith("# Nmap"):
        # print("Not starting with # Nmap")
        return None
    if "scan initiated" not in lines[0]:
        # print("Not scan initiated on first line")
        return None
    if "# Nmap done at" not in lines[-1]:
        # print("Not # Nmap done at at the end : "+str(lines[-1]))
        return None
    ipCIDR_m = None
    ipDom_m = None
    for line in lines:
        # Search ip in file
        # match an ip
        ip = re.search(
            r"^Nmap scan report for (\S+)(?: \(((?:[0-9]{1,3}\.){3}[0-9]{1,3})\))?$",
            line)
        if ip is not None:  # regex match
            lastIp = [
                ip.group(1),
                ip.group(2) if ip.group(2) is not None else ""
            ]
            notes_ip = "ip:" + \
                str(lastIp[1]) if lastIp[1] != "" and lastIp[1] is not None else ""
            ipCIDR_m = Ip().initialize(str(lastIp[0]), notes=notes_ip)
            if lastIp[1].strip() != "" and lastIp[1] is not None:
                ipDom_m = Ip().initialize(str(lastIp[1]),
                                          notes="domain:" + str(lastIp[0]))

            else:
                ipDom_m = None
        if " open " in line:
            if ipCIDR_m is None:  # Probably a gnmap
                return None
            notes += line + "\n"
            # regex to find open ports in gnmap file
            port_search = re.search(
                r"^(\d+)\/(\S+)\s+open\s+(\S+)(?: +(.+))?$", line)
            if port_search is not None:
                port_number = str(port_search.group(1))
                proto = str(port_search.group(2))
                service = "unknown" if str(
                    port_search.group(3)) == "" else str(port_search.group(3))
                product = str(port_search.group(4))
                # a port unique key is its protocole/number.
                countOpen += 1
                validIps = []
                if ipCIDR_m is not None:
                    ipCIDR_m.addInDb()
                    validIps.append(ipCIDR_m.ip)
                    if ipDom_m is not None:
                        res, iid = ipDom_m.addInDb()
                        if not res:
                            ipDom_m = Ip.fetchObject({"_id": iid})
                        ipDom_m.updateInfos({
                            "hostname":
                            list(
                                set(
                                    list(ipDom_m.infos.get("hostname", [])) +
                                    [str(ipCIDR_m.ip)]))
                        })
                        validIps.append(ipDom_m.ip)
                for ipFound in validIps:
                    if ip == "":
                        continue
                    port_o = Port().initialize(ipFound, port_number, proto,
                                               service, product)
                    res_insert, iid = port_o.addInDb()
                    if not res_insert:
                        port_o = Port.fetchObject({"_id": iid})
                    port_o.service = service
                    port_o.update()

    notes = str(countOpen) + " open ports found\n" + notes
    return notes
Beispiel #7
0
def smbmap_format(smbmap_output):
    """Parse raw smbmap file
    Args:
        smbmap_output: raw smbmap file content
    Returns:
        A tuple with values:
            0. a string formated where each line are : fullpath  permissions  date
            1. a list of interesting name file found
            2. targets as described in Parse
    """
    targets = {}
    regex_only_match_serv = re.compile(
        r"^\[\+\] IP: ([^:\s]+)(?::\d+)?\sName: \S+\s+$")
    # group 1 = SHARE NAME group 2 = PERMISSIONS
    regex_only_match_share_header = re.compile(r"^\t(\S+)\s+([A-Z , ]+)$")
    # group 1 = directory full path
    regex_only_match_dir = re.compile(r"^\t(\S+)$")
    # group 1 = d ou -, group 2 = permissions, group 3 = date, group 4 = filename
    regex_only_match_files = re.compile(
        r"^\s+([d-])([xrw-]{9})\s+([^\t]+)\t(.+)$")
    ret = ""
    interesting_files = {}
    interesting_name_list = [
        "passwd", "password", "pwd", "mot_de_passe", "motdepasse", "auth",
        "creds", "confidentiel", "confidential", "backup", ".xml", ".conf",
        ".cfg", "unattended"
    ]
    current_serv = ""
    current_share = ""
    current_dir = ""
    ip_states = []
    lines = smbmap_output.split("\n")
    for line in lines:
        result = regex_only_match_serv.match(line)
        if result is not None:
            ip = str(result.group(1))
            current_serv = ip
            if ip not in ip_states:
                ip_o = Ip().initialize(ip)
                ip_o.addInDb()
                Port().initialize(ip, "445", "tcp", "samba").addInDb()
                targets[str(ip_o.getId())] = {
                    "ip": ip,
                    "port": "445",
                    "proto": "tcp"
                }

                ip_states.append(ip)
            continue
        result = regex_only_match_share_header.match(line)
        if result is not None:
            share_name = str(result.group(1))
            permissions = str(result.group(2))
            current_share = share_name
            continue
        result = regex_only_match_dir.match(line)
        if result is not None:
            dir_path = str(result.group(1))
            current_dir = dir_path
            continue
        result = regex_only_match_files.match(line)
        if result is not None:
            # isDirectory = (str(result.group(1)) == "d")
            permissions = str(result.group(2))
            date = str(result.group(3))
            file_name = str(result.group(4))
            fullpath = "\\\\"+current_serv+"\\" + \
                current_share+current_dir[1:]+file_name
            for interesting_names in interesting_name_list:
                if interesting_names.lower() in file_name.lower():
                    interesting_files[
                        "Shared " + interesting_names] = interesting_files.get(
                            "Shared " + interesting_names, [])
                    interesting_files["Shared " +
                                      interesting_names].append(fullpath +
                                                                "\t" +
                                                                permissions +
                                                                "\t" + date)
            ret += fullpath + "\t" + permissions + "\t" + date + "\n"
            continue
    return ret, interesting_files, targets
Beispiel #8
0
    def Parse(self, file_opened, **_kwargs):
        """
        Parse a opened file to extract information
        Example:
[       
    {
        "arguments": "./dnsrecon.py -r 10.0.0.0/24 -j /home/barre/test.json",
        "date": "2020-01-06 11:43:37.701513",
        "type": "ScanInfo"
    },
    {
        "address": "10.0.0.1",
        "name": "_gateway",
        "type": "PTR"
    },
    {
        "address": "10.0.0.77",
        "name": "barre-ThinkPad-E480",
        "type": "PTR"
    },
    {
        "address": "10.0.0.77",
        "name": "barre-ThinkPad-E480.local",
        "type": "PTR"
    }
]
        Args:
            file_opened: the open file
            _kwargs: not used
        Returns:
            a tuple with 4 values (All set to None if Parsing wrong file): 
                0. notes: notes to be inserted in tool giving direct info to pentester
                1. tags: a list of tags to be added to tool 
                2. lvl: the level of the command executed to assign to given targets
                3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
        """
        notes = ""
        tags = []
        countInserted = 0
        try:
            dnsrecon_content = json.loads(file_opened.read())
        except json.decoder.JSONDecodeError:
            return None, None, None, None
        if len(dnsrecon_content) == 0:
            return None, None, None, None
        if not isinstance(dnsrecon_content[0], dict):
            return None, None, None, None
        if dnsrecon_content[0].get("type", "") != "ScanInfo":
            return None, None, None, None
        if dnsrecon_content[0].get("date", "") == "":
            return None, None, None, None
        for record in dnsrecon_content[1:]:
            ip = record["address"]
            name = record["name"]
            infosToAdd = {"hostname": name}
            ip_m = Ip().initialize(ip, infos=infosToAdd)
            res, iid = ip_m.addInDb()
            infosToAdd = {"ip": ip}
            ip_m = Ip().initialize(name, infos=infosToAdd)
            res, iid = ip_m.addInDb()
            # failed, domain is out of scope
            if not res:
                notes += name + " exists but already added.\n"
                ip_m = Ip.fetchObject({"_id": iid})
                infosToAdd = {"ip": list(set([ip] + ip_m.infos.get("ip", [])))}
                ip_m.updateInfos(infosToAdd)
            else:
                countInserted += 1
                notes += name + " inserted.\n"
        return notes, tags, "wave", {"wave": None}