俄罗斯APT组织Storm-2372 发起设备代码网络钓鱼活动

Microsoft 威胁情报中心发现,威胁行为者 Storm-2372 正在积极且成功地发起设备代码网络钓鱼活动。我们正在进行的调查表明,该活动自 2024 年 8 月以来一直处于活跃状态,行为者创建的诱饵类似于 WhatsApp、Signal 和 Microsoft Teams 等消息应用程序的体验。在此期间,Storm-2372 的目标包括欧洲、北美、非洲和中东的政府、非政府组织 (NGO)、信息技术 (IT) 服务和技术、国防、电信、医疗、高等教育以及能源/石油和天然气。Microsoft 以中等可信度评估 Storm-2372 符合俄罗斯的利益、受害者学和间谍技巧。
在设备代码钓鱼中,威胁者利用设备代码身份验证流程获取身份验证令牌,然后利用这些令牌访问目标帐户,并进一步获取受感染帐户可以访问的数据和其他服务的访问权限。只要令牌有效,这种技术就可以实现持续访问,因此这种攻击技术对威胁者很有吸引力。
本博客中提到的网络钓鱼攻击伪装成通过电子邮件发送的 Microsoft Teams 会议邀请。当目标点击会议邀请时,系统会提示他们使用威胁行为者生成的设备代码进行身份验证。然后,行为者从用户交互中收到有效的访问令牌,从而窃取经过身份验证的会话。
由于 Storm-2372 和其他威胁行为者利用设备代码网络钓鱼技术所代表的主动威胁,我们正在分享我们对此活动的最新研究、检测和缓解指导,以提高对观察到的策略、技术和程序 (TTP) 的认识,教育组织如何强化其攻击面,并破坏此威胁行为者未来的行动。Microsoft 使用 Storm 名称作为未知、新兴或正在发展的威胁活动集群的临时名称,允许 Microsoft 将其作为一组唯一信息进行跟踪,直到我们对活动背后的威胁行为者的来源或身份有很高的把握。
Microsoft 威胁情报中心继续跟踪 Storm-2372 发起的活动,并在可能的情况下直接通知受到攻击或受到攻击的客户,为他们提供必要的信息以帮助保护他们的环境。Microsoft 还在跟踪使用类似技术的其他团体,包括 Volexity 在其最新出版物中记录的团体。
设备代码网络钓鱼如何运作?
设备代码身份验证流程是一种数字或字母数字代码,用于对输入受限的设备中的帐户进行身份验证,该设备无法使用 Web 流程执行交互式身份验证,因此必须在另一台设备上执行此身份验证才能登录。在设备代码网络钓鱼中,威胁行为者会利用设备代码身份验证流程。
在攻击过程中,威胁行为者会生成合法的设备代码请求,并诱骗目标将其输入合法的登录页面。这将授予行为者访问权限,并使他们能够捕获生成的身份验证(访问和刷新)令牌,然后使用这些令牌访问目标的帐户和数据。行为者还可以使用这些钓鱼的身份验证令牌来访问用户有权限的其他服务,例如电子邮件或云存储,而无需密码。只要令牌仍然有效,威胁行为者就可以继续访问。然后,攻击者可以使用有效的访问令牌在环境中横向移动。
图 1. 设备代码钓鱼攻击周期
Storm-2372 网络钓鱼诱饵和访问
Storm-2372 的设备代码网络钓鱼活动自 2024 年 8 月以来一直活跃。观察到的早期活动表明,Storm-2372 可能使用第三方消息服务(包括 WhatsApp、Signal 和 Microsoft Teams)瞄准潜在受害者,伪装成与目标相关的知名人士以建立融洽关系,然后通过网络钓鱼电子邮件发送后续的在线活动或会议邀请。
图 2. 威胁行为者冒充知名人士并在 Signal 上建立融洽关系的示例消息
这些邀请诱使用户完成模拟消息服务体验的设备代码验证请求,这为 Storm-2372 提供了对受害者帐户的初始访问权限,并启用了 Graph API 数据收集活动,例如电子邮件收集。
图 3. 网络钓鱼活动中使用的诱饵示例
在设备代码认证页面上,用户被诱骗输入威胁行为者包含的代码作为虚假 Teams 会议邀请的 ID。
入侵后活动
一旦受害者使用设备代码进行身份验证,威胁行为者就会收到有效的访问令牌。然后,威胁行为者利用此有效会话在新受感染的网络中横向移动,通过来自受害者帐户的组织内部电子邮件向其他用户发送包含设备代码身份验证链接的其他网络钓鱼消息。
图4. 合法设备代码认证页面
此外,微软还观察到 Storm-2372 使用 Microsoft Graph 搜索他们入侵的帐户的消息。威胁行为者使用关键字搜索来查看包含用户名、密码、管理员、teamviewer、anydesk、凭据、机密、部门和政府等字词的消息。然后,微软通过 Microsoft Graph 观察到从这些搜索中找到的电子邮件被泄露。
2025年2月14日更新:
在过去 24 小时内,微软观察到 Storm-2372 已转向在设备代码登录流程中使用 Microsoft 身份验证代理的特定客户端 ID。使用此客户端 ID,Storm-2372 可以接收刷新令牌,该令牌可用于为设备注册服务请求另一个令牌,然后在 Entra ID 中注册参与者控制的设备。使用相同的刷新令牌和新的设备标识,Storm-2372 能够获得主刷新令牌 (PRT) 并访问组织的资源。我们观察到 Storm-2372 使用连接的设备来收集电子邮件。
据观察,攻击者还使用适合目标区域的代理,可能是为了进一步隐藏可疑的登录活动。
虽然下面列出的许多缓解措施和查询仍然适用于这种情况,但涉及近时设备注册的异常令牌或 PRT 活动的警报也可能是识别这种技术转变的有用方法。此外,[注册限制](限制可以将设备注册到 Microsoft Entra ID 环境的用户权限)也可以帮助解决这种攻击行为。
归因
微软追踪的 Storm-2372 是一个疑似民族国家行为者,其目的是为俄罗斯国家利益服务。它曾使用设备代码钓鱼来攻击目标。Storm-2372 可能最初通过第三方消息服务接近目标,冒充与目标相关的知名人士以建立融洽关系,然后发送在线活动或会议邀请。这些邀请会诱使用户进行设备代码身份验证,从而授予 Storm-2372 的初始访问权限并启用 Graph API 数据收集活动(例如电子邮件收集)。
Storm-2372 的目标包括欧洲、北美、非洲和中东的政府、非政府组织、IT 服务和技术、国防、电信、卫生、高等教育以及能源/石油和天然气。
狩猎查询
Microsoft Defender XDR
以下查询可帮助识别可能的设备代码网络钓鱼尝试:
let suspiciousUserClicks = materialize(UrlClickEvents <br><br> | where ActionType in ("ClickAllowed", "UrlScanInProgress", "UrlErrorPage") or IsClickedThrough != "0" <br><br> | where UrlChain has_any ("microsoft.com/devicelogin", "login.microsoftonline.com/common/oauth2/deviceauth") <br><br> | extend AccountUpn = tolower(AccountUpn) <br><br> | project ClickTime = Timestamp, ActionType, UrlChain, NetworkMessageId, Url, AccountUpn); <br><br>//Check for Risky Sign-In in the short time window <br><br>let interestedUsersUpn = suspiciousUserClicks <br><br> | where isnotempty(AccountUpn) <br><br> | distinct AccountUpn; <br><br>let suspiciousSignIns = materialize(AADSignInEventsBeta <br><br> | where ErrorCode == 0 <br><br> | where AccountUpn in~ (interestedUsersUpn) <br><br> | where RiskLevelDuringSignIn in (10, 50, 100) <br><br> | extend AccountUpn = tolower(AccountUpn) <br><br> | join kind=inner suspiciousUserClicks on AccountUpn <br><br> | where (Timestamp - ClickTime) between (-2min .. 7min) <br><br> | project Timestamp, ReportId, ClickTime, AccountUpn, RiskLevelDuringSignIn, SessionId, IPAddress, Url <br><br>); <br><br>//Validate errorCode 50199 followed by success in 5 minute time interval for the interested user, which suggests a pause to input the code from the phishing email <br><br>let interestedSessionUsers = suspiciousSignIns <br><br> | where isnotempty(AccountUpn) <br><br> | distinct AccountUpn; <br><br>let shortIntervalSignInAttemptUsers = materialize(AADSignInEventsBeta <br><br> | where AccountUpn in~ (interestedSessionUsers) <br><br> | where ErrorCode in (0, 50199) <br><br> | summarize ErrorCodes = make_set(ErrorCode) by AccountUpn, CorrelationId, SessionId <br><br> | where ErrorCodes has_all (0, 50199) <br><br> | distinct AccountUpn); <br><br>suspiciousSignIns <br><br>| where AccountUpn in (shortIntervalSignInAttemptUsers) |
以下来自公共研究的查询显示了新注册的设备,并且可以与异常或可疑的用户或令牌活动结合使用:
CloudAppEvents <br><br>| where AccountDisplayName == "Device Registration Service" <br><br>| extend ApplicationId_ = tostring(ActivityObjects[0].ApplicationId) <br><br>| extend ServiceName_ = tostring(ActivityObjects[0].Name) <br><br>| extend DeviceName = tostring(parse_json(tostring(RawEventData.ModifiedProperties))[1].NewValue) <br><br>| extend DeviceId = tostring(parse_json(tostring(parse_json(tostring(RawEventData.ModifiedProperties))[6].NewValue))[0]) <br><br>| extend DeviceObjectId_ = tostring(parse_json(tostring(RawEventData.ModifiedProperties))[0].NewValue) <br><br>| extend UserPrincipalName = tostring(RawEventData.ObjectId) <br><br>| project TimeGenerated, ServiceName_, DeviceName, DeviceId, DeviceObjectId_, UserPrincipalName |