본문 바로가기

CloudGoat

SQS_FLAG_Shop(Easy) Write-up


시나리오를 생성하면 Access Key, Secret Key, 웹 IP주소를 준다.

먼저 웹부터 살펴보자.


1. 웹 분석

1. 웹 페이지 접속 시 자산과 구매할 수 있는 물건들이 있다. 

2. 각 물건들은 현재 자산에 맞게 구매할 수 있고, 구매 시 물품 가격만큼 자산이 차감되며 /recipet 경로에 구매한 물품 리스트가 추가된다.

3. 자산은 /charge 경로에서 충전이 가능하며 한 번 충전 후 자산에 반영되기까지 10에서 20초가 소요된다고 적혀있다.

4. 메인 페이지 소스코드를 보면 백에 검증 로직이 있어 Client Side 공격으로는 우회가 불가능해보인다.

5. 하지만 소스코드의 조건문을 보면 SQS 서비스를 이용하며, 충전할 금액을 JSON 형태로 담아 쿼리를 보내 자산을 충전하는 방식으로 로직이 동작하는 것을 확인 할 수 있다.


2. 유저 및 정책 확인

실습문제에서 제공하는 Access key와 Secret Key를 이용하여 sqs라는 이름을 가진 profile을 생성한다.

※편의를 위해 각 변수들은 환경변수로 등록 후 변수명으로 사용※

그후 aws sts get-caller-identity --profile sqs명령어를 사용해 어떠한 유저인지 확인한다.

유저명이 cg-sqs-user-cgidlbinmccdbc 인 것을 확인 할 수 있다.

※환경 변수 등록(이하 생략) export userName=cg-sqs-user-cgidlbinmccdbc

유저명을 알았으니 아래 사항들을 확인해 보았다.

1. 유저그룹

2. Managed Policy

3. Inline Policy

명령어 실행 결과 인라인 정책만 존재하는 것을 확인했다.

export policyName=cg-sqs-scenario-assumed-role

1. cg-sqs-scenario-assumed-role 정책 확인

2. 해당 유저는 iam에 대한 읽기 권한 및 cg-sqs-send-message Role 을 위임 받을 수 있는 권한 존재


3. Role 확인 및 분석

유저, 유저그룹, 정책을 확인했으니 Role을 확인해보자.

aws iam list-roles 명령어를 통해 아래와 같은 Role들이 존재하는 것을 확인 가능하다.

※ export role1=cg-sqs-lambda-cgidlbinmccdbc
※ export role2=cg-sqs-send-message-cgidlbinmccdbc

각 Role을 순서대로 분석해면,

1.1. cg-sqs-lambda은 lambda 서비스에 Assume 될 수 있다.

1.2. cg-sqs-lambda는 AWSLambdaSQSQueueExecutionRole과 AWSLambdaVPCAccessExecutionRole을 가지고 있다.

1.3.  AWSLambdaSQSQueueExecutionRole의 권한을 확인해보자. 먼저 Default 버전이 v1인것을 확인했다.

1.4. AWSLambdaSQSQueueExecutionRole은 SQS ReceiveMessage, DeleteMessage, GetQueueAttributes 권한 및 로깅 권한을 가지고 있다. 

1.5. AWSLambdaVPCAccessExecutionRole도 동일하게 권한을 확인해보자. 먼저 디폴트 버전은 v3이다.

1.6 AWSLambdaVPCAccessExecutionRole은 로깅 및 네트워크 관련 권한을 가지고 있다.

2.1. cg-sqs-send-message 은 신뢰 주체가 sqs-user고, Action이 AssumeRole이다. 즉, sqs-user에게만 해당 Role이 위임될 수 있다.

2.2. cg-sqs-send-message Role은 cg-sqs 정책을 가지고 있다.

2.3. cg-sqs 정책은 cash_charging_queue라는 sqs 리소스에 대해 sqs GetQueueUrl 및 SendMessage 권한을 가지고 있다.

Role 명 cg-sqs-lambda cg-sqs-send-message
정책 명 AWSLambdaSQSQueueExecutionRole
AWSLambdaVPCAccessExecutionRole
cg-sqs
Role Principal lambda  cg-sqs-user
정책 Action
AWSLambdaSQSQueueExecutionRole Action

sqs:ReceiveMessage
sqs:DeleteMessage
sqs:GetQueueAttributes
logs:CreateLogGroup
logs:CreateLogStream
logs:PutLogEvents
sqs:GetQueueUrl
sqs:SendMessage
AWSLambdaVPCAccessExecutionRole Action

logs:CreateLogGroup
logs:CreateLogStream
logs:PutLogEvents
ec2:CreateNetworkInterface
ec2:DescribeNetworkInterfaces
ec2:DescribeSubnets
ec2:DeleteNetworkInterface
ec2:AssignPrivateIpAddresses
ec2:UnassignPrivateIpAddresse

위 정보 수집 과정을 pacu 를 이용해서 동일하게 진행해보자.

1. run iam__enum_users_roles_policies_groups 명령어를 통해 유저, 그룹, Role, 정책을 한 번에 검색 가능하다.

2. data iam 명령어로 스캐닝 결과를 확인해보자. 먼저 유저이다.

3. 다음은 정책이다. 위 과정에서는 찾지 못했던 lambda 실행 정책이 존재하는 것을 확인 가능하다.

5

4. 마지막으로 Role이다.


4. Assume Role

2번과 3번 과정에서 아래 사항들을 확인할 수 있다.
1. sqs 유저는 cg-sqs-send-message Role을 위임 받을 수 있다.
2. cg-sqs-send-message Role은 sqs GetQueueUrl ,SendMessage 권한이 있다.
3. cg-sqs-send-message Role은 sqs 유저에게 위임될 수 있다.

sqs user policy cg-sqs-send-message Role

따라서, sqs유저에게 cg-sqs-send-message Role을 Assume 한 뒤 조작된 sqs message를 보내 자산을 원하는 값으로 바꿀 수 있다는 것을 알 수 있다.

1. sqs 유저에게 cg-sqs-send-message Role을 Assume 해준 뒤 exploit 이라는 프로필을 생성했다.

2. aws sts get-caller-identity 로 확인해보면 Assume 된 것 확인 가능하다.


5. Exploit

sqs SendMessage 권한을 얻었으므로 적절한 형태로 메시지를 보내면 된다.

send message 명령어를 사용하려면 Query Url과 Message Body값이 필요하다. 

1. Body에 들어가야할 값은 메시지 형태는 소스코드 내부를 살펴보면 Key 값은 charge_amount 이고 Value 값은 충전할 자산 값인 JSON 포멧이다.

2. Query Url은 sqs get-queue-url 명령어와 SQS Queue Name 파라미터를 통해 알 수 있다.

3. 최종적으로 충전할 금액을 넣고 aws sqs send-message --queue-url https://sqs.us-east-1.amazonaws.com/941755627009/cash_charging_queue --message-body '{"charge_amount": 1000000000000}' --profile exploit 명령어를 입력했을때 아래와 같이 나오면 성공이다.

4. 웹 접속 시 자산이 충전되어 있는것을 확인할 수 있다.

5. Flag Order 후 receipt 페이지로 이동해보면 Flag를 확인할 수 있다.

'CloudGoat' 카테고리의 다른 글

RDS_snapshot(Medium) Write up  (0) 2025.05.01
iam_privesc_by_rollback(Easy) Write Up  (0) 2025.04.27
iam_privesc_by_key_rotation(Easy) Write Up  (0) 2025.04.20
lambda_privesc(Easy) Write up  (0) 2025.04.20
beanstalk_secrets(Easy) Write up  (1) 2025.04.13