限制 AWS 帳號必須啟動多因素認證 (Multi Factor Auth, MFA)

前言

越來越多企業將服務甚至內部核心搬上雲端,因此雲端平台的帳號保護就顯得非常重要,保護帳號的原則除了密碼複雜度外,我都會建議要啟動多因素認證 (MFA) 來進一步強化帳號的保護。

今天就來介紹一下該如何透過 IAM Policy 來限制帳號必須啟動 MFA (Multi Factor Auth) 才可以進行操作。

實行方法

IAM Policy Condition

要進行這樣的限制其實非常容易,在 Condition 中加入 aws:MultiFactorAuthPresent 的判斷即可,範例如下:

"Condition": {
    "BoolIfExists": {
        "aws:MultiFactorAuthPresent": "true"
    }
}

反向表達 (Deny)

如果針對每一個資源進行一次 aws:MultiFactorAuthPresent 判斷是非常耗時的,因此我們將條件反過來寫,範例如下:

"Sid": "DenyAllExceptListedIfNoMFA",
    "Effect": "Deny",
    "Resource": "*",
    "Condition": {
        "BoolIfExists": {
            "aws:MultiFactorAuthPresent ": "false"
        }
    }
 }

排除必要操作的限制 (NotAction)

如果我們將所有資源 "Resource": "*" 都加入 aws:MultiFactorAuthPresent,這將會導致沒有 MFA 的帳號無法啟用 MFA。

為了避免上述的問題,我們可以透過 NotAction 反過來排除相關限制,並允許 MFA 相關操作,讓使用者可以正常啟用帳號的 MFA,不會因此陷入死循環中,範例如下:

[
  {
    "Sid": "AllowViewAccountInfo",
    "Effect": "Allow",
    "Action": "iam:ListVirtualMFADevices",
    "Resource": "*"
  },
  {
    "Sid": "AllowManageOwnVirtualMFADevice",
    "Effect": "Allow",
    "Action": [
      "iam:CreateVirtualMFADevice",
      "iam:DeleteVirtualMFADevice"
    ],
    "Resource": "arn:aws:iam::*:mfa/${aws:username}"
  },
  {
    "Sid": "AllowManageOwnUserMFA",
    "Effect": "Allow",
    "Action": [
      "iam:DeactivateMFADevice",
      "iam:EnableMFADevice",
      "iam:GetUser",
      "iam:ListMFADevices",
      "iam:ResyncMFADevice"
    ],
    "Resource": "arn:aws:iam::*:user/${aws:username}"
  },
  {
    "Sid": "DenyAllExceptListedIfNoMFA",
    "Effect": "Deny",
    "NotAction": [
      "iam:GetUser",
      "iam:ListMFADevices",
      "iam:ListVirtualMFADevices",
      "iam:CreateVirtualMFADevice",
      "iam:EnableMFADevice",
      "iam:ResyncMFADevice",
      "sts:GetSessionToken",
      "iam:ChangePassword"
    ],
    "Resource": "*",
    "Condition": {
      "BoolIfExists": {
        "aws:MultiFactorAuthPresent": "false"
      }
    }
  }
]

最後一步

我們只需要將 Policy 套用到使用者身上,就可以達到強制啟動 MFA 才可以進行資源操作的目的。

備註

  1. aws:MultiFactorAuthPresent 只有在使用者登入的時候才會更新,也就是設定完 MFA 要重新登入一次
  2. 上方的範例要求 MFA 的名稱要跟使用者名稱相同,可以透過修改 arn:aws:iam::*:mfa/${aws:username}arn:aws:iam::*:mfa/${aws:username}-*,讓使用者可以在名稱後方加上 - 來加上自己的標註資訊

用 AWS API Key 登入 AWS 管理主控台 (Web Console)

前言

雖然平常都使用標準帳號來登入 AWS 的管理主控台 (Web Console),但如果我們只有 API Key 的時候,是不是也能用來登入 Web Console 呢 ?

答案是: 可以

我們只需要透過 聯合存取/登入 ( Federated Access/Login ) 機制,就可以拿 AWS API Key 來登入 AWS 的管理主控台 (Web Console)。

整體流程

流程摘要

透過聯合存取/登入機制產生登入連結的大致上流程如下:

  1. 向 AWS STS 請求 Federation Token
  2. 向 AWS Signin Federation 送出請求,取得 Signin Token
  3. 產生登入網址
  4. 登入 Web Console

流程說明

向 AWS STS 請求 Federation Token

我們先使用 AWS API Key 向 AWS STS (AWS Security Token Service),請求一個 Federation Token。

# aws sts get-federation-token --name "Rilakkuma" --policy '{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Action": "*", "Resource": "*"}]}'

參數的 name 可以隨意填寫,不需要真的存在。

Policy 的部分我們直接給 All ,來避免拿不到任何權限,但這也不代表我們可以拿到 Root ,AWS 會進行權限交集運算,計算最終可以拿到的權限。


來源: AWS Policies Evaluation Logic

從回應中我們可以得到 STS Token 三件組 AccessKeyId, SecretAccessKey, SessionToken

向 AWS Signin Federation API 送出請求,取得 Signin Token

在拿到 STS Token 三件組後,我們就可以向 AWS Signin Federation API (https://signin.aws.amazon.com/federation) 提出請求

請求結構如下

{
    "Action": "getSigninToken",
    "Session": {
       "sessionId": AccessKeyId,
       "sessionKey": SecretAccessKey,
       "sessionToken": SessionToken
   }
}

使用 HTTP Get 方式送出請求

curl "https://signin.aws.amazon.com/federation?Action=getSigninToken&Session=%7B%22sessionId%22:%22[AccessKeyId]%22,%22sessionKey%22:%22[SecretAccessKey]%22,%22sessionToken%22:%22[SessionToken]%22%7D"

記得要 URL Encode

從回應中取得 SigninToken

產生登入網址

取得 SigninToken 後,我們就可以產生登入網址

請求結構如下

{
    "Action": "login",
    "Issuer": "Keniver",
    "Destination": "https://console.aws.amazon.com/console/home",
    "SigninToken": SigninToken
}

將請求結構進行 URL Encode 後直接做為參數傳入 https://signin.aws.amazon.com/federation

https://signin.aws.amazon.com/federation?Action=login&Issuer=Keniver&Destination=https%3A%2F%2Fconsole%2Eaws%2Eamazon%2Ecom%2Fconsole%2Fhome&SigninToken=[SigninToken]

登入 Web Console

最後,我們訪問上面做出來的網址,就可以成功登入 AWS 的管理主控台 (Web Console)

Python Code

偵測

這類型的登入行為,透過 AWS CloudTrail 是很容易可以發現的。

我們可以從 ConsoleLogin 事件下手

在事件的細節中,可以觀察到聯合登入的使用者名稱(可能是假的),以及這個 Token 簽出的使用者

或者可以考慮用更前期的事件 GetFederationToken 去做偵測

後記

雖然有 API Key 就可以直接操作 API ,但對於雲端不太熟悉的同仁來說,直接用 Web GUI 會比較輕鬆。

請各位好好保護 AWS API Key,非自動化的帳號不要沒事產生 API Key。

避免 AWS GuardDuty 偵測到 PenTest Finding

前言

如果我們使用滲透用 Liunx (Kali, Parrot, Pentoo) 去對 AWS 做滲透測試,很容易會觸發 GuardDuty 的 PenTest Finding,導致提早被抓包。

0x00 GuardDuty

Amazon GuardDuty 是一種威脅偵測服務,可持續監控您的 AWS 帳戶和工作負載是否有惡意活動,並提供詳細的安全問題清單以了解及進行修復。 – AWS

簡單來說呢,就是一個會智慧偵測威脅的服務,協助管理者發現攻擊行為。

0x01 PenTest Finding

這是 GuardDuty 偵測到的一種發現,主要是針對 IAM 這個服務去進行偵測,GuardDuty 會去偵測有沒有 IAM 相關呼叫是透過 Kali/Parrot 之類的滲透 Linux 發出請求的。

0x02 繞過 PenTest Finding

根據手冊 GuardDuty Finding Types IAM 的說法,這個發現的資料來源是 CloudTrail ,這就意味著是從 API 的呼叫紀錄去進行分析。

有了這樣的線索,我們就可以推測應該是透過 HTTP Header: User-Agent 關鍵字進行偵測,如此一來我們只要追蹤關鍵字的產生方法,就可以避開這個發現了。

從 botocore 的原始碼 中可以觀察到 platform.release() 會洩漏我們的發行版本

如果使用的 AWS ClI,那我們就必須直接 Patch 這行,如果是自行呼叫 botocore 是可以自訂 User-Agent,但為了方便我個人還是把他 Patch 掉,避免哪天被其他工具出賣。

如何在 AWS EC2 建立 Windows Server 2016 主機

最近系統測試環境需要使用 Windows Server 2016, 但手邊沒有多餘的測試主機, 想到平常工作都是使用 Linux, 所以 Amazon Web Service(AWS)上的主機也都是以 Linux 系統為主, 那就在 AWS EC2 上開一台 Windows 2016 玩玩看好了, 實際使用後才發現流程上有點差異, 決定做個筆記紀錄一下

Step 1. 建立 Windows EC2

創建 Windows EC2 的方法就跟建立 Linux EC2 的方法大致相同, 只要選擇 Windows 的 AMI 即可(這邊選擇 Windows Server 2016)

後續步驟跟平常建立 EC2相同, 這邊就不再贅述

Step 2. 選擇憑證

在 EC2 建立精靈的最後一步會要求選擇憑證, 請務必選擇憑證, 這憑證是用來解開密碼用的, 很多人在這個步驟想說 Windows 不支援 PEM 登入就不選擇, 導致最後無法解開登入資訊

Setp 3. 取得登入密碼

在主機建立完成後, 可以在主機上按下右鍵選擇 Get Windows Password

若主機上尚未準備完成會顯示如下訊息, 過幾分鐘後重試就可以了(主機建立後四分鐘通常就可以正常取得密碼)

當系統準備完成時, 系統會要求我們上傳自己的 PEM(建立EC2時選的那張憑證)

上傳PEM後選擇 Decrypt Password

畫面上就會顯示登入資訊

Setp 3. 取得連線資訊

在主機上按下右鍵選擇 Connect

點選 Download Remote Desktop File, 下載 RDP 資訊檔

接著只要打開下載的 RDP 檔就可以建立遠端連線了!