Routine-Poll-Logs nicht in DB persistieren

- AddLog() neuer Parameter 'persist' (default true)
- 4 Routine-Poll-Logs nur noch im In-Memory-Log:
  - '0 PushEvents empfangen'
  - 'X Events, 0 neue PushEvents'
  - 'X Events, X neue PushEvents → X scannen'
  - 'X Diffs gescannt, 0 neue Keys'
- 'X Diffs gescannt, X neue Keys' wird bei Keys > 0 weiterhin persistiert
This commit is contained in:
Meleki committed 2026-03-15 10:13:14 +01:00
1 parent 30662caab7
commit fea605dfe5
3 files changed
+359 -5

No files matched your search

+187
View File
@@ -0,0 +1,187 @@
# Umsetzungsplan: Pastebin Scraping Scanner
## Zusammenfassung
Kontinuierliches Scraping neuer öffentlicher Pastebin-Pastes über die Scraping API.
Pastebin ist eine der häufigsten Quellen für geleakte API-Keys, Credentials und Secrets.
## Warum Pastebin?
- **Klassische Dump-Plattform** für Secrets, Credentials, Config-Dateien
- User posten Keys zum Teilen, Debuggen oder versehentlich
- Automated Dumps von Credential-Stealern landen häufig auf Pastebin
- Kein Suchindex → man muss den Firehose-Stream der neuen Pastes scannen
- Ergänzt alle anderen Scanner die nur per Suchquery arbeiten
## Voraussetzung: Pastebin PRO Account
- **Pastebin PRO** ($29 Lifetime) ist **zwingend erforderlich**
- IP-Adresse muss auf https://pastebin.com/doc_scraping_api gewhitelisted werden
- Nur 1 IP pro Account, kann aber beliebig oft geändert werden (Änderungen greifen innerhalb 1 Minute)
- Ohne Whitelist → API-Zugriff wird blockiert
## API-Analyse
### Scraping API – 3 Endpoints
#### 1. Recent Pastes (Firehose)
```
GET https://scrape.pastebin.com/api_scraping.php?limit=250
```
- Liefert die **neuesten öffentlichen** Pastes (max 250 pro Request)
- Response: JSON-Array mit `scrape_url`, `full_url`, `date`, `key`, `size`, `expire`, `title`, `syntax`, `user`
- Caching: ~2 Minuten Verzögerung
- **Kein Suchfilter** – man bekommt ALLE neuen Pastes und muss lokal filtern
#### 2. Paste Content
```
GET https://scrape.pastebin.com/api_scrape_item.php?i={paste_key}
```
- Liefert den Rohtext eines Pastes
- Nur über die Scraping-API abrufbar (nicht /raw/)
#### 3. Paste Metadata
```
GET https://scrape.pastebin.com/api_scrape_item_meta.php?i={paste_key}
```
- Liefert erweiterte Metadaten (Hits, Syntax, etc.)
- Für unseren Use Case nicht zwingend nötig
### Rate Limits
- Kein hartes Rate Limit dokumentiert
- Empfehlung: Max 1 Request/Sekunde
- IP-basiert – nur gewhitelistete IP hat Zugriff
- Bei Missbrauch → IP-Block
## Implementierungsplan
### Phase 1: Config – Server Settings
Neues Setting in `ServerSettingsService.cs`:
```csharp
("PastebinScrapeEnabled", "toggle", "false", "Scanner", "Pastebin Scraping", "Pastebin Scraping API aktivieren (erfordert PRO Account + IP Whitelist)"),
```
Kein API-Key nötig – die Authentifizierung läuft über IP-Whitelist.
### Phase 2: Neue Scan-Methode `ScanPastebin`
```csharp
private async Task<List<(string Key, string Url)>> ScanPastebin(CancellationToken ct)
```
**Ablauf:**
1. Neueste Pastes abrufen: `GET api_scraping.php?limit=250`
2. Für jeden Paste:
- Prüfen ob `paste_key` bereits gescannt (lokales HashSet + DB-Check)
- Paste-Content abrufen: `GET api_scrape_item.php?i={key}`
- Content mit `KeyPatterns.Compiled` Regex scannen
- Bei Treffer: Key + `full_url` sammeln
3. Gescannte Paste-Keys merken (um Re-Scans zu vermeiden)
4. Zwischen Content-Requests: 1s Pause
### Phase 3: Paste-Key Tracking (Deduplication)
Da die Firehose dieselben Pastes mehrfach liefern kann, brauchen wir ein Tracking:
**Option A: In-Memory HashSet** (einfach, geht bei Neustart verloren)
```csharp
private readonly HashSet<string> _scannedPasteKeys = new();
```
**Option B: DB-Tabelle** (persistent, verhindert Re-Scans nach Neustart)
```sql
CREATE TABLE IF NOT EXISTS pastebin_scanned (
paste_key TEXT PRIMARY KEY,
scanned_at TEXT NOT NULL
);
```
**Empfehlung:** Option A (In-Memory) mit TTL – die Pastes laufen sowieso ab.
Das HashSet wird beim Scan-Start befüllt und nach 24h geleert.
### Phase 4: Integration in RunScan
```csharp
// In RunScan(), nach HuggingFace:
if (mode != "quick")
{
var pastebinEnabled = _settings.GetBool("PastebinScrapeEnabled", false);
if (pastebinEnabled)
{
SetProgress("Pastebin Scraping", "Starte…");
var pbKeys = await ScanPastebin(ct);
allFoundKeys.AddRange(pbKeys.Select(k => (k.Key, k.Url, "pastebin")));
AddLog("scan", "Pastebin-Scan: " + pbKeys.Count + " Key(s) gefunden");
}
}
```
- **Mode `quick`:** Kein Pastebin-Scan (zu viele Requests)
- **Mode `web`:** Pastebin-Scan aktiv (Web-Quelle)
- **Mode `full`:** Pastebin-Scan aktiv
### Phase 5: Intelligentes Filtern
Nicht jeder Paste muss heruntergeladen werden. Vor-Filterung über Metadaten:
```csharp
// Relevante Syntax-Typen (höhere Wahrscheinlichkeit für Keys)
private static readonly HashSet<string> RelevantSyntax = new(StringComparer.OrdinalIgnoreCase)
{
"", "text", "python", "javascript", "bash", "json", "yaml", "ini",
"php", "ruby", "java", "csharp", "go", "rust", "typescript",
"powershell", "shell", "markdown", "xml", "toml", "properties"
};
// Relevante Titel-Keywords
private static readonly string[] TitleKeywords =
{
"key", "api", "token", "secret", "credential", "config", "env",
"anthropic", "openai", "aws", "claude", "password", "leak"
};
```
**Strategie:**
1. **Titel-Match:** Wenn Titel ein Keyword enthält → immer scannen
2. **Syntax-Match:** Wenn Syntax relevant (Code/Text) → scannen
3. **Größen-Filter:** Nur Pastes < 500 KB (keine riesigen Dumps)
4. **Syntax-Ausschluss:** Binär-Formate, Bilder, etc. → überspringen
### Phase 6: Scan-Frequenz
Da der tägliche Full-Scan nur einmal läuft, würden wir zwischen zwei Scans viele Pastes verpassen (Pastebin hat ~10.000+ neue Pastes/Tag).
**Zwei Optionen:**
**A. Einmaliger Snapshot pro Full-Scan (einfach)**
- Beim Full-Scan einmal 250 neueste Pastes abrufen + scannen
- Verpfasst die meisten Pastes, aber fängt zumindest aktuelle ab
- Empfohlen für den Anfang
**B. Kontinuierlicher Hintergrund-Scanner (komplex)**
- Eigener BackgroundService der alle 2-3 Minuten pollt
- Fängt nahezu alle neuen Pastes ab
- Deutlich mehr Requests (~720/Tag × 250 = 180.000 Pastes/Tag)
- Kann später hinzugefügt werden
**Empfehlung:** Option A für Phase 1, Option B als optionales Follow-up.
## Scan-Volumina (geschätzt)
| Szenario | Pastes gescannt | API Requests | Dauer |
|---|---|---|---|
| Einmal 250 Pastes | 250 | ~251 (1 Liste + 250 Content) | ~5 Min |
| Einmal 250, nur gefiltert | ~100 | ~101 | ~2 Min |
| Kontinuierlich (alle 3 Min) | ~180.000/Tag | ~720 Listen + ~180.000 Content | Dauerhaft |
## Aufwandsschätzung
- **Implementierung:** ~200 Zeilen Code
- **Komplexität:** Niedrig-Mittel (einfache API, aber Dedup + Filterung)
- **Erwarteter Ertrag:** 🔥 Hoch (Pastebin = klassische Secret-Dump-Plattform)
- **Kosten:** $29 einmalig für Pastebin PRO
## Risiken
- IP-Whitelist → funktioniert nur von einer festen IP (Server)
- Nur **öffentliche** Pastes sind sichtbar (unlisted/private nicht)
- Pastes können schnell gelöscht werden → zeitnahes Scraping wichtig
- Hohe Paste-Menge → viele Keys sind False Positives (Test-Keys, bereits revoked)
- Bei zu aggressivem Polling → IP-Block möglich
- Pastebin kann API-Bedingungen jederzeit ändern