def _get_workstation_by_source_ip(self, source_ip) -> str: """ 查找最近该IP认证主机名 返回主机名和域名 """ account_history = AccountHistory() return account_history.get_last_workstation_by_ip(source_ip)
class MachineAuth(object): def __init__(self): self.account_history = AccountHistory() def run(self, log: Log): ip = log.source_info.ip_address if ip_filter(ip): return if log.event_data["Status"] != "0x0": return if log.event_data["PreAuthType"] != 2: return if not log.target_info.user_name.endswith("$"): return workstation = log.target_info.user_name[:-1] self.account_history.set_workstation_by_ip(ip=ip, workstation=workstation) self.account_history.set_ip_by_workstation(ip=ip, workstation=workstation)
def __init__(self): super().__init__(code=ALERT_CODE, title=TITLE, desc=DESC_TEMPLATE) self.account_info = AccountInfo() self.account_history = AccountHistory()
class NTLMRelay(DetectBase): def __init__(self): super().__init__(code=ALERT_CODE, title=TITLE, desc=DESC_TEMPLATE) self.account_history = AccountHistory() self.account_info = AccountInfo() self.es = ElasticHelper() def run(self, log: Log): self.init(log=log) # 处于数据统计时间内,不检测 if datetime_now_obj() < main_config.learning_end_time: return if not log.source_info.ip_address: return if log.event_data["AuthenticationPackageName"] != "NTLM": return work_station = log.source_info.work_station_name netbios_name = get_netbios_domain(log.target_info.domain_name) if filter_domain(netbios_name): return # 为较小误报 目前只考虑来源主机为敏感主机的行为 if not self.account_info.computer_is_sensitive_by_name( work_station, domain=netbios_name): return ip_address = log.source_info.ip_address if ip_filter(ip_address): return # 根据主机名去查最近的认证IP last_ip = self.account_history.search_last_ip_by_workstation( work_station) if not last_ip or last_ip == "unknown" or last_ip == ip_address: return # 二次确认,如果上次认证IP与当前IP不相同,则对主机名进行解析,判断IP是否相等 resolver_ips = self._get_host_ip(log) if ip_address in resolver_ips: return if "V1" in log.event_data["LmPackageName"]: version = "v1" else: version = "v2" relay_workstation = self.account_history.get_last_workstation_by_ip( ip_address) return self._generate_alert_doc(relay_workstation=relay_workstation, ntlm_version=version, resolver_ips=resolver_ips, last_ip=last_ip) def _generate_alert_doc(self, **kwargs) -> dict: form_data = { "source_ip": self.log.source_info.ip_address, "relay_ip": self.log.source_info.ip_address, "source_workstation": self.log.source_info.work_station_name, "target_user_name": self.log.target_info.user_name, "target_domain": self.log.target_info.domain_name, "target_user_sid": self.log.target_info.user_sid, "target_logon_id": self.log.target_info.logon_id, "dc_hostname": self.log.dc_host_name, **kwargs } doc = self._get_base_doc(level=self._get_level(), unique_id=self._get_unique_id( self.code, self.log.source_info.ip_address), form_data=form_data) return doc def _get_level(self) -> str: return HIGH_LEVEL def _get_host_ip(self, log: Log) -> list: """ 对主机名进行DNS解析 """ dns_name = "{workstation}.{domain}".format( workstation=log.source_info.work_station_name, domain=self.get_FQDN_domain(log.target_info.domain_name)) try: ip_list = get_ip_from_domain(dns_name) except Exception as e: return [] return ip_list def get_FQDN_domain(self, domain) -> str: for each in main_config.domain_list: if each.startswith(domain.lower()): return each return ""
def __init__(self): self.redis = RedisHelper() self.account_history = AccountHistory() self.es = ElasticHelper()
def __init__(self): self.account_history = AccountHistory()
def _get_source_ip_by_workstation(self, source_ip) -> str: """ """ account_history = AccountHistory() return account_history.get_last_ip_by_workstation(source_ip)