4、最小权限原则:为什么最小权限能防止滥用,如何实施

咱们聊点实在的。你琢磨琢磨,IAM 策略滥用是怎么发生的?十有八九是因为权限给得太大方了。给了一个 S3 的 FullAccess,结果整个桶被删光了;给了一个管理员权限,结果员工离职后数据被批量导走。说白了,滥用,往往始于“权限超标”。

我刚开始做云安全那会儿,也觉得“权限多点没事,省得麻烦”。直到有一次,一个开发小哥为了测试方便,把 Lambda 的执行角色绑上了 AdministratorAccess。结果函数被外部调用,攻击者直接拿这个角色把 RDS 的备份给删了。嗯,从那以后,我再也不敢讲“给大权限没事”这种话了。

最小权限为什么能防滥用?

最小权限,英文叫 Least Privilege。它的核心逻辑很简单:只给做某件事必需的最小权限,多一点都不给。

从安全角度讲,它切断了三条主要的滥用路径:

  • 权限扩大路径——攻击者拿到一个高权限账户后,可以做更多事情;最小权限让攻击者“举手无措”。
  • 误操作路径——开发者不小心执行了删除命令,但因为没权限,命令失败,数据保住。
  • 横向移动路径——一个服务只能访问自己桶里的数据,无法跳到别人的桶里去。

你想想看,如果一个角色只能读自己桶里的对象,就算凭证泄露,攻击者能干什么?最多看看日志文件。这就是最小权限的“缩小攻击面”效果。

我的习惯:每次创建角色,我都会先问自己三个问题:
1. 这个角色必须访问哪些资源?
2. 必须执行哪些操作?
3. 在什么条件下可以执行?
答不上来的权限,一律不放行。

核心思路:拒绝优先,显式授权

很多团队的策略写得像“白名单”+“黑名单”混合体。其实正确的做法是:先拒绝所有,再显式放行需要的。IAM 默认就是隐式拒绝,所以你只需要把要允许的动作列清楚就行。

举个例子,一个负责读取 S3 日志的分析员,你给他这样的策略:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-logs-bucket",
        "arn:aws:s3:::my-logs-bucket/*"
      ]
    }
  ]
}

看到了吗?没有 s3:PutObject,没有 s3:DeleteObject。就算他写代码时不小心调了删除接口,也会返回 AccessDenied。这就是最小权限的落地形态。

我曾经踩过的坑:给一个 Lambda 函数配了 s3:*,觉得“只限定了桶应该没问题”。结果函数被注入攻击,攻击者用 s3:PutObjectAcl 把桶公开了。各位,Action 一定要精确到最小粒度,别用通配符糊弄。

如何评估现有角色的权限

光说理论不行,你得有方法。我常用的评估手段有几种:

方法 适用场景 说明
IAM Access Analyzer 已有策略 自动分析策略,找出未使用的权限、隐式允许等问题
CloudTrail + Athena 查询 运行中的工作负载 查找过去90天内实际调用的API,跟策略比对
手动审计 小团队/关键角色 逐条检查策略中的Action和Resource,剔除多余项
模拟策略(Simulate Principal Policy) 测试新策略 在IAM控制台或CLI模拟执行,看哪些API会失败

说白了,不要相信你写的策略“已经够小了”。我见过太多策略里写着 s3:ListAllMyBuckets 但实际根本不需要——这个东西能枚举整个账号下的所有桶名,信息泄露风险很大。

权限收缩的实战技巧

怎么把一个大权限策略“瘦身”?我总结了几步,百试百灵:

  1. 先列出角色实际使用的API——从CloudTrail里导出最近30天的日志,统计出所有调用的Action。
  2. 生成最小策略——用 Access Analyzer 的“生成策略”功能,基于你的API调用自动生成一个最小策略。
  3. 加上条件限制——比如限制只能在 VPC 内调用、只能访问指定标签的资源、必须使用 TLS 等。
  4. 替换通配符——把 Action: ["*"] 换成列表,把 Resource: ["*"] 换成具体ARN。
  5. 测试、测试、再测试——先在非生产环境模拟执行,确认没有功能报错才切换。

硬性要求:生产角色不允许出现 "Action": "*" 或 "Resource": "*"。如果有,必须走例外审批流程,而且例外策略要附带到期自动删除的机制。

最小权限与临时权限提升

有些场景下,你确实需要临时扩大权限,比如运维排障、紧急数据恢复。这时候不是放弃最小权限,而是用“临时提升”来替代永久授权。

我的做法是:把临时提升封装成审批流。比如用 AWS Systems Manager 配合 IAM 角色自动切换,或者用 sts:AssumeRole 切换到高权限角色,并在 CloudTrail 中记录每次提升。员工完成任务后,角色自动到期或手动回收。

这样既满足了紧急需求,又保持了日常的最小权限。你想想看,是不是比直接给永久高权限好得多?

最小权限实施流程 1. 识别角色/用户 2. 分析实际API调用 3. 生成最小策略 4. 添加条件限制 5. 测试 & 切换 定期审核并收缩 📌 关键动作 使用 IAM Access Analyzer 生成最小策略;利用 CloudTrail 分析实际调用; 加上 VPC/SourceIP/TLS 条件;通过模拟策略确认无影响后再上线。

这张图展示了我推荐的实施闭环。从识别角色开始,到分析实际调用、生成最小策略、加条件、测试切换,最后定期审核并继续收缩。这是一个持续优化过程,别指望一次就能做到完美。

避坑指南

我曾经见过一个团队:他们严格遵循了最小权限,但没考虑“跨账号访问”。A 账号的角色对 B 账号的桶有s3:GetObject权限,但 B 账号的桶策略没限制,导致 A 账号的凭证泄露后,攻击者通过这个角色把 B 账号的桶也扫了一遍。所以记得:最小权限不仅管自己账号,还要管信任关系中的外部实体。

另外一个常见问题是权限膨胀。今天加一个权限,明天加一个权限,一年后角色权限比最初大了五六倍。所以我建议每个角色都贴上创建时间,每隔90天做一次权限复核,把没用到的一律删除。

我的个人习惯:用 aws iam get-service-last-accessed-details 这个 API,可以查出一个角色最近多久没用某个服务。超过90天没用的权限,我先在策略里注释掉(用 "Condition" 临时禁止),观察一周没问题再彻底删除。

说了这么多,你可能会觉得最小权限有点麻烦。没错,它确实比“一把梭”麻烦一些。但你想一下,一次数据泄露带来的损失,可能是一个运维团队半年的工作量。花一个小时把策略写精确,对比花几个星期救火,哪个更划算?答案很明显。