diff --git a/frontend/src/app/(public-area)/articles/[slug]/page.tsx b/frontend/src/app/(public-area)/articles/[slug]/page.tsx new file mode 100644 index 00000000..fc1fa1c8 --- /dev/null +++ b/frontend/src/app/(public-area)/articles/[slug]/page.tsx @@ -0,0 +1,68 @@ +import type { Metadata } from 'next'; +import Link from 'next/link'; + +import { articles } from '..'; + +export const dynamicParams = false; + +export async function generateStaticParams() { + return Object.keys(articles).map((slug) => ({ + slug, + })); +} + +type Props = { params: Promise<{ slug: string }> }; + +export async function generateMetadata({ params }: Props): Promise { + const { slug } = await params; + const article = articles[slug]; + + return { + title: article.title, + description: article.description, + openGraph: { + title: article.title, + description: article.description, + type: 'article', + publishedTime: article.date.toISOString(), + }, + }; +} + +export default async function Page({ params }: Props) { + const { slug } = await params; + const article = articles[slug]; + + return ( +
+
+

{article.title}

+
+ Published{' '} + {article.date.toLocaleDateString('en-US', { + weekday: 'long', + year: 'numeric', + month: 'long', + day: 'numeric', + })} +
+ {article.content} +
+ + {article.relatedLinks && ( +
+

Further Reading

+
    + {article.relatedLinks.map((item, index) => ( +
  • + + {item.title} + +
  • + ))} +
+
+ )} +
+ ); +} diff --git a/frontend/src/app/(public-area)/articles/capital-one-data-breach.tsx b/frontend/src/app/(public-area)/articles/capital-one-data-breach.tsx new file mode 100644 index 00000000..db93bd06 --- /dev/null +++ b/frontend/src/app/(public-area)/articles/capital-one-data-breach.tsx @@ -0,0 +1,97 @@ +const article = { + title: 'Capital One Data Breach – A Cautionary Tale', + description: + 'Capital One lost hundreds of millions after being notified by a third party of an intruder that had been lurking in their AWS account for four months.', + date: new Date(Date.parse('2025-04-15T23:10:00-04:00')), + content: ( + <> +

+ In July of 2019, Capital One Financial Corporation announced that they had recently become aware of a + data breach compromising the personal data of over 100 million customers in the United States, including + 140,000 Social Security numbers and 80,000 bank account numbers. Capital One estimated that the direct + financial impact of the incident would be between $100 million and $150 million for notifications, + credit monitoring, technology, and legal support. Furthermore, trust in the company had plummeted, and + within two weeks of the incident, Capital One's share price had dropped by 14%. +

+

+ The impact was substantial, but it might have been much less severe if not for the fact that{' '} + the breach had occurred almost four months before it was discovered. Capital One had + been moving its operations to the cloud, and had failed to adequately manage the risk of doing so. This + mistake would later cost them another $80 million in fines when all was said and done. +

+

+ So what should they have done to manage their risk better? Let's break down the incident in detail + so we can learn from their mistakes. +

+

Foothold

+

+ On March 22, 2019, the attacker discovered that they could trick Capital One EC2 servers running in AWS + into executing arbitrary HTTP requests, enabling a type of attack known as Server Side Request Forgery + (SSRF). They were able to do this as a result of a misconfigured web application firewall (WAF) known as + ModSecurity. The WAF allowed the attacker to send requests to the AWS metadata service, which among + other things provides the EC2 servers with temporary credentials for the purpose of invoking AWS APIs. +

+

+ At this point, the attacker could impersonate the EC2 servers and perform any action that the associated + IAM role allowed. +

+

Lateral Movement

+

+ Once the attacker gained their foothold, they began to enumerate everything they had access to. Usually,{' '} + this is loud as attackers typically just have to try things and see what works. If you + were to look at this role in Cloud Snitch, you would see it attempting (and hopefully failing) to do a + lot of things that you would not expect a WAF to do. +

+

+ In Capital One's case, the permissions attached to the role allowed the attacker to read and + decrypt sensitive data from Amazon S3 buckets. The attacker was able to exfiltrate all of this data via + the WAF's credentials, which again should have sounded alarm bells. +

+

Discovery

+

+ Capital One had completely failed to detect the intrusion. They only became aware of it when a third + party notified them via their Responsible Disclosure Program on July 17, 2019. +

+

+ Capital One was completely oblivious to the fact that there was an intruder in their cloud for almost + four months. The presence of the intruder would have made a lot of noise in their CloudTrail logs, but + without the proper tools, that log activity went completely unnoticed. This is why Cloud Snitch was + created. +

+

+ + With Cloud Snitch, you can easily confirm that your AWS resources are doing what you expect them to + do and nothing more. + +

+ + ), + relatedLinks: [ + { + title: 'Capital One Announces Data Security Incident', + url: 'https://investor.capitalone.com/news-releases/news-release-details/capital-one-announces-data-security-incident/', + }, + { + title: 'Information on the Capital One cyber incident', + url: 'https://www.capitalone.com/digital/facts2019/', + }, + { + title: 'A Systematic Analysis of the Capital One Data Breach: Critical Lessons Learned', + url: 'https://dl.acm.org/doi/10.1145/3546068', + }, + { + title: 'Capital One to pay $80 million fine after data breach', + url: 'https://www.reuters.com/article/business/capital-one-to-pay-80-million-fine-after-data-breach-idUSKCN2522D8/', + }, + { + title: 'Capital One Data Breach — 2019', + url: 'https://medium.com/nerd-for-tech/capital-one-data-breach-2019-f85a259eaa60', + }, + { + title: 'Lessons from the Capital One Breach on Cloud Security', + url: 'https://www.darktrace.com/blog/back-to-square-one-the-capital-one-breach-proved-we-must-rethink-cloud-security', + }, + ], +}; + +export default article; diff --git a/frontend/src/app/(public-area)/articles/capital-one-data-breach/page.tsx b/frontend/src/app/(public-area)/articles/capital-one-data-breach/page.tsx deleted file mode 100644 index 75f79c11..00000000 --- a/frontend/src/app/(public-area)/articles/capital-one-data-breach/page.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import type { Metadata } from 'next'; -import Link from 'next/link'; - -const FURTHER_READING = [ - { - title: 'Capital One Announces Data Security Incident', - url: 'https://investor.capitalone.com/news-releases/news-release-details/capital-one-announces-data-security-incident/', - }, - { - title: 'Information on the Capital One cyber incident', - url: 'https://www.capitalone.com/digital/facts2019/', - }, - { - title: 'A Systematic Analysis of the Capital One Data Breach: Critical Lessons Learned', - url: 'https://dl.acm.org/doi/10.1145/3546068', - }, - { - title: 'Capital One to pay $80 million fine after data breach', - url: 'https://www.reuters.com/article/business/capital-one-to-pay-80-million-fine-after-data-breach-idUSKCN2522D8/', - }, - { - title: 'Capital One Data Breach — 2019', - url: 'https://medium.com/nerd-for-tech/capital-one-data-breach-2019-f85a259eaa60', - }, - { - title: 'Lessons from the Capital One Breach on Cloud Security', - url: 'https://www.darktrace.com/blog/back-to-square-one-the-capital-one-breach-proved-we-must-rethink-cloud-security', - }, -]; - -export const metadata: Metadata = { - title: 'Capital One Data Breach – A Cautionary Tale', - description: - 'Capital One lost hundreds of millions after being notified by a third party of an intruder that had been lurking in their AWS account for four months.', -}; - -const Page = () => { - return ( -
-
-

Capital One Data Breach – A Cautionary Tale

-

- In July of 2019, Capital One Financial Corporation announced that they had recently become aware of - a data breach compromising the personal data of over 100 million customers in the United States, - including 140,000 Social Security numbers and 80,000 bank account numbers. Capital One estimated - that the direct financial impact of the incident would be between $100 million and $150 million for - notifications, credit monitoring, technology, and legal support. Furthermore, trust in the company - had plummeted, and within two weeks of the incident, Capital One's share price had dropped by - 14%. -

-

- The impact was substantial, but it might have been much less severe if not for the fact that{' '} - the breach had occurred almost four months before it was discovered. Capital One - had been moving its operations to the cloud, and had failed to adequately manage the risk of doing - so. This mistake would later cost them another $80 million in fines when all was said and done. -

-

- So what should they have done to manage their risk better? Let's break down the incident in - detail so we can learn from their mistakes. -

-

Foothold

-

- On March 22, 2019, the attacker discovered that they could trick Capital One EC2 servers running in - AWS into executing arbitrary HTTP requests, enabling a type of attack known as Server Side Request - Forgery (SSRF). They were able to do this as a result of a misconfigured web application firewall - (WAF) known as ModSecurity. The WAF allowed the attacker to send requests to the AWS metadata - service, which among other things provides the EC2 servers with temporary credentials for the - purpose of invoking AWS APIs. -

-

- At this point, the attacker could impersonate the EC2 servers and perform any action that the - associated IAM role allowed. -

-

Lateral Movement

-

- Once the attacker gained their foothold, they began to enumerate everything they had access to. - Usually, this is loud as attackers typically just have to try things and see what - works. If you were to look at this role in Cloud Snitch, you would see it attempting (and hopefully - failing) to do a lot of things that you would not expect a WAF to do. -

-

- In Capital One's case, the permissions attached to the role allowed the attacker to read and - decrypt sensitive data from Amazon S3 buckets. The attacker was able to exfiltrate all of this data - via the WAF's credentials, which again should have sounded alarm bells. -

-

Discovery

-

- Capital One had completely failed to detect the intrusion. They only became aware of it when a third - party notified them via their Responsible Disclosure Program on July 17, 2019. -

-

- Capital One was completely oblivious to the fact that there was an intruder in their cloud for - almost four months. The presence of the intruder would have made a lot of noise in their CloudTrail - logs, but without the proper tools, that log activity went completely unnoticed. This is why Cloud - Snitch was created. -

-

- - With Cloud Snitch, you can easily confirm that your AWS resources are doing what you expect them - to do and nothing more. - -

-
- -
-

Further Reading

-
    - {FURTHER_READING.map((item, index) => ( -
  • - - {item.title} - -
  • - ))} -
-
-
- ); -}; - -export default Page; diff --git a/frontend/src/app/(public-area)/articles/index.tsx b/frontend/src/app/(public-area)/articles/index.tsx new file mode 100644 index 00000000..8f17216b --- /dev/null +++ b/frontend/src/app/(public-area)/articles/index.tsx @@ -0,0 +1,13 @@ +import CapitalOneDataBreach from './capital-one-data-breach'; + +interface Article { + title: string; + description: string; + date: Date; + content: React.ReactNode; + relatedLinks?: Array<{ title: string; url: string }>; +} + +export const articles: Record = { + 'capital-one-data-breach': CapitalOneDataBreach, +}; diff --git a/frontend/src/app/(public-area)/articles/page.tsx b/frontend/src/app/(public-area)/articles/page.tsx new file mode 100644 index 00000000..e906dbac --- /dev/null +++ b/frontend/src/app/(public-area)/articles/page.tsx @@ -0,0 +1,49 @@ +import { ChevronRightIcon } from '@heroicons/react/24/outline'; +import type { Metadata } from 'next'; +import Link from 'next/link'; + +import { articles } from '.'; + +export const metadata: Metadata = { + title: 'Articles', + description: 'Articles and resources related to AWS, InfoSec, and Cloud Snitch.', +}; + +const Page = () => { + const sortedArticles = Object.entries(articles).sort(([, a], [, b]) => b.date.getTime() - a.date.getTime()); + + return ( +
+
+

Articles

+
+ {sortedArticles.map(([slug, article]) => ( +
+

{article.title}

+
+ {article.date.toLocaleDateString('en-US', { + weekday: 'long', + year: 'numeric', + month: 'long', + day: 'numeric', + })} +
+

{article.description}

+
+ + Read More + + +
+
+ ))} +
+
+
+ ); +}; + +export default Page;