# Serverless.com 보안
{{#include ../banners/hacktricks-training.md}}
## 기본 정보
### 조직
**조직**은 Serverless Framework 생태계 내에서 가장 높은 수준의 엔티티입니다. 이는 여러 프로젝트, 팀 및 애플리케이션을 포함하는 **집단 그룹**을 나타냅니다. 예를 들어 회사, 부서 또는 기타 대규모 엔티티가 될 수 있습니다.
### 팀
**팀**은 조직 내에서 접근 권한이 있는 사용자들입니다. 팀은 역할에 따라 구성원을 조직하는 데 도움을 줍니다. **`협력자`**는 기존 앱을 보고 배포할 수 있으며, **`관리자`**는 새로운 앱을 생성하고 조직 설정을 관리할 수 있습니다.
### 애플리케이션
**앱**은 조직 내에서 관련 서비스의 논리적 그룹화입니다. 이는 여러 서버리스 서비스로 구성된 완전한 애플리케이션을 나타내며, 이 서비스들은 함께 작동하여 일관된 기능을 제공합니다.
### **서비스**
**서비스**는 서버리스 애플리케이션의 핵심 구성 요소입니다. 이는 전체 서버리스 프로젝트를 나타내며, 필요한 모든 함수, 구성 및 리소스를 캡슐화합니다. 일반적으로 `serverless.yml` 파일에 정의되며, 서비스에는 서비스 이름, 제공자 구성, 함수, 이벤트, 리소스, 플러그인 및 사용자 정의 변수를 포함한 메타데이터가 포함됩니다.
```yaml
service: my-service
provider:
name: aws
runtime: nodejs14.x
functions:
hello:
handler: handler.hello
```
Function
A **Function**는 AWS Lambda 함수와 같은 단일 서버리스 함수를 나타냅니다. 이벤트에 응답하여 실행되는 코드를 포함합니다.
`serverless.yml`의 `functions` 섹션 아래에 정의되며, 핸들러, 런타임, 이벤트, 환경 변수 및 기타 설정을 지정합니다.
```yaml
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
```
이벤트
**이벤트**는 서버리스 함수를 호출하는 트리거입니다. 이들은 함수가 어떻게 그리고 언제 실행되어야 하는지를 정의합니다.
일반적인 이벤트 유형에는 HTTP 요청, 예약된 이벤트(크론 작업), 데이터베이스 이벤트, 파일 업로드 등이 포함됩니다.
```yaml
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
- schedule:
rate: rate(10 minutes)
```
리소스
**리소스**는 데이터베이스, 스토리지 버킷 또는 IAM 역할과 같이 서비스가 의존하는 추가 클라우드 리소스를 정의할 수 있게 해줍니다.
이들은 `resources` 섹션 아래에 지정되며, 종종 AWS의 CloudFormation 구문을 사용합니다.
```yaml
resources:
Resources:
MyDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: my-table
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
```
Provider
**Provider** 객체는 클라우드 서비스 제공업체(예: AWS, Azure, Google Cloud)를 지정하고 해당 제공업체와 관련된 구성 설정을 포함합니다.
런타임, 지역, 단계 및 자격 증명과 같은 세부정보를 포함합니다.
```yaml
yamlCopy codeprovider:
name: aws
runtime: nodejs14.x
region: us-east-1
stage: dev
```
단계 및 지역
단계는 서비스가 배포될 수 있는 다양한 환경(예: 개발, 스테이징, 프로덕션)을 나타냅니다. 이는 환경별 구성 및 배포를 허용합니다.
```yaml
provider:
stage: dev
```
지역은 리소스가 배포될 지리적 지역을 지정합니다. 이는 지연 시간, 규정 준수 및 가용성 고려 사항에 중요합니다.
```yaml
provider:
region: us-west-2
```
플러그인
**플러그인**은 새로운 기능을 추가하거나 다른 도구 및 서비스와 통합하여 Serverless Framework의 기능을 확장합니다. 이들은 `plugins` 섹션에 정의되며 npm을 통해 설치됩니다.
```yaml
plugins:
- serverless-offline
- serverless-webpack
```
레이어
**레이어**는 공유 코드 또는 종속성을 함수와 별도로 패키징하고 관리할 수 있게 해줍니다. 이는 재사용성을 촉진하고 배포 패키지 크기를 줄입니다. 레이어는 `layers` 섹션 아래에 정의되며 함수에서 참조됩니다.
```yaml
layers:
commonLibs:
path: layer-common
functions:
hello:
handler: handler.hello
layers:
- { Ref: CommonLibsLambdaLayer }
```
변수 및 사용자 정의 변수
**변수**는 배포 시 해결되는 자리 표시자를 사용하여 동적 구성을 가능하게 합니다.
- **구문:** `${variable}` 구문은 환경 변수, 파일 내용 또는 기타 구성 매개변수를 참조할 수 있습니다.
```yaml
functions:
hello:
handler: handler.hello
environment:
TABLE_NAME: ${self:custom.tableName}
```
* **사용자 정의 변수:** `custom` 섹션은 `serverless.yml` 전반에 걸쳐 재사용할 수 있는 사용자 특정 변수 및 구성을 정의하는 데 사용됩니다.
```yaml
custom:
tableName: my-dynamodb-table
stage: ${opt:stage, 'dev'}
```
출력
**출력**은 서비스가 배포된 후 반환되는 값들을 정의하며, 리소스 ARN, 엔드포인트 또는 기타 유용한 정보가 포함됩니다. 이들은 `outputs` 섹션 아래에 지정되며, 종종 다른 서비스에 정보를 노출하거나 배포 후 쉽게 접근할 수 있도록 사용됩니다.
```yaml
¡outputs:
ApiEndpoint:
Description: "API Gateway endpoint URL"
Value:
Fn::Join:
- ""
- - "https://"
- Ref: ApiGatewayRestApi
- ".execute-api."
- Ref: AWS::Region
- ".amazonaws.com/"
- Ref: AWS::Stage
```
IAM 역할 및 권한
**IAM 역할 및 권한**은 함수 및 기타 리소스에 대한 보안 자격 증명과 접근 권한을 정의합니다. 이들은 필요한 권한을 지정하기 위해 `provider` 또는 개별 함수 설정에서 관리됩니다.
```yaml
provider:
[...]
iam:
role:
statements:
- Effect: 'Allow'
Action:
- 'dynamodb:PutItem'
- 'dynamodb:Get*'
- 'dynamodb:Scan*'
- 'dynamodb:UpdateItem'
- 'dynamodb:DeleteItem'
Resource: arn:aws:dynamodb:${aws:region}:${aws:accountId}:table/${self:service}-customerTable-${sls:stage}
```
환경 변수
**변수**는 하드코딩하지 않고도 구성 설정 및 비밀을 함수에 전달할 수 있게 해줍니다. 이들은 제공자 또는 개별 함수의 `environment` 섹션 아래에 정의됩니다.
```yaml
provider:
environment:
STAGE: ${self:provider.stage}
functions:
hello:
handler: handler.hello
environment:
TABLE_NAME: ${self:custom.tableName}
```
종속성
**종속성**은 함수에 필요한 외부 라이브러리와 모듈을 관리합니다. 일반적으로 npm 또는 pip와 같은 패키지 관리자를 통해 처리되며, `serverless-webpack`과 같은 도구나 플러그인을 사용하여 배포 패키지와 함께 번들됩니다.
```yaml
plugins:
- serverless-webpack
```
후크
**후크**는 배포 생애 주기의 특정 지점에서 사용자 정의 스크립트나 명령을 실행할 수 있게 해줍니다. 이들은 플러그인을 사용하거나 `serverless.yml` 내에서 정의되어 배포 전후에 작업을 수행합니다.
```yaml
custom:
hooks:
before:deploy:deploy: echo "Starting deployment..."
```
### 튜토리얼
이것은 공식 튜토리얼의 요약입니다 [**문서에서**](https://www.serverless.com/framework/docs/tutorial):
1. AWS 계정 생성 (Serverless.com은 AWS 인프라에서 시작)
2. serverless.com에 계정 생성
3. 앱 생성:
```bash
# Create temp folder for the tutorial
mkdir /tmp/serverless-tutorial
cd /tmp/serverless-tutorial
# Install Serverless cli
npm install -g serverless
# Generate template
serverless #Choose first one (AWS / Node.js / HTTP API)
## Indicate a name like "Tutorial"
## Login/Register
## Create A New App
## Indicate a name like "tutorialapp)
```
이것은 **app**인 `tutorialapp`을 생성했어야 하며, [serverless.com](serverless.com-security.md)에서 확인할 수 있고, `helloworld` 코드가 포함된 JS 코드가 있는 **`handler.js`** 파일과 해당 함수를 선언하는 **`serverless.yml`** 파일이 있는 `Tutorial`이라는 폴더를 생성했어야 합니다:
{{#tabs }}
{{#tab name="handler.js" }}
```javascript
exports.hello = async (event) => {
return {
statusCode: 200,
body: JSON.stringify({
message: "Go Serverless v4! Your function executed successfully!",
}),
}
}
```
{{#endtab }}
{{#tab name="serverless.yml" }}
```yaml
# "org" ensures this Service is used with the correct Serverless Framework Access Key.
org: testing12342
# "app" enables Serverless Framework Dashboard features and sharing them with other Services.
app: tutorialapp
# "service" is the name of this project. This will also be added to your AWS resource names.
service: Tutorial
provider:
name: aws
runtime: nodejs20.x
functions:
hello:
handler: handler.hello
events:
- httpApi:
path: /
method: get
```
{{#endtab }}
{{#endtabs }}
4. **대시보드**에서 AWS 공급자를 생성합니다: `https://app.serverless.com//settings/providers?providerId=new&provider=aws`.
1. `serverless.com`에 AWS 접근 권한을 부여하기 위해, 이 구성 파일을 사용하여 클라우드포메이션 스택을 실행하라는 요청이 있습니다 (이 글을 작성할 당시): [https://serverless-framework-template.s3.amazonaws.com/roleTemplate.yml](https://serverless-framework-template.s3.amazonaws.com/roleTemplate.yml)
2. 이 템플릿은 **`SFRole-`**라는 역할을 생성하며, **`arn:aws:iam::aws:policy/AdministratorAccess`**를 통해 `Serverless.com` AWS 계정이 역할에 접근할 수 있도록 허용하는 신뢰 ID를 갖습니다.
Yaml roleTemplate
```yaml
Description: This stack creates an IAM role that can be used by Serverless Framework for use in deployments.
Resources:
SFRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: arn:aws:iam::486128539022:root
Action:
- sts:AssumeRole
Condition:
StringEquals:
sts:ExternalId: !Sub "ServerlessFramework-${OrgUid}"
Path: /
RoleName: !Ref RoleName
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
ReporterFunction:
Type: Custom::ServerlessFrameworkReporter
Properties:
ServiceToken: "arn:aws:lambda:us-east-1:486128539022:function:sp-providers-stack-reporter-custom-resource-prod-tmen2ec"
OrgUid: !Ref OrgUid
RoleArn: !GetAtt SFRole.Arn
Alias: !Ref Alias
Outputs:
SFRoleArn:
Description: "ARN for the IAM Role used by Serverless Framework"
Value: !GetAtt SFRole.Arn
Parameters:
OrgUid:
Description: Serverless Framework Org Uid
Type: String
Alias:
Description: Serverless Framework Provider Alias
Type: String
RoleName:
Description: Serverless Framework Role Name
Type: String
```
신뢰 관계
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::486128539022:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "ServerlessFramework-7bf7ddef-e1bf-43eb-a111-4d43e0894ccb"
}
}
}
]
}
```
5. 튜토리얼에서는 `createCustomer.js` 파일을 생성하라고 요청하며, 이 파일은 기본적으로 새로운 API 엔드포인트를 생성하고, `serverless.yml` 파일을 수정하여 **새로운 DynamoDB 테이블**을 생성하고, **환경 변수**를 정의하며, 생성된 람다를 사용할 역할을 설정하라고 요청합니다.
{{#tabs }}
{{#tab name="createCustomer.js" }}
```javascript
"use strict"
const AWS = require("aws-sdk")
module.exports.createCustomer = async (event) => {
const body = JSON.parse(Buffer.from(event.body, "base64").toString())
const dynamoDb = new AWS.DynamoDB.DocumentClient()
const putParams = {
TableName: process.env.DYNAMODB_CUSTOMER_TABLE,
Item: {
primary_key: body.name,
email: body.email,
},
}
await dynamoDb.put(putParams).promise()
return {
statusCode: 201,
}
}
```
{{#endtab }}
{{#tab name="serverless.yml" }}
```yaml
# "org" ensures this Service is used with the correct Serverless Framework Access Key.
org: testing12342
# "app" enables Serverless Framework Dashboard features and sharing them with other Services.
app: tutorialapp
# "service" is the name of this project. This will also be added to your AWS resource names.
service: Tutorial
provider:
name: aws
runtime: nodejs20.x
environment:
DYNAMODB_CUSTOMER_TABLE: ${self:service}-customerTable-${sls:stage}
iam:
role:
statements:
- Effect: "Allow"
Action:
- "dynamodb:PutItem"
- "dynamodb:Get*"
- "dynamodb:Scan*"
- "dynamodb:UpdateItem"
- "dynamodb:DeleteItem"
Resource: arn:aws:dynamodb:${aws:region}:${aws:accountId}:table/${self:service}-customerTable-${sls:stage}
functions:
hello:
handler: handler.hello
events:
- httpApi:
path: /
method: get
createCustomer:
handler: createCustomer.createCustomer
events:
- httpApi:
path: /
method: post
resources:
Resources:
CustomerTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: primary_key
AttributeType: S
BillingMode: PAY_PER_REQUEST
KeySchema:
- AttributeName: primary_key
KeyType: HASH
TableName: ${self:service}-customerTable-${sls:stage}
```
{{#endtab }}
{{#endtabs }}
6. **`serverless deploy`** 명령어로 배포합니다.
1. 배포는 CloudFormation Stack을 통해 수행됩니다.
2. **람다 함수는 직접 URL이 아닌 API 게이트웨이를 통해 노출됩니다.**
7. **테스트합니다.**
1. 이전 단계에서는 API 엔드포인트 람다 함수가 배포된 **URL**을 출력합니다.
## Serverless.com의 보안 검토
### **잘못 구성된 IAM 역할 및 권한**
과도하게 허용된 IAM 역할은 클라우드 리소스에 대한 무단 액세스를 허용하여 데이터 유출 또는 리소스 조작으로 이어질 수 있습니다.
람다 함수에 대한 권한이 지정되지 않으면, 로그 생성 권한만 있는 역할이 생성됩니다.
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogStream",
"logs:CreateLogGroup",
"logs:TagResource"
],
"Resource": [
"arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/jito-cranker-scripts-dev*:*"
],
"Effect": "Allow"
},
{
"Action": ["logs:PutLogEvents"],
"Resource": [
"arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/jito-cranker-scripts-dev*:*:*"
],
"Effect": "Allow"
}
]
}
```
#### **완화 전략**
- **최소 권한 원칙:** 각 함수에 필요한 권한만 할당합니다.
```yaml
provider:
[...]
iam:
role:
statements:
- Effect: 'Allow'
Action:
- 'dynamodb:PutItem'
- 'dynamodb:Get*'
- 'dynamodb:Scan*'
- 'dynamodb:UpdateItem'
- 'dynamodb:DeleteItem'
Resource: arn:aws:dynamodb:${aws:region}:${aws:accountId}:table/${self:service}-customerTable-${sls:stage}
```
- **별도의 역할 사용:** 함수 요구 사항에 따라 역할을 구분합니다.
---
### **안전하지 않은 비밀 및 구성 관리**
민감한 정보(예: API 키, 데이터베이스 자격 증명)를 **`serverless.yml`** 또는 코드에 직접 저장하면 리포지토리가 손상될 경우 노출될 수 있습니다.
**추천되는** 방법은 serverless.com의 **`serverless.yml`** 파일에서 환경 변수를 저장하는 것으로, `ssm` 또는 `s3` 공급자를 사용하여 **배포 시 이러한 소스에서 환경 값을 가져오고** **lambdas** 환경 변수를 **값이 없는 텍스트로 구성**하는 것입니다!
> [!CAUTION]
> 따라서 AWS 내에서 lambdas 구성을 읽을 수 있는 권한이 있는 사람은 **모든 이러한 환경 변수를 평문으로 접근할 수 있습니다!**
예를 들어, 다음 예제는 SSM을 사용하여 환경 변수를 가져옵니다:
```yaml
provider:
environment:
DB_PASSWORD: ${ssm:/aws/reference/secretsmanager/my-db-password~true}
```
그리고 이것이 **`serverless.yml`** 파일에 환경 변수 값을 하드코딩하는 것을 방지하더라도, 값은 배포 시점에 얻어지며 **람다 환경 변수 안에 평문으로 추가됩니다**.
> [!TIP]
> serveless.com을 사용하여 환경 변수를 저장하는 권장 방법은 **AWS 비밀에 저장**하고 비밀 이름만 환경 변수에 저장하며 **람다 코드가 이를 수집해야 합니다**.
#### **완화 전략**
- **비밀 관리자 통합:** **AWS Secrets Manager**와 같은 서비스를 사용합니다.
- **암호화된 변수:** 민감한 데이터에 대해 Serverless Framework의 암호화 기능을 활용합니다.
- **접근 제어:** 역할에 따라 비밀에 대한 접근을 제한합니다.
---
### **취약한 코드 및 종속성**
구식 또는 안전하지 않은 종속성은 취약점을 도입할 수 있으며, 부적절한 입력 처리는 코드 주입 공격으로 이어질 수 있습니다.
#### **완화 전략**
- **종속성 관리:** 종속성을 정기적으로 업데이트하고 취약점을 스캔합니다.
```yaml
plugins:
- serverless-webpack
- serverless-plugin-snyk
```
- **입력 검증:** 모든 입력에 대해 엄격한 검증 및 정화를 구현합니다.
- **코드 리뷰:** 보안 결함을 식별하기 위해 철저한 리뷰를 수행합니다.
- **정적 분석:** 코드베이스의 취약점을 감지하기 위해 도구를 사용합니다.
---
### **부적절한 로깅 및 모니터링**
적절한 로깅 및 모니터링이 없으면 악의적인 활동이 감지되지 않을 수 있으며, 사건 대응이 지연될 수 있습니다.
#### **완화 전략**
- **중앙 집중식 로깅:** **AWS CloudWatch** 또는 **Datadog**와 같은 서비스를 사용하여 로그를 집계합니다.
```yaml
plugins:
- serverless-plugin-datadog
```
- **상세 로깅 활성화:** 민감한 데이터를 노출하지 않으면서 필수 정보를 캡처합니다.
- **알림 설정:** 의심스러운 활동이나 이상 징후에 대한 알림을 구성합니다.
- **정기 모니터링:** 잠재적인 보안 사건에 대해 로그 및 메트릭을 지속적으로 모니터링합니다.
---
### **불안전한 API 게이트웨이 구성**
열려 있거나 부적절하게 보호된 API는 무단 접근, 서비스 거부(DoS) 공격 또는 교차 사이트 공격에 악용될 수 있습니다.
#### **완화 전략**
- **인증 및 권한 부여:** OAuth, API 키 또는 JWT와 같은 강력한 메커니즘을 구현합니다.
```yaml
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
authorizer: aws_iam
```
- **요청 속도 제한 및 조절:** 요청 속도를 제한하여 남용을 방지합니다.
```yaml
provider:
apiGateway:
throttle:
burstLimit: 200
rateLimit: 100
```
- **안전한 CORS 구성:** 허용된 출처, 메서드 및 헤더를 제한합니다.
```yaml
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
cors:
origin: https://yourdomain.com
headers:
- Content-Type
```
- **웹 애플리케이션 방화벽(WAF) 사용:** 악의적인 패턴에 대해 HTTP 요청을 필터링하고 모니터링합니다.
---
### **불충분한 함수 격리**
공유 리소스와 불충분한 격리는 권한 상승 또는 함수 간의 의도하지 않은 상호작용을 초래할 수 있습니다.
#### **완화 전략**
- **함수 격리:** 독립적인 작동을 보장하기 위해 고유한 리소스 및 IAM 역할을 할당합니다.
- **리소스 분할:** 서로 다른 함수에 대해 별도의 데이터베이스 또는 저장소 버킷을 사용합니다.
- **VPC 사용:** 향상된 네트워크 격리를 위해 가상 사설 클라우드 내에서 함수를 배포합니다.
```yaml
provider:
vpc:
securityGroupIds:
- sg-xxxxxxxx
subnetIds:
- subnet-xxxxxx
```
- **함수 권한 제한:** 함수가 명시적으로 요구되지 않는 한 서로의 리소스에 접근하거나 간섭할 수 없도록 합니다.
---
### **불충분한 데이터 보호**
정지 상태 또는 전송 중 암호화되지 않은 데이터는 노출될 수 있으며, 데이터 유출 또는 변조로 이어질 수 있습니다.
#### **완화 전략**
- **정지 상태 데이터 암호화:** 클라우드 서비스 암호화 기능을 활용합니다.
```yaml
resources:
Resources:
MyDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
SSESpecification:
SSEEnabled: true
```
- **전송 중 데이터 암호화:** 모든 데이터 전송에 대해 HTTPS/TLS를 사용합니다.
- **API 통신 보안:** 암호화 프로토콜을 시행하고 인증서를 검증합니다.
- **암호화 키를 안전하게 관리:** 관리형 키 서비스를 사용하고 키를 정기적으로 교체합니다.
---
### **적절한 오류 처리 부족**
상세한 오류 메시지는 인프라 또는 코드베이스에 대한 민감한 정보를 유출할 수 있으며, 처리되지 않은 예외는 애플리케이션 충돌로 이어질 수 있습니다.
#### **완화 전략**
- **일반 오류 메시지:** 오류 응답에서 내부 세부 정보를 노출하지 않도록 합니다.
```javascript
javascriptCopy code// Node.js의 예
exports.hello = async (event) => {
try {
// 함수 로직
} catch (error) {
console.error(error);
return {
statusCode: 500,
body: JSON.stringify({ message: 'Internal Server Error' }),
};
}
};
```
- **중앙 집중식 오류 처리:** 모든 함수에서 오류를 일관되게 관리하고 정화합니다.
- **오류 모니터링 및 로깅:** 세부 정보를 최종 사용자에게 노출하지 않고 내부적으로 오류를 추적하고 분석합니다.
---
### **불안전한 배포 관행**
노출된 배포 구성 또는 CI/CD 파이프라인에 대한 무단 접근은 악의적인 코드 배포 또는 잘못된 구성을 초래할 수 있습니다.
#### **완화 전략**
- **CI/CD 파이프라인 보안:** 엄격한 접근 제어, 다단계 인증(MFA) 및 정기 감사 구현합니다.
- **구성을 안전하게 저장:** 배포 파일에서 하드코딩된 비밀 및 민감한 데이터를 제거합니다.
- **코드로서의 인프라(IaC) 보안 도구 사용:** **Checkov** 또는 **Terraform Sentinel**과 같은 도구를 사용하여 보안 정책을 시행합니다.
- **불변 배포:** 불변 인프라 관행을 채택하여 배포 후 무단 변경을 방지합니다.
---
### **플러그인 및 확장 프로그램의 취약점**
검증되지 않거나 악의적인 제3자 플러그인을 사용하면 서버리스 애플리케이션에 취약점을 도입할 수 있습니다.
#### **완화 전략**
- **플러그인 철저 검토:** 통합 전에 플러그인의 보안을 평가하고 평판이 좋은 출처의 플러그인을 선호합니다.
- **플러그인 사용 제한:** 공격 표면을 최소화하기 위해 필요한 플러그인만 사용합니다.
- **플러그인 업데이트 모니터링:** 보안 패치를 활용하기 위해 플러그인을 최신 상태로 유지합니다.
- **플러그인 환경 격리:** 잠재적인 손상을 방지하기 위해 플러그인을 격리된 환경에서 실행합니다.
---
### **민감한 엔드포인트 노출**
공개적으로 접근 가능한 함수 또는 제한 없는 API는 무단 작업에 악용될 수 있습니다.
#### **완화 전략**
- **함수 접근 제한:** VPC, 보안 그룹 및 방화벽 규칙을 사용하여 신뢰할 수 있는 출처로의 접근을 제한합니다.
- **강력한 인증 구현:** 모든 노출된 엔드포인트가 적절한 인증 및 권한 부여를 요구하도록 합니다.
- **API 게이트웨이를 안전하게 사용:** API 게이트웨이를 구성하여 입력 검증 및 속도 제한을 포함한 보안 정책을 시행합니다.
- **사용하지 않는 엔드포인트 비활성화:** 더 이상 사용하지 않는 엔드포인트를 정기적으로 검토하고 비활성화합니다.
---
### **팀원 및 외부 협력자에 대한 과도한 권한**
팀원 및 외부 협력자에게 과도한 권한을 부여하면 무단 접근, 데이터 유출 및 리소스 남용으로 이어질 수 있습니다. 이 위험은 여러 개인이 다양한 수준의 접근 권한을 가진 환경에서 더욱 커지며, 공격 표면과 내부 위협의 가능성을 증가시킵니다.
#### **완화 전략**
- **최소 권한 원칙:** 팀원 및 협력자가 작업을 수행하는 데 필요한 권한만 가지도록 합니다.
---
### **액세스 키 및 라이센스 키 보안**
**액세스 키** 및 **라이센스 키**는 Serverless Framework CLI와의 상호작용을 인증하고 권한을 부여하는 데 사용되는 중요한 자격 증명입니다.
- **라이센스 키:** CLI를 통해 로그인할 수 있도록 하는 Serverless Framework 버전 4에 대한 인증에 필요한 고유 식별자입니다.
- **액세스 키:** Serverless Framework Dashboard와 인증하기 위해 Serverless Framework CLI가 사용하는 자격 증명입니다. `serverless` cli로 로그인할 때 액세스 키가 **생성되어 노트북에 저장됩니다**. 또한 `SERVERLESS_ACCESS_KEY`라는 환경 변수로 설정할 수 있습니다.
#### **보안 위험**
1. **코드 리포지토리를 통한 노출:**
- 액세스 키 및 라이센스 키를 하드코딩하거나 실수로 버전 관리 시스템에 커밋하면 무단 접근이 발생할 수 있습니다.
2. **안전하지 않은 저장:**
- 적절한 암호화 없이 환경 변수나 구성 파일 내에 평문으로 키를 저장하면 유출 가능성이 높아집니다.
3. **부적절한 배포:**
- 안전하지 않은 채널(예: 이메일, 채팅)을 통해 키를 공유하면 악의적인 행위자에게 가로채질 수 있습니다.
4. **회전 부족:**
- 키를 정기적으로 회전하지 않으면 키가 손상된 경우 노출 기간이 연장됩니다.
5. **과도한 권한:**
- 광범위한 권한을 가진 키는 여러 리소스에서 무단 작업을 수행하는 데 악용될 수 있습니다.
{{#include ../banners/hacktricks-training.md}}