스크립트 인젝션(Script injections) 살펴보기
스크립트 인젝션(Script injections) 살펴보기
스크립트 인젝션과 GitHub Actions 워크플로와 관련된 보안 위험을 이해하는 내용이에요.
본문
스크립트 인젝션의 위험 이해하기
워크플로, 사용자 지정 액션, 복합 액션(composite actions)을 만들 때, 코드가 공격자의 신뢰할 수 없는 입력(untrusted input)을 실행할 수 있는지 항상 고려해야 해요. 이는 공격자가 컨텍스트에 악성 명령과 스크립트를 추가할 때 발생할 수 있어요. 워크플로가 실행되면 그 문자열들이 코드로 해석되어 러너에서 실행될 수 있어요.
공격자는 github 컨텍스트에 자신의 악성 콘텐츠를 추가할 수 있는데, 이 컨텍스트는 잠재적으로 신뢰할 수 없는 입력으로 취급해야 해요. 이런 컨텍스트는 일반적으로 body, default_branch, email, head_ref, label, message, name, page_name, ref, title로 끝나요. 예를 들어 github.event.issue.title 또는 github.event.pull_request.body가 있어요.
이 값들이 워크플로, 액션, API 호출 또는 실행 가능한 코드로 해석될 수 있는 다른 어떤 곳으로도 직접 흘러가지 않도록 해야 해요. 다른 권한 있는 애플리케이션 코드에 사용하는 것과 동일한 방어적 프로그래밍 자세를 채택하면 GitHub Actions 사용의 보안을 강화하는 데 도움이 돼요. 공격자가 취할 수 있는 몇 가지 단계에 대한 정보는 안전한 사용 참조를 참고하세요.
또한 분기 이름과 이메일 주소처럼 허용되는 내용이 꽤 유연한, 덜 명확한 잠재적 신뢰 불가 입력 소스도 있어요. 예를 들어 zzz\";echo${IFS}\"hello\";#는 유효한 분기 이름이며 대상 리포지토리에 대한 가능한 공격 벡터가 될 수 있어요.
다음 섹션들에서는 스크립트 인젝션 위험을 완화하는 데 도움이 되는 방법을 설명할게요.
스크립트 인젝션 공격 예시
스크립트 인젝션 공격은 워크플로의 인라인 스크립트 안에서 직접 발생할 수 있어요. 다음 예시에서 액션은 표현식을 사용해 풀 리퀘스트 제목의 유효성을 테스트하지만 스크립트 인젝션의 위험도 더해요:
- name: Check PR title
run: |
title="${{ github.event.pull_request.title }}"
if [[ $title =~ ^octocat ]]; then
echo "PR title starts with 'octocat'"
exit 0
else
echo "PR title did not start with 'octocat'"
exit 1
fi
이 예시는 run 명령이 러너의 임시 셸 스크립트에서 실행되기 때문에 스크립트 인젝션에 취약해요. 셸 스크립트가 실행되기 전에 ${{ }} 안의 표현식이 평가되고 결과 값으로 치환되므로 셸 명령 인젝션에 취약해질 수 있어요.
이 워크플로에 명령을 주입하기 위해 공격자는 제목이 a"; ls $GITHUB_WORKSPACE"인 풀 리퀘스트를 만들 수 있어요:

이 예시에서 " 문자는 title="${{ github.event.pull_request.title }}" 문을 끊는 데 사용되어 ls 명령이 러너에서 실행될 수 있게 해요. 로그에서 ls 명령의 출력을 볼 수 있어요:
Run title="a"; ls $GITHUB_WORKSPACE""
README.md
code.yml
example.js
러너를 안전하게 유지하는 모범 사례는 안전한 사용 참조를 참고하세요.