Abusing Github Actions
기본 정보
이 페이지에서 찾을 수 있는 내용:
공격자가 Github Action에 접근했을 때의 모든 영향 요약
액션에 접근하는 다양한 방법:
액션을 생성할 권한이 있는 경우
pull request 관련 트리거 악용
다른 외부 접근 기술 악용
이미 손상된 저장소에서 피벗팅
마지막으로, 내부에서 액션을 악용하는 포스트 익스플로잇 기술에 대한 섹션
영향 요약
Github Actions 기본 정보에 대한 소개를 참조하세요.
저장소에서 임의의 Github actions를 실행/코드 주입할 수 있는 경우, 다음을 수행할 수 있습니다:
해당 저장소/조직의 비밀을 탈취.
주입만 가능하다면, 워크플로우에 이미 존재하는 것을 탈취할 수 있습니다.
저장소 권한을 악용하여 AWS 및 GCP와 같은 다른 플랫폼에 접근.
커스텀 워커에서 코드 실행 (커스텀 워커가 사용되는 경우) 및 거기서 피벗 시도.
저장소 코드 덮어쓰기.
이는
GITHUB_TOKEN
의 권한에 따라 다릅니다 (있는 경우).배포 및 기타 아티팩트 손상.
코드가 무언가를 배포하거나 저장하는 경우, 이를 수정하여 추가 접근 권한을 얻을 수 있습니다.
GITHUB_TOKEN
이 "비밀" ( ${{ secrets.GITHUB_TOKEN }}
및 ${{ github.token }}
에서 제공됨)은 관리자가 이 옵션을 활성화할 때 제공됩니다:
이 토큰은 Github Application이 사용할 동일한 토큰이므로 동일한 엔드포인트에 접근할 수 있습니다: https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps
Github는 cross-repository 접근을 허용하는 flow를 출시해야 합니다, 그래서 저장소가 GITHUB_TOKEN
을 사용하여 다른 내부 저장소에 접근할 수 있습니다.
이 토큰의 가능한 권한을 확인할 수 있습니다: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
토큰은 작업이 완료된 후 만료된다는 점에 유의하세요.
이 토큰은 다음과 같이 생겼습니다: ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7
이 토큰으로 할 수 있는 몇 가지 흥미로운 작업:
여러 경우에 Github Actions 환경 또는 secrets 내에서 github 사용자 토큰을 찾을 수 있습니다. 이러한 토큰은 저장소 및 조직에 대한 더 많은 권한을 부여할 수 있습니다.
다른 사용자의 리포지토리에서 Github Token에 부여된 권한을 로그를 확인하여 확인할 수 있습니다:
허용된 실행
이것은 Github actions을 손상시키는 가장 쉬운 방법일 것입니다. 이 경우는 조직에서 새로운 리포지토리를 생성할 수 있는 접근 권한이 있거나, 리포지토리에 대한 쓰기 권한이 있는 경우를 가정합니다.
이 시나리오에 해당하는 경우 Post Exploitation techniques를 확인할 수 있습니다.
리포지토리 생성에서의 실행
조직의 구성원이 새로운 리포지토리를 생성할 수 있고 Github actions을 실행할 수 있는 경우, 새로운 리포지토리를 생성하고 조직 수준에서 설정된 비밀을 탈취할 수 있습니다.
새로운 브랜치에서의 실행
이미 Github Action이 구성된 리포지토리에서 새로운 브랜치를 생성할 수 있는 경우, 이를 수정하고 업로드한 다음 새로운 브랜치에서 해당 액션을 실행할 수 있습니다. 이 방법으로 리포지토리 및 조직 수준의 비밀을 유출할 수 있습니다 (하지만 그들이 어떻게 호출되는지 알아야 합니다).
수정된 액션을 수동으로, PR이 생성될 때 또는 코드가 푸시될 때 실행 가능하게 만들 수 있습니다 (얼마나 눈에 띄고 싶은지에 따라 다릅니다):
포크된 실행
공격자가 다른 저장소의 Github Action을 실행할 수 있게 하는 다양한 트리거가 있습니다. 이러한 트리거 가능한 액션이 잘못 구성된 경우, 공격자가 이를 손상시킬 수 있습니다.
pull_request
pull_request
워크플로우 트리거 **pull_request
**는 몇 가지 예외를 제외하고 풀 리퀘스트가 수신될 때마다 워크플로우를 실행합니다: 기본적으로 처음으로 협업하는 경우, 유지 관리자가 워크플로우의 실행을 승인해야 합니다:
기본 제한이 처음 기여자에게 적용되므로, 유효한 버그/오타를 수정하고 새로운 pull_request
권한을 남용하는 다른 PR을 보낼 수 있습니다.
이것을 테스트했지만 작동하지 않습니다: 또 다른 옵션은 프로젝트에 기여하고 계정을 삭제한 사람의 이름으로 계정을 만드는 것입니다.
게다가, 기본적으로 대상 저장소에 대한 쓰기 권한과 비밀 접근을 방지합니다. 이는 문서에 언급된 대로입니다:
GITHUB_TOKEN
을 제외하고, 비밀은 포크된 저장소에서 트리거된 워크플로우에 전달되지 않습니다. 포크된 저장소에서의 풀 리퀘스트에서는GITHUB_TOKEN
이 읽기 전용 권한을 가집니다.
공격자는 Github Action의 정의를 수정하여 임의의 작업을 실행하고 임의의 액션을 추가할 수 있습니다. 그러나 앞서 언급한 제한 때문에 비밀을 훔치거나 저장소를 덮어쓸 수는 없습니다.
예, 공격자가 PR에서 트리거될 Github Action을 변경하면, 그의 Github Action이 사용되고 원본 저장소의 것이 사용되지 않습니다!
공격자가 실행되는 코드를 제어하기 때문에, 비밀이나 GITHUB_TOKEN
의 쓰기 권한이 없더라도 공격자는 예를 들어 악성 아티팩트를 업로드할 수 있습니다.
pull_request_target
pull_request_target
워크플로우 트리거 **pull_request_target
**은 대상 저장소에 대한 쓰기 권한과 비밀 접근을 가지고 있습니다 (그리고 권한을 묻지 않습니다).
워크플로우 트리거 **pull_request_target
**은 기본 컨텍스트에서 실행되며 PR에서 제공된 컨텍스트에서 실행되지 않습니다 (즉, 신뢰할 수 없는 코드를 실행하지 않기 위해). pull_request_target
에 대한 자세한 정보는 문서를 참조하십시오.
또한, 이 특정 위험한 사용에 대한 자세한 정보는 이 github 블로그 게시물을 참조하십시오.
실행된 워크플로우가 PR이 아닌 기본에서 정의된 것이기 때문에 **pull_request_target
**을 사용하는 것이 안전해 보일 수 있지만, 몇 가지 경우에는 그렇지 않습니다.
이 경우 비밀에 접근할 수 있습니다.
workflow_run
workflow_run
workflow_run 트리거는 다른 워크플로우가 completed
, requested
또는 in_progress
상태일 때 워크플로우를 실행할 수 있게 합니다.
이 예제에서는 별도의 "Run Tests" 워크플로우가 완료된 후 워크플로우가 실행되도록 구성되어 있습니다:
또한, 문서에 따르면: workflow_run
이벤트에 의해 시작된 워크플로우는 이전 워크플로우가 그렇지 않더라도 비밀과 쓰기 토큰에 접근할 수 있습니다.
이러한 종류의 워크플로우는 외부 사용자가 pull_request
또는 **pull_request_target
**을 통해 트리거할 수 있는 워크플로우에 의존하는 경우 공격받을 수 있습니다. 몇 가지 취약한 예시는 이 블로그에서 찾을 수 있습니다. 첫 번째 예시는 workflow_run
트리거된 워크플로우가 공격자의 코드를 다운로드하는 것입니다: ${{ github.event.pull_request.head.sha }}
두 번째 예시는 신뢰할 수 없는 코드에서 아티팩트를 workflow_run
워크플로우로 전달하고 이 아티팩트의 내용을 RCE에 취약한 방식으로 사용하는 것입니다.
workflow_call
workflow_call
TODO
TODO: pull_request에서 실행될 때 사용/다운로드된 코드가 원본인지 포크된 PR인지 확인
포크된 실행 악용
외부 공격자가 github 워크플로우를 실행하도록 만들 수 있는 모든 방법을 언급했으니, 이제 이러한 실행이 잘못 구성된 경우 어떻게 악용될 수 있는지 살펴보겠습니다:
신뢰할 수 없는 체크아웃 실행
**pull_request
**의 경우, 워크플로우는 PR의 컨텍스트에서 실행됩니다 (따라서 악성 PR 코드를 실행합니다), 하지만 누군가가 먼저 승인해야 하고 몇 가지 제한과 함께 실행됩니다.
**pull_request_target
또는 workflow_run
**을 사용하는 워크플로우의 경우 **pull_request_target
또는 pull_request
**에서 트리거될 수 있는 워크플로우에 의존하는 경우 원본 저장소의 코드가 실행되므로 공격자가 실행되는 코드를 제어할 수 없습니다.
그러나, 액션이 명시적인 PR 체크아웃을 가지고 있어 PR의 코드를 가져오는 경우 (기본이 아닌), 공격자가 제어하는 코드를 사용하게 됩니다. 예를 들어 (PR 코드가 다운로드되는 12번째 줄을 확인하십시오):
신뢰할 수 없는 코드가 npm install
또는 npm build
중에 실행될 수 있으며, 빌드 스크립트와 참조된 패키지는 PR 작성자가 제어합니다.
취약한 액션을 검색하기 위한 github dork는: event.pull_request pull_request_target extension:yml
입니다. 그러나, 액션이 안전하지 않게 구성되었더라도 작업을 안전하게 실행하도록 구성하는 다양한 방법이 있습니다 (예: PR을 생성하는 배우가 누구인지에 대한 조건 사용).
컨텍스트 스크립트 인젝션
일부 github 컨텍스트의 값은 PR을 생성하는 사용자에 의해 제어된다는 점에 유의하십시오. github 액션이 무언가를 실행하기 위해 해당 데이터를 사용하는 경우, 이는 임의 코드 실행으로 이어질 수 있습니다:
Gh Actions - Context Script InjectionsGITHUB_ENV 스크립트 인젝션
문서에 따르면: 환경 변수를 정의하거나 업데이트하고 이를 GITHUB_ENV
환경 파일에 작성하여 워크플로우 작업의 후속 단계에서 사용할 수 있도록 할 수 있습니다.
공격자가 이 env 변수에 어떤 값이든 주입할 수 있다면, LD_PRELOAD 또는 NODE_OPTIONS와 같은 후속 단계에서 코드를 실행할 수 있는 env 변수를 주입할 수 있습니다.
예를 들어 (이것 및 이것), 업로드된 아티팩트를 신뢰하여 그 내용을 GITHUB_ENV
env 변수에 저장하는 워크플로우를 상상해보십시오. 공격자는 이를 손상시키기 위해 다음과 같은 것을 업로드할 수 있습니다:
취약한 서드 파티 Github 액션
이 블로그 게시물에서 언급된 바와 같이, 이 Github 액션은 다른 워크플로우 및 심지어 저장소의 아티팩트에 접근할 수 있습니다.
문제는 path
매개변수가 설정되지 않은 경우, 아티팩트가 현재 디렉토리에 추출되어 나중에 사용되거나 심지어 워크플로우에서 실행될 수 있는 파일을 덮어쓸 수 있다는 것입니다. 따라서, 아티팩트가 취약한 경우, 공격자는 이를 악용하여 아티팩트를 신뢰하는 다른 워크플로우를 손상시킬 수 있습니다.
취약한 워크플로우의 예:
이것은 이 workflow로 공격할 수 있습니다:
Other External Access
Deleted Namespace Repo Hijacking
계정이 이름을 변경하면 일정 시간이 지난 후 다른 사용자가 그 이름으로 계정을 등록할 수 있습니다. 만약 이름 변경 이전에 별이 100개 미만인 저장소가 있었다면, Github은 동일한 이름으로 새로 등록된 사용자가 동일한 이름의 저장소를 생성할 수 있도록 허용합니다.
따라서 액션이 존재하지 않는 계정의 저장소를 사용하고 있다면, 공격자가 그 계정을 생성하고 액션을 손상시킬 가능성이 여전히 존재합니다.
다른 저장소가 이 사용자 저장소의 종속성을 사용하고 있다면, 공격자는 이를 하이재킹할 수 있습니다. 여기 더 완전한 설명이 있습니다: https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/
Repo Pivoting
이 섹션에서는 첫 번째 저장소에 어떤 형태로든 접근할 수 있다고 가정할 때, 한 저장소에서 다른 저장소로 피벗할 수 있는 기술에 대해 이야기하겠습니다 (이전 섹션을 확인하세요).
Cache Poisoning
캐시는 같은 브랜치에서 워크플로우 실행 간에 유지됩니다. 이는 공격자가 패키지를 손상시키고 이를 캐시에 저장한 후 더 높은 권한을 가진 워크플로우가 이를 다운로드하고 실행하면, 그 워크플로우도 손상시킬 수 있다는 것을 의미합니다.
GH Actions - Cache PoisoningArtifact Poisoning
워크플로우는 다른 워크플로우나 저장소의 아티팩트를 사용할 수 있습니다. 만약 공격자가 아티팩트를 업로드하는 Github Action을 손상시키고, 그 아티팩트가 나중에 다른 워크플로우에서 사용된다면, 그는 다른 워크플로우도 손상시킬 수 있습니다:
Gh Actions - Artifact PoisoningPost Exploitation from an Action
Accessing AWS and GCP via OIDC
다음 페이지를 확인하세요:
AWS - Federation AbuseGCP - Federation AbuseAccessing secrets
스크립트에 내용을 주입하는 경우, 비밀에 접근하는 방법을 아는 것이 중요합니다:
비밀 또는 토큰이 환경 변수로 설정된 경우, **
printenv
**를 사용하여 환경을 통해 직접 접근할 수 있습니다.
비밀이 표현식에 직접 사용되는 경우, 생성된 셸 스크립트가 디스크에 저장되며 접근이 가능합니다.
cat /home/runner/work/_temp/*
커스텀 액션의 경우, 프로그램이 인수에서 얻은 비밀을 사용하는 방식에 따라 위험이 달라질 수 있습니다:
Self-hosted runners 악용
Github Actions가 비github 인프라에서 실행되는지 확인하는 방법은 Github Action 구성 yaml에서 **runs-on: self-hosted
**를 검색하는 것입니다.
Self-hosted runners는 추가적인 민감 정보나 다른 네트워크 시스템(네트워크의 취약한 엔드포인트? 메타데이터 서비스?)에 접근할 수 있으며, 격리되고 파괴되더라도 여러 액션이 동시에 실행될 수 있고 악성 액션이 다른 액션의 비밀을 훔칠 수 있습니다.
Self-hosted runners에서는 _Runner.Listener_** 프로세스**에서 메모리를 덤프하여 워크플로의 모든 비밀을 얻는 것도 가능합니다:
Github Docker Images Registry
Github actions를 사용하여 Docker 이미지를 빌드하고 Github에 저장할 수 있습니다. 다음 확장 가능한 예제에서 확인할 수 있습니다:
Last updated