One of the great things about AWS is they’ve really thought about security. In fact, they’ve created many services specifically designed and dedicated to security. For example, the Key Management Service (KMS) tightly integrates with other services to provide almost seamless encryption. It just so happens that integration includes CloudTrail.

It’s a little bit more effort to get CloudTrail encryption bootstrapped but it’s well worth it. Once enabled, log files will be encrypted but everything else will look normal; configuration will remain almost identical and log files will continue to be delivered to the correct location, in the expected structure.

First, let’s setup a policy file for a new key, ensuring it only allows encryption by CloudTrail and nothing else — we don’t want those pesky administrators using it for decryption. Note the references to [account-id] which have to be replaced as appropriate.

AWS policies default to deny rules so this policy also denies its own deletion. While not useful, its a painful kick to the nether regions requiring manual Support intervention.

Create a key, attaching the policy:

aws kms create-key --bypass-policy-lockout-safety-check --policy [file:///my-policy.json]

The “bypass-policy-lockout-safety-check” flag allows you the make the key’s policy immutable after creation, making logging just an exercise in lighting money on fire with disk consumption. You can’t say Amazon didn’t warn you!

Finally, put it all together by encrypting the target trail with the immutable encryption-only key:

aws cloudtrail update-trail --name [my-trail] --kms-key-id [my-key]

While that’s by far the slickest encryption tactic, there are others. You can start encrypting a trail, disable the key and schedule it for deletion. If you aren’t going to disable the key, you can remove the disable and delete actions from the policy to make the key undeletable (it’s a word, trust me).

aws kms disable-key --key-id [my-key]

aws kms schedule-key-deletion --key-id [my-key] --pending-window-in-days 7

The deletion won’t happen for 7 days but the trail won’t be written regardless. Manually inspecting the trail in the AWS web interface won’t show any signs of failure either, unless the vicim is familiar enough with the interface to notice a missing ‘last delivered’ section. However, checking the trail status via cli will show “LatestDeliveryError” as “KMS.DisabledException”.

aws cloudtrail get-trail-status --name [my-trail]

Finally, if you really wanted to be mean, you could set the encryption key to be one hosted in another account you control. The only minor change required to the base tactic is to ensure the “GenerateDataKey*” action includes the source account-id in the condition section.

If you wanted to be even meaner and found out your victim knew you did this mean thing, you could send them an email suggesting they make a one time tax-free donation to get a copy of the key. That’s a joke — ransomware is pure evil and needs to die in a fire but doing it through AWS does add some dramatic effect, no?