Q&A Laufend: Gitea Spam-Angriff & HĂ€rtung
Channel: #laufend
Kategorie: Q&A
Datum: 30.03.2026
Status: â Gelöst
Persona: Deepbit đ§
Was ist passiert?
28.â29. MĂ€rz 2026: Rund 50 Spam-Accounts wurden auf git.crumbforest.org erstellt.
Die Registrierung war 16 Monate lang offen â erster Angriff ĂŒberhaupt.
Wie wurde es bemerkt?
Manuell. Admin sah unbekannte User in der Gitea-Ăbersicht beim nĂ€chtlichen Check.
Angriffs-Muster
| Merkmal | Detail |
|---|---|
| Domain | @topcompanygroup.com (fast alle) |
| IPs | 183.6.47.107, 183.221.101.89, 123.57.146.97 |
| Timing | Bulk innerhalb weniger Stunden |
| Repos | 0 erstellt, einige leere Fork-Versuche |
| Commits | 0 |
| Profil-Spam | URLs zu externen Gitea-Instanzen auf Port 3000/30000 |
| Ziel | SEO-Backlinks (kein Schadcode) |
Wie wurde es gelöst?
Runde 1: Manuell (Nacht)
- ~30 Accounts per Hand im Gitea Admin-Panel gelöscht
DISABLE_REGISTRATION = trueinapp.inigesetzt
Runde 2: Script mit Rate-Limit
# gitea_ninja.sh --analyze zeigt verbleibende Accounts
# Dann per Script mit sleep 2 zwischen Deletes
while read user; do
sudo -u gitea gitea admin user delete --username "$user" --purge -c /etc/gitea/app.ini
sleep 2
done < /tmp/spam_users.txt
Problem: "user still has ownership of repositories"
Spam-User hatten leere Repos erstellt (Fork-Versuche). Lösung: --purge Flag löscht User + alle Repos.
Problem: "user does not exist"
Usernames waren im ersten Durchlauf abgeschnitten (Copy-Paste aus Web-UI). Lösung: korrekte Usernames aus der Gitea-DB oder User-Liste.
Problem: Rate-Limiting
Gitea hat eigenes Rate-Limit bei schnellen CLI-Aufrufen. Lösung: sleep 2 zwischen jedem Delete.
HĂ€rtung (permanent)
# /etc/gitea/app.ini
[service]
DISABLE_REGISTRATION = true
REQUIRE_SIGNIN_VIEW = true
ENABLE_CAPTCHA = true
DEFAULT_ALLOW_CREATE_ORGANIZATION = false
SHOW_REGISTRATION_BUTTON = false
[openid]
ENABLE_OPENID_SIGNIN = false
ENABLE_OPENID_SIGNUP = false
[other]
SHOW_FOOTER_VERSION = false
Nach Ănderung:
systemctl restart gitea
Erkennung: Wie finde ich Spam-Accounts?
# 1. User ohne Repos (verdÀchtig wenn nicht Admin)
sqlite3 /var/lib/gitea/data/gitea.db "
SELECT lower_name, email FROM user
WHERE type=0 AND is_admin=0 AND num_repos=0
"
# 2. Bulk-Registrierungen (>3 pro Tag)
sqlite3 /var/lib/gitea/data/gitea.db "
SELECT date(created_unix, 'unixepoch') AS d, COUNT(*) AS c
FROM user WHERE type=0
GROUP BY d HAVING c > 3
"
# 3. Bekannte Spam-Domains
sqlite3 /var/lib/gitea/data/gitea.db "
SELECT lower_name, email FROM user
WHERE email LIKE '%@topcompanygroup.com'
"
# 4. Spam-URLs in Profilen
sqlite3 /var/lib/gitea/data/gitea.db "
SELECT lower_name, website FROM user
WHERE website LIKE '%:3000%' OR website LIKE '%:30000%'
"
Löschen: Einzel vs. Bulk
# Einzeln
sudo -u gitea gitea admin user delete --username SPAMUSER --purge -c /etc/gitea/app.ini
# Bulk (mit Rate-Limit Schutz)
cat userlist.txt | while read user; do
sudo -u gitea gitea admin user delete --username "$user" --purge -c /etc/gitea/app.ini
sleep 2
done
# Wichtig: --purge löscht User + Repos + Kommentare + alles
# Ohne --purge: Fehler wenn User Repos besitzt
Monitoring
# RegelmĂ€Ăig prĂŒfen (z.B. via cron oder manuell)
gitea_ninja.sh --analyze
# Nginx Logs: Registrierungs-Versuche
grep "user/sign_up" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
Lessons Learned
- 16 Monate offen â 1 Angriff. Offene Registrierung war lange kein Problem, aber irgendwann findet dich jeder Bot.
- Kein Schadcode. Der Angriff war SEO-Spam, keine Infiltration. Trotzdem sofort handeln.
- Rate-Limiting beachten. Gitea und der eigene nginx-Proxy können Bulk-Löschungen bremsen.
sleep 2ist dein Freund. --purgekennen. Ohne das Flag scheitert das Löschen wenn der User Repos hat.- REQUIRE_SIGNIN_VIEW ist genauso wichtig wie DISABLE_REGISTRATION. Sonst sehen Bots weiterhin die User-Profile.
- Forensik â Vektor. Jeder Vorfall wird dokumentiert und geseeded. Der Wald lernt.
Tools
| Tool | Zweck |
|---|---|
gitea_ninja.sh --analyze |
Spam-Accounts finden |
gitea_ninja.sh --harden |
Config prĂŒfen |
gitea_ninja.sh --report |
Markdown fĂŒr Vektor |
gitea admin user delete --purge |
User + Repos löschen |
gitea admin user list |
Alle User anzeigen |
Der Wald schĂŒtzt sich selbst. đ„·đČ