现在最危险的钓鱼越来越不像“钓鱼”:Google 昨天披露的 OAuth、App Password 和设备绑定攻击,正好给 Agent 身份设计上了一课

Google Threat Intelligence 昨天公开了一组针对高风险人群的长期攻击活动。

这批攻击有个共同点:它们大量滥用的是合法认证流程,而不是纯粹伪造一个登录页。

Google 跟踪的多个疑似俄罗斯网络间谍集群,会组合使用:

App Password
OAuth Flow
Device Linking
Cloud Project
合法云基础设施

去完成账户接管。

这件事对普通用户当然是安全问题。

但我觉得对 Agent 工程同样重要,因为企业 Agent 正在大量使用:

OAuth
Delegated Permission
Short-lived Token
Connected App
MCP

如果我们还把“用户点过一次授权”理解成:

这个 Agent 以后就可以一直做这些事

风险会越来越大。

App Password 这个案例特别值得看

Google 披露的 UNC6293 会诱导目标创建 App Password。

这类密码是为了让较旧或不支持现代认证的应用获得账户访问能力。

攻击者会伪装成官方人员,引导目标在账户设置里创建一个 App Password,然后把它提交到攻击者控制的页面。

关键在于:

它绕开了正常的 2FA 体验

用户甚至可能觉得:

“我是按照官方设置页面一步一步操作的。”

这比一个粗糙的假登录页难识别得多。

OAuth 攻击更说明问题:合法授权页面也可能被滥用

Google 还披露,UNC7005、UNC5976 会使用 Cloud Project 和 OAuth 流程做钓鱼。

用户看到的授权页面可能来自真实的 OAuth 基础设施。

问题不是:

这个页面是真的假的?

而是:

我到底在授权给谁?
授权了什么 Scope?
这个应用为什么需要这些权限?

这和企业 Agent 的 Delegated Authority 完全是同一个问题。

“身份是真的”不等于“行为就可信”

这是很多 Agent 平台最容易犯的错误。

系统拿到一个合法 OAuth Token:

token valid = true

于是默认:

request trusted = true

不对。

OAuth Token 只能证明:

某个主体被授予了某些 Scope

不能证明:

这次具体动作是用户真正想要的

例如用户授权一个销售 Agent 读取 CRM。

并不意味着它应该自动:

导出全部客户
发送给第三方
修改负责人
删除记录

身份认证只是第一层。

Agent 调用至少要回答四个问题

我现在会要求每个高风险 Tool Call 都能回答:

Who:
谁发起?

On behalf of whom:
代表谁?

Why:
为了什么任务?

What authority:
基于什么授权?

例如:

{
  "agent": "sales-renewal-agent",
  "user": "zhangsan",
  "tenant": "team-a",
  "purpose": "renewal-review-1842",
  "capability": "crm.customer.read",
  "grant": "grant-92"
}

如果日志里只有:

service-account=sales-agent

其实还不够。

Purpose Binding 是我觉得 Agent 授权里最缺的一层

传统 OAuth 主要表达:

Scope

例如:

crm.read

Agent 场景还需要:

Purpose

比如:

crm.read

用于:

分析客户续约风险

和用于:

批量导出客户做外部广告

不是同一个风险。

所以我会让授权对象包含:

public record DelegatedGrant(
        String grantId,
        String subjectId,
        String agentId,
        String tenantId,
        String purpose,
        Set scopes,
        Set resourcePatterns,
        Instant expiresAt) {
}

Scope 还要继续缩成 Resource

只有:

crm.read

仍然太大。

更好的授权可能是:

crm.customer.read
resource:
customer/12345

甚至:

customer/12345
fields:
name
stage
recent_activity

Agent 权限应该尽量:

任务级
资源级
短时间

而不是一次授权后长期拥有整个系统。

Device Linking 攻击也给 Browser Agent 一个提醒

Google 的报告还提到对消息应用的 Device Linking 滥用。

这类攻击不是直接偷密码,而是诱导用户把攻击者设备“合法地”绑定到账户。

这和 Browser Agent 很像。

如果用户在 Agent 控制的 Browser Session 里完成登录:

会话就获得真实账户权限

所以 Browser Session 本身就是高价值凭证。

不能只保护密码。

还要保护:

Cookie
Storage State
Linked Device
Session Token
OAuth Grant
Refresh Token

我现在会把 Browser Session 当 Credential 管

状态:

ACTIVE
PAUSED
REVOKED
EXPIRED

并记录:

owner
agent
purpose
allowed_sites
allowed_actions
expires_at

一个用于:

查看订单

的浏览器会话,不应该自动拿去:

修改支付信息

Consent Screen 也不能承担全部安全责任

很多系统认为:

用户已经点了“允许”

就结束了。

但真实世界里,用户很难理解长 Scope 列表。

尤其 Agent 可能在几天以后才执行具体动作。

所以高风险动作最好再做:

Just-in-time Confirmation

例如:

Agent 已获得邮箱读取权限

不代表它可以自动:

向 300 个联系人发信

真正发送前再确认:

将向 300 人发送
主题为……
是否继续?

Delegated Authority 最好有两层时间窗口

第一层:

Connection Grant

例如用户连接了 Google Drive。

可以持续较长时间。

第二层:

Execution Grant

例如:

本次 Run 可以读取 folder/abc
有效 10 分钟
最多 20 次

这样长期连接不会直接变成长期无限执行权限。

一个简单的授权链

User Connection
↓
Agent requests capability
↓
Policy Engine
↓
Run-scoped Grant
↓
Short-lived Credential
↓
Tool Call
↓
Audit

这比:

Agent 直接拿用户 OAuth Token

安全得多。

App Password 为什么在企业里应该尽量消失

Google 的报告明确提醒,高风险用户可以使用 Advanced Protection,企业也可以通过更严格的 2-Step Verification 策略禁用 App Specific Password。

这个方向和 Agent 基础设施也一致。

只要有条件,就优先:

OAuth
Workload Identity
Service Identity
Short-lived Token

而不是:

长期静态密码

静态 Secret 的问题不是只有“会泄漏”。

还有:

很难知道是谁在用
很难按用途缩权
很难快速撤销单个任务

Tool Credential 不应该出现在 Prompt 和环境变量里

尤其 Agent 能运行代码时。

危险:

CRM_TOKEN=...
GMAIL_TOKEN=...

然后交给一个通用代码执行环境。

更合理:

Agent 只请求 Capability

Credential Broker 在调用瞬间给:

短期、单用途 Token

Agent 本身最好永远看不到长期 Refresh Token。

OAuth Refresh Token 是长期 Agent 的真正风险点

Access Token 很短。

Refresh Token 可以长期续。

如果平台让多个 Agent 共享同一个 Refresh Token:

撤权
审计
归因

都会变难。

我更建议连接层保存 Refresh Token,执行层只拿:

Ephemeral Access Token

并且每次签发都经过 Policy。

一个必须记录的字段:grant_source

{
  "grant_source": "user_connection",
  "connection_id": "conn-82",
  "execution_grant_id": "exec-191",
  "approval_id": "approval-28"
}

这样事故后可以反查:

这次工具调用到底从哪次用户授权演化出来的

还需要“授权衰减”

一个权限去年授权,不代表今年仍然应该继续。

可以设置:

30 天未使用
→要求重新确认

高风险权限 7 天
→重新确认

组织角色变化
→立即重新评估

尤其员工调岗或离职。

Agent 权限最好跟角色变化联动

用户从:

Finance

转到:

Sales

旧连接和 Delegated Grant 不应该无限保留。

系统应该触发:

Identity Change Event
→ Re-evaluate Grants
→ Revoke Invalid Grants

Google 这组攻击真正让我警惕的是“合法流程被滥用”

安全设计经常把世界分成:

合法登录
非法登录

但现代攻击越来越多是在:

合法基础设施
合法协议
合法授权页面

里诱导用户做错误授权。

Agent 时代同样如此。

未来最危险的事故未必是:

黑客偷到了 Token

也可能是:

用户合法授权了一个 Agent,
Agent 又合法调用了 Tool,
但最终做了用户根本没想让它做的事。

这时候:

Authentication

全部是成功的。

失败的是:

Authority Semantics

所以我现在看 Agent 身份系统,不再只问:

Token 是合法的吗?

而会继续追问:

这次调用代表谁?
授权目的是什么?
权限是不是最小?
多久过期?
资源范围多大?
高风险动作有没有再次确认?

Google 昨天披露的 OAuth、App Password 和 Device Linking 攻击,恰好说明了一件事:

真正成熟的身份安全,从来不只是“让登录更安全”,而是让授权本身更难被误用。

这也是生产 Agent 接下来必须补上的一层。


更多企业级 AI 应用、Agent、RAG 与模型工程化内容,我会继续整理在 智元界

https://www.zyentor.com/