> ## Content Index
> Fetch the complete content index at: https://taiwanding.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# GitHub Enumeration 101 writeup (zh-TW)
- URL: https://taiwanding.com/github-enumeration-101-writeup-zh-tw/
- Published: 2026-08-10T03:36:28.000Z
- Updated: 2026-08-10T11:10:00.000Z
- Author: Kevin Chen
- Tags: github, ci/cd, #cyberwarefare labs

📚 系列文章 · CyberWarFare Labs · CI/CD Security

1. ▸ GitHub Enumeration 101 — 用一組 PAT 做完整列舉 （本篇）
2. [GCP CI/CD 01 — 掃描私有 Repo 找 Cloud Run service](https://taiwanding.com/gcp-ci-cd-01-scanning-gcp-ci-cds-private-github-repository-writeup-zh-tw/)

# 題目資訊

- 平台: CyberWarFare Labs (CWL)
- 分類: CI/CD Security / GitHub CI/CD
- 難度: Easy (10 points)
- 題目給予: 一組 GitHub Personal Access Token

這個題目並沒有要求要像筆者這樣完整的enumeration，題目要求很簡單就是要第一個commit的sha hash值而已，但是完整走一遍還是會很有收獲的喔! 所以如果要答案，可以直接跳到Step 6即可。

## 解題過程

題目只給一組 token，目標是靠這把鑰匙做 credential-driven enumeration，摸出它能碰到什麼。

### Step 1: Token 型號判讀

先看 token 前綴：

```
github_pat_XXXXXXXXXXXXXXXXXXXXXXXX

```

`github_pat_` 開頭為 fine-grained PAT（非 classic 的 `ghp_`），差別在於 fine-grained 綁定特定 repo／權限，且不會在回應 header 明列 scope，權限得靠實測反推。

### Step 2: 身分與存活確認

```bash
TOKEN="[REDACTED_PAT]"

curl -si -H "Authorization: Bearer $TOKEN" https://api.github.com/user

```

回應重點：

```
HTTP/2 200
x-accepted-github-permissions: allows_permissionless_access=true

"login": "secure-corp-devops-operator"
"public_repos": 0

```

token 存活（200），擁有者為 `secure-corp-devops-operator`，公開 repo 為 0（價值全在私有側）。

注意 `allows_permissionless_access=true` 是描述 `/user` 這個 endpoint 本身「不需特定權限即可存取」，並非代表 token 有無限權限。

### Step 3: 權限邊界列舉

```bash
curl -s -H "Authorization: Bearer $TOKEN" https://api.github.com/user/orgs
curl -s -H "Authorization: Bearer $TOKEN" "https://api.github.com/user/repos?per_page=100&visibility=all"

```

`/user/orgs` 回傳空陣列（無 org）。`/user/repos` 回傳一個私有 repo，只看關鍵欄位：

```json
"full_name": "secure-corp-devops-operator/GitHub-Enumeration-101",
"private": true,
"permissions": { "admin": true, "maintain": true, "push": true, "triage": true, "pull": true }

```

`permissions` 區塊由 API 直接給出，這把 token 對該 repo 有 admin 權限。

### Step 4: repo 檔案盤點

```bash
curl -s -H "Authorization: Bearer $TOKEN" \
  https://api.github.com/repos/secure-corp-devops-operator/GitHub-Enumeration-101/contents/

```

清單中最可疑者為 `infinity.key`（SSL 私鑰）與 `infinity.crt`（憑證），其次 `Dockerfile`，排序依據：該檔外流後對攻擊者的價值。

### Step 5: 讀檔與交叉印證

用 `Accept: application/vnd.github.raw` 取原始純文字（省去預設 base64 解碼）：

```bash
curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.github.raw" \
  https://api.github.com/repos/secure-corp-devops-operator/GitHub-Enumeration-101/contents/infinity.key

```

`infinity.key` 為完整可用的 RSA 私鑰（`-----BEGIN RSA PRIVATE KEY-----` … `-----END-----`）。

再讀 `Dockerfile` 交叉印證用途：

```dockerfile
RUN apt install apache2 ...
COPY infinity.key /etc/ssl/private/
RUN a2enmod ssl
ENV PORT 443

```

確認 `infinity.key` 即為某台正式 HTTPS 伺服器的 SSL 私鑰。

### Step 6: 翻 commit 歷史取第一個 commit

題目問: What is the hash of the very first commit made into the repository?

現有檔案只是表面，commit 歷史才是重點——舊版本永遠留存，clone 後用 `--reverse` 讓最舊的排最前：

```bash
git clone https://$TOKEN@github.com/secure-corp-devops-operator/GitHub-Enumeration-101.git
cd GitHub-Enumeration-101
git log --oneline --reverse

```

```
f224060 Initial Commit          <- 第一個 commit
89e6955 Added webserver config
a678f0c Added TLS certificates
...

```

`--oneline` 僅顯示 7 碼縮寫，取完整 40 碼可用 API commit 清單交叉核對（API 預設由新到舊，第一個 commit 在最底）：

```bash
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://api.github.com/repos/secure-corp-devops-operator/GitHub-Enumeration-101/commits?per_page=100" | grep '"sha"'

```

兩法互驗指向同一 commit。

Flag:

```
f224060XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

```

## 學習重點

- credential-driven enumeration 節奏: 先確認身分與存活（`/user`），再由外而內縮小範圍（擁有者 → org → repo → 權限），每一步的答案決定下一步。
- fine-grained PAT 不在 header 自曝 scope，但 repo 物件的 `permissions` 區塊會直接給出權限地圖，不需瞎猜。
- `allows_permissionless_access` 是 endpoint 屬性，非 token 權限，勿誤讀。
- 檔案優先序判斷: 問「此檔外流攻擊者能拿去幹嘛」，私鑰／憑證／寫死 secret 排最前；單一線索不夠，私鑰配 Dockerfile 才確定其用途。
- 私鑰進 git 等於作廢——舊版本永遠留在歷史，最早的 commit 最常藏 secret。
- SSL 私鑰外流可用於解密側錄的 HTTPS 流量，或偽裝伺服器發動 MITM。

## 實用技巧

```bash
# 讀 GitHub 檔案內容取原始純文字(免 base64 解碼)
curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.github.raw" \
  https://api.github.com/repos/[owner]/[repo]/contents/[path]

# 定位 secret 是哪個 commit 引入的
git show [commit]

# secret 掃描(push 前攔截誤入的憑證)
gitleaks detect --source .
trufflehog git file://.

```