
Forgejo 16.0.5 - 높음 - 원격 - 파일 읽기 - restore-repo가 dump 측 file://를 attachments로 따라감
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · forgejo-restore-file-open
분류: 파일 읽기 도달 범위: 로컬
Forgejo 16.0.5 (8d24b7d) - Forgejo
신뢰할 수 없는 덤프에 대한 forgejo restore-repo는 릴리스 자산 URL을 raw filepath.Join(baseDir, download_url)로 재작성하고 file:// 접두사를 붙인다. uri.Open은 여전히 해당 경로를 os.Open한다. 빈 --units는 릴리스를 복원한다. Gitea 1.27.0은 localFileURL을 추가하고 이스케이프 항목을 건너뛰었다. 그 헬퍼는 여기에 없다.
신뢰할 수 없는 덤프에 대한 운영자 복원은 forgejo uid가 열 수 있는 호스트 파일을 릴리스 첨부 파일로 복사한다.
| ID | 아직 CVE 없음 |
| 분류 | 파일 읽기 |
| 도달 범위 | 로컬 (신뢰할 수 없는 덤프에 대한 운영자 forgejo restore-repo) |
| CWE | CWE-22 / CWE-73 |
| CVSS | 높음: 7.3 CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N |
| 제품 | Forgejo |
| 영향받음 | v16.0.5 (8d24b7d)까지; 로컬 운영자 복원 |
| 인증 | 신뢰할 수 없는 덤프에 대한 로컬 운영자 복원 |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1 전용 |
운영자에게 덤프 디렉터리를 건네거나(또는 이미 INTERNAL_TOKEN과 서버가 읽을 수 있는 경로를 보유). 유닛에는 releases / release_assets가 포함된다.
| 권한 | 메서드 / 싱크 | 정찰 / 무결성 / 가용성 | 랩 입증 또는 추론 |
|---|---|---|---|
덤프 밖으로 ..를 통해 forgejo uid가 열 수 있는 호스트 파일 읽기 | release.yml download_url: ../FORGEJO-FILE-WITNESS.txt; 복원이 조인하고, uri.Open이 os.Open하며, 바이트가 witness.txt로 저장됨 | 정찰 (호스트 파일 기밀성) | 랩 입증. 첨부 본문은 FORGEJO-RESTORE-FILE-OPEN-WITNESS. 덤프 내 미끼 INSIDE-DUMP-NOT-HOST는 제공되지 않음 |
| 덤프 내부에 심은 심볼릭 링크로 동일한 결과 | 조인된 경로가 baseDir 아래에 유지됨; os.Open이 링크를 따라감 | 정찰 | uri.Open file -> os.Open에서 추론. 랩은 심볼릭 링크가 아닌 ..를 사용 |
| PR 패치에 동일한 싱크 | pull_request.yml PatchURL이 같은 방식으로 재작성된 후 uri.Open으로 repo/pulls/<n>.patch에 기록됨 | 정찰 | restore.go GetPullRequests에서 추론. 랩은 릴리스만 복원 |
| 복원된 저장소의 독자가 호스트 파일을 다운로드 | GET /<owner>/<repo>/releases/download/<tag>/<name> | 정찰 | 복원된 공개 저장소에서 labadmin Basic으로 랩 입증 |
일반적인 호스트 파일: app.ini, INTERNAL_TOKEN, SECRET_KEY, DB 비밀번호 | forgejo uid가 설정 트리를 읽을 수 있음 | 정찰 | 추론. 랩 증인은 실제 비밀이 아닌 덤프 옆에 심은 파일 |
여기서 차단된 것: 라이브 POST /repos/migrate file:// LFI (DownloadFunc 설정됨; PR PatchURL은 클론 HTTP 베이스에 대해 접두사 검사됨). 절대 DownloadURL 덤프 루트 조인 이스케이프 (Go filepath.Join("/dump", "/etc/passwd")는 /dump/etc/passwd로 유지됨). 비인증 HTTP 복원 (CLI / 내부 토큰 전용). 백업 dump가 app.ini를 패킹 (설계상 비밀, 아카이브 모드 0600). OS LPE 아님. 원격 LFI 아님.
두 가지 복원 아이디어가 있었다. Gitea 절대 조인을 머릿속에서 먼저 랩했다. Go filepath.Join은 Python os.path.join처럼 절대 두 번째 인수를 버리지 않는다. 작동하는 입력은 상대 경로 ..이다. Gitea의 localFileURL은 이 트리에 없다.
이미 기록된 잘못된 시도: 절대 DownloadURL을 통한 덤프 루트 조인 이스케이프; 라이브 migrate file:// LFI; X-Forgejo-Internal-Auth (복원은 /api/internal이 아닌 forgejo uid로서의 CLI); 복원 HTTP를 원격 비인증으로 취급; 리버스 셸. 쇼에 불과.
python3 forgejo-restore-file-open-Abraxas-Labs.py
또는:
cd lab
./run.sh
오직 http://127.0.0.1:19340만 대상으로 한다. 이미지 codeberg.org/forgejo/forgejo:16.0.5. 증인 FORGEJO-RESTORE-FILE-OPEN-WITNESS.
IOC asset name='witness.txt' ...
IOC download status=200 bytes=34 snippet=b'FORGEJO-RESTORE-FILE-OPEN-WITNESS\n'
SUCCESS forgejo-restore-file-open how=live ..-join file:// os.Open FORGEJO-RESTORE-FILE-OPEN-WITNESS
EvalSymlinks 후 조인된 경로를 baseDir 아래에 가둔다 (Gitea PR 38215 localFileURL). ..를 거부한다. 덤프 측 심볼릭 링크를 덤프 밖으로 따라가지 않는다. 덤프 루트 기반 헬퍼를 제외하고 uri.Open에서 file://를 제거한다.
restore.go · uri.goGNU Affero GPL v3.0. LICENSE 참조. 루프백 랩 전용. 보증 없음.