스크립트 인젝션(Script injections) 살펴보기

스크립트 인젝션(Script injections) 살펴보기

스크립트 인젝션과 GitHub Actions 워크플로와 관련된 보안 위험을 이해하는 내용이에요.

출처: Script injections

본문

스크립트 인젝션의 위험 이해하기

워크플로, 사용자 지정 액션, 복합 액션(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"인 풀 리퀘스트를 만들 수 있어요:

편집 모드의 풀 리퀘스트 제목 스크린샷. 필드에 새 제목이 입력됨: a"; ls $GITHUB_WORKSPACE".

이 예시에서 " 문자는 title="${{ github.event.pull_request.title }}" 문을 끊는 데 사용되어 ls 명령이 러너에서 실행될 수 있게 해요. 로그에서 ls 명령의 출력을 볼 수 있어요:

Run title="a"; ls $GITHUB_WORKSPACE""
README.md
code.yml
example.js

러너를 안전하게 유지하는 모범 사례는 안전한 사용 참조를 참고하세요.

더 알아보기 (Learn more)