예제 #1
0
 def check_target_is_user_by_sid(self, sid: str, domain: str) -> bool:
     """
         检查目标账号是否为 OU=Users
     """
     key = sid + REDIS_KEY_SID_IS_USERS_SUFFIX
     record = self.redis.get_str_value(key)
     # 存在redis缓存记录
     if record:
         if record == "true":
             return True
         else:
             return False
     # 不存在 则通过ldap查询,再更新redis缓存
     else:
         ldap = LDAPSearch(domain)
         user_entry = ldap.search_by_sid(sid=sid, attributes=["cn"])
         if user_entry:
             dn = user_entry.entry_dn
             if "OU=Users" in dn:
                 self.redis.set_str_value(
                     key, "true", expire=ACCOUNT_INFO_REDIS_EXPIRE_TIME)
                 return True
         self.redis.set_str_value(key,
                                  "false",
                                  expire=ACCOUNT_INFO_REDIS_EXPIRE_TIME)
         return False
예제 #2
0
 def check_target_is_admin_by_sid(self, sid: str, domain: str) -> bool:
     """
         检查一个账户是否拥有管理员权限
     """
     key = sid + REDIS_KEY_SID_IS_ADMIN_SUFFIX
     record = self.redis.get_str_value(key)
     # 存在redis缓存记录
     if record:
         if record == "true":
             return True
         else:
             return False
     # 不存在 则通过ldap查询,再更新redis缓存
     else:
         ldap = LDAPSearch(domain)
         user_entry = ldap.search_by_sid(sid=sid, attributes=["adminCount"])
         if user_entry:
             entry_attributes = user_entry.entry_attributes_as_dict
             if len(entry_attributes["adminCount"]
                    ) > 0 and entry_attributes["adminCount"][0] == 1:
                 self.redis.set_str_value(
                     key, "true", expire=ACCOUNT_INFO_REDIS_EXPIRE_TIME)
                 return True
         self.redis.set_str_value(key,
                                  "false",
                                  expire=ACCOUNT_INFO_REDIS_EXPIRE_TIME)
         return False
예제 #3
0
    def user_is_sensitive_by_sid(self, sid: str, domain: str) -> bool:
        """
            检查某个用户是否为敏感用户

            1. adminCount 1
            2. 属于敏感组
            3. 蜜罐账户
            4. 自定义敏感用户

            LDAP查询是性能瓶颈,需要使用redis进行缓存加速

        """
        # 蜜罐账户
        for user in main_config.honeypot_account:
            if user["sid"] == sid:
                return True

        # 自定义敏感用户
        for user in main_config.sensitive_users:
            if user["sid"] == sid:
                return True

        # 先查缓存
        _cache_is_sensitive = self.get_target_sensitive_cache(sid)
        if _cache_is_sensitive is not None:
            return _cache_is_sensitive == "true"

        # LDAP 查询较慢,性能瓶颈
        ldap = LDAPSearch(domain)
        user_entry = ldap.search_by_sid(sid,
                                        attributes=["adminCount", "memberOf"])
        if not user_entry:
            self.set_target_sensitive_cache(sid, "false")
            return False

        # adminCount
        if len(user_entry.entry_attributes_as_dict["adminCount"]) > 0 and \
                user_entry.entry_attributes_as_dict["adminCount"][0] == 1:
            self.set_target_sensitive_cache(sid, "true")
            return True

        # 敏感组
        groups = user_entry.entry_attributes_as_dict["memberOf"]
        sensitive_groups = list(
            map(lambda x: x["name"], main_config.sensitive_groups))
        for g in groups:
            g_name = get_cn_from_dn(g)
            if g_name in sensitive_groups:
                self.set_target_sensitive_cache(sid, "true")
                return True
        self.set_target_sensitive_cache(sid, "false")
        return False
예제 #4
0
    def run(self, log: Log):
        self.init(log=log)

        if log.object_info.type != "SAM_USER":
            return

        user_name = log.subject_info.user_name
        if user_name.endswith("$"):
            return

        target_sid = log.object_info.name
        if not target_sid.startswith("S-1-5-21-"):
            return

        # 查询自身也忽略
        if log.subject_info.user_sid == target_sid:
            return

        # 判断域名是否存在于需要检查的域名中
        domain_name = log.subject_info.domain_name
        if filter_domain(domain_name):
            return

        # 如果账号是管理员 直接忽略
        if self.account_info.check_target_is_admin_by_sid(
                sid=log.subject_info.user_sid, domain=domain_name):
            return

        # 判断操作者是否为Users
        if not self.account_info.check_target_is_user_by_name(
                user_name, domain_name):
            return

        # 判断是否为敏感用户
        if not self.account_info.user_is_sensitive_by_sid(sid=target_sid,
                                                          domain=domain_name):
            return

        ldap = LDAPSearch(domain_name)
        target = ldap.search_by_sid(target_sid, attributes=["cn"])
        if not target:
            return
        target_user_name = str(target["cn"])
        return self._generate_alert_doc(target_user_name=target_user_name)
예제 #5
0
 def get_user_info_by_sid(self, sid: str, domain: str) -> User:
     key = sid + REDIS_KEY_SID_USERNAME_SUFFIX
     # 先查redis
     user_name = self.redis.get_str_value(key)
     if not user_name:
         ldap = LDAPSearch(domain)
         user_entry = ldap.search_by_sid(sid, attributes=["sAMAccountName"])
         if not user_entry:
             return None
         user_name = user_entry.entry_attributes_as_dict["sAMAccountName"][
             0]
         self.redis.set_str_value(key,
                                  user_name,
                                  expire=ACCOUNT_INFO_REDIS_EXPIRE_TIME)
     user = User({
         "user_name": user_name,
         "user_sid": sid,
         "logon_id": "",
         "domain_name": domain
     })
     return user
예제 #6
0
    def user_is_sensitive_by_sid(self, sid: str, domain: str) -> bool:
        """
            检查某个用户是否为敏感用户

            1. adminCount 1
            2. 属于敏感组
            3. 蜜罐账户
            4. 自定义敏感用户
        """
        # 蜜罐账户
        for user in main_config.honeypot_account:
            if user["sid"] == sid:
                return True

        # 自定义敏感用户
        for user in main_config.sensitive_users:
            if user["sid"] == sid:
                return True

        ldap = LDAPSearch(domain)
        user_entry = ldap.search_by_sid(sid,
                                        attributes=["adminCount", "memberOf"])
        if not user_entry:
            return False

        # adminCount
        if len(user_entry.entry_attributes_as_dict["adminCount"]) > 0 and \
                user_entry.entry_attributes_as_dict["adminCount"][0] == 1:
            return True

        # 敏感组
        groups = user_entry.entry_attributes_as_dict["memberOf"]
        sensitive_groups = list(
            map(lambda x: x["name"], main_config.sensitive_groups))
        for g in groups:
            g_name = get_cn_from_dn(g)
            if g_name in sensitive_groups:
                return True
        return False
예제 #7
0
 def _get_group_name(self, sid, domain):
     ldap = LDAPSearch(domain)
     entry = ldap.search_by_sid(sid, attributes=["cn"])
     if entry:
         return str(entry["cn"])