Jak wykryć aktywność roota na koncie AWS

Jak wykryć aktywność roota na koncie AWS

Zakładając nowe konto w AWS musimy podać unikalny adres e-mail. Z tym adresem powiązany jest użytkownik typu root, który jest sterem i okrętem. Może w ramach konta zrobić wszystko. I między innymi dlatego nie powinniśmy tego konta używać. Jako odpowiedzialni użytkownicy AWS chcielibyśmy na pewno wiedzieć jeżeli root zacznie działać. Więc rodzi się pytanie, jak wykryć aktywność roota na koncie AWS?

CloudTrail

Jak zapewne wiecie, każda aktywność na naszym koncie zapisywana jest w usłudze CloudTrail. Możemy te logi przeglądać, możemy zasubskrybować się pod konkretne eventy. Ale w tym przypadku łatwiej będzie utworzyć metrykę w usłudze CloudWatch. Tu musimy jednak połączyć nasz CloudTrail z usługą CloudWatch.

W tym momencie mamy już cały log zdarzeń w usłudze CloudWatch i możemy dodać zasoby, które będą informowały nas o konkretnym zdarzeniu.

Metryka CloudWatch

Pierwszą z nich będzie metryka CloudWatch, która „wykryje” czynności wykonywane przez kogoś, kto korzysta z konta root.

RootActivityMetricFilter:
  Type: AWS::Logs::MetricFilter
  Properties:
    FilterPattern: '{ $.userIdentity.type = "Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != "AwsServiceEvent" }'
    LogGroupName: 
      Ref: LogGroupName
    MetricTransformations:
      - MetricValue:  '1'
        MetricNamespace:  CloudTrailMetrics
        MetricName:  RootActivityMetric

Co tu się dzieje? Metryka wyszukuje nam w logach wszystkie zdarzenia, które spełniają warunek { $.userIdentity.type = "Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != "AwsServiceEvent" } Jeżeli taka sytuacja ma miejsce, to zwiększa metrykę RootActivityMetric o jeden.

Alarm

Mamy już metrykę, trzeba teraz dodać alarm, który zostanie wywołany w przypadku gdy metryka będzie miała wartość równą lub większą niż jeden.

RootActivityMetricAlarm:
  Type: AWS::CloudWatch::Alarm
  Properties:
    MetricName: RootActivityMetric
    Namespace: CloudTrailMetrics
    ComparisonOperator: GreaterThanOrEqualToThreshold
    EvaluationPeriods: 1
    Period: 300
    Statistic: Sum
    Threshold: 1
    AlarmActions: 
      - Ref: CloudWatchAlarmsTopic
    AlarmDescription: Alarms when an API call is made by root.
    AlarmName: CloudTrailRootActivity
Jak widzicie, w momencie gdy na przestrzeni 5 minut wartość metryki RootActivityMetric wyniesie jeden lub więcej, wywołany zostanie alarm, który spowoduje, że topic SNS wyśle powiadomienia do sybskrybentów.

Powiadomienie

Jeżeli uważnie popatrzyłeś na definicję alarmu to zobaczyłeś na pewno, że akcja przypisana do alarmu to referencja do topica w usłudze SNS. Może nie wynika to bezpośrednio z kodu, ale wskazuje na to nazwa akcji. Oto definicja topica:

CloudWatchAlarmsTopic:
  Type: AWS::SNS::Topic
  Properties:
    DisplayName: !Sub '${AWS::StackName}-RootActivity-Topic'
    TopicName: !Sub '${AWS::StackName}-RootActivity-Topic'

i polisy dla niego:
CloudWatchAlarmsTopicPolicy:
  Type: AWS::SNS::TopicPolicy
  Properties:
    Topics:
      - Ref: CloudWatchAlarmsTopic
    PolicyDocument:
      Version: '2012-10-17'
      Statement:
      - Effect: Allow
        Principal: 
          Service: cloudwatch.amazonaws.com
        Action: sns:Publish
        Resource: 
          Ref: CloudWatchAlarmsTopic
Jeżeli już dbamy o bezpieczeństwo naszego konta AWS, to wypada nasz topic SNS zaszyfrować. Potrzebny będzie do tego klucz szyfrujący:
SNSKey:
  Type: AWS::KMS::Key
  Properties: 
    Description: 'The key used for rott activities SNS topic encryption'
    Enabled: true
    EnableKeyRotation: true
    KeyPolicy: 
      Version: '2012-10-17'
      Statement:
      - Sid: Enable IAM User Permissions
        Effect: Allow
        Principal:
          AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root'
        Action: kms:*
        Resource: '*'
      - Sid: Statement for CloudWatch
        Effect: Allow
        Principal:
          Service: cloudwatch.amazonaws.com
        Action: 
        - kms:Decrypt
        - kms:GenerateDataKey
        Resource: '*'
    KeySpec: SYMMETRIC_DEFAULT
    KeyUsage: ENCRYPT_DECRYPT
    PendingWindowInDays: 7

I na koniec jako sybskrybenta podepniemy adres email, na który będą przesyłane powiadomienia o aktywności roota:

CloudWatchAlarmsSubscription:
  Type: AWS::SNS::Subscription
  Properties:
    Endpoint:
       Ref: Email
    Protocol: 'email'
    TopicArn:
      Ref: CloudWatchAlarmsTopic

Sprawdzamy

Template CloudFormation, który pozwoli utworzyć wszystkie zasoby możecie pobrać tu.

Po utworzeniu stacka dostępny będzie między innymi alarm

który powinien być w stanie Insufficient data. Jest tak, gdyż żadna aktywność roota nie miała miejsca. Mam nadzieję, że nie testujesz tego wykorzystując konto roota. 🙂

Jeżeli jednak wykonamy jakieś czynności jako root, to po pewnej chwili zmieni się status

i powinniśmy dostać powiadomienie mailem o tym, że na naszym koncie grasuje root.

Podsumowanie

Zarządzanie zasobami to nie tylko dbanie o to, żeby wszystko działało poprawnie i szybko, a jednocześnie jak najtaniej. To także, a może przede wszystkim dbanie o bezpieczeństwo naszych zasobów.

AWS dostarcza nam sporo narzędzi, które mogą nas w tym wspomagać. Korzystajmy z nich. Chmura ma tą zaletę, że wiele z czynności możemy zautomatyzować.

Zobaczyliście jak można wykorzystać dostępne usługi, żeby automatycznie dostać powiadomienie o sytuacji, która nie powinna mieć miejsca. Na co dzień pracuję z kilkoma dużymi instytucjami, gdzie naprawdę takich rozwiązań jest bardzo dużo. Może to paranoja, ale zawsze staram się:

  1. Zapobiegać – np. poprzez odpowiednie polityki uprawnień
  2. Powiadamiać – gdy już coś się złego wydarzy
  3. Reagować – np. przez automatyczne zmiany ustawień zasobów

Teoretycznie punkt pierwszy powinien wystarczyć. Ale… Licho nie śpi. 🙂

Comments are closed.