AWS 보안 스터디 그룹 ( 23.08.27 ~ 

 

1주차 : S3 취약점 및 보안

 

  1. AWS CloudFormation 스택 배포
    ▶ AWS CloudFormation : AWS의 대표적인 IaC 기반의 구성 조정 도구
    스택을 생성할 때 마다 AWS CloudFormation에서 템플릿에 설명된 리소스를 프로비저닝과 구성을 담당
    AWS 리소스를 수동으로 생성하거나 구성할 필요가 없고 어떤 것이 무엇에 의존하는지 파악할 필요 X
    ▶ 장점 : 인프라 관리 간소화, 신속하게 인프라 복제, 인프라 변경 사항을 쉽게 제어 및 추적
    ▶ 템플릿 및 스택으로 작업
    - 템플릿을 생성하여 AWS 리소스와 해당 속성에 대해 설명
    - 스택을 생성할 때마다 AWS CloudFormation에서 템플릿에 설명된 리소스를 프로비저

스택 생성
스택 세부 정보 지정

KeyName에서 사용하는 Key 선택 필요

스택 옵션 구성
생성한 스택 리스트(상태 값이 CREATE_COMPLETE 뜨면 EC2 확인 가능)
스택으로 인해 생성된 EC2 확인


2. IAM 자격증명 설정 및 CloudFormation 스택 배포 (cli에서)
# aws configure

초기화 방법 : .aws 폴더 삭제

더보기

# 변수 지정
KEYNAME=<각자 자신의 SSH Keypair Name>

# YAML 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/security/ahss-ec2.yaml

# CloudFormation 스택 배포
aws cloudformation deploy --template-file ahss-ec2.yaml --stack-name myec2 --parameter-overrides KeyName=$KEYNAME --region ap-northeast-2

# CloudFormation 스택 배포 완료 후 작업용 EC2 IP 출력
aws cloudformation describe-stacks --stack-name myec2 --query 'Stacks[*].Outputs[0].OutputValue' --output text
 
# 작업용 EC2 SSH 접속 : 아래 키파일 경로는 자신의 환경에 맞게 변경하자!
ssh -i ~/.ssh/kp-gasida.pem ec2-user@$(aws cloudformation describe-stacks --stack-name myec2 --query 'Stacks[*].Outputs[0].OutputValue' --output text)

3. [AWS 콘솔] AWS S3 버킷 생성

  • (옵션) AWS CLI로 실행 : IAM 자격증명 설정되어 있는 상태 / 자격증명 설정이 없을 경우 AWS CloudShell에서 사용 가능
# S3 버킷 생성
# aws s3 mb s3://버킷(유일한 이름) --region ap-northeast-2
NICKNAME=phj
aws s3 mb s3://ahss-$NICKNAME --region ap-northeast-2

# S3 버킷 조회
aws s3 ls
aws s3api get-public-access-block --bucket ahss-$NICKNAME

S3 버킷 생성, 조회, 퍼블릭 액세스 차단 설정 확인
AWS S3 페이지 확인


4. S3 권한 설정 실습 & IAM Access Analyzer

  • [AWS 콘솔] 퍼블릭 액세스 차단 편집 : (Uncheck) 모든 퍼블릭 액세스 차단 -> '변경 사항 저장' 클릭

퍼블릭 액세스 차단 편집

  • [AWS 콘솔] 버킷에 텍스트 파일 3개 객체 파일 업로드 (AWS CLI로 실행)
# 파일 생성
echo "memo1" > memo1.txt
echo "memo2" > memo2.txt
echo "memo3" > memo3.txt

# S3로 업로드
aws s3 cp memo1.txt s3://ahss-$NICKNAME
aws s3 cp memo2.txt s3://ahss-$NICKNAME
aws s3 cp memo3.txt s3://ahss-$NICKNAME

# 파일 확인
aws s3 ls s3://ahss-$NICKNAME --recursive --human-readable --summarize
aws s3api list-objects --bucket ahss-$NICKNAME | jq
  • [EC2] 자신의 버킷 탐색
# 출력 결과의 원인을 유추해보자!
NICKNAME=phj
aws s3 ls s3://ahss-$NICKNAME --human-readable
aws s3 ls s3://ahss-$NICKNAME --human-readable --no-sign-request

ec2 버킷 탐색

  • [AWS 콘솔] 권한 -> 객체 소유권 편집 : 'ACL 활성화','버킷 소유자 선호'
  • [AWS 콘솔] 권한 -> ACL(액세스 제어 목록) 편집 : 모든 사람(퍼블릭 액세스) - 객체(Check 나열) -> '변경 사항 저장'
  • [EC2] 자신의 버킷 탐색
# 탐색 실행
aws s3 ls s3://ahss-$NICKNAME --human-readable --no-sign-request

# 파일 복사 실행 : 출력 결과의 원인을 유추해보자!
aws s3 cp s3://ahss-$NICKNAME/memo1.txt . --no-sign-request

권한 변경 후 버킷 탐색

  • [AWS 콘솔] 객체 별 권한 설정
    - memo1.txt : 모든사람(퍼블릭 액세스) - 객체 (Check 읽기) -> '변경 사항 저장'
    - memo2.txt : 인증된 사용자 그룹(AWS 계정이 있는 모든 사용자) - 객체 (Check 읽기) -> '변경 사항 저장'

  • 버킷 새로고침 후 확인

버킷 액세스 확인

  • [EC2] 자신의 버킷 탐색
# 파일 복사 실행 : 출력 결과의 원인을 유추해보자!
aws s3 cp s3://ahss-$NICKNAME/memo1.txt . --no-sign-request

# 파일 복사 실행 : 출력 결과의 원인을 유추해보자!
aws s3 cp s3://ahss-$NICKNAME/memo2.txt . --no-sign-request

# 파일 복사 실행 : 출력 결과의 원인을 유추해보자!
aws s3 cp s3://ahss-$NICKNAME/memo3.txt . --no-sign-request

버킷 탐색

  • [AWS 콘솔] 리소스 정책 : 버킷 정책 설정 - 편집 클릭 후 아래 내용 입력 후 ‘변경 사항 저장’
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::ahss-phj/*"
        }
    ]
}

설정 후 aws cli로 S3 버킷 정책 확인

  • (옵션) IAM Access Analyzer 액세스 분석기
# 액세스 분석기 생성
#aws accessanalyzer create-analyzer --analyzer-name firstanalyzer --type ACCOUNT --output text --query arn
ANA_ARN=$(aws accessanalyzer create-analyzer --analyzer-name firstanalyzer --type ACCOUNT --output text --query arn)
echo $ANA_ARN

# S3 버킷 스캔 수행
aws accessanalyzer start-resource-scan --analyzer-arn $ANA_ARN --resource-arn arn:aws:s3:::ahss-$NICKNAME

# S3 버킷 스캔 결과 확인
aws accessanalyzer get-analyzed-resource --analyzer-arn $ANA_ARN --resource-arn arn:aws:s3:::ahss-$NICKNAME | jq
{
  "resource": {
    "resourceArn": "arn:aws:s3:::ahss-phj",
    "resourceType": "AWS::S3::Bucket",
    "createdAt": "2023-08-29T06:37:48.147000+00:00",
    "analyzedAt": "2023-08-29T06:38:07.985000+00:00",
    "updatedAt": "2023-08-29T06:37:48.147000+00:00",
    "isPublic": true,
    "actions": [
      "s3:GetObject",
      "s3:ListBucket",
      "s3:ListBucketMultipartUploads",
      "s3:ListBucketVersions"
    ],
    "sharedVia": [
      "BUCKET_ACL",
      "POLICY"
    ],
    "status": "ACTIVE",
    "resourceOwnerAccount": "414152998425"
  }
}
  • 버킷에 대한 퍼블릭 액세스 차단 설정
aws s3api put-public-access-block --bucket ahss-$NICKNAME --public-access-block-configuration \
"BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"

액세스 차단 설정 확인

 


[ S3 보안 강화 ]

1. Pre-signed URL & 버킷 생성

  • S3 버킷 생성 후 파일 다운로드 S3 업로드 - IAM 자격증명 설정 되어 있는 상태
# S3 버킷 생성
NICKNAME=phj
aws s3 mb s3://ahss-$NICKNAME-presign --region ap-northeast-2

# 확인
aws s3 ls
aws s3api get-public-access-block --bucket ahss-$NICKNAME-presign | jq

# 그림파일 다운로드
curl https://www.nasa.gov/sites/default/files/thumbnails/image/main_image_star-forming_region_carina_nircam_final-5mb.jpg -o jameswebb.jpg

# S3로 업로드
aws s3 cp jameswebb.jpg s3://ahss-$NICKNAME-presign

# 파일 확인
aws s3 ls s3://ahss-$NICKNAME-presign --human-readable
aws s3api list-objects --bucket ahss-$NICKNAME-presign | jq

S3 파일 업로드 확인

  • 객체URL 접근 시도 - 자격증명 없는 상태
NICKNAME=phj
aws s3 ls s3://ahss-$NICKNAME-presign --human-readable --no-sign-request

# 객체URL로 웹 접근 시도
lynx --dump https://ahss-$NICKNAME-presign.s3.ap-northeast-2.amazonaws.com/jameswebb.jpg

객체 URL로 웹 접근 시도

  • 사전 서명된 URL 생성 - IAM 자격증명 설정 되어 있는 상태
# 사전 서명된 URL 생성 : 600초(10분)
aws s3 presign s3://ahss-$NICKNAME-presign/jameswebb.jpg --expires-in 600
https://cass-s3bucket4-gasida.s3.ap-northeast-2.amazonaws.com/jameswebb.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA5ILF2FJIZTA7DFWL%2F20220820%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20220820T014507Z&X-Amz-Expires=600&X-Amz-SignedHeaders=host&X-Amz-Signature=9237238b5c0a54210c116b4003f3aa89e984069a8f8fa116fea3f111d3c4a252
  • 서명된 URL 접속 확인 - 자격증명 없는 상태
# 변수 지정
URL='https://ahss-phj-presign.s3.ap-northeast-2.amazonaws.com/memo1.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA5ILF2FJIZHUVSWIW%2F20230826%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20230826T163750Z&X-Amz-Expires=600&X-Amz-SignedHeaders=host&X-Amz-Signature=cdc3587b9accd90a98fd558e104c5f6466b335d0978d3c8cb072064cee9b432'

# 서명된 URL 접속 확인
curl -O $URL
ls -al *.jpg

 

2. Require HTTPS

  • IAM 자격증명 설정 되어 있는 상태
# object's metadata 정보 확인 : ServerSideEncryption 확인
aws s3api head-object help
aws s3api head-object --bucket ahss-$NICKNAME-presign --key jameswebb.jpg | jq

# object's metadata 정보 확인 : endpoint-url 옵션 설정
aws s3api head-object --bucket ahss-$NICKNAME-presign --key jameswebb.jpg --endpoint-url http://s3.ap-northeast-2.amazonaws.com
aws s3api head-object --bucket ahss-$NICKNAME-presign --key jameswebb.jpg --endpoint-url https://s3.ap-northeast-2.amazonaws.com

object's metadata 정보 확인

  • [AWS 콘솔] 버킷 정책 설정 - 편집 클릭 후 아래 내용 입력 후 '변경 사항 저장'
{
	"Id": "S3-Security-Deny-unless-HTTPS",
	"Version": "2012-10-17",
	"Statement": [{
		"Action": "s3:*",
		"Effect": "Deny",
		"Principal": "*",
		"Resource": "arn:aws:s3:::ahss-phj-presign/*",
		"Condition": {
			"Bool": {
				"aws:SecureTransport": false
			}
		}
	}]
}

정책 설정 후 aws cli로 S3 버킷 정책 확인

# object's metadata 정보 확인 : endpoint-url 옵션 설정 >> http? https? 확인
aws s3api head-object --bucket ahss-$NICKNAME-presign --key jameswebb.jpg --endpoint-url http://s3.ap-northeast-2.amazonaws.com
aws s3api head-object --bucket ahss-$NICKNAME-presign --key jameswebb.jpg --endpoint-url https://s3.ap-northeast-2.amazonaws.com

endpoint-url 옵션 확인

3. Require SSE-KMS Encryption

  • 객체 버킷 업로드
# 캑체 버킷에 업로드
# default bucket encryption to SSE-KMS(AES256) to encrypt your data at rest and enforce encryption with a bucket policy.
echo "123456789abcdefg" > textfile
aws s3api put-object --key text01 --body textfile --bucket ahss-$NICKNAME-presign
{
    "ETag": "\"3ca451faac980583cffaadf8b63e6820\"",
    "ServerSideEncryption": "AES256"
}

#
aws s3api head-object --bucket ahss-$NICKNAME-presign --key text01 | jq
  • [AWS 콘솔] 버킷 속성 > 기본 암호화 (편집) : AWS KMS(SSE-KMS), AWS KMS 키 중 선택(s3), 버킷 키 (활성화)

  • IAM 자격증명 설정 되어 있는 상태

object's metadata 정보 확인

4. IAM 정책 실습

  • IAM 자격증명 설정 되어 있는 상태 : IAM User 생성 및 S3 권한 부여
# s3user 사용자 생성
aws iam create-user --user-name s3user

# iam 사용자 리스트 확인
aws iam list-users | jq

# 사용자에게 프로그래밍 방식 액세스 권한 부여
aws iam create-access-key --user-name s3user
{
    "AccessKey": {
        "UserName": "s3user",
        "AccessKeyId": "AKIA5ILF2FJIWN7VTY6X",
        "Status": "Active",
        "SecretAccessKey": "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",
        "CreateDate": "2023-08-27T04:32:47+00:00"
    }
}

# s3user 사용자에 AWS관리형정책(AmazonS3FullAccess)을 추가
aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess --user-name s3user

사용자 리스트 정책 권한 부여

  • 자격증명 없는 상태 : s3user 사용자 자격증명 설정 후 확인
# aws cli 명령 시도
aws s3 ls
aws ec2 describe-vpcs

# s3user 자격증명 profile
aws configure
AWS Access Key ID [None]: AKIA5ILF2FJIQAIEV7UB
AWS Secret Access Key [None]: 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
Default region name [None]: ap-northeast-2
Default output format [None]:

# 자격 증명 정보 저장되는 파일 확인
cat ~/.aws/credentials

# aws cli 명령 시도
aws s3 ls
aws ec2 describe-vpcs

# 퍼블릭 액세스 차단 비활성 설정
aws s3api put-public-access-block --bucket ahss-$NICKNAME-presign --public-access-block-configuration \
"BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false"

4. 퍼블릭 버킷 설정 후 IP 기반 통제

  • 리소스 정책 : 버킷 정책 설정 - 편집 클릭 후 아래 내용 입력 후 ‘변경 사항 저장’
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::ahss-phj-presign/*"
        }
    ]
}

버킷 정책 변경 cli 확인

  • 객체 다운로드 시도
# 파일 복사 실행
aws s3 cp s3://ahss-$NICKNAME-presign/jameswebb.jpg . 

# [EC2] 미리 자신의 공인 IP 확인 메모해두기
curl ipinfo.io
curl ipinfo.io/ip ;echo

공인ip 확인

  • 리소스 정책 : 버킷 정책 설정 - 편집 클릭 후 아래 내용 입력 후 ‘변경 사항 저장’ ← IP주소는 EC2의 공인 IP 입력

s3 버킷 정책 확인

# [자신의 PC] 파일 생성
echo "memo1" > memo1.txt

# [자신의 PC] S3로 업로드
aws s3 cp memo1.txt s3://ahss-$NICKNAME-presign

# [자신의 PC] 버킷 조회
aws s3 ls s3://ahss-$NICKNAME-presign
aws s3api list-objects --bucket ahss-$NICKNAME-presign | jq


# [EC2] 파일 생성
echo "memo2" > memo2.txt

# [EC2] S3로 업로드
aws s3 cp memo2.txt s3://ahss-$NICKNAME-presign

# [EC2] 버킷 조회
aws s3 ls s3://ahss-$NICKNAME-presign
aws s3api list-objects --bucket ahss-$NICKNAME-presign | jq

5. Auditing Amazon S3's Default Encryption Configurations at Scale & AWS SDK(boto3)

# boto3 설치
sudo python3 -m pip install boto3

# 버킷 리스트 조회
cat <<EOT > bucket-all.py
import boto3

s3 = boto3.resource('s3')
for bucket in s3.buckets.all():
  print(bucket.name)
EOT
python3 bucket-all.py
#
git clone https://github.com/aws-samples/amazon-s3-default-encryption-audit
cd amazon-s3-default-encryption-audit/
tree

#
python3 amazon-s3-default-encryption-audit.py
...
Output Location:  /home/ec2-user/
You can now access the report in the following location:  
/home/ec2-user/bucketEncryptionReport_20230827-054611.csv

#
cat /home/ec2-user/bucketEncryptionReport_20230827-054611.csv

 

 

6. Use AWS Config Rules to Detect a Public Bucket

 

  • config 서비스 → 시작하기 → 단계1~3 설정 : 결과 저장용 신규 버킷(유일 이름)을 생성!

AWS Config 규칙 생성

[ 참고 영상 ]