Aleksander Roszig
27 września 2026 | 6 min czytaniaIAM PassRole w AWS: dlaczego iam:PassRole jest zagrożeniem
Spis treści
Podczas audytów kont AWS najciekawsze znaleziska rzadko są tymi oczywistymi, jak publiczny bucket S3 czy klucz dostępowy wrzucony do Gita. Znaleziska, które zmieniają profil ryzyka całego konta, zwykle kryją się w jednej linijce polityki IAM. Jedną z linijek, które od razu przykuwają uwagę, jest "Action": "iam:PassRole", "Resource": "*".
iam:PassRole wygląda niewinnie. Niczego nie tworzy, nie odczytuje danych i nie pojawia się nawet jako osobne zdarzenie w CloudTrail, a mimo to potrafi zamienić „ograniczoną” rolę dewelopera czy pipeline’u CI/CD w administratora konta.
W tym artykule wyjaśniam, co faktycznie robi iam:PassRole, dlaczego tak często jest częścią ścieżek eskalacji uprawnień (ang. privilege escalation) w AWS i jak ją ograniczyć za pomocą polityk zgodnych z zasadą najmniejszych uprawnień (ang. least privilege) oraz zabezpieczeń na poziomie organizacji.
Czym jest iam:PassRole?
Często aby skonfigurować usługę musisz przekazać tej usłudze rolę IAM. Dzięki temu usługa może przy użyciu tej roli wykonywać działania. Funkcja Lambda zapisuje dane do DynamoDB, instancja EC2 czyta z S3. Robią to, przejmując rolę IAM, którą przypisujesz podczas tworzenia lub aktualizacji zasobu:
- Lambda – rola wykonawcza (ang. execution role),
- EC2 – rola w profilu instancji (ang. instance profile),
- ECS – rola zadania (ang. task role),
- SageMaker, Step Functions i wiele innych – rola usługi (ang. service role).
Aby przypisać rolę do takiego zasobu, podmiot potrzebuje uprawnienia do wywołania API usługi (na przykład lambda:CreateFunction) oraz uprawnienia iam:PassRole do tej roli. PassRole to odpowiedź AWS na pytanie: „Czy ten podmiot może przekazać tę rolę usłudze?”
Bez iam:PassRole podmiot może utworzyć zasób, ale nie może przypisać do niego roli. To częsta ścieżka eskalacji uprawnień w AWS, ponieważ iam:PassRole często wchodzi w skład uprawnień wymaganych do tworzenia zasobów, ale często bez zawężenia na konkretne role.
Na przykład mając uprawnienie "lambda:*", ale bez iam:PassRole, podmiot może utworzyć funkcję Lambda, ale nie może przypisać do niej roli, więc w konsoli webowej zobaczy:
"User: arn:aws:iam::123456789:user1 is not authorized to perform: iam:PassRole on resource: arn:aws:iam::123456789:role/service-role/test-role-xxx with an explicit deny ..."
Minimalny działający przykład: deweloper, który może tworzyć funkcje Lambda wyłącznie z użyciem dedykowanych ról wykonawczych.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CreateFunctions",
"Effect": "Allow",
"Action": ["lambda:CreateFunction", "lambda:UpdateFunctionConfiguration"],
"Resource": "arn:aws:lambda:eu-central-1:123456789:function:app-*"
},
{
"Sid": "PassOnlyLambdaExecutionRoles",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::123456789:role/lambda-exec-app-*",
"Condition": {
"StringEquals": { "iam:PassedToService": "lambda.amazonaws.com" }
}
}
]
}
Kluczowe są tu Resource (które role można przekazać) oraz warunek iam:PassedToService.
Jak działa PassRole: PassRole vs AssumeRole i trust policy
Przekazanie roli obejmuje dwa niezależne sprawdzenia:
- Uprawnienia wywołującego - czy tożsamość wywołująca
lambda:CreateFunctionmaiam:PassRoledo ARN tej roli? - Trust policy roli - czy rola ufa service principalowi, na przykład
lambda.amazonaws.com, na tyle, by pozwolić mu ją przejąć?
Dopiero gdy oba warunki są spełnione, usługa przejmuje rolę i otrzymuje tymczasowe poświadczenia.
To kluczowa różnica w porównaniu z sts:AssumeRole:
| sts:AssumeRole | iam:PassRole | |
|---|---|---|
| kto otrzymuje rolę | sam podmiot wywołujący | usługa AWS (Lambda, EC2, …) |
| czy to wywołanie API | tak, widoczne w CloudTrail | nie, tylko uprawnienie sprawdzane przez inne API |
| co to kontroluje | trust policy roli | polityka IAM wywołującego + trust policy roli |
| typowe ryzyko | zbyt szeroka trust policy | przekazanie roli silniejszej niż wywołujący |
PassRole nie jest akcją API. To wyłącznie uprawnienie, więc nie jest logowane jako zdarzenie PassRole w CloudTrail. Możliwe jest zobaczenie w parametrach wywołań API typu CreateFunction lub RunInstances.
Dlaczego iam:PassRole jest zagrożeniem
Usługa, która otrzymuje rolę, uruchamia kod kontrolowany przez wywołującego. Przykładowo funkcja Lambda uruchamia kod, który wgrywasz przy użyciu roli wykonującej (ang. execution role).
Dlatego właściwe pytanie w audycie nie brzmi „co może zrobić ten użytkownik?”, ale:
Co może zrobić ten użytkownik plus wszystko, co może zrobić dowolna rola, którą może przekazać - poprzez każdą usługę, którą może skonfigurować?
Jeśli rola CI/CD ma ograniczone uprawnienia, ale może przekazać rolę administratora usłudze, którą potrafi skonfigurować, to w praktyce rola CI/CD jest administratorem. Żadna polityka nie mówi tego wprost i samo przejrzenie ról tego nie pokaże. Dlatego ścieżki oparte na PassRole to osobna kategoria eskalacji uprawnień w AWS IAM.
Najczęstsze błędy konfiguracji iam:PassRole
To wzorce, które najczęściej widzimy podczas audytów bezpieczeństwa AWS:
iam:PassRolenaResource: "*"- pozwala przekazać dowolną rolę dowolnej usłudze. Tworzy wiele możliwych ścieżek eskalacji.iam:*lub"Action": "*"- w pipeline’ach CI/CD, runnerach Terraform i użytkownikach technicznych do automatyzacji.- Brak warunku
iam:PassedToService- przez co rolę przeznaczoną dla Lambdy można przekazać także EC2, czy dowolnej innej usłudze, która ma możliwość przejęcia roli. - Nazewnictwo ról bez konwencji - jeśli role administracyjne i role workloadów mają wspólne wzorce nazw to ciężko w łatwy sposób zdefiniować globalne zasady z wildcardem.
Jak ograniczyć iam:PassRole
1. Zawęź Resource do konkretnych ról
Nadawaj PassRole tylko do ról, których dany workload naprawdę potrzebuje. Pomaga w tym konwencja nazewnicza taka jak: lambda-exec-<app>-*, ecs-task-<app>-*.
2. Zawsze dodawaj iam:PassedToService
iam:PassedToService ogranicza, która usługa może otrzymać rolę.
"Condition": {
"StringEquals": { "iam:PassedToService": "ecs-tasks.amazonaws.com" }
}
3. Utrzymuj wąskie trust policy
Rola powinna ufać jednemu service principalowi, o ile to możliwe. W scenariuszach międzyusługowych lub między kontami używaj warunków takich jak aws:SourceArn i aws:SourceAccount, aby zapobiec problemowi confused deputy.
4. Dodaj zabezpieczenia na poziomie organizacji (Service Control Policy)
W AWS Organizations Service Control Policy (SCP) może zablokować przekazywanie uprzywilejowanych ról wszystkim poza na przykład, dedykowaną rolą automatyzacji platformy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyPassingPrivilegedRoles",
"Effect": "Deny",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::123456789:role/admin-*",
"Condition": {
"ArnNotLike": {
"aws:PrincipalArn": "arn:aws:iam::123456789:role/platform-automation"
}
}
}
]
}
To samo podejście można zastosować do zabezpieczenia innych przypadków.
Na kontach, na których deweloperzy mogą tworzyć własne role, połącz to z permissions boundary: nowe role tworzone przez deweloperów muszą mieć przypisany boundary, więc nawet jeśli przekażą taką rolę, nigdy nie wyjdzie ona poza granice.
5. Oddziel role wdrożeniowe od ról workloadów
Pipeline czy użytkownik Terraform, który wdraża funkcję Lambda, potrzebuje PassRole do jej roli wykonawczej, ale nie potrzebuje uprawnień tej roli. Upewnij się, że role automatyzacji mogą przekazywać wyłącznie role workloadów aplikacji, którą wdrażają.
Jak wykrywać ryzyka związane z iam:PassRole
Ryzyko wynika z kombinacji uprawnień. Najlepsze metody detekcji analizują cały graf podmiotów, ról i usług, a nie pojedyncze instrukcje polityk:
- IAM Access Analyzer - walidacja pod kątem wildcardów oraz znaleziska dotyczące nieużywanego dostępu, pozwalające usunąć uprawnienia, z których nikt nie korzysta.
- CloudTrail - alerty na pojawienie się ARN uprzywilejowanych ról w parametrach żądań.
Podsumowanie
iam:PassRole to uprawnienie, które samo w sobie niczego nie robi i nie jest widoczne w CloudTrail i właśnie dlatego tak często nadaje się je zbyt szeroko. Traktuj każdą instrukcję PassRole jak potencjalną ścieżkę eskalacji: zawężaj ją do konkretnych ARN ról, zawsze dodawaj iam:PassedToService, utrzymuj wąskie trust policy i zabezpieczaj całość za pomocą SCP oraz permissions boundaries.


