Gewahrwerdung#

Wie so oft beginnt auch diese Geschichte mit einem Netzwerk der menschlichen Kommunikation. Dieser unersetzliche Austausch hat schon viel zur Sicherheit der Software beigetragen, mit der ich diesen Blog betreibe. Nun kann ich eine weitere Sicherheitslücke schließen. Aber der Reihe nach.

Gitea als Angriffsziel#

Ich hörte, dass die selbst gehostete Versionsverwaltungslösung Gitea eines meiner Bekannten Ziel einer Attacke geworden ist. Hierbei wurde eine RCE (Remote Code Execution) möglich und tatsächlich auch ausgeführt.

Warum ist Gitea ein attraktives Ziel?#

  • Diebstahl von (Firmen)geheimnissen: Bei Zugriff auf Repositories ist vertraulicher Quellcode gefährdet, offengelegt zu werden.
  • Abfluss von Zugangsdaten: Wird ein größeres Produkt mit Schnittstellen in Gitea verwaltet, sind API keys, Konten und Passwörter in Gefahr, falls sie unverschlüsselt vorliegen. Abhilfe schaffen Tools wie git-secret; sie werden aber durch Einführen zusätzlicher Komplexität noch nicht flächendeckend eingesetzt.
  • Klassische Rechteeskalation: Unter Umständen kann man durch Ausbruch aus der Gitea-Software die ganze Maschine übernehmen.
  • Nutzen des runner: Schafft man es den Runner zu kapern, kann man auch ohne erweiterte Rechte Ressourcen der Hostmaschine in Beschlag nehmen und für eigene Zwecke missbrauchen (Stichwort Cryptominers in CI/CD).

Was ist eine RCE?#

Eine Remote Code Execution ist ein erfolgreicher Angriff, bei dem nicht autorisierter Code ohne Zutun von Besitzer oder Administration der befallenen Ressource aus der Ferne über das Netzwerk eingespielt und ausgeführt werden kann.

Das Gitea-Ökosystem#

Als Versionsverwaltung und forge gehört zum Basisumfang von Gitea die Möglichkeit, webbasiert und kollaborativ Software zu entwickeln und zu bauen. Daher ist vorgesehen, dass sich Nutzer registrieren und unter Umständen sogar Aktionen ausführen können, damit Software automatisiert gebaut und/oder ausgeliefert werden kann.

Genau dieses automatische Nachladen und Ausführen von Code kann böse Folgen haben, wenn Sicherheitslücken in der Verwaltungssoftware selbst bestehen.

Verwundbarkeit durch offene Registrierung#

Lässt man als Betreiberin die Registrierung neuer Accounts (“self-registration”) in Giteas Konfiguration auf dem Standardwert DISABLE_REGISTRATION = false, so können sich Nutzerinnen selbst einschreiben, eigene Repository anlegen, issues aufmachen und alles tun, was ohne Adminrechte möglich ist.

Hat man zusätzlich noch den Standardwert REQUIRE_SIGNIN_VIEW = false gesetzt, können auch unauthentisierte Besucher öffentliche Repositories sehen, die Seiten von Gitea browsen und vor allem die öffentliche API des Gitea Endpoints ansprechen.

Verwundbarkeit durch Standardkonfiguration für Reverse Proxies#

In der Standardkonfiguration des Gitea Docker image vertraut Gitea <V1.26.3 allen Proxies.

# gitea/app.ini

[security]
REVERSE_PROXY_LIMIT = 1
REVERSE_PROXY_TRUSTED_PROXIES = * # This is a vulnerability!

Die Sicherheitslücken#

Womit haben wir es hier zu tun? Mit mehreren kritischen Sicherheitslücken des Ausmaßes 9.8/10 CVSS score, von denen es bekannte Fälle der Ausnutzung gibt.

Image: Common vulnerability scoring system calculator. The selectors are switched in a way that reproduces a critical vulnerability over a network vector without user interaction as discussed in this post.

Exkurs: Die CVSS-Bewertung#

Zur Einordnung der Bewertung von “kritisch”: Die CVSS-Kriterien sind ähnlich aufgebaut wie in der klassischen Gefahren- und Risikoanalyse, einem Zweig der Ingenieurswissenschaften. Anders als dort liegt der Fokus allerdings nicht in der Analyse möglicher Fehlerfälle, Schweregrad, Eintritts- und Ausfallwahrscheinlichkeit oder Detektierbarkeit, sondern auf dem Schwierigkeitsgrad der Ausnutzung und möglicher Auswirkungen.

Bedeutung der CVSS-Einzelwerte#

Je höher der CVSS-Wert, desto einfacher ist die Sicherheitslücke auszunutzen und desto gravierender sind mögliche Folgen hinsichtlich der Datensicherheitskriterien (Confidentiality, Integrity, Availability).

Das Bild oben zeigt eine Konstellation, in der eine mögliche Attacke aus der Ferne (Netzwerk) mit geringem Aufwand (Complexity, meint Systemhärtung) ohne Randbedingungen (Requirement, z.B. das Anfahren einer vulnerablen Stelle im Code, Vorhandensein eines bestimmten Zustandes des angegriffenen Systems, Auslösen einer race condition etc.), ohne zusätzliche Rechte (als Gast ohne Authentisierung oder Autorisierung) oder Interaktion mit dem User oder der Administratorin des Systems durchgeführt werden kann.

Das wäre für sich genommen noch nicht schlimm, wenn niemand das System benötigt Score 0.0 und nichts Interessantes darauf gespeichert ist. Liegen dort allerdings sensitive Daten Confidentiality, 8.7 oder zum Beispiel eine Datenbank, deren Werte sich nun manipulieren lassen Integrity, 8.7, oder wird auch nur die Verfügbarkeit von benötigten Daten eingeschränkt Availability, 8.7, befindet man sich bereits im Bereich High.

Mit diesem Wissen nehmen wir nun den Transfer auf die kritischen Lücken von Gitea vor.

CVE-2026-20896: Authentication bug in Gitea through reverse-proxies#

Kommt ein Angreifer hinter den Reverse Proxy (oder ist gar kein Reverse Proxy vorgeschaltet), kann er eine Anfrage mit X-WEBAUTH-USER im Header direkt an die Gitea-Instanz senden und sich für einen Reverse Proxy ausgeben. Ist Gitea gleichzeitig darauf eingestellt, allen reverse proxies zu vertrauen REVERSE_PROXY_TRUSTED_PROXIES = *, so geht es davon aus, dass bereits authentisiert wurde und eine gültige Session vorliegt. Der Angreifer erhält also Nutzerrechte mit Schreibzugriff auf Repositories, obwohl er nicht mal einen Account angelegt hat.

Das eigentliche Lücke ist hier das unhinterfragte Vertrauen gegenüber dem Sender des Headers ohne weiteren Abgleich mit einem Session Token oder ähnlichem; das Annehmen desselben von fremden Quellen erzeugt lediglich die Verwundbarkeit.

Für diesen Bug gibt es Belege für bereits erfolgte Attacken.

CVE-2026-59774: File-read flaw for anything the Gitea Service Account can read#

Diese kritische Sicherheitslücke basiert auf einer unzureichenden Eingabeprüfung des eingebauten Textrenderers von Gitea für org-mode Dateien. Eine detaillierte Beschreibung des Vektors und zu möglichen Wegen eines Angriffs kann auf Saytam Rastogis hervorragendem Blog nachgelesen werden.

Kurzgesagt kann sich ein Angreifer mit Zugriff auf zumindest ein öffentliches Repository eine bösartige .org-Datei zusammenbasteln, mit deren Hilfe er Giteas Konfiguration app.ini auslesen und damit auf darin enthaltene Secrets zugreifen kann, welche ihm erweiterte Rechte zugestehen oder ihn zumindest lateral auf dem System bewegen lassen.

Dies kann laut hacker news und Giteas eigenen Leuten zufolge beispielsweise auch dazu ausgenutzt werden, die Registration Token eines Runners auszulesen und selbigen zu übernehmen.

CVE-2026-60004: RCE allowing attacker with ordinary user rights to execute arbitrary shell commands as the Gitea OS user.#

Diese Sicherheitslücke ist deswegen besonders schlimm, weil sie zusätzlich eine privilege escalation ermöglicht.

“The vulnerability in question is CVE-2026-60004 (CVSS score: 9.8), a case of remote code execution that allows an attacker with ordinary write access to a repository to execute arbitrary shell commands as the Gitea OS user.” thehackernews, Aug-2026

Das Ausnutzen dieser Lücke kann den Angreifer also die gesamte Gitea-Instanz übernehmen lassen, sofern er Schreibzugriff auf irgendein (evtl. sogar öffentliches) Repository hat.

Das Lagebild#

Image: A decision tree, connecting the dots between the three discussed CVEs. Baseline message is that the system has to be regarded as compromised in case an attacker is able to get ordinary write access to any repository on the instance which can be done by exploiting any of the discussed CVEs.
Es gibt noch weitere kritische Sicherheitslücken, allerdings könen sich Angreifer mit einer Kombination der obigen Darstellungen ohne großen Aufwand

  1. Als normale User auf dem Gitea-System bewegen, ohne sich registriert zu haben, und ohne SSH-Zugriff zu benötigen
  2. Sich als Gitea-Service User ausgeben
  3. Actions übernehmen oder sogar Workflows injizieren und ausführen
  4. Mit etwas Mehraufwand die gesamte Instanz übernehmen, verschlüsseln, Lösegeld verlangen usw.

Was mein Bekannter erlebt hat betraf die Punkte eins und drei. Der Angriff wurde sehr wahrscheinlich automatisiert ausgeführt, nachdem das Internet auf verwundbare Instanzen gescannt worden war.

Zusammengefasst kann man im vorliegenden Fall von einer Mass-Exploitation Campaign für Cryptomining ausgehen.

Der Cryptominer#

Bei meinem Bekannten wird folgende Datei als statisch gelinkte Executable (!) auf dem System abgelegt: gitea/data/gitea/sys_health_s3 Der Hash der Datei legt seiner Ansicht nach nahe, dass ein XMRig cyptominer als bösartige Payload eingesetzt wurde, der mit pool.hashvault.pro kommuniziert und dabei einen Großteil der verfügbaren CPU-Leistung für sich beansprucht.

Noch größerer Schaden möglich#

Sogar für den auslegungsüberschreitenden Stöfall habe ich ein aktuelles (Sep-2026) Beispiel auf Hackernews finden können: Diebstahl von Quellcode, Sammlung von Zugangsdaten, Privilege escalation bis hin zum root-Zugriff auf das betroffene System.

Wie entdecke ich einen Angriff?#

Schlimmstenfalls gar nicht. Sind Profis zielgerichtet am Werk, können allenfalls die Logdateien zum Zeitpunkt direkt nach dem Einbruch Aufschluss geben. Im Falle, dass man sie sofort liest und interpretieren kann. Aber ich schweife ab1.

Dannoch sollte man sich folgende Fragen stellen:

  1. Betreibe ich eine vulnerable Gitea-Version (<1.27.2)?
  2. Verzichte ich auf eine Monitoring-Lösung, die bei Auffälligkeiten warnt?
  3. Liegt eine ungewöhnlich hohe CPU-Last des Systems vor (Deutet auf Kryptominer-Befall hin)?
  4. Für diesen konkreten Miner kann man zusätzlich nachsehen, ob auf dem System folgende Datei zu finden ist:
find / -name '.sys_health_s3' 2>/dev/null

Beantwortet man sich nur eine dieser Fragen mit ja, ist zügiges Handeln angebracht. Dabei ist durch den Schweregrad der Sicherheitslücken das gesamte Hostsystem als kompromittiert anzusehen, insbesondere wenn der Gitea-Container oder ein eventuell eingebundener Runner rootful läuft, also mit dem Docker Socket ausgestattet wurde.

Bei Befall: Quarantäne#

Nächste Schritte: Sofort die betroffene Maschine isolieren und vom Netz nehmen. Die Container herunterfahren, Hostmaschine durchbooten und Updates nachladen. Aschließend die Docker Registry auf Stand bringen und über die Logdateien (Zeitstempel!) ermitteln, ob andere Teile des Systems betroffen sind. Für weitere Details siehe mein Artikel über einen selbsterlebten Angriff auf Gitea.

Lösungen#

Gitea Updaten!#

Gitea muss dringend auf eine Version >1.27.1 gebracht werden. Dafür kann beispielsweise die docker-compose.yml geändert und die Container danach durchgebootet werden:

# docker-compose.yml
gitea:
    image: gitea/gitea:latest
    container_name: gitea

Weitere Informationen zu aktuellen Fixes finden sich auf Giteas Blog. Der Major Release auf Version 27 löst eine ellenlange Liste an kritischen Sicherheitslücken. Ich habe in diesem Artikel nur ein paar davon herausgepickt, da sie mein direktes Umfeld betreffen und ihre Ausnutzung bekannt ist.

Gitea und Runner rootless ausführen#

Führt das Ausnutzen einer Sicherheitslücke zum Verlust von Gitea oder dem Action Runner, sollte nicht auch noch das Hostsystem kompromittiert werden. Der Betrieb in einem Container kann den Schadensumfang deutlich reduzieren. Das Aufsetzen einer rootless-Lösung habe ich daher hier beschrieben.

Zusätzliche Maßnahmen (Härtung)#

CVE-2026-20896: Netzwerkzugriff erschweren#

Bei den folgenden Schritten folge ich der Empfehlung von d00ftech.

  1. Einfügen des Adressraumes des selbst verwendeten Reverse Proxy. Dafür gilt erst einmal herauszufinden, unter welcher Adresse der Reverse Proxy im Netzwerk erreichbar ist. Auf meinem Server beispielsweise laufen Gitea und Reverse Proxy (Caddy) in Docker. Daher finde ich die IP-Adresse wie folgt:
docker inspect caddy \
  --format='{{range $name, $network := .NetworkSettings.Networks}}{{$name}}: {{$network.IPAddress}}{{"\n"}}{{end}}'
caddy-proxy: 172.20.0.2

Dieser Wert wird nun in der gitea/app.ini eingetragen:

[security]
REVERSE_PROXY_LIMIT = 1
REVERSE_PROXY_TRUSTED_PROXIES = 172.20.0.2/32
  1. Direkten Netzwerkzugriff auf Gitea unter Umgehung des eigenen Reverse Proxy blockieren. Dazu darf der Port von Gitea (meist 3000) nicht in der Portfreigabe beispielsweise der Docker-Konfiguration erscheinen:
# docker-compose.yml
services:
  gitea:
    ports:
      - "3000:3000" # remove this!

CVE-2026-59774: Gitea updaten!#

Es gibt zwar die Möglichkeit, den org-mode renderer in der app.ini zu deaktivieren (Siehe Gitea Documentation zum Thema), der weitaus bessere Weg ist aus meiner Sicht aber das Update von Gitea selbst!

CVE-2026-60004: Falls möglich Self-Registration abschalten#

Der eigentliche Fix ist nur durch ein Update der Gitea-Version möglich. Für kleinere Instanzen mit wenigen Usern mag es zusätzlich zweckmäßig erscheinen, die Selbstregistrierung für neue User abzuschalten. Sie müssen eine Registrierung von nun an bei den Administratoren anfragen (sofern sie nicht eine der anderen oben beschriebenen CVEs ausnutzen).

# gitea/app.ini
[service]
DISABLE_REGISTRATION = true

Weitere hilfreiche Einstellungen sind:

REGISTER_EMAIL_CONFIRM = true # Requires user's email to be confirmed for registration to complete
ENABLE_OPENID_SIGNUP = false # Disallow logons via external API
REQUIRE_SIGNIN_VIEW = true # Force users to login before they can view content or use the public API 

Ausblick und Fazit#

Versionsverwaltungen sind sehr atttraktive Ziele für gleich einen ganzen Strauß an Angreifertypen: Von Cryptominern wegen der Möglichkeit der Ressourcenübernahme über Ransomware-Gruppen wegen der Quellcodedateien und möglicher Zugangsdaten bis hin zu hochprofessionellen, zielgerichteten Angreifern und staatlichen Akteuren dadurch, dass die Software eine Art Infrastruktur darstellt.

Daher:

“Alle Patches einspielen. Immer. Sofort. Ohne Ausnahmen.” - Felix von Leitner, sagt aber auch das BSI

Was mich ein wenig ratlos zurücklässt ist die schiere Zahl und Kritikalität der gestopften Sicherheitslücken (35 CVEs binnen eines Monats laut Giteas eigenem Blog!). Aus meiner blauäugigen Sicherheitsperspektive ist diese Lösung ein Schweizer Käse und ich bin mir nicht sicher, ob ich Gitea weiter betreiben sollte.

Sofort: Härtung durchführen#

Na klar: Gitea auf latest bringen und die oben beschriebenen Härtungsmaßnahmen durchführen.

Kurzfristig: Automatische Updates#

In den nächsten Tagen und Wochen werde ich mich damit beschäftigen, die Docker Registry automatisch nach Updates für meine Software zu durchsuchen und sie ebenso automatisch auf meinem Server auszurollen. Blog-Post folgt!

Mittelfristig: Her mit Monitoring#

Ich werde mich auf die Suche machen nach einer kleinen und leichten Monitoring-Lösung, die Auffälligkeiten wie “CPU-Last ungewöhnlich hoch seit HH:MM:SS” meldet und healthchecks durchführen und überwachen kann. Dabei darf sie selbst kein Einfallstor dastellen, muss also praktisch ohne Rechte auskommen. Ob das wohl einfach möglich ist?

Mittelfristig 2: Weg mit den Secrets#

Unverschlüsselte Secrets haben in Repositories nichts verloren. Selbst auf dem Server selbst ist eine .env-Datei, die dort herumliegt, als nicht mehr sicher zu werten. Auch hier werde ich mir Gedanken machen und entsprechend berichten, wenn ich eine Lösung ausgerollt habe.

Mittelfristig 3: News-Feeds einrichten#

Hierunter fallen Abos z.B. von Newslettern oder RSS-Feeds idealerweise aller meiner Softwareanbieter, IT-Security-Institutionen oder -Journalisten und weiteren Quellen, aus denen ich Sicherheitslücken, Patches und Maßnahmen zur Systemhärtung entnehmen kann.

Langfristig: Mit Leuten weiterhin ins Gespräch gehen#

Es endet wie es beginnt. Bevor ich Probleme mit meiner Software lösen kann, bevor ich überhaupt von den Problemen weiß, ja genau da! Ganz am Anfang, bevor ich überhaupt entschieden habe, welche Software ich einsetze, da stehen: Andere Menschen.

Leute, die ich fragen kann, um Hilfe bitten kann. Deren Zeit ich in Anspruch nehmen darf für eigene Belange. Die ich zum Beispiel per Messenger aus dem Nichts heraus anschreibe und aus ihrem Fokus reiße.

Leute, die sich besser auskennen als ich, die einen anderne Blick auf die Dinge haben, oder deren Meinung ich interessant finde.

Kolleginnen, auch Ehemalige, Bekannte und Freunde, Familie, die ich zufällig oder zielgerichtet auf einen Austausch treffe. Auf einen Kaffee, ein Eis, ein Kaltgetränk, zum Musizieren oder für einen Brettspielnachmittag.

Leute, die mir trotz der Unterbrechung und doofer Fragen freundlich und geduldig helfen. Die vielleicht kurz mit den Augen rollen, mir die Dinge dann aber doch noch ein weiteres mal erklären. Die meine Monologe, kritische Nachfragen und gelegentliche Gegenrede irgendwie tolerieren.

Leute, mit denen ich in einen Austausch treten kann, der am Ende hoffentlich beiden Seiten nützt.

Image: A computer-drawn image of Schallbert, pixelized, and in 256 colors.
Bei euch allen möchte ich mich bedanken. Mit Leuten wie euch wird alles viel einfacher. Auch der Betrieb dieses Blogs, wo so viel meiner Zeit hineingeht. Ich kann mit euch Entscheidungen diskutieren, erfahren wie ihr Dinge gemacht habt und warum genau so, die Perspektiven wechseln. Und neue Ideen entwickeln.

Bitte bleibt mir erhalten.


  1. Verweis an “Fefe” Felix von Leitner. Zitat: “Annahmen […]: Wir werden angegriffen. Wir merken es zeitnah. Aller Erfahrung nach: Nein, tun wir nicht. Typischer Zeitraum vor Entdeckung von blinden Passagieren: Ein halbes bis fünf Jahre.” - aus dem Vortrag Hackback, Link führt zu Codeberg. ↩︎