AWS workshop IMDSv1의 SSRF - simulation 및 detection
IMDSv1의 SSRF - simulation 및 detection
해당 workshop에서는 IMDSv1을 사용하도록 구성된 EC1 인스턴스에서 호스팅 되고있는 SSRF(Server Side Request Forgery) 에 취약한 웹 어플리케이션을 unauthorized use 를 시뮬레이션 한다. 그 뒤 AWS CIRT(고객 인시던트 대응팀)가 이러한 보안 event에 대응할 때 수행하는 몇가지 detection activity를 살펴본다.
*SSRF : Server Side에서 생성되는 요청을 변조해 해커가 의도한 서버로 요청을 보내거나 요청 자체를 수정할 수 있는 공격
사용 tool
Assisted Log Enabler for AWS
해당 툴은 S3 버킷을 생성하고, 서비스를 확인하여 logging이 켜져있는지 확인 후, logging이 꺼져있는 경우 logging을 활성화 해 준다.
Security Analytics Bootstrap
해당툴은 로그를 검색하거나, 분석할때 사용된다. 보안 정보 관리, 보안이벤트 관리 통합 관리 솔루션인 SIEM이 없을때 사용.
Workshop 환경세팅
US-EAST-1 리전만 사용 그외 리전 사용시 오류발생
CloudFormation 템플릿 다운로드 링크
Cloudformation 에서 yaml파일 업로드
2단계에서 날짜와, 내 공인 IP를 입력
3단계는 기본설정
4단계에서는 IAM리로스 생성 승인후 스택생성
AWS CLI 설정
https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
Install or update the latest version of the AWS CLI - AWS Command Line Interface
When updating from a previous version, the unzip command prompts to overwrite existing files. To skip these prompts, such as with script automation, use the -u update flag for unzip. This flag automatically updates existing files and creates new ones as ne
docs.aws.amazon.com
Athena 설정
작업 그룹 IRWorkshopAthenaWorkgroup
SELECT * FROM "irworkshopgluedatabase"."irworkshopgluetablevpcflow" limit 10;
쿼리 테스트
쿼리 결과가 정상적으로 나온다면 workshop 준비 완료.
노출되어 있는 IAM 증명
Cloudshell을 통한 IAM 무단사용
AWS 에서 재공하는 쉘스크립트 업로드
chmod +x iam-credential-exposure.sh
./iam-credential-exposure.sh
실행권한 부여후 스크립트 실행
시뮬레이션 후 하단에 엑세스 키 ID 표시
CloudTrail과 Athena를 통하여 Access Key ID 찾기
Athena 이동후
작업그룹 : IRWorkshopAthenaWorkgroup
데이터 베이스 irworkshopgluedatabase 확인
SELECT * FROM "irworkshopgluedatabase"."irworkshopgluetablecloudtrail" where useridentity.accesskeyid = '<insert_access_key_id_here>'
insert_access_key 항목에 시뮬레이션 이후 받은 Access Key 입력후 쿼리 실행
시뮬레이션에 의해 여러 event들이 실행됬었고, athena 쿼리실행을 통하여 Access Key ID 가 언제 처음으로 사용되었는지 확인할 수 있음.
해당 쿼리를 통해 내 Access Key ID 는 2023-09-08T09:15:39Z 에 노출되어 처음 사용되었음을 알 수 있음.
또한 침입자가 Security Token Service 라는 source에서 GetCallerIdentity API를 호출했으며, 어떤 source를 사용했는지 source IP address를 통하여 확인 할 수 있음.
Useragent 라는 Column을 통해 실제 사용하는 사용자와 환경과 다른 환경에서 애플리케이션이 실행되었는지 확인 가능함.
reponseelement Column을 통해 해당 API의 결과값을 간략하게 볼 수 있음. 해당 결과값들은 각각 CreateAccessKey, CreateUser라는 API를 호출하고 나온 결과값들로 공격자가 어떤 api를 호출하고 어떤 결과값을 받았는지 알 수 있음.
또한 Column을 통하여 어떤 파라미터를 넣었는지 확인해 볼 수 있음.
따라서 해당 쿼리를 통하여 Access Key ID가 노출당한 사용자는 유저생성과 Accesskey를 원하지 않았지만, tdir-workshop-sysdev 라는 UserName으로 여러 요청을 했다는 것을 알 수 있음.
만약 Access Key ID를 노출당한 사용자가 해당 시간대에 어떠한 API호출과 명령을 하지 않았다면, 하기 쿼리로
SELECT "eventtime", "eventname", "errorcode", "requestparameters", "responseelements" FROM "irworkshopgluedatabase"."irworkshopgluetablecloudtrail" where useridentity.accesskeyid = 'My ACCESS KEY'
타임라인 순으로 공격자가 여러 API호출을 날리고 몇번 denied를 당했지만 결국 AdministratorAccess 권한을 가진 tdir-workshop-sysdev 라는 User를 생성하고, AccessKey 까지 새로 생성했다는 것을 알 수 있음.
responseelements Column을 통해 어떤 AccessKey를 만들었는지 확인 하였으니 거의 동일한 쿼리로 accesskeyid 값을 공격자가 만든 accesskey를 검색하면
SELECT "eventtime", "eventname", "errorcode", "responseelements" FROM "irworkshopgluedatabase"."irworkshopgluetablecloudtrail" where useridentity.accesskeyid = 'Created AccessKey'
Admin권한을 가진 AccessKeyID를 생성해낸 공격자가 해당 권한을 가지고 또 어떠한 API호출을 하였는지 파악가능함.
이번엔 Instance실행, login profile생성과 또 다른 Access Key ID를 두개나 다시 생성해내었음.
결론
해당 워크샵을 통해 AWS가 제공하는 tool를 사용하여 로깅을 자동으로 켜주고, 해당 서비스 로그들을 Athena를 통하여 쿼리를 하여 공격자가 어떤 공격을 했는지 파악할 수 있었음.
쿼리를 통해 공격자가 만들어낸 AccessKey들과 인스턴스, 버킷을 파악하고 노출되어 삭제할 Access Key ID 의도하지 않게 생성되어 삭제할 Access Key ID, 삭제해야할 Instance와 bucket을 파악할 수 있었음.
공격자가 어떤 공격을 했는지 파악하고 대응하는것을 파악하는것도 중요하지만 결국 권한이 많은 key를 털리지 않게 잘 관리하던가, 혹은 고정하여 쓰는 장기 key를 사용하지 않고 Expire되는 시간이 있는 임시 key를 사용하는것이 더 보안에 좋을 것임.
워크샵에서 사용된 리소스 정리
EC2 인스턴스 삭제
aws ec2 terminate-instances --instance-ids $(aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId' --filters "Name=tag:tdir-workshop,Values=test-servers" --output text)
cleanup_users.sh 다운 및 업로드 및 실행
버킷 삭제
aws resourcegroupstaggingapi get-resources --tag-filters Key=tdir-workshop,Values=test-buckets --query 'ResourceTagMappingList[].ResourceARN' > buckets.json
((for bucket in {0..1}; do cat buckets.json |jq -r ".[$bucket]";done) |cut -d":" -f 6) > buckets-to-delete
while read line; do aws s3 rb s3://$line --force; done < buckets-to-delete
rm buckets.json
rm buckets-to-delete
CloudFormation 스택 삭제