` you copied earlier (from the principal ID you gathered in the GuardDuty finding).
181 |
182 | * Now copy the Amazon Resource Name (ARN) from the **Resource ID** for the first match. The ARN will look something like this `arn:aws:ec2:us-west-2:166199753942:instance/i-0efc5172a5d7ecc6b`
183 |
184 | * Add one more filter by clicking the **Add filter** box again and selecting **Resource ID** and paste in the ARN from the previous step
185 |
186 | !!! question "What GuardDuty findings do you see related to this instance ID?"
187 |
188 |
192 |
193 | One of the findings should indicate that the EC2 instance is communicating with an IP address on a threat list (**disallowed IP**) which adds further evidence to the conclusion that the instance has been compromised. The other finding should indicate that a system at a particular IP address is performing an SSH brute force attack against your instance. You now need to investigate if the SSH brute force attack was successful and if that is what allowed the attacker to gain access to the instance.
194 |
195 | **Determine if ssh password authentication is enabled on the EC2 instance (AWS Security Hub)**
196 |
197 | Automated responses to threats can do many things. For example, you could have an trigger that helps gather information about the threat that could then be used in the investigation by the security team. With that option in mind, we have a CloudWatch event rule in place that will trigger an Amazon Inspector scan of an EC2 instance when GuardDuty detects a particular attack. We will use AWS Security Hub to view the findings from Inspector. We want to determine if the SSH configuration adheres to best practices.
198 |
199 | 1. Go to the AWS Security Hub console.
200 | 2. The link should take you to the **Findings** section (if not, click on **Findings** in the navigation on the left).
201 | * Add a filter by clicking in the **Add filter** box and scrolling down to **Product Name**, and paste in the word `Inspector`.
202 | * Use your browser's find function **Control-F** and paste in `password authentication over SSH`
203 | * The finding may not be on the first page of findings, use the `>` to move to the next page.
204 |
205 |
208 |
209 | Click on the finding regarding SSH and password authentication for the instance that experienced the SSH brute force attack and review.
210 |
211 |
219 |
220 | !!! info "If you do not see any findings after a while, there may have been an issue with your Inspector agent. Go to the Inspector console, click on **Assessment Templates**, check the template that starts with **threat-detection-wksp**, and click **Run**. Please allow **15 minutes** for the scan to complete. You can also look in **Assessment runs** and check the **status**. Feel free to continue through this module and check the results later on."
221 |
222 | After review you should see that password authentication over SSH is configured on the instance. In addition, if you examine some of the other Inspector findings you will see that there are no password complexity restrictions. This means the instance is more susceptible to an SSH brute force attack.
223 |
224 |
230 |
231 | **Determine if the attacker was able to login to the EC2 instance (CloudWatch logs)**
232 |
233 | Now that we know that the instance was more susceptible to an SSH brute force attack, let’s look at the CloudWatch logs and create a metric to see if there were any successful SSH logins (to finally answer the question of whether the SSH brute force attack was successful.) Your corporate policy is to send security certain logs from EC2 instances to CloudWatch.
234 |
235 | 1. Go to CloudWatch logs.
236 | 2. Click on the log group **/threat-detection-wksp/var/log/secure**
237 | 3. If you have multiple log streams, filter using the Instance ID you copied earlier and click on the stream.
238 | 4. Within the **Filter Events** text box put the following Filter Pattern: **`[Mon, day, timestamp, ip, id, msg1= Invalid, msg2 = user, ...]`**
239 |
240 | !!! question "Do you see any failed (invalid user) attempts to log into the instance? Would that be consistent with an SSH brute force attack?"
241 |
242 | 5. Now replace the Filter with one for successful attempts: **`[Mon, day, timestamp, ip, id, msg1= Accepted, msg2 = password, ...]`**
243 |
244 | !!! question "Do you see any successful attempts to log into the instance? Which linux user was compromised?"
245 |
246 | ### Respond
247 |
248 | **Modify the EC2 security group (EC2)**
249 |
250 | The active session from the attacker was automatically stopped by an update to the NACL on the subnet where the instance resides. This was done by a CloudWatch event rule trigger that is invoked based on certain GuardDuty findings. You've decided that all administration on EC2 Instances will be done through AWS Systems Manager so you no longer need administrative ports open so a good next step would be to modify the security group associated with the EC2 instance to prevent the attacker or anyone else from connecting.
251 |
252 | 1. Go to the Amazon EC2 Console.
253 |
254 | 2. Find the running instances with the name **threat-detection-wksp: Compromised Instance**.
255 |
256 | 3. Under the **Description** tab, click on the Security Group for the compromised instance.
257 |
258 | 4. View the rules under the **Inbound** tab.
259 |
260 | 5. Click **Edit** and delete the inbound SSH rule.
261 |
262 | !!! info "The SSM Agent was installed on your EC2 Instance during the initial configuration."
263 |
264 | 6. Click **Save**
265 |
266 |
267 | ## Part 3 - Compromised S3 bucket
268 |
269 | ### Detect and investigate
270 |
271 | Now that we know the SSH brute force attack was successful and we disabled the IAM credentials that were stolen, we need to determine if anything else occurred. One step we could take here is to examine the IAM policy attached the IAM role that generated the temp credentials. We notice in the policy that there are permissions relating to the Amazon S3 service so that is something to keep in mind as you continue the investigation.
272 |
273 | Here is a truncated view of the policy from the IAM role attached to the compromised EC2 instance:
274 |
275 | ```json
276 | {
277 | "Version": "2012-10-17",
278 | "Statement": [
279 | {
280 | "Action": "s3:PutObject",
281 | "Resource": "arn:aws:s3:::threat-detection-wksp-ACCOUNT_ID-us-west-2-gd-threatlist/*",
282 | "Effect": "Allow"
283 | },
284 | {
285 | "Action": [
286 | "s3:*"
287 | ],
288 | "Resource": "arn:aws:s3:::threat-detection-wksp-ACCOUNT_ID-us-west-2-data/*",
289 | "Effect": "Allow"
290 | },
291 | {
292 | "Action": [
293 | "s3:*"
294 | ],
295 | "Resource": "arn:aws:s3:::threat-detection-wksp-ACCOUNT_ID-us-west-2-data",
296 | "Effect": "Allow"
297 | }
298 | ]
299 | }
300 | ```
301 |
302 | **Investigate any S3 related findings (AWS Security Hub)**
303 |
304 | There are many ways to approach this next step. We are going to start with a Security Hub insight that may be helpful in situations like this. This is not the only way you could approach this but it can definitely save time initially as you investigate the full repercussions of an attack.
305 |
306 | 1. Go to AWS Security Hub in the AWS Management Console.
307 | 2. The link should take you to the **Insights** section (if not, click on ** Insights** in the navigation on the left).
308 | 3. Click in the **Filter insights** box and type **`Top S3`** which will display the built in Insight "Top S3 buckets by counts of findings." Click on that Insight.
309 | 4. There should be one that with **threat-detection-wksp-** and ends in **-data**. Click on that.
310 | 5. Evaluate the Macie findings shown under the Insight.
311 |
312 | This **Security Hub** Insight is one way of determining what an attacker may have done. It is not going to help in every situation though.
313 |
314 | **Check if sensitive data was involved (Macie)**
315 |
316 | At this point you know how the attacker was able to get into your systems and a general idea of what they did. In the previous step you determined that the S3 bucket that starts with **threat-detection-wksp-** and ends in **-data** has an ACL that grants global read rights. We will now check if there is any sensitive and business-critical data in the bucket and take a closer at the Macie Alerts.
317 |
318 | 1. Go to the Amazon Macie in the AWS Management console.
319 |
320 | 2. Click **Dashboard** on the left navigation. You should see the following data classifications:
321 | 
322 |
323 | !!! info "You can slide the risk slider to filter data classifications based on risk levels."
324 |
325 | 3. Above the risk slider, click the icon for **S3 public objects and buckets**. The icon will be in the shape of a globe but you can also hover over the icons to find the right one.
326 | 
327 |
328 | 4. Click the magnifying glass to the left of the bucket name listed.
329 | 5. Check if any of the data in the bucket is considered a high risk. Look for the **Object PII priority** field and **Object risk level** field.
330 |
331 | 6. Verify if any of the data is unencrypted. Look for the **Object encryption** field.
332 |
333 | !!! question "Does a portion of the blue bar indicate that encryption is set to none?."
334 |
335 | ### Respond
336 |
337 | **Fix the permissions and encryption on the bucket (S3)**
338 |
339 | In the previous step we determined that the S3 bucket that starts with **threat-detection-wksp-** and ends in **-data** has sensitive data and some of that data is unencrypted. We also know that the bucket grants global read rights. We need to manually fix these issues.
340 |
341 | 1. First we will fix the permissions. Go to Amazon S3 in the AWS Management Console.
342 | 3. Find the bucket that starts with **threat-detection-wksp-** and ends in **-data**
343 | 4. Click on the **Permissions** tab then click on **ACL Control List**
344 | 5. Under **Public access** click on the radio button next to **Everyone**. Uncheck **List objects** then click **Save**.
345 | 7. Now we need to fix the encryption. In the same bucket, click on the **Properties** tab then click on **Default encryption**
346 | 8. Set the encryption to AWS-KMS. Select the **aws/s3** key. Finally click **Save**.
347 |
348 | !!! info "What impact does enabling default encryption have on existing objects in the bucket?"
349 |
350 | Congratulations! You have successfully remediated the incident and further hardened your environment. This is obviously a simulation and we can not cover every aspect of the response function in the short time allotted but hopefully this gave you an idea of the capabilities available on AWS to detect, investigate and respond to threats and attacks.
351 |
352 | ---
353 |
354 | Here is a diagram of the attack you just investigated. Numbers 1 & 2 show the SSH brute force attack and successful SSH login. Number 3 shows the S3 bucket changes the attacker made. Number 4 shows the API calls the attacker made with the IAM temporary credentials stolen from the compromised EC2 instance.
355 | 
356 |
357 | !!! warning "If you are going through this workshop in a classroom setting then the instructor should start the module 4 presentation soon."
358 |
359 |
--------------------------------------------------------------------------------
/docs/04-review-and-discussion.md:
--------------------------------------------------------------------------------
1 | # Module 4: Review and Discussion
2 |
3 | In the last module we will have a short discussion and discuss exactly what occurred. We will also go over a number of questions to test your knowledge.
4 |
5 |
7 |
8 | **Agenda**
9 |
10 | 1. Review & Discussion – 10 min
11 | 2. Questions – 10 min
12 | 3. Cleanup – 5 min
13 |
14 | ## Architecture Overview
15 | Below is a diagram of the overall workshop setup:
16 | 
17 |
18 | ## What is Really Going On?
19 |
20 | In **Module 1** of the workshop you setup the initial components of your infrastructure including detective controls such as GuardDuty, Inspector, SecurityHub as well as simple notification and remediation pipeline. Some of the steps required manual configuration but you also ran a CloudFormation template which setup some of the components.
21 |
22 | In **Module 2** you launched a second CloudFormation template that initiated the attack simulated by this workshop. The CloudFormation template created two EC2 instances. One instance (named **Malicious Host**) had an EIP attached to it that was added to your GuardDuty custom threat list. Although the **Malicious Host** is in the same VPC as the other instance, for the sake of the scenario (and to prevent the need to submit a penetration testing request) we acted as if it is on the Internet and represented the attack's computer. The other instance (named **Compromised Instance**) was your web server and it was taken over by the **Malicious Host**.
23 |
24 | In **Module 3** you investigated the attack, remediated the damage, and setup some automated remediations for future attacks.
25 |
26 | **Here is what occurred in the attack:**
27 |
28 | 1. There are two instances created by the Module 2 CloudFormation template. They are in the same VPC but different subnets. The **Malicious Host** represents the attacker which we pretend is on the Internet. The Elastic IP on the **Malicious Host** is in a custom threat list in GuardDuty. The other instance named **Compromised Instance** represents the web server that was lifted and shifted into AWS.
29 |
30 | 2. Although company policy is that only key-based authentication should be enabled for SSH, at some point password authentication for SSH was enabled on the **Compromised Instance**. This misconfiguration is identified in the Inspector scan that is triggered from the GuardDuty finding.
31 |
32 | 3. The **Malicious Host** performed a brute force SSH password attack against the **Compromised Instance**. The brute force attack is designed to be successful.
33 |
34 | !!! info "**GuardDuty Finding**: UnauthorizedAccess:EC2/SSHBruteForce"
35 |
36 | 4. The SSH brute force attack was successful and the attacker was able to log in to the **Compromised Instance**.
37 |
38 | !!! info "Successful login is confirmed in CloudWatch Logs (/threat-detection-wksp/var/log/secure)."
39 |
40 | 5. The EC2 Instance that is created in the **Module** 2 CloudFormation template disabled default encryption on the **Data** bucket. In addition the CloudFormation template made the **Data** bucket public. This is used for the Macie part of the investigation in Module 3. We pretend that the attacker made the bucket public and removed the default encryption from the bucket.
41 |
42 | !!! info "**Macie Alert**: S3 Bucket IAM policy grants global read rights."
43 |
44 | 6. The Compromised Instance also has a cron job that continuously pings the Malicious Host to generate a GuardDuty finding based off the custom threat list.
45 |
46 | !!! info "**GuardDuty Finding**: UnauthorizedAccess:EC2/MaliciousIPCaller.Custom"
47 |
48 | 7. The API Calls that generated the API findings come from the **Malicious Host**. The calls use the temp creds from the IAM role for EC2 running on the **Malicious Host**. The GuardDuty findings are generated because the EIP attached to the **Malicious Host** is in a custom threat list.
49 |
50 | !!! info "**GuardDuty Finding**: Recon:IAMUser/MaliciousIPCaller.Custom or **GuardDuty Finding**: UnauthorizedAccess:IAMUser/MaliciousIPCaller.Custom"
51 |
52 | 8. A number of CloudWatch Events Rules are evoked by the GuardDuty findings and then these trigger various services.
53 | 1. **CloudWatch Event Rule**: The generic GuardDuty finding invokes a CloudWatch Event rule which triggers SNS to send an email.
54 | 2. **CloudWatch Event Rule**: The generic Macie alert invokes a CloudWatch Event rule which triggers SNS to send an email.
55 | 3. **CloudWatch Event Rule**: The SSH brute force attack finding invokes a CloudWatch Event rule which triggers a Lambda function to block the attacker IP address of the attacker via a NACL as well as a Lambda function that runs an Inspector scan on the EC2 instance.
56 | 4. **CloudWatch Event Rule**: The Unauthorized Access Custom MaliciousIP finding invokes a CloudWatch Event rule which triggers a Lambda function to block the IP address of the attacker via a NACL.
57 |
58 | ## Cleanup
59 | In order to prevent charges to your account we recommend cleaning up the infrastructure that was created. If you plan to keep things running so you can examine the workshop a bit more please remember to do the cleanup when you are done. It is very easy to leave things running in an AWS account, forgot about it, and then accrue charges.
60 |
61 | !!! info "If you are using this in an instructor led session, with the AWS Event Engine you do not need to run the cleanup steps"
62 |
63 | !!! info "If you are running this in your own account. You will need to manually delete some resources before you delete the CloudFormation stacks so please do the following steps in order."
64 |
65 | 1. Delete the Inspector objects created for the workshop.
66 | * Go to the Amazon Inspector console.
67 | * Click on **Assessment targets** in the navigation pane on the left.
68 | * Delete all that start with **threat-detection-wksp**.
69 |
70 | 2. Delete the IAM Role for the compromised EC2 instance and the Service-Linked Role for Inspector (if you didn't already have this Role created).
71 | * Go to AWS IAM console.
72 | * Click on **Roles**
73 | * Search for the role named **threat-detection-wksp-compromised-ec2**.
74 | * Click the check box next to it and click **Delete**.
75 | * Repeat the steps above for the role named **AWSServiceRoleForAmazonInspector**.
76 |
77 | 3. Delete all three S3 buckets created by the Module 1 CloudFormation template (the buckets that start with **threat-detection-wksp** and end with **-data**, **-threatlist** and **-logs**)
78 | * Go to Amazon S3 console.
79 | * Click on the appropiate bucket.
80 | * Click **Delete Bucket**.
81 | * Copy and paste the name of the bucket (this is an extra verification that you actually want to delete the bucket).
82 | * Repeat the steps above for all three buckets.
83 |
84 | 4. Delete Module 1 and 2 CloudFormation stacks (**ThreatDetectionWksp-Env-Setup** and **ThreatDetectionWksp-Attacks**).
85 | * Go to the AWS CloudFormation console.
86 | * Select the appropiate stack.
87 | * Select **Action**.
88 | * Click **Delete Stack**.
89 | * Repeat the steps above for each stack.
90 |
91 | !!! info "You do not need to wait for the first stack to delete before you delete the second one."
92 |
93 | 5. Delete the GuardDuty custom threat list and disable GuardDuty (if you didn't already have it configured before the workshop)
94 | * Go to the Amazon GuardDuty console.
95 | * Click on **Lists** on the left navigation.
96 | * Click the **X** next to the threat list that starts with **Custom-Threat-List**.
97 | * Click **Settings** in the navigation pane on the left navigation.
98 | * Click the check box next to **Disable**.
99 | * Click **Save settings** and then click **Disable** in the pop-up box.
100 |
101 | 6. Disable AWS Security Hub
102 | * Go to the AWS Security Hub console.
103 | * Click on **Settings** on the left navigation.
104 | * Click the **General** on the top navigation.
105 | * Click **Disable AWS Security Hub**.
106 |
107 | 6. Delete the manual CloudWatch Event Rule you created and the CloudWatch Logs that were generated.
108 | * Go to the AWS CloudWatch console.
109 | * Click on **Rules** in the navigation pane on the left.
110 | * Click the radio button next **threat-detection-wksp-guardduty-finding-maliciousip**.
111 | * Select **Action** and click **Delete**.
112 | * Click on **Logs** in the navigation pane on the left.
113 | * Click the radio button next to **/aws/lambda/threat-detection-wksp-inspector-role-creation**.
114 | * Select **Action** and click **Delete log group** and then click **Yes, Delete** in the pop-up box.
115 | * Repeat for:
116 | * **/aws/lambda/threat-detection-wksp-remediation-inspector**
117 | * **/aws/lambda/threat-detection-wksp-remediation-nacl**
118 | * **/threat-detection-wksp/var/log/secure**
119 |
120 | 7. Delete the SNS subscription that was created when you subscribed to SNS Topic.
121 | * Go to the AWS SNS console.
122 | * Click on **Subscriptions** on the left navigation.
123 | * Select the check box next to the subscription that shows your e-mail as the Endpoint and has **threat-detection-wksp** in the **Subscription ARN**.
124 | * Select **Action** and then click **Delete subscriptions**
125 |
126 | 8. Disable Macie (if you didn't already have Macie enabled before the workshop).
127 | * Go the Amazon Macie console.
128 | * In the upper right-hand corner select the down arrow to the left of the Region and select **Macie General Settings**.
129 | * Check the two boxes and click **Disable Amazon Macie**
130 |
131 | ## Finished!
132 |
133 | Congratulations on completing this workshop! This is the workshop's permanent home, so feel free to revisit as often as you'd like.
134 |
135 |
136 |
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | scaling-threat-detection.awssecworkshops.com
--------------------------------------------------------------------------------
/docs/assets/images/aws-favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/assets/images/aws-favicon.ico
--------------------------------------------------------------------------------
/docs/assets/images/aws_smile_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/assets/images/aws_smile_logo.png
--------------------------------------------------------------------------------
/docs/assets/images/second-nav-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/assets/images/second-nav-blue.png
--------------------------------------------------------------------------------
/docs/contribute.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
4 | documentation, we greatly value feedback and contributions from our community.
5 |
6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
7 | information to effectively respond to your bug report or contribution.
8 |
9 |
10 | ## Reporting Bugs/Feature Requests
11 |
12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features.
13 |
14 | When filing an issue, please check [existing open](https://github.com/aws-samples/aws-scaling-threat-detection-workshop/issues), or [recently closed](https://github.com/aws-samples/aws-scaling-threat-detection-workshop/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already
15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
16 |
17 | * A reproducible test case or series of steps
18 | * The version of our code being used
19 | * Any modifications you've made relevant to the bug
20 | * Anything unusual about your environment or deployment
21 |
22 |
23 | ## Contributing via Pull Requests
24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
25 |
26 | 1. You are working against the latest source on the *master* branch.
27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
29 |
30 | To send us a pull request, please:
31 |
32 | 1. Fork the repository.
33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
34 | 3. Ensure local tests pass.
35 | 4. Commit to your fork using clear commit messages.
36 | 5. Send us a pull request, answering any default questions in the pull request interface.
37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
38 |
39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
41 |
42 |
43 | ## Finding contributions to work on
44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws-samples/aws-scaling-threat-detection-workshop/labels/help%20wanted) issues is a great place to start.
45 |
46 |
47 | ## Code of Conduct
48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
50 | opensource-codeofconduct@amazon.com with any additional questions or comments.
51 |
52 |
53 | ## Security issue notifications
54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
55 |
56 |
57 | ## Licensing
58 |
59 | See the [LICENSE](https://github.com/aws-samples/aws-scaling-threat-detection-workshop/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
60 |
61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.
62 |
--------------------------------------------------------------------------------
/docs/images/01-current-roles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/01-current-roles.png
--------------------------------------------------------------------------------
/docs/images/01-diagram-module1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/01-diagram-module1.png
--------------------------------------------------------------------------------
/docs/images/01-diagram-modulev2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/01-diagram-modulev2.png
--------------------------------------------------------------------------------
/docs/images/01-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/01-diagram.png
--------------------------------------------------------------------------------
/docs/images/01-inspector-role-error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/01-inspector-role-error.png
--------------------------------------------------------------------------------
/docs/images/01-macie-bucket-selection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/01-macie-bucket-selection.png
--------------------------------------------------------------------------------
/docs/images/01-macie-ct-error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/01-macie-ct-error.png
--------------------------------------------------------------------------------
/docs/images/01-specify-details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/01-specify-details.png
--------------------------------------------------------------------------------
/docs/images/01-stack-complete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/01-stack-complete.png
--------------------------------------------------------------------------------
/docs/images/02-diagram-module2-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/02-diagram-module2-3.png
--------------------------------------------------------------------------------
/docs/images/02-diagram-module2-3v2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/02-diagram-module2-3v2.png
--------------------------------------------------------------------------------
/docs/images/02-stack-complete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/02-stack-complete.png
--------------------------------------------------------------------------------
/docs/images/03-config-keypair.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/03-config-keypair.png
--------------------------------------------------------------------------------
/docs/images/03-config-message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/03-config-message.png
--------------------------------------------------------------------------------
/docs/images/03-diagram-attack-v2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/03-diagram-attack-v2.png
--------------------------------------------------------------------------------
/docs/images/03-diagram-attack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/03-diagram-attack.png
--------------------------------------------------------------------------------
/docs/images/03-gd-findings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/03-gd-findings.png
--------------------------------------------------------------------------------
/docs/images/03-high-severity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/03-high-severity.png
--------------------------------------------------------------------------------
/docs/images/03-inspector-findings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/03-inspector-findings.png
--------------------------------------------------------------------------------
/docs/images/03-low-severity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/03-low-severity.png
--------------------------------------------------------------------------------
/docs/images/03-macie-data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/03-macie-data.png
--------------------------------------------------------------------------------
/docs/images/03-macie-public-objects-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/03-macie-public-objects-button.png
--------------------------------------------------------------------------------
/docs/images/04-diagram-module4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/04-diagram-module4.png
--------------------------------------------------------------------------------
/docs/images/deploy-to-aws.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/deploy-to-aws.png
--------------------------------------------------------------------------------
/docs/images/diagram-basic-arch-v2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/diagram-basic-arch-v2.png
--------------------------------------------------------------------------------
/docs/images/diagram-basic-arch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/diagram-basic-arch.png
--------------------------------------------------------------------------------
/docs/images/iam-capabilities.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/iam-capabilities.png
--------------------------------------------------------------------------------
/docs/images/launch-stack-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/images/launch-stack-button.png
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # Overview
2 |
3 | This workshop is designed to help you get familiar with AWS Security services and learn how to use them to identify and remediate threats in your environment. You'll be working with services such as Amazon GuardDuty (threat detection), Amazon Macie (discover, classify & protect data), Amazon Inspector (vulnerability & behavior analysis), AWS Security Hub (centralized security view). You will learn how to use these services to investigate threats during and after an attack, set up a notification and response pipeline, and add additional protections to improve the security posture of your environment.
4 |
5 | * **Level**: Intermediate
6 | * **Duration**: 2 - 3 hours
7 | * **CSF Functions**: Detect, Respond, Recover
8 | * **CAF Components**: Detective, Responsive
9 | * **Prerequisites**: AWS Account, Admin IAM User
10 |
11 | ## Scenario
12 |
13 | Your company is new to the cloud and has recently performed a lift-and-shift of your infrastructure for piloting purposes. You are a systems administrator and have been tasked with security monitoring within your AWS environment. As part of that maintenance you are also responsible for responding to any security event in your environment.
14 |
15 | ## Architecture
16 |
17 | For this Workshop you will have a single instance setup in the us-west-2 region. As this was a “lift-and-shift” migration for piloting, you have yet to build redundancy into your application, so you have a single public-facing web server. The web server has access to the Internet Gateway through an Elastic Network Interface. Customers access your web server through a DNS entry pointing to the Elastic Network Interface. You store static content in an S3 bucket and use the VPC S3 Endpoint Gateway for access from the web server.
18 |
19 | For this Workshop you will have a simple setup with a single instance setup in the us-west-2 region. As this was a “lift-and-shift” migration for piloting, you have yet to build redundancy into your application, so you have a single public-facing web server that is accessed through an internet gateway and retrieves static content from an S3 bucket.
20 |
21 | 
22 |
23 | ## Presentation deck
24 | [Workshop Presentation Deck](./threat-detect-workshop-presentation.pdf)
25 |
26 | ## Region
27 | Please use the **us-west-2 (Oregon)** region for this workshop.
28 |
29 | ## Modules
30 |
31 | This workshop is broken up into the four modules below:
32 |
33 | 1. [Environment Build and Configuration](./01-environment-setup.md)
34 | 2. [Attack Simulation](./02-attack-simulation.md)
35 | 3. [Detection and Remediation](./03-detection-and-remediation.md)
36 | 4. [Review and Discussion](./04-review-and-discussion.md)
37 |
--------------------------------------------------------------------------------
/docs/license.md:
--------------------------------------------------------------------------------
1 | # License
2 |
3 | **MIT License**
4 |
5 | Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this
8 | software and associated documentation files (the "Software"), to deal in the Software
9 | without restriction, including without limitation the rights to use, copy, modify,
10 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | permit persons to whom the Software is furnished to do so.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
15 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
16 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
18 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/docs/stylesheets/custom.css:
--------------------------------------------------------------------------------
1 |
2 | .md-header {
3 | background-color: #232f3e !important;
4 | border-bottom: 1px solid #1b2532 !important;
5 | }
6 |
7 | @media only screen and (max-width: 76.1875em) {
8 |
9 | html .md-nav--primary .md-nav__title--site {
10 | background-color: #232f3e !important;
11 | border-bottom: 1px solid #1b2532 !important;
12 | }
13 |
14 | .md-nav__source {
15 | background-color: #1f4e79 !important;
16 | }
17 |
18 | html .md-nav--primary .md-nav__title {
19 | background-color: #232f3e !important;
20 | border-bottom: 1px solid #1b2532 !important;
21 | color: #ffffff;
22 | }
23 |
24 | html .md-nav--primary .md-nav__title::before {
25 | color: #ffffff;
26 | }
27 |
28 | }
29 |
30 | .md-tabs__link {
31 | font-weight: bold !important;
32 | font-size: 1.5rem !important;
33 | }
34 |
35 | .md-header-nav__source {
36 | margin-left: 0;
37 | }
38 |
39 | /* Language Drop Down */
40 | .md-header-nav__lang {
41 | padding: 10px 40px 0 10px;
42 | display: inline-block;
43 | font-family: "Roboto","Helvetica Neue",Helvetica,Arial,sans-serif;
44 | width: 30px;
45 | font-size: x-large;
46 | }
47 |
48 | .md-lang-dropbtn {
49 | color: white;
50 | border: none;
51 | cursor: pointer;
52 | padding: 0px 10px;
53 | font-weight: bold;
54 | }
55 |
56 | .md-lang-dropbtn:hover, .md-lang-dropbtn:focus {
57 | opacity: 0.7;
58 | }
59 |
60 | .md-dropdown-content {
61 | display: none;
62 | width: 100%;
63 | background-color: #f1f1f1;
64 | box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
65 | z-index: 1;
66 | overflow: auto;
67 | }
68 |
69 | .md-dropdown-content a {
70 | color: black;
71 | padding: 0px 10px;
72 | text-decoration: none;
73 | display: block;
74 | line-height: 3rem;
75 | font-weight: bold;
76 | font-size: 1.3rem;
77 | }
78 |
79 | .md-dropdown-content a:hover {
80 | color: #f8991d;
81 | }
82 |
83 | .show {
84 | display:block;
85 | }
86 |
87 | /* Second Navigation */
88 |
89 | .md-tabs {
90 | background-image: url(../assets/images/second-nav-blue.png);
91 | background-color: #1f4e79 !important;
92 | padding-top: 10px;
93 | }
94 |
95 | .md-tabs__list {
96 | display:none;
97 | }
98 |
99 | .md-tabs__item {
100 | margin-right: 15px;
101 | }
102 |
103 | .md-content__icon {
104 | display: none;
105 | }
106 |
107 | .md-typeset table:not([class]) th {
108 | min-width: 15rem;
109 | background-color: #6c6c6c !important;
110 | font-size: 1.5rem;
111 | }
112 |
113 | .md-typeset table:not([class]) td {
114 | vertical-align: middle;
115 | }
116 |
117 | .table {
118 | font-size: 1.4rem;
119 | }
120 |
121 | /* Footer */
122 |
123 | .md-footer-nav {
124 | background-image: url(../assets/images/second-nav-blue.png);
125 | background-color: #1f4e79 !important;
126 | }
127 |
128 | .md-footer-meta {
129 | background-color: #232f3e !important;
130 | border-top: 1px solid #1b2532 !important;
131 | }
132 |
--------------------------------------------------------------------------------
/docs/theme/partials/header.html:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/docs/theme/partials/nav.html:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/docs/threat-detect-workshop-presentation.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awsrossw/aws-scaling-threat-detection-workshop/b439514b475504f54cbfa3cc3205c16d996336c1/docs/threat-detect-workshop-presentation.pdf
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | # Project information
2 |
3 | site_name: Scaling threat detection and response in AWS
4 | site_short_name: Scaling threat detection
5 | site_description: 'This hands-on workshop is where you will learn about a number of AWS services involved with threat detection and response as we walk through real-world threat scenarios. Learn about the threat detection capabilities of Amazon GuardDuty, Amazon Macie and AWS Security Hub and the available response options. For each hands-on scenario, we review methods to detect and respond to threats using the following services: AWS CloudTrail, Amazon VPC flow logs, Amazon CloudWatch Events, Amazon Macie, AWS Lambda, Amazon Inspector, Amazon GuardDuty and Amazon Security Hub.'
6 | site_author: 'aws-security-workshops@amazon.com'
7 | site_url: 'https://scaling-threat-detection.awssecworkshops.com/'
8 |
9 | # Repository
10 | repo_name: 'aws-samples/aws-scaling-threat-detection-workshop'
11 | repo_url: 'https://github.com/aws-samples/aws-scaling-threat-detection-workshop'
12 |
13 | # Copyright
14 | copyright: '© 2019, Amazon Web Services, Inc. or its affiliates. All rights reserved.'
15 |
16 | # Configuration
17 | theme:
18 | name: 'material'
19 | logo: 'assets/images/aws_smile_logo.png'
20 | favicon: 'assets/images/aws-favicon.ico'
21 | feature:
22 | tabs: true
23 | custom_dir: 'docs/theme'
24 |
25 | # Customization
26 | extra_css:
27 | - 'stylesheets/custom.css'
28 | extra:
29 | social:
30 | - type: 'home'
31 | link: 'https://awssecworkshops.com'
32 | - type: 'shield'
33 | link: 'https://aws.amazon.com/security/'
34 | - type: 'twitter'
35 | link: 'https://twitter.com/awssecurityinfo?lang=en'
36 | - type: 'rss'
37 | link: 'https://aws.amazon.com/blogs/security/'
38 |
39 | # Extensions
40 | markdown_extensions:
41 | - admonition
42 | - codehilite
43 | - pymdownx.details
44 |
45 | # Navigation
46 | nav:
47 | - Overview: 'index.md'
48 | - 'Module 1: Environment Build': '01-environment-setup.md'
49 | - 'Module 2: Attack Simulation': '02-attack-simulation.md'
50 | - 'Module 3: Detect & Respond': '03-detection-and-remediation.md'
51 | - 'Module 4: Discussion': '04-review-and-discussion.md'
52 | - Contributing: 'contribute.md'
53 | - License: 'license.md'
--------------------------------------------------------------------------------
/templates/01-environment-setup.yml:
--------------------------------------------------------------------------------
1 | AWSTemplateFormatVersion: '2010-09-09'
2 |
3 | Description: This AWS CloudFormation Template configures an environment with the necessary detective controls to support the Threat Detection Workshop. DO NOT run this template in a production AWS Account.
4 |
5 | Parameters:
6 |
7 | ResourceName:
8 | Type: String
9 | Default: threat-detection-wksp
10 | AllowedValues:
11 | - threat-detection-wksp
12 | Description: Prefix of Resources created for this workshop.
13 |
14 | Email:
15 | Type: String
16 | Description: Enter a valid email address for receiving alerts.
17 |
18 | Metadata:
19 | AWS::CloudFormation::Interface:
20 | ParameterGroups:
21 | -
22 | Label:
23 | default: "Resource and Notification Configuration"
24 | Parameters:
25 | - ResourceName
26 | - Email
27 |
28 | ParameterLabels:
29 | ResourceName:
30 | default: "Resource Prefix"
31 | Email:
32 | default: "Email Address"
33 |
34 |
35 | Mappings: {}
36 |
37 | Conditions: {}
38 |
39 | Resources:
40 |
41 | ### CloudTrail and Logging Bucket
42 | CloudTrail:
43 | DependsOn:
44 | - LogBucketPolicy
45 | Type: "AWS::CloudTrail::Trail"
46 | Properties:
47 | S3BucketName: !Ref LogBucket
48 | IsLogging: true
49 | EnableLogFileValidation: true
50 | IsMultiRegionTrail: false
51 | IncludeGlobalServiceEvents: true
52 | TrailName:
53 | Fn::Join:
54 | - '-'
55 | - [!Ref ResourceName, 'trail']
56 | LogBucket:
57 | Type: 'AWS::S3::Bucket'
58 | Properties:
59 | BucketEncryption:
60 | ServerSideEncryptionConfiguration:
61 | - ServerSideEncryptionByDefault:
62 | SSEAlgorithm: 'AES256'
63 | BucketName:
64 | Fn::Join:
65 | - '-'
66 | - [!Ref ResourceName, !Ref "AWS::AccountId", !Ref "AWS::Region",'logs']
67 | LogBucketPolicy:
68 | DependsOn:
69 | - LogBucket
70 | Type: "AWS::S3::BucketPolicy"
71 | Properties:
72 | Bucket: !Ref LogBucket
73 | PolicyDocument:
74 | Version: "2012-10-17"
75 | Statement:
76 | -
77 | Sid: "AWSCloudTrailAclCheck"
78 | Effect: "Allow"
79 | Principal:
80 | Service: "cloudtrail.amazonaws.com"
81 | Action: "s3:GetBucketAcl"
82 | Resource:
83 | Fn::Join:
84 | - ''
85 | - ["arn:aws:s3:::", !Ref LogBucket]
86 | -
87 | Sid: "AWSCloudTrailWrite"
88 | Effect: "Allow"
89 | Principal:
90 | Service: "cloudtrail.amazonaws.com"
91 | Action: "s3:PutObject"
92 | Resource:
93 | Fn::Join:
94 | - ''
95 | - ["arn:aws:s3:::", !Ref LogBucket,'/AWSLogs/*']
96 | Condition:
97 | StringEquals:
98 | s3:x-amz-acl: "bucket-owner-full-control"
99 |
100 | ### Data Bucket
101 |
102 | DataBucket:
103 | Type: 'AWS::S3::Bucket'
104 | Properties:
105 | BucketEncryption:
106 | ServerSideEncryptionConfiguration:
107 | - ServerSideEncryptionByDefault:
108 | SSEAlgorithm: 'AES256'
109 | BucketName:
110 | Fn::Join:
111 | - '-'
112 | - [!Ref ResourceName, !Ref "AWS::AccountId", !Ref "AWS::Region",'data']
113 |
114 | ### GuardDuty ThreatListBucket
115 | GDThreatListBucket:
116 | Type: 'AWS::S3::Bucket'
117 | Properties:
118 | BucketEncryption:
119 | ServerSideEncryptionConfiguration:
120 | - ServerSideEncryptionByDefault:
121 | SSEAlgorithm: 'AES256'
122 | BucketName:
123 | Fn::Join:
124 | - '-'
125 | - [!Ref ResourceName, !Ref "AWS::AccountId", !Ref "AWS::Region",'gd-threatlist']
126 |
127 | ### Centralized Detection SNS Topic
128 | DetectionSNSTopic:
129 | Type: AWS::SNS::Topic
130 | Properties:
131 | TopicName: !Ref ResourceName
132 | Subscription:
133 | - Endpoint: !Ref Email
134 | Protocol: Email
135 | DetectionSNSTopicPolicy:
136 | Type: AWS::SNS::TopicPolicy
137 | Properties:
138 | PolicyDocument:
139 | Id: ID-GD-Topic-Policy
140 | Version: '2012-10-17'
141 | Statement:
142 | - Sid: SID-Detection-Workshop
143 | Effect: Allow
144 | Principal:
145 | Service:
146 | - events.amazonaws.com
147 | - inspector.amazonaws.com
148 | Action: sns:Publish
149 | Resource: !Ref DetectionSNSTopic
150 | Topics:
151 | - !Ref DetectionSNSTopic
152 |
153 | # CloudWatch Event Rules
154 | GuardDutyIAMFindingEvent:
155 | Type: "AWS::Events::Rule"
156 | Properties:
157 | Name:
158 | Fn::Join:
159 | - '-'
160 | - [!Ref ResourceName, 'guardduty-iam-finding']
161 | Description: "GuardDuty: AWS IAM Findings"
162 | EventPattern:
163 | source:
164 | - aws.guardduty
165 | detail-type:
166 | - "GuardDuty Finding"
167 | detail:
168 | resource:
169 | resourceType:
170 | - AccessKey
171 | State: "ENABLED"
172 | Targets:
173 | -
174 | Arn:
175 | Ref: "DetectionSNSTopic"
176 | Id: "DetectionSNSTopic-GuardDuty"
177 | InputTransformer:
178 | InputTemplate: "\"Amazon GuardDuty Finding : \"\n\n\"Account : \"\n\"Region : \"\n\"Description : \"\n\"Access Key ID : \"\n\"User Type : \""
179 | InputPathsMap:
180 | type: "$.detail.type"
181 | description: "$.detail.description"
182 | account: "$.account"
183 | region: "$.region"
184 | accessKey: "$.detail.resource.accessKeyDetails.accessKeyId"
185 | userType: "$.detail.resource.accessKeyDetails.userType"
186 |
187 | GuardDutyEC2FindingEvent:
188 | Type: "AWS::Events::Rule"
189 | Properties:
190 | Name:
191 | Fn::Join:
192 | - '-'
193 | - [!Ref ResourceName, 'guardduty-ec2-finding']
194 | Description: "GuardDuty: AWS EC2 Findings"
195 | EventPattern:
196 | source:
197 | - aws.guardduty
198 | detail-type:
199 | - "GuardDuty Finding"
200 | detail:
201 | resource:
202 | resourceType:
203 | - Instance
204 | State: "ENABLED"
205 | Targets:
206 | -
207 | Arn:
208 | Ref: "DetectionSNSTopic"
209 | Id: "DetectionSNSTopic-GuardDuty"
210 | InputTransformer:
211 | InputTemplate: "\"Amazon GuardDuty Finding : \"\n\n\"Account : \"\n\"Region : \"\n\"Description: \"\n\"Instance ID: \""
212 | InputPathsMap:
213 | type: "$.detail.type"
214 | description: "$.detail.description"
215 | account: "$.account"
216 | region: "$.region"
217 | instanceid: "$.detail.resource.instanceDetails.instanceId"
218 |
219 | GuardDutyFindingEventSSHBruteForce:
220 | Type: "AWS::Events::Rule"
221 | Properties:
222 | Name:
223 | Fn::Join:
224 | - '-'
225 | - [!Ref ResourceName, 'guardduty-finding', 'sshbruteforce']
226 | Description: "GuardDuty Finding: UnauthorizedAccess:EC2/SSHBruteForce"
227 | EventPattern:
228 | source:
229 | - aws.guardduty
230 | detail:
231 | type:
232 | - "UnauthorizedAccess:EC2/SSHBruteForce"
233 | State: "ENABLED"
234 | Targets:
235 | -
236 | Arn: !GetAtt LambdaRemediationInspector.Arn
237 | Id: "GuardDutyEvent-Lambda-Trigger-Inspector"
238 | -
239 | Arn: !GetAtt LambdaRemediationNACL.Arn
240 | Id: "GuardDutyEvent-Lambda-Trigger-NACL"
241 |
242 | MacieAlertEvent:
243 | Type: "AWS::Events::Rule"
244 | Properties:
245 | Name:
246 | Fn::Join:
247 | - '-'
248 | - [!Ref ResourceName, 'macie-alert']
249 | Description: "All Macie Alerts"
250 | EventPattern:
251 | source:
252 | - aws.macie
253 | detail-type:
254 | - "Macie Alert"
255 | State: "ENABLED"
256 | Targets:
257 | -
258 | Arn:
259 | Ref: "DetectionSNSTopic"
260 | Id: "DetectionSNSTopic-Macie"
261 | InputTransformer:
262 | InputTemplate: '"Amazon Macie Alert: "'
263 | InputPathsMap:
264 | macdesc: "$.detail.summary.Description"
265 |
266 |
267 | ### Configuration Lambda - Inspector
268 | LambdaAdditionalConfig:
269 | Type: "AWS::Lambda::Function"
270 | Properties:
271 | FunctionName:
272 | Fn::Join:
273 | - '-'
274 | - [!Ref ResourceName, 'additional-configuration']
275 | Handler: "index.handler"
276 | Environment:
277 | Variables:
278 | PREFIX: !Ref ResourceName
279 | Role:
280 | Fn::GetAtt:
281 | - "LambdaAdditionalConfigRole"
282 | - "Arn"
283 | Code:
284 | ZipFile: |
285 | from __future__ import print_function
286 | from urllib2 import build_opener, HTTPHandler, Request
287 | from botocore.exceptions import ClientError
288 | import boto3
289 | import json
290 | import httplib
291 | import os
292 |
293 | def handler(event, context):
294 |
295 | inspector = boto3.client('inspector')
296 |
297 | print("log -- Event: %s " % json.dumps(event))
298 | target_name = '%s-target-sample' % os.environ['PREFIX']
299 |
300 | if event['RequestType'] == 'Create':
301 | print("log -- Create Event ")
302 | try:
303 |
304 | group = inspector.create_resource_group(
305 | resourceGroupTags=[
306 | {
307 | 'key': 'Name',
308 | 'value': 'Test'
309 | },
310 | ]
311 | )
312 | target = inspector.create_assessment_target(
313 | assessmentTargetName=target_name,
314 | resourceGroupArn=group['resourceGroupArn']
315 | )
316 | response = sendResponse(event, context, "SUCCESS", { "Message": "Inspector Assessment Target successfully created!" })
317 | except ClientError as e:
318 | print(e)
319 | response = sendResponse(event, context, "SUCCESS", { "Message": "Inspector Assessment Target unsuccessful in being created!" })
320 | elif event['RequestType'] == 'Update':
321 | print("log -- Update Event")
322 | try:
323 |
324 | group = inspector.create_resource_group(
325 | resourceGroupTags=[
326 | {
327 | 'key': 'Name',
328 | 'value': 'Test'
329 | },
330 | ]
331 | )
332 | target = inspector.create_assessment_target(
333 | assessmentTargetName=target_name,
334 | resourceGroupArn=group['resourceGroupArn']
335 | )
336 |
337 | response = sendResponse(event, context, "SUCCESS", { "Message": "Inspector Assessment Target successfully created!" })
338 | except ClientError as e:
339 | print(e)
340 | response = sendResponse(event, context, "SUCCESS", { "Message": "Inspector Assessment Target unsuccessful in being created!" })
341 | elif event['RequestType'] == 'Delete':
342 | print("log -- Delete Event")
343 | response = sendResponse(event, context, "SUCCESS", { "Message": "Resource deletion successful! Please delete the Inspector Role manually." })
344 | else:
345 | print("log -- FAILED")
346 | response = sendResponse(event, context, "FAILED", { "Message": "Unexpected event received from CloudFormation" })
347 |
348 | return response
349 |
350 | def sendResponse(event, context, responseStatus, responseData):
351 | responseBody = json.dumps({
352 | "Status": responseStatus,
353 | "Reason": "See the details in CloudWatch Log Stream: " + context.log_stream_name,
354 | "PhysicalResourceId": context.log_stream_name,
355 | "StackId": event['StackId'],
356 | "RequestId": event['RequestId'],
357 | "LogicalResourceId": event['LogicalResourceId'],
358 | "Data": responseData
359 | })
360 |
361 | opener = build_opener(HTTPHandler)
362 | request = Request(event['ResponseURL'], data=responseBody)
363 | request.add_header('Content-Type', '')
364 | request.add_header('Content-Length', len(responseBody))
365 | request.get_method = lambda: 'PUT'
366 | response = opener.open(request)
367 | print("Status code: {}".format(response.getcode()))
368 | print("Status message: {}".format(response.msg))
369 |
370 | return responseBody
371 |
372 | Runtime: "python2.7"
373 | Timeout: "35"
374 |
375 | LambdaAdditionalConfigRole:
376 | Type: AWS::IAM::Role
377 | Properties:
378 | RoleName:
379 | Fn::Join:
380 | - '-'
381 | - [!Ref ResourceName, 'lambda', 'inspector-creation']
382 | AssumeRolePolicyDocument:
383 | Version: 2012-10-17
384 | Statement:
385 | -
386 | Effect: Allow
387 | Principal:
388 | Service:
389 | - lambda.amazonaws.com
390 | Action:
391 | - sts:AssumeRole
392 | Path: /
393 | Policies:
394 | -
395 | PolicyName: RemediationPolicy
396 | PolicyDocument:
397 | Version: 2012-10-17
398 | Statement:
399 | -
400 | Effect: Allow
401 | Action:
402 | - logs:CreateLogGroup
403 | - logs:CreateLogStream
404 | - logs:PutLogEvents
405 | Resource: '*'
406 | -
407 | Effect: Allow
408 | Action:
409 | - iam:CreateServiceLinkedRole
410 | - inspector:CreateAssessmentTarget
411 | - inspector:CreateResourceGroup
412 | Resource: '*'
413 | InspectorCustomResource:
414 | Type: Custom::CustomResource
415 | Properties:
416 | ServiceToken: !GetAtt 'LambdaAdditionalConfig.Arn'
417 | ParameterOne: Parameter to pass into Custom Lambda Function
418 |
419 | # Remediation Lambda - SSH Brute Force
420 | LambdaRemediationInspector:
421 | Type: "AWS::Lambda::Function"
422 | Properties:
423 | FunctionName:
424 | Fn::Join:
425 | - '-'
426 | - [!Ref ResourceName, 'remediation', 'inspector']
427 | Handler: "index.handler"
428 | Environment:
429 | Variables:
430 | TOPIC_ARN: !Ref DetectionSNSTopic
431 | PREFIX: !Ref ResourceName
432 | COMRPOMISED_INSTANCE_TAG:
433 | Fn::Join:
434 | - ':'
435 | - [!Ref ResourceName, ' Compromised Instance']
436 | Role:
437 | Fn::GetAtt:
438 | - "LambdaRemediationRole"
439 | - "Arn"
440 | Code:
441 | ZipFile: |
442 | from __future__ import print_function
443 | from botocore.exceptions import ClientError
444 | import json
445 | import boto3
446 | import os
447 | import uuid
448 | import time
449 |
450 | def handler(event, context):
451 |
452 | # Log Event
453 | print("log -- Event: %s " % json.dumps(event))
454 |
455 | instance_id = event["detail"]["resource"]["instanceDetails"]["instanceId"]
456 | gd_sev = event['detail']['severity']
457 | scan_id = str(uuid.uuid4())
458 | scan_name = '%s-inspector-scan' % os.environ['PREFIX']
459 | target_name = '%s-target-%s' % (os.environ['PREFIX'], event["id"])
460 | template_name = '%s-template-%s' % (os.environ['PREFIX'], event["id"])
461 | assess_name = '%s-assessment-%s' % (os.environ['PREFIX'], event["id"])
462 |
463 | response = "Skipping Remediation"
464 |
465 | ec2 = boto3.client('ec2')
466 | scan = True
467 | wksp = False
468 |
469 | for i in event['detail']['resource']['instanceDetails']['tags']:
470 | if i['value'] == os.environ['PREFIX']:
471 | wksp = True
472 | elif i['key'] == scan_name:
473 | scan = False
474 |
475 | print("log -- Event: Scan - %s" % scan)
476 | print("log -- Event: Workshop - %s" % wksp)
477 |
478 | if gd_sev == 2 and scan == True and wksp == True:
479 |
480 | print("log -- Event: Inspector Scan Kickoff")
481 | try:
482 | inspector = boto3.client('inspector')
483 |
484 | ec2.create_tags(
485 | Resources=[
486 | instance_id,
487 | ],
488 | Tags=[
489 | {
490 | 'Key': scan_name,
491 | 'Value': scan_id
492 | }
493 | ]
494 | )
495 | if os.environ['AWS_REGION'] == 'us-east-1':
496 | packages = ['arn:aws:inspector:us-east-1:316112463485:rulespackage/0-R01qwB5Q','arn:aws:inspector:us-east-1:316112463485:rulespackage/0-gEjTy7T7']
497 | elif os.environ['AWS_REGION'] == 'us-west-2':
498 | packages = ['arn:aws:inspector:us-west-2:758058086616:rulespackage/0-JJOtZiqQ','arn:aws:inspector:us-west-2:758058086616:rulespackage/0-9hgA516p']
499 |
500 | group = inspector.create_resource_group(
501 | resourceGroupTags=[
502 | {
503 | 'key': scan_name,
504 | 'value': scan_id
505 | },
506 | ]
507 | )
508 |
509 | target = inspector.create_assessment_target(
510 | assessmentTargetName=target_name,
511 | resourceGroupArn=group['resourceGroupArn']
512 | )
513 |
514 | template = inspector.create_assessment_template(
515 | assessmentTargetArn=target['assessmentTargetArn'],
516 | assessmentTemplateName=template_name,
517 | durationInSeconds=900,
518 | rulesPackageArns=packages,
519 | userAttributesForFindings=[
520 | {
521 | 'key': 'instance-id',
522 | 'value': instance_id
523 | },
524 | {
525 | 'key': 'scan-name',
526 | 'value': scan_name
527 | },
528 | {
529 | 'key': 'scan-id',
530 | 'value': scan_id
531 | }
532 | ]
533 | )
534 |
535 | for x in range(0, 5):
536 | try:
537 | time.sleep(5)
538 | assessment = inspector.start_assessment_run(
539 | assessmentTemplateArn=template['assessmentTemplateArn'],
540 | assessmentRunName=assess_name
541 | )
542 | break
543 | except ClientError as e:
544 | print(e)
545 |
546 | # Set Remediation Metadata
547 | response = "An Inspector scan has been initiated on this instance: %s" % instance_id
548 | except ClientError as e:
549 | print(e)
550 | print("log -- Error Starting an AWS Inspector Assessment")
551 | response = "Error"
552 |
553 | print(response)
554 | return response
555 | Runtime: "python2.7"
556 | Timeout: "120"
557 | LambdaRemediationInspectInvokePermissions:
558 | DependsOn:
559 | - LambdaRemediationInspector
560 | Type: "AWS::Lambda::Permission"
561 | Properties:
562 | FunctionName: !Ref "LambdaRemediationInspector"
563 | Action: "lambda:InvokeFunction"
564 | Principal: "events.amazonaws.com"
565 |
566 | # Remediation Lambda - NACL Modification
567 | LambdaRemediationNACL:
568 | Type: "AWS::Lambda::Function"
569 | Properties:
570 | FunctionName:
571 | Fn::Join:
572 | - '-'
573 | - [!Ref ResourceName, 'remediation', 'nacl']
574 | Handler: "index.handler"
575 | Environment:
576 | Variables:
577 | TOPIC_ARN: !Ref DetectionSNSTopic
578 | PREFIX: !Ref ResourceName
579 | COMRPOMISED_INSTANCE_TAG:
580 | Fn::Join:
581 | - ':'
582 | - [!Ref ResourceName, ' Compromised Instance']
583 | Role:
584 | Fn::GetAtt:
585 | - "LambdaRemediationRole"
586 | - "Arn"
587 | Code:
588 | ZipFile: |
589 | from __future__ import print_function
590 | from botocore.exceptions import ClientError
591 | import boto3
592 | import json
593 | import os
594 |
595 | def handler(event, context):
596 |
597 | # Log Event
598 | print("log -- Event: %s " % json.dumps(event))
599 |
600 | # Set Event Variables
601 | gd_sev = event['detail']['severity']
602 | gd_vpc_id = event["detail"]["resource"]["instanceDetails"]["networkInterfaces"][0]["vpcId"]
603 | gd_instance_id = event["detail"]["resource"]["instanceDetails"]["instanceId"]
604 | gd_subnet_id = event["detail"]["resource"]["instanceDetails"]["networkInterfaces"][0]["subnetId"]
605 | gd_offending_id = event["detail"]["service"]["action"]["networkConnectionAction"]["remoteIpDetails"]["ipAddressV4"]
606 |
607 | response = "Skipping Remediation"
608 |
609 | wksp = False
610 |
611 | for i in event['detail']['resource']['instanceDetails']['tags']:
612 | if i['value'] == os.environ['PREFIX']:
613 | wksp = True
614 |
615 | print("log -- Event: Workshop - %s" % wksp)
616 |
617 | try:
618 |
619 | # Setup a NACL to deny inbound and outbound calls from the malicious IP from this subnet
620 | ec2 = boto3.client('ec2')
621 |
622 | response = ec2.describe_network_acls(
623 | Filters=[
624 | {
625 | 'Name': 'vpc-id',
626 | 'Values': [
627 | gd_vpc_id,
628 | ]
629 | },
630 | {
631 | 'Name': 'association.subnet-id',
632 | 'Values': [
633 | gd_subnet_id,
634 | ]
635 | }
636 | ]
637 | )
638 |
639 | gd_nacl_id = response["NetworkAcls"][0]["NetworkAclId"]
640 |
641 | if gd_sev == 2 and wksp == True and event["detail"]["type"] == "UnauthorizedAccess:EC2/SSHBruteForce":
642 | response = ec2.create_network_acl_entry(
643 | DryRun=False,
644 | Egress=False,
645 | NetworkAclId=gd_nacl_id,
646 | CidrBlock=gd_offending_id+"/32",
647 | Protocol="-1",
648 | RuleAction='deny',
649 | RuleNumber=90
650 | )
651 |
652 | print("log -- Event: NACL Deny Rule for UnauthorizedAccess:EC2/SSHBruteForce Finding ")
653 |
654 | elif wksp == True and event["detail"]["type"] == "UnauthorizedAccess:EC2/MaliciousIPCaller.Custom":
655 | response = ec2.create_network_acl_entry(
656 | DryRun=False,
657 | Egress=True,
658 | NetworkAclId=gd_nacl_id,
659 | CidrBlock=gd_offending_id+"/32",
660 | Protocol="-1",
661 | RuleAction='deny',
662 | RuleNumber=90
663 | )
664 |
665 | print("log -- Event: NACL Deny Rule for UnauthorizedAccess:EC2/MaliciousIPCaller.Custom Finding ")
666 | else:
667 | print("A GuardDuty event occured without a defined remediation.")
668 |
669 | except ClientError as e:
670 | print(e)
671 | print("Something went wrong with the NACL remediation Lambda")
672 | return response
673 |
674 | Runtime: "python2.7"
675 | Timeout: "35"
676 | LambdaRemediationNACLInvokePermissions:
677 | DependsOn:
678 | - LambdaRemediationNACL
679 | Type: "AWS::Lambda::Permission"
680 | Properties:
681 | FunctionName: !Ref "LambdaRemediationNACL"
682 | Action: "lambda:InvokeFunction"
683 | Principal: "events.amazonaws.com"
684 |
685 | LambdaRemediationRole:
686 | Type: AWS::IAM::Role
687 | Properties:
688 | RoleName:
689 | Fn::Join:
690 | - '-'
691 | - [!Ref ResourceName, 'lambda', 'remediation']
692 | AssumeRolePolicyDocument:
693 | Version: 2012-10-17
694 | Statement:
695 | -
696 | Effect: Allow
697 | Principal:
698 | Service:
699 | - lambda.amazonaws.com
700 | Action:
701 | - sts:AssumeRole
702 | Path: /
703 | Policies:
704 | -
705 | PolicyName: RemediationPolicy
706 | PolicyDocument:
707 | Version: 2012-10-17
708 | Statement:
709 | -
710 | Effect: Allow
711 | Action:
712 | - inspector:CreateAssessmentTemplate
713 | - inspector:CreateAssessmentTarget
714 | - inspector:CreateResourceGroup
715 | - inspector:ListRulesPackages
716 | - inspector:StartAssessmentRun
717 | - inspector:SubscribeToEvent
718 | - inspector:SetTagsForResource
719 | - inspector:DescribeAssessmentRuns
720 | - ec2:CreateTags
721 | - ec2:Describe*
722 | - ec2:*NetworkAcl*
723 | - iam:CreateServiceLinkedRole
724 | Resource: '*'
725 | -
726 | Effect: Allow
727 | Action:
728 | - logs:CreateLogGroup
729 | - logs:CreateLogStream
730 | - logs:PutLogEvents
731 | Resource: '*'
732 |
733 | Outputs: {}
--------------------------------------------------------------------------------
/templates/02-attack-simulation.yml:
--------------------------------------------------------------------------------
1 | AWSTemplateFormatVersion: '2010-09-09'
2 |
3 | Description: This AWS CloudFormation Template creates the necessary resources to generate sample findings for the Threat Detection Workshop.
4 |
5 | Parameters:
6 |
7 | ResourceName:
8 | Type: String
9 | Default: threat-detection-wksp
10 | AllowedValues:
11 | - threat-detection-wksp
12 | Description: Prefix of Resources created for this workshop.
13 |
14 | # KeyName:
15 | # Type: AWS::EC2::KeyPair::KeyName
16 | # ConstraintDescription: Must be the name of an existing EC2 KeyPair.
17 | # Description: 'Name of an existing EC2 Key Pair.'
18 |
19 | Metadata:
20 | AWS::CloudFormation::Interface:
21 | ParameterGroups:
22 | -
23 | Label:
24 | default: "Resource Configuration"
25 | Parameters:
26 | - ResourceName
27 | # - KeyName
28 | ParameterLabels:
29 | ResourceName:
30 | default: "Resource Prefix"
31 | # KeyName:
32 | # default: "Existing Key Pair"
33 |
34 | Mappings:
35 |
36 | RegionMap:
37 | us-east-1:
38 | "aznlinux": "ami-afd15ed0"
39 | "ubuntu": "ami-43a15f3e"
40 | us-east-2:
41 | "aznlinux": "ami-2a0f324f"
42 | "ubuntu": "ami-916f59f4"
43 | us-west-1:
44 | "aznlinux": "ami-00d8c660"
45 | "ubuntu": "ami-925144f2"
46 | us-west-2:
47 | "aznlinux": "ami-31394949"
48 | "ubuntu": "ami-4e79ed36"
49 | ap-south-1:
50 | "aznlinux": "ami-7d95b612"
51 | "ubuntu": "ami-0189d76e"
52 | ap-northeast-1:
53 | "aznlinux": "ami-2724cf58"
54 | "ubuntu": "ami-0d74386b"
55 | ap-northeast-2:
56 | "aznlinux": "ami-d117bebf"
57 | "ubuntu": "ami-a414b9ca"
58 | ap-southeast-1:
59 | "aznlinux": "ami-a7f0c4db"
60 | "ubuntu": "ami-52d4802e"
61 | ap-southeast-2:
62 | "aznlinux": "ami-c267b0a0"
63 | "ubuntu": "ami-d38a4ab1"
64 | ca-central-1:
65 | "aznlinux": "ami-c59818a1"
66 | "ubuntu": "ami-ae55d2ca"
67 | eu-central-1:
68 | "aznlinux": "ami-43eec3a8"
69 | "ubuntu": "ami-7c412f13"
70 | eu-west-1:
71 | "aznlinux": "ami-921423eb"
72 | "ubuntu": "ami-f90a4880"
73 | eu-west-2:
74 | "aznlinux": "ami-924aa8f5"
75 | "ubuntu": "ami-f4f21593"
76 | eu-west-3:
77 | "aznlinux": "ami-a88233d5"
78 | "ubuntu": "ami-0e55e373"
79 | sa-east-1:
80 | "aznlinux": "ami-4fd48923"
81 | "ubuntu": "ami-423d772e"
82 |
83 | Conditions: {}
84 |
85 | Resources:
86 |
87 | ### Network Infrastructure
88 | VPC:
89 | Type: AWS::EC2::VPC
90 | Properties:
91 | CidrBlock: 10.0.0.0/16
92 | EnableDnsHostnames: true
93 | EnableDnsSupport: true
94 | Tags:
95 | - Key: Name
96 | Value: !Ref ResourceName
97 | InternetGateway:
98 | Type: AWS::EC2::InternetGateway
99 | Properties:
100 | Tags:
101 | - Key: Name
102 | Value: !Ref ResourceName
103 | GatewayAttachment:
104 | Type: AWS::EC2::VPCGatewayAttachment
105 | Properties:
106 | InternetGatewayId:
107 | Ref: InternetGateway
108 | VpcId: !Ref VPC
109 | RouteTable:
110 | DependsOn:
111 | - VPC
112 | Type: AWS::EC2::RouteTable
113 | Properties:
114 | Tags:
115 | - Key: Name
116 | Value: !Ref ResourceName
117 | VpcId: !Ref VPC
118 | PublicRoute:
119 | DependsOn:
120 | - RouteTable
121 | - GatewayAttachment
122 | Type: AWS::EC2::Route
123 | Properties:
124 | DestinationCidrBlock: 0.0.0.0/0
125 | GatewayId: !Ref InternetGateway
126 | RouteTableId: !Ref RouteTable
127 | Subnet:
128 | Type: AWS::EC2::Subnet
129 | Properties:
130 | CidrBlock: 10.0.0.0/24
131 | MapPublicIpOnLaunch: true
132 | Tags:
133 | - Key: Name
134 | Value: !Ref ResourceName
135 | VpcId: !Ref VPC
136 | SubnetAssoc:
137 | DependsOn:
138 | - Subnet
139 | - RouteTable
140 | Type: AWS::EC2::SubnetRouteTableAssociation
141 | Properties:
142 | RouteTableId: !Ref RouteTable
143 | SubnetId: !Ref Subnet
144 | PublicNACL:
145 | Type: AWS::EC2::NetworkAcl
146 | Properties:
147 | VpcId: !Ref VPC
148 | Tags:
149 | -
150 | Key: Name
151 | Value:
152 | Fn::Join:
153 | - '-'
154 | - [!Ref ResourceName, 'compromised']
155 | -
156 | Key: Network
157 | Value: Public
158 | InboundPublicNACLEntry:
159 | Type: AWS::EC2::NetworkAclEntry
160 | Properties:
161 | NetworkAclId: !Ref PublicNACL
162 | RuleNumber: 100
163 | Protocol: -1
164 | RuleAction: allow
165 | Egress: false
166 | CidrBlock: '0.0.0.0/0'
167 | PortRange:
168 | From: 0
169 | To: 65535
170 | OutboundPublicNACLEntry:
171 | Type: AWS::EC2::NetworkAclEntry
172 | Properties:
173 | NetworkAclId: !Ref PublicNACL
174 | RuleNumber: 100
175 | Protocol: -1
176 | RuleAction: allow
177 | Egress: true
178 | CidrBlock: 0.0.0.0/0
179 | PortRange:
180 | From: 0
181 | To: 65535
182 | SubnetNACLAssociation:
183 | Type: AWS::EC2::SubnetNetworkAclAssociation
184 | Properties:
185 | SubnetId: !Ref Subnet
186 | NetworkAclId: !Ref PublicNACL
187 | MaliciousSubnet:
188 | Type: AWS::EC2::Subnet
189 | Properties:
190 | CidrBlock: 10.0.1.0/24
191 | MapPublicIpOnLaunch: true
192 | Tags:
193 | - Key: Name
194 | Value:
195 | Fn::Join:
196 | - '-'
197 | - [!Ref ResourceName, 'malicious']
198 | VpcId: !Ref VPC
199 | MaliciousSubnetAssoc:
200 | DependsOn:
201 | - MaliciousSubnet
202 | - RouteTable
203 | Type: AWS::EC2::SubnetRouteTableAssociation
204 | Properties:
205 | RouteTableId: !Ref RouteTable
206 | SubnetId: !Ref MaliciousSubnet
207 | MaliciousPublicNACL:
208 | Type: AWS::EC2::NetworkAcl
209 | Properties:
210 | VpcId: !Ref VPC
211 | Tags:
212 | -
213 | Key: Name
214 | Value:
215 | Fn::Join:
216 | - '-'
217 | - [!Ref ResourceName, 'malicious']
218 | -
219 | Key: Network
220 | Value: Public
221 | MaliciousInboundPublicNACLEntry:
222 | Type: AWS::EC2::NetworkAclEntry
223 | Properties:
224 | NetworkAclId: !Ref MaliciousPublicNACL
225 | RuleNumber: 100
226 | Protocol: -1
227 | RuleAction: allow
228 | Egress: false
229 | CidrBlock: '0.0.0.0/0'
230 | PortRange:
231 | From: 0
232 | To: 65535
233 | MaliciousOutboundPublicNACLEntry:
234 | Type: AWS::EC2::NetworkAclEntry
235 | Properties:
236 | NetworkAclId: !Ref MaliciousPublicNACL
237 | RuleNumber: 100
238 | Protocol: -1
239 | RuleAction: allow
240 | Egress: true
241 | CidrBlock: 0.0.0.0/0
242 | PortRange:
243 | From: 0
244 | To: 65535
245 | MaliciousSubnetNACLAssociation:
246 | Type: AWS::EC2::SubnetNetworkAclAssociation
247 | Properties:
248 | SubnetId: !Ref MaliciousSubnet
249 | NetworkAclId: !Ref MaliciousPublicNACL
250 |
251 | ### Malicious Host IAM Role
252 | MaliciousInstanceRole:
253 | Type: AWS::IAM::Role
254 | Properties:
255 | RoleName:
256 | Fn::Join:
257 | - '-'
258 | - [!Ref ResourceName, 'malicious-ec2']
259 | AssumeRolePolicyDocument:
260 | Version: 2012-10-17
261 | Statement:
262 | -
263 | Effect: Allow
264 | Principal:
265 | Service:
266 | - ec2.amazonaws.com
267 | Action:
268 | - sts:AssumeRole
269 | Path: /
270 | Policies:
271 | -
272 | PolicyName: MaliciousInstancePolicy
273 | PolicyDocument:
274 | Version: 2012-10-17
275 | Statement:
276 | -
277 | Effect: Allow
278 | Action:
279 | - ssm:GetParameter
280 | - ssm:GetParameters
281 | - ssm:DescribeParameters
282 | Resource:
283 | Fn::Join:
284 | - ':'
285 | - ["arn:aws:ssm", !Ref "AWS::Region", !Ref "AWS::AccountId", "*"]
286 | MaliciousInstanceProfile:
287 | Type: AWS::IAM::InstanceProfile
288 | Properties:
289 | InstanceProfileName:
290 | Fn::Join:
291 | - '-'
292 | - [!Ref ResourceName, 'malicious-ec2-profile']
293 | Path: /
294 | Roles:
295 | - !Ref MaliciousInstanceRole
296 |
297 | ### Malicious Instance Security Group
298 | MaliciousSecurityGroup:
299 | Type: AWS::EC2::SecurityGroup
300 | Properties:
301 | GroupDescription:
302 | Fn::Join:
303 | - '-'
304 | - [!Ref ResourceName,'malicious']
305 | VpcId: !Ref VPC
306 | SecurityGroupIngress:
307 | - IpProtocol: icmp
308 | FromPort: '-1'
309 | ToPort: '-1'
310 | CidrIp: 0.0.0.0/0
311 |
312 | ### Malicious Instance
313 | MaliciousIP:
314 | DependsOn:
315 | - GatewayAttachment
316 | Type: AWS::EC2::EIP
317 | Properties:
318 | InstanceId: !Ref MaliciousInstance
319 | Domain: vpc
320 |
321 | MaliciousInstance:
322 | Type: AWS::EC2::Instance
323 | Properties:
324 | IamInstanceProfile: !Ref MaliciousInstanceProfile
325 | InstanceType: t3.medium
326 | ImageId:
327 | Fn::FindInMap:
328 | - RegionMap
329 | - !Ref AWS::Region
330 | - 'ubuntu'
331 | # KeyName: !Ref KeyName
332 | NetworkInterfaces:
333 | - AssociatePublicIpAddress: 'false'
334 | DeviceIndex: '0'
335 | GroupSet:
336 | - !Ref MaliciousSecurityGroup
337 | SubnetId:
338 | Ref: MaliciousSubnet
339 | Tags:
340 | - Key: Name
341 | Value:
342 | Fn::Join:
343 | - ': '
344 | - [!Ref ResourceName, 'Malicious Host']
345 | - Key: Service
346 | Value: !Ref ResourceName
347 | UserData:
348 | Fn::Base64: !Sub
349 | - |
350 | #!/bin/bash -ex
351 |
352 | # Get Updates and Install Necessary Packages
353 | sudo apt-get update && sudo apt-get upgrade && sudo apt-get dist-upgrade
354 | sudo apt-get install build-essential -y
355 | sudo apt-get install git sshpass python-pip libssl-dev libssh-dev libidn11-dev libpcre3-dev libgtk2.0-dev libmysqlclient-dev libpq-dev libsvn-dev -y
356 | pip install awscli
357 | export PATH=$PATH:/usr/local/bin:/usr/sbin:/root/.local/bin
358 | echo 'export PATH=/root/.local/bin:/usr/sbin:$PATH' >> /home/ubuntu/.profile
359 |
360 | # Set Region
361 | aws configure set default.region ${Region}
362 |
363 | # Install thc-hydra
364 | mkdir /home/ubuntu/thc-hydra
365 | git clone https://github.com/vanhauser-thc/thc-hydra /home/ubuntu/thc-hydra
366 | cd /home/ubuntu/thc-hydra
367 | sudo /home/ubuntu/thc-hydra/configure && sudo make && sudo make install
368 |
369 | # Create Password List
370 | sudo /home/ubuntu/thc-hydra/dpl4hydra.sh root
371 | sudo echo "alice:ThreatDetectionPassword123!" >> dpl4hydra_root.lst
372 |
373 | # Create Targets File
374 | com_ip=10.0.0.15
375 | echo $com_ip:22 >> /home/ubuntu/targets.txt
376 |
377 | # Create SSH Brute Force Cron Job
378 | cat <> /home/ubuntu/ssh-bruteforce.sh
379 | #!/bin/bash
380 | /usr/local/bin/hydra -C /home/ubuntu/thc-hydra/dpl4hydra_root.lst -M /home/ubuntu/targets.txt ssh -t 4
381 | EOT
382 |
383 | chmod 744 /home/ubuntu/ssh-bruteforce.sh
384 | chown ubuntu /home/ubuntu/ssh-bruteforce.sh
385 |
386 | # Create Script Retrieval Script
387 | cat <> /home/ubuntu/get-script.sh
388 | #!/bin/bash
389 | /usr/bin/sshpass -p "ThreatDetectionPassword123!" scp -o StrictHostKeyChecking=no -r alice@10.0.0.15:/home/alice/gd-findings.sh /home/ubuntu/gd-findings.sh
390 | chmod 744 /home/ubuntu/gd-findings.sh
391 | chown ubuntu /home/ubuntu/gd-findings.sh
392 | EOT
393 |
394 | chmod 744 /home/ubuntu/get-script.sh
395 | chown ubuntu /home/ubuntu/get-script.sh
396 |
397 | echo "*/2 * * * * /home/ubuntu/ssh-bruteforce.sh > /home/ubuntu/ssh-bruteforce.log 2>&1" >> cron
398 | echo "*/2 * * * * /home/ubuntu/get-script.sh > /home/ubuntu/get-script.log 2>&1" >> cron
399 | echo "*/2 * * * * /home/ubuntu/gd-findings.sh > /home/ubuntu/gd-findings.log 2>&1" >> cron
400 |
401 | crontab -u ubuntu cron
402 | -
403 | Region:
404 | !Ref "AWS::Region"
405 | Bucket:
406 | Fn::Join:
407 | - '-'
408 | - [!Ref ResourceName, !Ref "AWS::AccountId", !Ref "AWS::Region",'gd-threatlist']
409 |
410 |
411 | ### Compromised Instance IAM Role
412 | CompromisedRole:
413 | Type: AWS::IAM::Role
414 | Properties:
415 | RoleName:
416 | Fn::Join:
417 | - '-'
418 | - [!Ref ResourceName, compromised-ec2]
419 | AssumeRolePolicyDocument:
420 | Version: 2012-10-17
421 | Statement:
422 | -
423 | Effect: Allow
424 | Principal:
425 | Service:
426 | - ec2.amazonaws.com
427 | Action:
428 | - sts:AssumeRole
429 | Path: /
430 | ManagedPolicyArns:
431 | - arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM
432 | Policies:
433 | -
434 | PolicyName: CompromisedPolicy
435 | PolicyDocument:
436 | Version: 2012-10-17
437 | Statement:
438 | -
439 | Effect: Allow
440 | Action:
441 | - guardduty:GetDetector
442 | - guardduty:ListDetectors
443 | - guardduty:CreateThreatIntelSet
444 | - guardduty:UpdateThreatIntelSet
445 | - dynamodb:ListTables
446 | Resource: '*'
447 | -
448 | Effect: Allow
449 | Action:
450 | - iam:PutRolePolicy
451 | Resource:
452 | Fn::Join:
453 | - ':'
454 | - ["arn:aws:iam:",!Ref "AWS::AccountId", "role/aws-service-role/guardduty.amazonaws.com/*"]
455 | -
456 | Effect: Allow
457 | Action: 's3:PutObject'
458 | Resource:
459 | Fn::Join:
460 | - ''
461 | - ["arn:aws:s3:::",!Ref ResourceName, "-", !Ref "AWS::AccountId", "-", !Ref "AWS::Region", "-", 'gd-threatlist', "/*"]
462 | -
463 | Effect: Allow
464 | Action:
465 | - ssm:PutParameter
466 | - ssm:DescribeParameters
467 | - ssm:GetParameters
468 | - ssm:DeleteParameter
469 | Resource:
470 | Fn::Join:
471 | - ':'
472 | - ["arn:aws:ssm", !Ref "AWS::Region", !Ref "AWS::AccountId", "parameter/*"]
473 | -
474 | Effect: Allow
475 | Action:
476 | - ssm:DescribeParameters
477 | Resource: "*"
478 | -
479 | Effect: Allow
480 | Action:
481 | - dynamodb:ListTables
482 | - dynamodb:DescribeTable
483 | Resource: '*'
484 | -
485 | Effect: Allow
486 | Action:
487 | - logs:PutLogEvents
488 | - logs:DescribeLogStreams
489 | - logs:CreateLogStream
490 | - logs:CreateLogGroup
491 | Resource: 'arn:aws:logs:*:*:*'
492 | -
493 | Effect: Allow
494 | Action:
495 | - 's3:*'
496 | Resource:
497 | Fn::Join:
498 | - ''
499 | - ["arn:aws:s3:::",!Ref ResourceName, "-", !Ref "AWS::AccountId", "-", !Ref "AWS::Region", "-", 'data', "/*"]
500 | -
501 | Effect: Allow
502 | Action:
503 | - 's3:*'
504 | Resource:
505 | Fn::Join:
506 | - ''
507 | - ["arn:aws:s3:::",!Ref ResourceName, "-", !Ref "AWS::AccountId", "-", !Ref "AWS::Region", "-", 'data']
508 | CompromisedInstanceProfile:
509 | Type: AWS::IAM::InstanceProfile
510 | Properties:
511 | InstanceProfileName:
512 | Fn::Join:
513 | - '-'
514 | - [!Ref ResourceName, 'compromised-ec2-profile']
515 | Path: /
516 | Roles:
517 | - !Ref CompromisedRole
518 |
519 | ### Compromised Instance Security Group
520 | CompromisedSecurityGroup:
521 | Type: AWS::EC2::SecurityGroup
522 | Properties:
523 | GroupDescription:
524 | Fn::Join:
525 | - '-'
526 | - [!Ref ResourceName,'compromised']
527 | VpcId: !Ref VPC
528 | SecurityGroupIngress:
529 | - IpProtocol: tcp
530 | FromPort: '22'
531 | ToPort: '22'
532 | CidrIp: 10.0.0.0/16
533 |
534 | ### Compromised Instance
535 | CompromisedInstance:
536 | Type: AWS::EC2::Instance
537 | Properties:
538 | InstanceType: t3.medium
539 | IamInstanceProfile: !Ref CompromisedInstanceProfile
540 | # KeyName: !Ref KeyName
541 | ImageId:
542 | Fn::FindInMap:
543 | - RegionMap
544 | - !Ref "AWS::Region"
545 | - 'aznlinux'
546 | NetworkInterfaces:
547 | - AssociatePublicIpAddress: true
548 | DeviceIndex: 0
549 | GroupSet:
550 | - !Ref CompromisedSecurityGroup
551 | SubnetId:
552 | Ref: Subnet
553 | PrivateIpAddress: '10.0.0.15'
554 | Tags:
555 | - Key: Name
556 | Value:
557 | Fn::Join:
558 | - ': '
559 | - [!Ref ResourceName, 'Compromised Instance']
560 | - Key: Service
561 | Value: !Ref ResourceName
562 | UserData:
563 | Fn::Base64: !Sub
564 | - |
565 | #!/bin/bash
566 |
567 | # Set Region
568 | aws configure set default.region ${Region}
569 |
570 | # Set Credential Variables
571 | access_key_id=`curl http://169.254.169.254/latest/meta-data/iam/security-credentials/${Role} | grep AccessKeyId | cut -d':' -f2 | sed 's/[^0-9A-Z]*//g'`
572 | secret_key=`curl http://169.254.169.254/latest/meta-data/iam/security-credentials/${Role} | grep SecretAccessKey | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g'`
573 | token=`curl http://169.254.169.254/latest/meta-data/iam/security-credentials/${Role} | grep Token | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g'`
574 | expiration=`curl http://169.254.169.254/latest/meta-data/iam/security-credentials/${Role} | grep Expiration | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g'`
575 | compromisedip=`curl http://169.254.169.254/latest/meta-data/local-ipv4`
576 |
577 | # Install AWS Inspector Agent
578 | wget https://d1wk0tztpsntt1.cloudfront.net/linux/latest/install
579 | sudo bash install
580 |
581 | # Install CloudWatch Logs Agent
582 | sudo yum install awslogs -y
583 |
584 | # Set CloudWatch Logs Agent Region
585 | cat <> /tmp/awscli.conf
586 | [plugins]
587 | cwlogs = cwlogs
588 | [default]
589 | region = ${Region}
590 | EOT
591 | sudo cp /tmp/awscli.conf /etc/awslogs/
592 |
593 | # Set CloudWatch Logs Agent Config
594 | cat <> /tmp/awslogs.conf
595 | [general]
596 | state_file = /var/lib/awslogs/agent-state
597 |
598 | [/var/log/secure]
599 | file = /var/log/secure
600 | log_group_name = /${ResourceName}/var/log/secure
601 | log_stream_name = {instance_id}/ssh
602 | datetime_format = %d/%b/%Y:%H:%M:%S
603 | EOT
604 | sudo cp /tmp/awslogs.conf /etc/awslogs/
605 |
606 | # Start CloudWatch Log Agent
607 | sudo systemctl start awslogsd
608 |
609 | # Start SSM Agent
610 | sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
611 |
612 | # Modify Instance Configurations
613 | sudo sed 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config > temp.txt
614 | mv -f temp.txt /etc/ssh/sshd_config
615 | sudo systemctl restart sshd
616 |
617 | # Install and start Apache
618 | sudo yum install httpd -y
619 | sudo systemctl start httpd
620 |
621 | sudo systemctl restart rsyslog
622 |
623 | # Create Sample User
624 | sudo useradd -u 12345 -g users -d /home/alice -s /bin/bash -p $(echo ThreatDetectionPassword123! | openssl passwd -1 -stdin) alice
625 |
626 | # Create Fake Customer Data Files
627 | cat <> /tmp/employee-data.txt
628 | # Sample Report - No identification of actual persons or places is
629 | # intended or should be inferred
630 |
631 | 74323 Julie Field
632 | Lake Joshuamouth, OR 30055-3905
633 | 1-196-191-4438x974
634 | 53001 Paul Union
635 | New John, HI 94740
636 | American Express
637 | Amanda Wells
638 | 5135725008183484 09/26
639 | CVE: 550
640 |
641 | 354-70-6172
642 | 242 George Plaza
643 | East Lawrencefurt, VA 37287-7620
644 | GB73WAUS0628038988364
645 | 587 Silva Village
646 | Pearsonburgh, NM 11616-7231
647 | LDNM1948227117807
648 | American Express
649 | Brett Garza
650 | 347965534580275 05/20
651 | CID: 4758
652 | EOT
653 |
654 | # Upload employee data to S3
655 | sleep 5
656 | aws s3 cp /tmp/employee-data.txt s3://${Bucket}/employee-data.txt
657 |
658 | # Create Fake Config File
659 | echo 'aws_access_key_id =' $access_key_id >> /tmp/config.py
660 | echo 'aws_secret_access_key =' $secret_key >> /tmp/config.py
661 | echo 'github_key = 8a2aa88896371b444666f641aa65392222dd3333' >> /tmp/config.py
662 |
663 | # Upload employee data to S3
664 | sleep 5
665 | aws s3 cp /tmp/config.py s3://${Bucket}/config.py
666 |
667 | # Create Fake Classified File
668 | cat <> /tmp/memo.pst
669 | Proprietary Information
670 | arn:aws:iam::339394046901:role/aws-security-workshops-easteregg1 (Ex ID: aws-security-workshops)
671 | S3: aws-security-workshops-easteregg1a
672 | Do not share with any other employee.
673 | EOT
674 |
675 | # Upload employee data to S3
676 | sleep 5
677 | aws s3 cp /tmp/memo.pst s3://${Bucket}/memo.pst
678 |
679 | # Delete Default Encryption
680 | aws s3api delete-bucket-encryption --bucket ${Bucket}
681 | aws s3api put-bucket-acl --bucket ${Bucket} --grant-read uri=http://acs.amazonaws.com/groups/global/AllUsers
682 |
683 | # Create Fake /etc/passwd
684 | cat <> /tmp/passwd.txt
685 | blackwidow:x:10:100::/home/blackwidow:/bin/bash
686 | thor:x:11:100::/home/thor:/bin/bash
687 | ironman:x:12:100::/home/ironman:/bin/bash
688 | captain:x:13:100::/home/captain:/bin/bash
689 | hulk:x:14:100::/home/hulk:/bin/bash
690 | hawkeye:x:15:100::/home/hawkeye:/bin/bash
691 | EOT
692 |
693 | # Upload employee data to S3
694 | sleep 5
695 | aws s3 cp /tmp/passwd.txt s3://${Bucket}/passwd.txt
696 |
697 | #Upload Attack Security
698 | cat <> /home/alice/gd-findings.sh
699 | #!/bin/bash
700 | /usr/local/bin/aws configure set profile.attacker.region ${Region}
701 | /usr/local/bin/aws configure set profile.attacker.aws_access_key_id $access_key_id
702 | /usr/local/bin/aws configure set profile.attacker.aws_secret_access_key $secret_key
703 | /usr/local/bin/aws configure set profile.attacker.aws_session_token $token
704 | /usr/local/bin/aws s3api get-object --bucket ${Bucket} --key config.py /home/ubuntu/config.py --profile attacker
705 | /usr/local/bin/aws s3api list-buckets --profile attacker
706 | /usr/local/bin/aws cloudtrail describe-trails --profile attacker
707 | /usr/local/bin/aws s3api delete-bucket --bucket ${BucketLogs} --region ${Region} --profile attacker
708 | /usr/local/bin/aws iam delete-account-password-policy --profile attacker
709 | EOT
710 |
711 | chown alice /home/alice/gd-findings.sh
712 |
713 | # Threatlist Variables
714 | uuid=$(uuidgen)
715 | list="gd-threat-list-example-$uuid.txt"
716 |
717 | # Create Threatlist
718 | echo ${MaliciousIP} >> /tmp/$list
719 |
720 | # Upload list to S3
721 | aws s3 cp /tmp/$list s3://${BucketThreatList}/$list
722 | sleep 5
723 |
724 | # Create GuardDuty Threat List
725 | id=`aws guardduty list-detectors --query 'DetectorIds[0]' --output text`
726 | aws guardduty create-threat-intel-set --activate --detector-id $id --format TXT --location https://s3.amazonaws.com/${BucketThreatList}/$list --name Custom-Threat-List-$uuid
727 |
728 |
729 | # Set Ping cron Job
730 | echo "* * * * * ping -c 6 -i 10 ${MaliciousIP}" | tee -a /var/spool/cron/ec2-user
731 |
732 | aws iam create-user --user-name Superman
733 | aws iam create-user --user-name Batman
734 |
735 | -
736 | Role:
737 | !Ref CompromisedRole
738 | Region:
739 | !Ref "AWS::Region"
740 | Bucket:
741 | Fn::Join:
742 | - '-'
743 | - [!Ref ResourceName, !Ref "AWS::AccountId", !Ref "AWS::Region",'data']
744 | BucketThreatList:
745 | Fn::Join:
746 | - '-'
747 | - [!Ref ResourceName, !Ref "AWS::AccountId", !Ref "AWS::Region",'gd-threatlist']
748 | BucketLogs:
749 | Fn::Join:
750 | - '-'
751 | - [!Ref ResourceName, !Ref "AWS::AccountId", !Ref "AWS::Region",'logs']
752 | ResourceName:
753 | !Ref ResourceName
754 |
755 | Outputs: {}
756 |
--------------------------------------------------------------------------------