From 48e1d85eb0946ccfa079d0129a723767d909ecd2 Mon Sep 17 00:00:00 2001 From: "maor.rayzin" Date: Tue, 24 Jul 2018 19:09:19 +0300 Subject: [PATCH] * fixed a lot of safe dict access * some small fixed and typos --- .../system_info/windows_info_collector.py | 12 ++- monkey_island/cc/services/pth_report.py | 2 +- monkey_island/cc/services/pth_report_utils.py | 99 ++++++++++--------- .../cc/ui/src/components/pages/ReportPage.js | 38 ++++--- 4 files changed, 76 insertions(+), 75 deletions(-) diff --git a/infection_monkey/system_info/windows_info_collector.py b/infection_monkey/system_info/windows_info_collector.py index 1444f5805..d6c852801 100644 --- a/infection_monkey/system_info/windows_info_collector.py +++ b/infection_monkey/system_info/windows_info_collector.py @@ -12,6 +12,7 @@ from mimikatz_collector import MimikatzCollector from . import InfoCollector LOG = logging.getLogger(__name__) +LOG.info('started windows info collector') __author__ = 'uri' @@ -138,16 +139,17 @@ class WindowsInfoCollector(InfoCollector): self.get_hostname() self.get_process_list() self.get_network_info() - self.get_azure_info() + #self.get_azure_info() - self.get_wmi_info() - self.get_reg_key(r"SYSTEM\CurrentControlSet\Control\Lsa") + #self.get_wmi_info() + #self.get_reg_key(r"SYSTEM\CurrentControlSet\Control\Lsa") self.get_installed_packages() mimikatz_collector = MimikatzCollector() mimikatz_info = mimikatz_collector.get_logon_info() - self.info["credentials"].update(mimikatz_info) - self.info["mimikatz"] = mimikatz_collector.get_mimikatz_text() + if mimikatz_info: + self.info["credentials"].update(mimikatz_info) + self.info["mimikatz"] = mimikatz_collector.get_mimikatz_text() return self.info diff --git a/monkey_island/cc/services/pth_report.py b/monkey_island/cc/services/pth_report.py index adb07cb78..45a6e3668 100644 --- a/monkey_island/cc/services/pth_report.py +++ b/monkey_island/cc/services/pth_report.py @@ -112,7 +112,7 @@ class PTHReportService(object): for node_id in pth.vertices: machine = Machine(node_id) node = { - "id": machine.get_monkey_id, + "id": str(machine.get_monkey_id()), "label": '{0} : {1}'.format(machine.GetHostName(), machine.GetIp()), 'group': 'critical' if machine.IsCriticalServer() else 'normal', 'users': list(machine.GetCachedUsernames()), diff --git a/monkey_island/cc/services/pth_report_utils.py b/monkey_island/cc/services/pth_report_utils.py index e6c1b8c47..06c40f023 100644 --- a/monkey_island/cc/services/pth_report_utils.py +++ b/monkey_island/cc/services/pth_report_utils.py @@ -115,14 +115,14 @@ class Machine(object): if not doc: return None - return doc["data"]["mimikatz"] + return doc.get("data").get("mimikatz") @cache def GetHostName(self): doc = self.latest_system_info - for comp in doc["data"]["Win32_ComputerSystem"]: - return eval(comp["Name"]) + for comp in doc.get("data").get("Win32_ComputerSystem", {}): + return eval(comp.get("Name")) return None @@ -130,7 +130,7 @@ class Machine(object): def GetIp(self): doc = self.latest_system_info - for addr in doc["data"]["network_info"]["networks"]: + for addr in doc.get("data").get("network_info", {}).get("networks", {}): return str(addr["addr"]) return None @@ -139,14 +139,14 @@ class Machine(object): def get_monkey_id(self): doc = self.monkey_info - return str(doc['_id']) + return str(doc.get('_id')) @cache def GetDomainName(self): doc = self.latest_system_info - for comp in doc["data"]["Win32_ComputerSystem"]: - return eval(comp["Domain"]) + for comp in doc.get("data").get("Win32_ComputerSystem", {}): + return eval(comp.get("Domain")) return None @@ -154,8 +154,8 @@ class Machine(object): def GetDomainRole(self): doc = self.latest_system_info - for comp in doc["data"]["Win32_ComputerSystem"]: - return comp["DomainRole"] + for comp in doc.get("data").get("Win32_ComputerSystem", {}): + return comp.get("DomainRole") return None @@ -167,17 +167,17 @@ class Machine(object): def GetSidByUsername(self, username, domain=None): doc = self.latest_system_info - for user in doc["data"]["Win32_UserAccount"]: - if eval(user["Name"]) != username: + for user in doc.get("data").get("Win32_UserAccount", {}): + if eval(user.get("Name")) != username: continue - if user["SIDType"] != SidTypeUser: + if user.get("SIDType") != SidTypeUser: continue - if domain and user["Domain"] != domain: + if domain and user.get("Domain") != domain: continue - return eval(user["SID"]) + return eval(user.get("SID")) if not self.IsDomainController(): for dc in self.GetDomainControllers(): @@ -195,24 +195,24 @@ class Machine(object): if not info: return None - return info["Domain"] + "\\" + info["Username"] + return str(info.get("Domain")) + "\\" + str(info.get("Username")) @cache def GetSidInfo(self, sid): doc = self.latest_system_info - for user in doc["data"]["Win32_UserAccount"]: - if eval(user["SID"]) != sid: + for user in doc.get("data").get("Win32_UserAccount",{}): + if eval(user.get("SID")) != sid: continue - if user["SIDType"] != SidTypeUser: + if user.get("SIDType") != SidTypeUser: continue - return {"Domain": eval(user["Domain"]), - "Username": eval(user["Name"]), - "Disabled": user["Disabled"] == "true", - "PasswordRequired": user["PasswordRequired"] == "true", - "PasswordExpires": user["PasswordExpires"] == "true", } + return {"Domain": eval(user.get("Domain")), + "Username": eval(user.get("Name")), + "Disabled": user.get("Disabled") == "true", + "PasswordRequired": user.get("PasswordRequired") == "true", + "PasswordExpires": user.get("PasswordExpires") == "true", } if not self.IsDomainController(): for dc in self.GetDomainControllers(): @@ -247,21 +247,21 @@ class Machine(object): if self.IsDomainController(): found.append("Domain Controller") - for product in doc["data"]["Win32_Product"]: - service_name = eval(product["Name"]) + for product in doc.get("data").get("Win32_Product", {}): + service_name = eval(product.get("Name")) if not IsNameOfCriticalService(service_name): continue found.append(service_name) - for service in doc["data"]["Win32_Service"]: - service_name = eval(service["Name"]) + for service in doc.get("data").get("Win32_Service", {}): + service_name = eval(service.get("Name")) if not IsNameOfCriticalService(service_name): continue - if eval(service["State"]) != "Running": + if eval(service.get("State")) != "Running": continue found.append(service_name) @@ -293,14 +293,14 @@ class Machine(object): def GetGroupSidByGroupName(self, group_name): doc = self.latest_system_info - for group in doc["data"]["Win32_Group"]: - if eval(group["Name"]) != group_name: + for group in doc.get('data').get("Win32_Group", {}): + if eval(group.get("Name")) != group_name: continue - if not is_group_sid_type(group["SIDType"]): + if not is_group_sid_type(group.get("SIDType")): continue - return eval(group["SID"]) + return eval(group.get("SID")) return None @@ -310,20 +310,20 @@ class Machine(object): users = dict() - for group_user in doc["data"]["Win32_GroupUser"]: - if eval(group_user["GroupComponent"]["SID"]) != sid: + for group_user in doc.get('data').get("Win32_GroupUser", {}): + if eval(group_user.get("GroupComponent", {}).get("SID")) != sid: continue - if not is_group_sid_type(group_user["GroupComponent"]["SIDType"]): + if not is_group_sid_type(group_user.get("GroupComponent", {}).get("SIDType")): continue if "PartComponent" not in group_user.keys(): continue - if type(group_user["PartComponent"]) in (str, unicode): + if type(group_user.get("PartComponent")) in (str, unicode): # PartComponent is an id to Win32_UserAccount table - wmi_id = group_user["PartComponent"] + wmi_id = group_user.get("PartComponent") if "cimv2:Win32_UserAccount" not in wmi_id: continue @@ -336,10 +336,11 @@ class Machine(object): users[sid] = username else: - if group_user["PartComponent"]["SIDType"] != SidTypeUser: + if group_user.get("PartComponent", {}).get("SIDType") != SidTypeUser: continue - users[eval(group_user["PartComponent"]["SID"])] = eval(group_user["PartComponent"]["Name"]) + users[eval(group_user.get("PartComponent", {}).get("SID"))] = eval(group_user.get("PartComponent") + .get("Name")) return users @@ -351,10 +352,10 @@ class Machine(object): GUIDs = set() for doc in cur: - if not Machine(doc["monkey_guid"]).IsDomainController(): + if not Machine(doc.get("monkey_guid")).IsDomainController(): continue - GUIDs.add(doc["monkey_guid"]) + GUIDs.add(doc.get("monkey_guid")) return GUIDs @@ -377,11 +378,11 @@ class Machine(object): SIDs = set() - for user in doc["data"]["Win32_UserAccount"]: - if user["SIDType"] != SidTypeUser: + for user in doc.get('data').get("Win32_UserAccount", {}): + if user.get("SIDType") != SidTypeUser: continue - SIDs.add(eval(user["SID"])) + SIDs.add(eval(user.get("SID"))) return SIDs @@ -408,11 +409,11 @@ class Machine(object): sam_user = dict([map(unicode.strip, line.split(":")) for line in filter(lambda l: l.count(":") == 1, sam_user_txt.splitlines())]) - ntlm = sam_user["NTLM"] + ntlm = sam_user.get("NTLM") if "[hashed secret]" not in ntlm: continue - sam[sam_user["User"]] = ntlm.replace("[hashed secret]", "").strip() + sam[sam_user.get("User")] = ntlm.replace("[hashed secret]", "").strip() return sam @@ -533,7 +534,7 @@ class Machine(object): SIDs = set() - for username in doc["data"]["credentials"]: + for username in doc.get('data').get("credentials", {}): sid = self.GetSidByUsername(username) if not sid: @@ -549,7 +550,7 @@ class Machine(object): names = set() - for username in doc["data"]["credentials"]: + for username in doc.get('data').get("credentials", {}): names.add(username) return names @@ -576,7 +577,7 @@ class PassTheHashReport(object): GUIDs = set() for doc in cur: - GUIDs.add(doc["monkey_guid"]) + GUIDs.add(doc.get("monkey_guid")) return GUIDs diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index f459af8ce..03939b01d 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -41,6 +41,8 @@ class ReportPageComponent extends AuthComponent { super(props); this.state = { report: {}, + pthreport: {}, + pthmap: {}, graph: {nodes: [], edges: []}, allMonkeysAreDead: false, runStarted: true @@ -49,6 +51,7 @@ class ReportPageComponent extends AuthComponent { componentDidMount() { this.updateMonkeysRunning().then(res => this.getReportFromServer(res)); + this.getPTHReportFromServer(); this.updateMapFromServer(); this.interval = setInterval(this.updateMapFromServer, 1000); } @@ -108,6 +111,17 @@ class ReportPageComponent extends AuthComponent { }); }; + getPTHReportFromServer(res) { + this.authFetch('/api/pthreport') + .then(res => res.json()) + .then(res => { + this.setState({ + pthreport: res.report_info, + pthmap: res.map + }); + }); + } + getReportFromServer(res) { if (res['completed_steps']['run_monkey']) { this.authFetch('/api/report') @@ -432,29 +446,13 @@ class ReportPageComponent extends AuthComponent {
- { /* TODO: use dynamic data */} - +
- { /* TODO: use dynamic data */} - +
- { /* TODO: use dynamic data */} - +
); @@ -488,7 +486,7 @@ class ReportPageComponent extends AuthComponent { Credential Map
- +