brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Aug 28. 2023

37탄-2.  AWS- S3 보안 강화


<1> Pre-signed URL

<2> 버킷 정책으로 https 만 되도록 설정하자.

<3> SSE-KMS Encryption

<4> IAM 정책 실습

<5> 퍼블릭 버킷 설정 후 IP 기반 통제하기

<6> IAM 정책 내용이 충돌 시 어떻게 동작 할까요 ?

<7> Auditing Amazon S3's Default Encryption Configurations at Scale & AWS SDK(boto3)

<8>  Use AWS Config Rules to Detect a Public Bucket 

<9> 보안 가이드

<10>  Cloudfront 사용법    




<1> Pre-signed URL 


참고

https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/using-presigned-url.html 

https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html   



1

<자격증명 설정되어 있는 서버에서>


# S3 버킷 생성

NICKNAME=<자신의닉네임>

NICKNAME=topasvga

aws s3 mb s3://ahss-$NICKNAME-presign --region ap-northeast-2 



# 확인

aws s3 ls

ahss-topasvga


public 허용은 블럭 되어 있다. 

aws s3api get-public-access-block --bucket ahss-$NICKNAME-presign | jq  

{

  "PublicAccessBlockConfiguration": {

    "BlockPublicAcls": true,

    "IgnorePublicAcls": true,

    "BlockPublicPolicy": true,

    "RestrictPublicBuckets": true

  }

}



# 그림파일 다운로드

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   



2

<자격증명 없는 상태 서버 >


NICKNAME=<자신의닉네임>

NICKNAME=topasvga

aws s3 ls s3://ahss-$NICKNAME-presign --human-readable --no-sign-request 

An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

안됨



# 객체URL로 웹 접근 시도

lynx --dump https://ahss-$NICKNAME-presign.s3.ap-northeast-2.amazonaws.com/jameswebb.jpg 

   AccessDeniedAccess

   DeniedDSENGZVXJH0PQ9RTc7nLJDAUfUhqUv9jwXbNyu9e25Tq/kOt4lGH6qF2Mz+3C+cFM

   8UCCafbyjfP1k4LQSBRC4EvgZY=



3

AWS 콘솔에서 확인

기본이 all 차단.  



4

<자격증명 설정되어 있는 서버에서>


# 사전 서명된 URL 생성 : 600초(10분)

aws s3 presign s3://ahss-$NICKNAME-presign/jameswebb.jpg --expires-in 600 


아래 주소를 웹브라우저로 접근하면  이미지가 나온다.

600초(10분) 지나면 안된다.  (1분~12시간까지 시간 가능 , sdk는 7일까지 가능)

https://cass-s3bucket4-gasida.s3.ap-northeast-2.amazonaws.com/jameswebb.jpg?X-Amz-Algorithm=AWS4-HMACest&X-Amz-Date=20220820T014507Z&X-Amz-Expires=600&X-Amz-SignedHeaders=host&X-Amz-Signature=9237238b5c0a54210c116b4003f3aa89e984069a8f8fa116fea3f111d3c4a252   


https url을  Notepad에 복사해 놓는다.



<자격증명 없는 상태 서버 >


# 변수 지정

URL='<서명된 URL>' 


URL='https://ahss-topasvga-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   

jameswebb.jpg



7

서명된 URL 주소를 10분 이내에 아무 단말/PC의 웹 브라우저에서 접속 가능하다.   

기본 Public 차단 환경에서도 가능하다. 자격증명이 없는 서버도 서명된 URL 주소를 사용해 허용 된다.


8

백엔드서버가 10분만 사용하도록 어플리케이션을 구현하는 부분등에 사용하면 좋다.





<2> 버킷 정책으로 https 만 되도록 설정하자. 



1

자세한 부분 워크셥 참고

https://catalog.us-east-1.prod.workshops.aws/workshops/74237958-77c8-4e7f-a02f-ae201a04d759/en-US/s3-security-best-practices-lab/02-securityexercises  

https://catalog.us-east-1.prod.workshops.aws/workshops/8f6b34da-c21e-4094-8070-8d98e2e6ca08/en-US 

https://catalog.us-east-1.prod.workshops.aws/workshops/8f6b34da-c21e-4094-8070-8d98e2e6ca08/en-US/s3-security-best-practices-lab/02-securityexercises/01-requirehttps  



2

버킷 정책으로 https 만 되도록 설정하자. 

{

"Id": "S3-Security-Deny-unless-HTTPS",

"Version": "2012-10-17",

"Statement": [{

"Action": "s3:*",

"Effect": "Deny",

"Principal": "*",

"Resource": "arn:aws:s3:::ahss-topasvga-presign/*",

"Condition": {

"Bool": {

"aws:SecureTransport": false

}

}

}]

}   



Https 연결이 아닐때는 차단하는것이다.

"aws:SecureTransport": false   


3

정책 확인

aws s3api get-bucket-policy --bucket ahss-$NICKNAME-presign | jq -r .Policy | jq   


4

# 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 


차단됨

An error occurred (403) when calling the HeadObject operation: Forbidden



HTTPS 로 조회 ?

aws s3api head-object --bucket ahss-$NICKNAME-presign --key jameswebb.jpg --endpoint-url https://s3.ap-northeast-2.amazonaws.com    


허용됨

{

    "AcceptRanges": "bytes",

    "LastModified": "2023-08-29T01:30:26+00:00",

    "ContentLength": 5310371,

    "ETag": "\"3bae2c6845352e627516a529fd507ffb\"",

    "ContentType": "image/jpeg",

    "ServerSideEncryption": "AES256", // 기본적 암호화 되어 있다. 2023년 4월부터 디폴트 암호화됨.

    "Metadata": {}

}





<3> SSE-KMS Encryption 



1

https://catalog.us-east-1.prod.workshops.aws/workshops/8f6b34da-c21e-4094-8070-8d98e2e6ca08/en-US/s3-security-best-practices-lab/02-securityexercises/02-s3encrypt  



2

서버 측 암호화는 S3 관리 키(SSE-S3)를 사용한 서버 측 암호화, KMS 관리키(SSE-KMS)를 사용한 서버 측 암호화, 고객 측에 제공된 키(SSE-C)를 사용한 서버 측 암호화가 있다.   



3

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


# 객체 버킷에 업로드

# 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   



4

AWS 콘솔] 

버킷 속성 → 기본 암호화 (편집) : 

AWS KMS(SSE-KMS) >

AWS KMS키 중 선택(s3) >

버킷 키(활성화)   > 변경 사항 저장.



5

파일 2번 올려 본다.

Sse-kms로 변경 된다. 


# object's metadata 정보 확인 : ServerSideEncryption 확인

aws s3api head-object --bucket ahss-$NICKNAME-presign --key jameswebb.jpg | jq 



# 캑체 버킷에 업로드

# default bucket encryption to SSE-KMS(AES256) to encrypt your data at rest and enforce encryption with a bucket policy.


echo "abcdef" > textfile2


aws s3api put-object --key text02 --body textfile2 --bucket ahss-$NICKNAME-presign | jq


{

  "ETag": "\"55a4986797e8235ed7a0b75f0ae2f4f1\"",

  "ServerSideEncryption": "aws:kms",

  "SSEKMSKeyId": "arn:aws:kms:ap-northeast-2:451034083:key/755e93619-4e0e-b997-11cb07e72db0",

  "BucketKeyEnabled": true

}



# object's metadata 정보 확인 : ServerSideEncryption 확인

aws s3api head-object --bucket ahss-$NICKNAME-presign --key text02 | jq   

{

  "AcceptRanges": "bytes",

  "LastModified": "2023-08-29T02:09:44+00:00",

  "ContentLength": 7,

  "ETag": "\"55a4986797e8235ed7a0b75f0ae2f4f1\"",

  "ContentType": "binary/octet-stream",

  "ServerSideEncryption": "aws:kms",

  "Metadata": {},

  "SSEKMSKeyId": "arn:aws:kms:ap-northeast-2:451032684083:key/755e938d-4619-4e0e-b997-11cb07e72db0",

  "BucketKeyEnabled": true

}




<4> IAM 정책 실습 


IAM 정책으로 S3 버킷을 통제 하자!!!


1

자격 증명 설정 되어 있는 상태 서버 에서  iam계정을 만들자! 


# 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": "AKIA5ITY6X",

        "Status": "Active",

        "SecretAccessKey": "yfVSpyRQOogrr6hQBlWqQ",

        "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   



2

자격 증명이 없는 서버에서 


사용자 자격증명 설정후 확인


# aws cli 명령 시도

aws s3 ls

aws ec2 describe-vpcs 


# s3user 자격증명 profile

aws configure

AWS Access Key ID [None]: AKI2FV7UB

AWS Secret Access Key [None]: 2Xp6oZ3A3P1NsdH

Default region name [None]: ap-northeast-2

Default output format [None]: 


# 자격 증명 정보 저장되는 파일 확인

cat ~/.aws/credentials 


# aws cli 명령 시도

aws s3 ls   

잘됨.


aws ec2 describe-vpcs

// ec2 조회는 권한이 없어 안됨.  



IAM정책이 S3 full 권한을 가져서 아래 실행도 가능하다.


# 퍼블릭 액세스 차단 비활성 설정

aws s3api put-public-access-block --bucket ahss-$NICKNAME-presign --public-access-block-configuration "BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false"   





<5> 퍼블릭 버킷 설정 후 IP 기반 통제하기


특정한 소스 IP만 퍼블릭 버킷에 접속 되도록 설정해보자~


1

https://dev.classmethod.jp/articles/control-access-to-s3-by-private-ip-address/ 



2

권한 > 버킷 정책


{

    "Version": "2012-10-17",

    "Statement": [

        {

            "Sid": "PublicReadGetObject",

            "Effect": "Allow",

            "Principal": "*",

            "Action": "s3:GetObject",

            "Resource": "arn:aws:s3:::ahss-topasvga-presign/*"

        }

    ]

}   



3

aws s3api get-bucket-policy --bucket ahss-$NICKNAME-presign | jq -r .Policy | jq  



4

아무곳에서나 다운로드 시도

모두 잘 됨


# 파일 복사 실행

aws s3 cp s3://ahss-$NICKNAME-presign/jameswebb.jpg .  



# [EC2] 미리 자신의 공인 IP 확인 메모해두기

curl ipinfo.io

curl ipinfo.io/ip ;echo     


54.180.154.217



5

Ip로  제한. 


{

    "Statement": [

        {

            "Effect": "Deny",

            "Principal": "*",

            "Action": [

                "s3:PutObject",

                "s3:GetObject",

                "s3:ListBucket"

            ],

            "Resource": [

                "arn:aws:s3:::ahss-topasvga-presign",

                "arn:aws:s3:::ahss-topasvga-presign/*"

            ],

            "Condition": {

                "NotIpAddress": {

                    "aws:SourceIp": "54.180.154.217/32"

                }

            }

        }

    ]

}  



// 해당  IP가 아니면 차단. 해당 IP로만 가능함.    아래 권한을 차단한다.

            "Effect": "Deny",

                "s3:PutObject",

                "s3:GetObject",

                "s3:ListBucket" 



6

aws s3api get-bucket-policy --bucket ahss-$NICKNAME-presign | jq -r .Policy | jq   



해당 IP 서버에서만 모든것이 됨.


아래 테스트

# [자신의 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     




<6> IAM 정책 내용이 충돌 시 어떻게 동작 할까요 ? 



1

동영상 확인 

https://youtu.be/zIZ6_tYujts 

Identity-base 정책 = IAM 정책.  



2

IAM정책과 리소스 정책 충돌 날때  동작? 


IAM 정책과 Resource 정책이 있다면 ? 


동일 계정에서 동작은 ?

합집합의 형태로 동작. 


크로스 어카운트 계정에서 동작은?

교집합의 형태로 동작한다.  



3

만약?

IAM = Allow이고, Resource  정책이 없으면 ? 

같은 계정은 허용한다. = 합집합

다른 계정은 거부된다. = 교집합이 없으므로 거부.   

한쪽의 정책이 없다면, 같은 계정은 나머지 한쪽의 정책을 따르고

다른 계정은 차단된다.



4

만약?

IAM = Allow이고 ,Resource = Deny  이면? 

2개의 정책이 모두 있는경우는 deny정책이 우선한다.

같은 계정이나 다른 계정이나 안된다.   

한쪽이라도 Deny가 있으면 Deny이다.




<7> Auditing Amazon S3's Default Encryption Configurations at Scale & AWS SDK(boto3) 


정책을 주기적으로 확인하자!!


1

https://github.com/aws-samples/amazon-s3-default-encryption-audit 

https://www.notion.so/gasidaseo/10-AWS-SDK-50783e80e8a94b7db58ac32afcb0a082  



2

정책 없는 서버에서


# 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  



버킷 리스트가 조회 된다.

ahss-topasvga-presign

ahss-topasvga1

cf-templates-18pmd1tc8r6q0-ap-northeast-2


sdk 를 통해 버킷 리스트를 조회했다.



3

감사 툴

https://aws.amazon.com/ko/blogs/storage/how-to-audit-an-amazon-s3-buckets-default-encryption-configuration-at-scale/  



git clone https://github.com/aws-samples/amazon-s3-default-encryption-audit

cd amazon-s3-default-encryption-audit/

tree 


.

├── amazon-s3-default-encryption-audit.py

├── CODE_OF_CONDUCT.md

├── CONTRIBUTING.md

├── LICENSE

├── README.md

└── requirements.txt


4

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 


5

cat /home/ec2-user/bucketEncryptionReport_20230829-023902.csv

ahss-topasvga1, AES256, N/A

cf-templates-18pmd1tc8r6q0-ap-northeast-2, AES256, N/A

ahss-topasvga-presign, arn:aws:kms:ap-northeast-2:451032684083:alias/aws/s3, AccessDenied, True


위 툴로 버킷 정보를 수집할수 있다!!!

키가 있는지 등  




<8>  Use AWS Config Rules to Detect a Public Bucket  



Config Rules로 퍼블릭 버킷을 찾아보자.


1

https://catalog.us-east-1.prod.workshops.aws/workshops/8f6b34da-c21e-4094-8070-8d98e2e6ca08/en-US/s3-security-best-practices-lab/02-securityexercises/06-awsconfig  



2

AWS 콘솔] config 서비스 → 


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



Record specific resource types



3

단계1


AWS 리소스?

AWS s3 AccountPublicAccessBlock , AWS S3 Bucket 


AWS Config  역할?

AWS Config서비스 연결 역할 생성 


전송방법?

Amazone S3 버킷


버킷 생성 - 결과 파일 생성 위치

Config-detect-s3-topasvga 



4

단계2


AWS 관리형 규칙?

필요 부분을 체크.  


5

단계3

확인

3분 후 결과가 나온다. 




6

(선택)

Slack등에 알람을 보내도록 설정가능. 

https://github.com/awslabs/aws-config-rules/blob/master/aws-config-conformance-packs/Operational-Best-Practices-for-Amazon-S3.yaml

선언 했던 것들이 true인지 확인  



7

(선택) 버킷의 내용 접근 로그 확인 가능

Monitor Amazon S3 activity using S3 server access logs and Pandas in Python  

https://aws.amazon.com/ko/blogs/storage/monitor-amazon-s3-activity-using-s3-server-access-logs-and-pandas-in-python/   






<9> 보안 가이드 


1

판단 기준, 조치법등 정리 된 블로그


https://rogue-gouda-f87.notion.site/AWS-de0b5749d03b464ea2e555cba3974d0b 


https://mr-zero.tistory.com/   




<10>  Cloudfront 사용법 



1

Amazon CloudFront를 사용하여 아키텍처 개선하기 : S3 원본 접근 제어 

https://catalog.us-east-1.prod.workshops.aws/workshops/4557215e-2a5c-4522-a69b-8d058aba088c/ko-KR/security/origin-access-control  



2

AWS Workshop Ransomware on S3 - Simulation and Detection

https://catalog.workshops.aws/aws-cirt-ransomware-simulation-and-detection/en-US   




3

실습      리소스들 삭제


AWS  Config → 생성된 규칙 삭제

AWS IAM User       (s3user) 삭제

AWS 버킷 → 버킷 정책 삭제 →       비우기 → 삭제

AWS CloudFormation       스택 삭제




다음 자료 보기


https://brunch.co.kr/@topasvga/3429




몰아보기

https://brunch.co.kr/@topasvga/3430



다음은 주말 CloudNet 스터디 내용 참고하여  정리한 부분입니다.

https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863  





감사합니다. 

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari