← 전체 글 IAM

iam:PassRole: 작동 방식, 공격자가 악용하는 방법, 범위를 좁히는 방법

요약

  • iam:PassRole은 주체가 IAM 역할을 서비스에 넘길 때 AWS가 확인하는 권한입니다. 예를 들어 Lambda 함수의 실행 역할이나 EC2 인스턴스의 인스턴스 프로파일로 넘기는 경우입니다. 이 권한에는 자체 API 호출이 없습니다.
  • AWS는 세 가지가 모두 맞아떨어질 때만 전달을 허용합니다. 호출자의 정책이 해당 역할에 대한 iam:PassRole을 허용하고, 역할의 신뢰 정책이 대상 서비스를 허용하며, 역할이 호출자와 같은 계정에 있어야 합니다.
  • 컴퓨팅 리소스를 만들거나 업데이트하는 권한과 결합되면, iam:PassRole은 주체가 한 번도 부여받지 않은 역할로 코드를 실행할 수 있게 합니다. Pathbreak 공격 맵에서는 권한 상승 경로의 55퍼센트가 이 권한에 의존합니다.
  • CloudTrail은 전달 자체에 대해서는 이벤트를 기록하지 않으므로, 탐지는 생성 또는 업데이트 호출과 역할 ARN을 담은 요청 파라미터에 달려 있습니다.
  • 해결책은 Resource 요소에 특정 역할 ARN이나 IAM 경로를 지정하는 것입니다. 와일드카드 리소스에 iam:PassedToService 조건을 걸면 서비스는 좁혀지지만, 그 서비스를 신뢰하는 모든 역할은 여전히 허용됩니다.

iam:PassRole은 주체가 AWS 서비스에 어떤 역할을 넘길 수 있는지 제어하는 AWS IAM 권한입니다. Lambda 함수의 실행 역할, EC2 인스턴스의 인스턴스 프로파일, CodeBuild 프로젝트의 서비스 역할이 그런 예입니다. 또한 Pathbreak 공격 맵에 가장 자주 등장하는 권한이기도 합니다. 맵에 있는 권한 상승 경로의 55퍼센트가 이 권한에 의존하고, 그 경로들은 23개의 AWS 서비스에 이릅니다. 여러분을 대신해 워크로드를 실행하는 모든 서비스가 여러분이 넘겨주는 역할을 받아들이기 때문입니다. 정책 검토에서 와일드카드 리소스는 무해해 보이고 전달 자체는 CloudTrail에 전혀 나타나지 않기 때문에, 이 권한은 지나치게 넓게 부여되기 쉽습니다. 이 글에서는 이 권한이 하는 일, AWS가 하는 검사, 공격자가 이를 사용하는 방식, 로그에 남는 내용, 그리고 경로가 닫히도록 범위를 좁히는 방법을 설명합니다.

iam:PassRole이란 무엇인가

많은 AWS 서비스는 리소스를 구성할 때 여러분이 지정한 IAM 역할로 동작합니다. Lambda 함수는 실행 역할로 실행되고, EC2 인스턴스는 인스턴스 프로파일에서 자격 증명을 받으며, CodeBuild 프로젝트는 서비스 역할로 AWS를 호출합니다. 그 역할을 서비스에 넘기는 것을 역할 전달이라고 하며, AWS는 호출자에게 그렇게 할 권한이 있는지 확인합니다.

그 확인이 바로 iam:PassRole입니다. AWS 문서는 PassRole이 권한이며 API 호출이 없다고 명시하므로, SDK에는 PassRole 작업이 없습니다. 역할 ARN은 Lambda CreateFunction의 Role 파라미터처럼 다른 호출의 파라미터로 전달되며, 서비스는 그 호출을 처리하는 동안 호출자의 iam:PassRole 권한을 확인합니다.

이 권한은 주체가 자신이 가진 것보다 더 많은 액세스를 서비스에 넘기지 못하게 하려고 존재합니다. Amazon S3 권한이 없는 개발자가 S3를 허용하는 역할을 전달할 수 있다면 서비스가 그 개발자를 대신해 S3 작업을 수행하게 되며, 이것이 바로 AWS가 같은 페이지에서 경고하는 권한 상승입니다.

역할이 전달될 때 AWS가 하는 세 가지 검사

PassRole에 관한 AWS Security Blog 게시물은 서비스가 전달된 역할을 사용하기 전에 모두 충족되어야 하는 세 가지 조건을 제시합니다.

  1. 호출자가 그 역할을 전달할 수 있어야 합니다. 호출자의 자격 증명 기반 정책이 Resource 요소에 해당 역할을 지정한 iam:PassRole을 허용해야 하고, 그 명령문의 모든 조건이 충족되어야 하며, 서비스 제어 정책, 권한 경계, 세션 정책, VPC 엔드포인트 정책을 포함해 다른 어떤 것도 이를 거부해서는 안 됩니다.
  2. 역할이 대상 서비스를 신뢰해야 합니다. 역할의 신뢰 정책이 서비스 주체를 허용해야 합니다. 예를 들어 Lambda 실행 역할이라면 lambda.amazonaws.com입니다. AWS는 신뢰가 없어도 경우에 따라 리소스가 생성되기는 하지만, 그러면 서비스가 그 역할을 사용할 수 없다고 설명합니다.
  3. 역할과 호출자가 같은 계정에 있어야 합니다. IAM 사용 설명서에 따르면 iam:PassRole은 같은 AWS 계정에 있는 서비스에만 역할을 전달하므로, 교차 계정 설계에는 두 번째 계정에 첫 번째 계정의 역할을 수임할 수 있는 역할이 필요합니다.

공격자에게는 두 번째 조건이 표적 목록을 정합니다. 공격자가 리소스를 만들 수 있는 서비스를 신뢰 정책에 지정한 계정 내 모든 역할이 후보가 되며, 공격자가 그 역할을 사용할 수 있는지는 첫 번째 조건이 결정합니다.

PassRole 검사가 일어나는 곳

이 검사는 서비스 역할과 함께 리소스가 생성될 때마다, 그리고 기존 리소스가 새 역할로 업데이트될 때마다 실행됩니다. Lambda 함수의 실행 역할을 바꾸는 것도 그런 업데이트이므로, 함수를 만들 때와 같은 권한이 필요합니다.

서비스 연결 역할을 사용하는 서비스는 대개 그 역할을 직접 만들고 관리하므로 전달이 일어나지 않습니다. 이름을 지정한 서비스 연결 역할로 생성하는 Amazon EC2 Auto Scaling 그룹처럼 서비스가 서비스 연결 역할을 고르게 해 주는 경우에는, AWS가 같은 방식으로 iam:PassRole을 확인합니다.

아래 표는 역할을 전달하는 흔한 호출 몇 가지와 그 역할을 담는 요청 파라미터를 보여 줍니다. 탐지 규칙이 읽어야 하는 것도 바로 이 파라미터입니다.

서비스역할을 전달하는 호출역할을 담는 파라미터공격 맵 항목
LambdaCreateFunctionRoleLambda에 역할 전달
EC2RunInstancesIamInstanceProfile (역할을 포함하는 인스턴스 프로파일)EC2에 역할 전달
CloudFormationCreateStackRoleARNCloudFormation에 역할 전달
CodeBuildCreateProjectserviceRoleCodeBuild에 역할 전달

맵에는 Glue 작업, SageMaker 훈련 작업, ECS 태스크, Step Functions, Bedrock AgentCore를 포함해 Pathbreak가 추적하는 모든 전달이 나와 있으며, 공격 맵을 iam:PassRole로 필터링하면 한데 모아 볼 수 있습니다.

공격자가 iam:PassRole을 악용하는 방법

01 Attacker principal CreateFunction 02 New Lambda iam:PassRole 03 Passed role runs as role 04 Administrator
iam:PassRole과 lambda:CreateFunction을 함께 보유한 주체는 함수를 만들고 그 함수에 특권 역할을 넘기며, 함수는 그 역할로 실행됩니다. 전달은 CloudTrail에 별도의 이벤트로 나타나지 않습니다.

어떤 서비스가 관련되든 악용은 같은 세 단계를 따릅니다.

서비스를 신뢰하는 특권 역할을 찾습니다. iam:ListRoles는 각 역할의 신뢰 정책을 AssumeRolePolicyDocument 필드에 담아 반환하므로, 호출 한 번으로 어떤 역할이 Lambda, EC2, CodeBuild 또는 다른 서비스를 신뢰하는지 알 수 있습니다. 공격자는 넓은 권한을 가지면서 자신이 리소스를 만들 수 있는 서비스를 신뢰 정책에 지정한 역할을 찾습니다.

그 역할을 연결한 리소스를 만듭니다. 해당 역할에 대한 iam:PassRole과 lambda:CreateFunction을 가진 공격자는 특권 역할을 실행 역할로 하는 함수를 만듭니다. 호출자의 정책이 전달을 허용하고 역할이 lambda.amazonaws.com을 신뢰하므로 AWS는 전달을 수락합니다.

그 역할로 코드를 실행합니다. 공격자가 함수를 호출하면, 그가 작성한 코드가 무엇이든 특권 역할의 권한으로 실행됩니다. 그 역할이 관리자라면 생성 한 번과 호출 한 번으로 계정이 넘어갑니다. 같은 수법이 EC2 사용자 데이터, CodeBuild buildspec, CloudFormation 템플릿, Glue 작업 스크립트를 통해서도 통하며, 그래서 지나치게 넓은 iam:PassRole 권한 부여 하나가 여러 경로를 한꺼번에 열 수 있습니다.

이 체인의 Lambda 버전과 각 단계의 CloudTrail 이벤트는 세 가지 AWS 권한 상승 공격, CloudTrail 증거와 해결책에서 다룹니다.

iam:PassedToService만으로는 충분하지 않은 이유

iam:PassedToService는 역할을 어떤 서비스에 전달할 수 있는지 제한하는 조건 키입니다. 유용한 조건이며, AWS 자체의 정책 검증도 와일드카드 리소스에 대한 iam:PassRole에 보안 경고를 표시하고 특정 역할 ARN이나 이 조건 중 하나를 권장합니다. 하지만 두 선택지는 결코 동등하지 않습니다. 조건은 서비스를 좁히지만 와일드카드는 여전히 계정의 모든 역할을 포함하기 때문입니다.

AWS 관리형 정책 AWSLambda_FullAccess는 이 차이를 분명히 보여 줍니다. 이 정책은 lambda:*, iam:ListRoles, iam:GetRole을 부여하고, iam:PassedToService를 lambda.amazonaws.com으로 설정한 채 "Resource": "*"에 대한 iam:PassRole을 허용합니다. 이 정책을 가진 주체는 계정의 역할을 나열하고, 신뢰 정책이 Lambda를 허용하는 역할을 찾아, 그 역할로 함수를 만들고 호출할 수 있습니다. 계정의 특권 역할이 Lambda를 신뢰한다면 조건은 권한 상승을 전혀 막지 못합니다. 전달 대상이 실제로 Lambda이기 때문입니다.

이 조건은 특정 리소스와 결합될 때 제 역할을 합니다. 특정 역할 ARN은 어떤 역할을 전달할 수 있는지 정하고, iam:PassedToService는 그 역할을 어떤 서비스에 전달할 수 있는지 정합니다. 이는 역할이 둘 이상의 서비스를 신뢰할 때 중요합니다.

CloudTrail에서 iam:PassRole 악용을 탐지하는 방법

AWS는 PassRole에 대해서는 CloudTrail 로그가 생성되지 않는다고 밝히므로, 증거는 언제나 역할을 받은 생성 또는 업데이트 호출입니다.

  • 파라미터를 지켜보세요. Lambda의 경우 요청 파라미터에 역할 ARN이 들어 있는 CreateFunction 관리 이벤트입니다. Lambda CloudTrail 참조 문서에는 이벤트 이름이 CreateFunction20150331로 나와 있으므로, 규칙은 이벤트 이름의 접두사로 일치시켜야 합니다. 같은 문서에 따르면 Environment와 ZipFile 파라미터는 로그에서 빠지므로, 공격자가 업로드한 코드는 이벤트에 들어 있지 않습니다.
  • 역할과 호출자를 비교하세요. 강한 신호는 호출하는 주체보다 더 많은 권한을 가진 역할을 연결하는 생성 호출이며, 특히 해당 리소스 유형을 만든 이력이 없는 주체에서 나온 경우입니다.
  • 후속 이벤트를 켜세요. Lambda Invoke는 데이터 이벤트이며, AWS가 확인하듯 CloudTrail은 기본적으로 이를 기록하지 않습니다. Lambda 데이터 이벤트를 활성화하면 규칙이 생성과 몇 분 뒤의 호출을 짝지을 수 있습니다.
  • 실패를 읽으세요. CloudTrail은 실패한 호출을 오류 코드 및 오류 메시지와 함께 기록합니다. AWS의 문제 해결 안내에 나와 있듯이, 전달이 거부되면 AWS가 반환하는 오류에 iam:PassRole과 역할 ARN이 명시됩니다. 각기 다른 역할을 지정한 생성 호출이 연달아 거부된다면, 공격자가 어떤 역할을 전달할 수 있는지 시험하고 있는 모습입니다.

전달이 성공한 뒤에는 역할 자체의 활동이 마지막으로 살펴볼 곳입니다. 한 시간 전에는 존재하지 않던 함수나 인스턴스에서 전달된 역할로 이루어진 API 호출은 자세히 들여다볼 가치가 있습니다.

iam:PassRole의 범위를 좁히는 방법

목표는 각 주체가 업무에 필요한 역할만, 그 역할을 사용하는 서비스에만 전달할 수 있게 하는 것입니다.

  • 역할을 지정하세요. Resource 요소에 특정 역할 ARN을 넣으세요. 역할이 자주 생성된다면 AWS Security Blog의 권장대로 arn:aws:iam::111122223333:role/application_role/* 같은 IAM 경로나 이름 접두사를 사용해, 그 경로의 새 역할이 정책 변경 없이 포함되게 하세요.
  • iam:PassedToService를 추가하세요. 특정 리소스와 함께 사용해, 여러 서비스를 신뢰하는 역할이 워크로드가 사용하는 서비스에만 전달될 수 있게 하세요.
  • 적합한 경우 iam:AssociatedResourceArn을 사용하세요. 이 조건 키는 역할을 어떤 리소스에 연결할 수 있는지 제한합니다. 일부 리소스 ARN은 리소스를 다시 만들면 바뀌기 때문에, AWS는 많은 조직이 대신 리소스를 수정할 수 있는 사람을 제한한다고 설명합니다.
  • 태그 기반 제어는 피하세요. AWS는 iam:PassRole에 대한 ResourceTag 조건이 신뢰할 만한 결과를 내지 않는다고 경고하므로, 역할의 태그는 이 권한에 맞지 않는 제어 수단입니다.
  • SCP로 특권 경로를 보호하세요. 서비스 제어 정책은 호출자에게 특정 태그가 있거나 호출자가 승인된 경로에 있지 않은 한, 보안 팀이 사용하는 역할 같은 보호 대상 경로에 대한 iam:PassRole을 거부할 수 있습니다.
  • 개발자가 만드는 역할에 경계를 두세요. 개발자가 직접 역할을 만들 수 있다면 그 역할에 권한 경계를 요구하고, 전용 경로에 있는 역할만 전달할 수 있게 하세요. 그러면 개발자가 만든 뒤 전달하는 역할이 경계를 넘어설 수 없습니다.

각 변경은 팀이 의존하는 기능을 유지하면서, 전달할 필요가 전혀 없었던 역할을 거쳐 가는 경로를 닫습니다.

PassRole 범위 설정으로 해결되지 않는 것

iam:PassRole의 범위를 좁히면 새 리소스에서 시작하는 경로가 닫힙니다. 하지만 이미 특권 역할이 연결된 리소스에는 아무 효과가 없습니다. 그런 리소스가 실행하는 내용을 바꿔도 역할 전달은 일어나지 않기 때문입니다. 이런 경로에는 수정 권한에 대한 별도의 제어가 필요합니다.

  • Lambda 함수 코드. lambda:UpdateFunctionCode는 기존 함수의 코드를 교체하면서 실행 역할은 그대로 두므로, 다음에 함수가 호출될 때 공격자의 코드가 그 역할로 실행됩니다.
  • EC2 사용자 데이터. ec2:StopInstances, ec2:ModifyInstanceAttribute, ec2:StartInstances를 가진 공격자는 인스턴스를 중지하고, 사용자 데이터를 다시 쓴 뒤, 인스턴스를 다시 시작합니다. 사용자 데이터는 기본적으로 첫 부팅 때만 실행되므로 공격자는 부팅할 때마다 실행되는 cloud-init 구성을 넣고, 스크립트는 인스턴스의 기존 프로파일로 실행됩니다.
  • SSM 명령. ssm:SendCommand는 관리형 인스턴스에서 스크립트를 실행하며, 그 스크립트는 인스턴스에 이미 연결된 역할의 자격 증명을 읽을 수 있습니다.
  • CloudFormation 스택 역할. AWS는 스택에 서비스 역할이 연결되면 그 스택에서 작업할 수 있는 사용자는 iam:PassRole 보유 여부와 관계없이 그 역할을 사용할 수 있다고 설명합니다. 따라서 스택을 업데이트하거나 변경 세트를 실행할 수 있는 주체는 그 역할을 물려받습니다. UpdateStack 변형도 같은 방식으로 작동합니다.
  • CodeBuild 프로젝트. 기존 프로젝트의 빌드를 buildspec을 재정의해 시작하면, 공격자의 명령이 프로젝트의 서비스 역할로 실행됩니다.

iam:PassRole에서 멈추는 계정 검토는 이 모든 것을 놓치게 되며, 그래서 맵은 이들을 별도 항목으로 나열합니다.

누가 특권 역할을 전달할 수 있는지 확인하는 방법

주체 하나와 역할 하나라면 IAM 정책 시뮬레이터가 빠르게 답을 줍니다. 시뮬레이터는 지정한 주체에 대해 조건을 포함한 자격 증명 기반 정책과 서비스 제어 정책을 평가합니다.

aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::111122223333:user/dev-user \
--action-names iam:PassRole \
--resource-arns arn:aws:iam::111122223333:role/AdminRole

주체의 정책이 iam:PassedToService를 사용한다면, iam:PassedToService 키를 lambda.amazonaws.com 같은 대상 서비스로 설정하는 --context-entries 인수를 추가하세요. 이 인수가 없으면 시뮬레이터에는 비교할 값이 없기 때문입니다. 결과는 세 가지 검사 중 첫 번째에만 답합니다. 역할의 신뢰 정책이 그 서비스를 허용하는지는 별개의 질문으로, 역할의 AssumeRolePolicyDocument를 읽어야 답할 수 있으며, 호출자에게는 여전히 그 서비스의 생성 권한이 필요합니다. AWS는 시뮬레이터 결과가 실제 환경과 다를 수 있다는 점도 언급합니다.

한 쌍이라면 감당할 만하지만, 주체와 역할이 수백 개인 계정 전체에서는 현실적이지 않습니다. 무료 오픈 소스 도구 pathbreak-audit는 한 계정의 IAM을 읽고, 생성 작업과 결합된 iam:PassRole 같은 악용 가능한 권한과 조합을 가진 역할과 사용자를 각각의 해결책과 함께 나열해 출발점을 제공합니다. Pathbreak는 한 걸음 더 나아가 모든 전달을 호출자의 정책, 경계, SCP, 역할의 신뢰 정책에 비추어 판정하므로, 실제로 성공할 경로만 보고되며 전달된 역할이 도달할 수 있는 대상을 기준으로 순위가 매겨집니다.

자주 묻는 질문

iam:PassRole은 무엇을 하나요?

iam:PassRole은 주체가 IAM 역할을 서비스에 넘길 때 AWS가 확인하는 권한입니다. 예를 들어 Lambda 함수의 실행 역할이나 EC2 인스턴스 프로파일로 넘기는 경우입니다. 이 권한은 주체가 어떤 역할을 서비스에 넘길 수 있는지 제어하므로, 서비스가 주체에게 의도된 것보다 더 많은 액세스로 동작하는 일이 없습니다. Pathbreak는 여러분의 계정에서 어떤 주체가 각 특권 역할을 전달할 수 있는지 보여 줍니다.

iam:PassRole은 그 자체로 위험한가요?

그 자체로는 위험하지 않습니다. lambda:CreateFunction이나 ec2:RunInstances처럼 역할을 받아들이는 리소스를 만들거나 업데이트하는 권한과 결합되고, 특권 역할이 해당 서비스를 신뢰할 때 권한 상승 경로가 됩니다. Resource 요소의 범위를 특정 역할로 좁히면 그 경로가 사라집니다. Pathbreak는 경로를 검증할 때 각 역할 전달의 신뢰 정책과 조건을 확인합니다.

CloudTrail은 iam:PassRole을 기록하나요?

아니요. AWS 문서에 따르면 PassRole은 권한이며 CloudTrail 이벤트를 생성하지 않습니다. 전달은 Lambda CreateFunction 이벤트의 역할 ARN처럼 리소스를 생성하거나 수정한 호출의 파라미터로 나타나며, 거부된 전달은 오류 메시지에 iam:PassRole이 명시된 실패한 생성 호출로 나타납니다.

iam:PassedToService만으로 iam:PassRole을 안전하게 만들 수 있나요?

리소스가 와일드카드라면 그렇지 않습니다. 조건은 서비스를 제한하지만, 그 서비스를 신뢰하는 계정 내 모든 역할은 여전히 전달될 수 있으며, AWSLambda_FullAccess 관리형 정책이 바로 그런 경우입니다. iam:PassedToService를 특정 역할 ARN이나 IAM 경로와 함께 사용하세요.

내 계정에서 누가 특권 역할을 전달할 수 있는지 어떻게 찾나요?

주체 하나라면 iam:PassRole과 역할 ARN을 지정한 aws iam simulate-principal-policy가 주체의 정책이 전달을 허용하는지 알려 주고, 역할의 신뢰 정책은 어떤 서비스가 그 역할을 받을 수 있는지 보여 줍니다. 계정 전체에 걸쳐서는 pathbreak-audit가 이러한 권한을 가진 주체를 나열하고, Pathbreak가 어떤 전달이 성공할지 검증해 도달 대상을 기준으로 순위를 매깁니다.

관련 글

지금 여러분의 계정에서 어떤 주체가 특권 역할을 전달할 수 있는지, 그리고 각 경로를 닫는 단 하나의 변경이 무엇인지 확인하세요.

데모 신청 데모 보기