Pentest 83.1-83.3: Auto-Import-Pfad härten
83.1 MEDIUM: Auto-Import in syncForwardingForEmail rief assertValidForwardingEmail nicht auf. Plesk-Member wie attacker@plesk.internal wären ohne TLD-Block-Check (71.1) in die DB importiert worden. Fix: jeder importierte Member läuft durch assertValidForwardingEmail, ungültige werden silent gedroppt + auf debug-Level geloggt. 83.2 LOW: Self-Forward-Schutz (81.1) griff nur im Add-Pfad. Wenn Plesk die eigene Adresse als Mailgroup-Member führte, wäre sie beim Auto-Import in die DB-Liste gerutscht → nach dem Umschalten auf Forwarding Mail-Loop. Fix: seenKeys mit der eigenen Adresse initialisieren bevor die Import-Schleife läuft. 83.3 INFO: PII-Log auf console.debug umgestellt (statt console.log). Smoke-Test mit gemischter Plesk-Liste: legitimer Member importiert, reservierte TLDs + Self-Mail (exakt + Plus-Tag) abgelehnt, Customer-Stamm + Default deduped.
This commit is contained in:
@@ -566,6 +566,12 @@ export async function syncForwardingForEmail(
|
|||||||
// additionalForwardingEmails-Liste rein. Der nachfolgende Plesk-Call
|
// additionalForwardingEmails-Liste rein. Der nachfolgende Plesk-Call
|
||||||
// deaktiviert dann die Mailgroup und schreibt die volle Liste als
|
// deaktiviert dann die Mailgroup und schreibt die volle Liste als
|
||||||
// Forwarding. Verlustfrei – kein Empfänger fällt raus.
|
// Forwarding. Verlustfrei – kein Empfänger fällt raus.
|
||||||
|
// Pentest 83.2: Self-Forward auch beim Import blocken. Die
|
||||||
|
// Stressfrei-Adresse selbst darf nicht aus Plesk in unsere DB
|
||||||
|
// landen – sonst läuft sie nach dem Mailgroup→Forwarding-Umschalten
|
||||||
|
// als Forwarding-Target auf sich selbst (Mail-Loop).
|
||||||
|
seenKeys.add(canonicalEmailKey(stressfreiEmail.email));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const pleskState = await checkEmailExists(localPart);
|
const pleskState = await checkEmailExists(localPart);
|
||||||
const existingMembers = [
|
const existingMembers = [
|
||||||
@@ -574,11 +580,26 @@ export async function syncForwardingForEmail(
|
|||||||
];
|
];
|
||||||
const newImports: string[] = [];
|
const newImports: string[] = [];
|
||||||
for (const member of existingMembers) {
|
for (const member of existingMembers) {
|
||||||
const key = canonicalEmailKey(member);
|
// Pentest 83.1: importierte Adressen aus Plesk müssen denselben
|
||||||
|
// Filter passieren wie User-Eingaben (TLD-Blocklist, Format).
|
||||||
|
// Sonst rutschen reservierte TLDs wie `.internal` ohne Check
|
||||||
|
// in unsere DB, falls ein Plesk-Admin sie dort manuell gepflegt
|
||||||
|
// hat. Ungültige werden silent gedroppt – Log informiert.
|
||||||
|
let validated: string;
|
||||||
|
try {
|
||||||
|
validated = assertValidForwardingEmail(member);
|
||||||
|
} catch (validationErr) {
|
||||||
|
const reason = validationErr instanceof Error ? validationErr.message : 'unbekannt';
|
||||||
|
console.debug(
|
||||||
|
`[syncForwardingForEmail] Plesk-Member "${member}" verworfen: ${reason}`,
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const key = canonicalEmailKey(validated);
|
||||||
if (!seenKeys.has(key)) {
|
if (!seenKeys.has(key)) {
|
||||||
seenKeys.add(key);
|
seenKeys.add(key);
|
||||||
forwardTargets.push(member);
|
forwardTargets.push(validated);
|
||||||
newImports.push(member);
|
newImports.push(validated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newImports.length > 0) {
|
if (newImports.length > 0) {
|
||||||
@@ -590,7 +611,8 @@ export async function syncForwardingForEmail(
|
|||||||
where: { id },
|
where: { id },
|
||||||
data: { additionalForwardingEmails: serializeAdditionalForwards(mergedAdditional) },
|
data: { additionalForwardingEmails: serializeAdditionalForwards(mergedAdditional) },
|
||||||
});
|
});
|
||||||
console.log(
|
// Pentest 83.3: PII-Logs auf debug-Level statt log-Level.
|
||||||
|
console.debug(
|
||||||
`[syncForwardingForEmail] Importiert aus Plesk-Mailgroup für ${stressfreiEmail.email}:`,
|
`[syncForwardingForEmail] Importiert aus Plesk-Mailgroup für ${stressfreiEmail.email}:`,
|
||||||
newImports,
|
newImports,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -97,6 +97,26 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
|
|||||||
|
|
||||||
## ✅ Erledigt
|
## ✅ Erledigt
|
||||||
|
|
||||||
|
- [x] **🔒 Pentest 83.1-83.3: Auto-Import-Pfad härten**
|
||||||
|
- **83.1 MEDIUM:** Auto-Import in `syncForwardingForEmail` umging
|
||||||
|
`assertValidForwardingEmail`. Plesk-Member wie `attacker@plesk.internal`
|
||||||
|
oder `evil@x.local` wären ohne TLD-Block-Check (71.1) in unsere
|
||||||
|
DB gewandert. Fix: jeder importierte Member läuft durch
|
||||||
|
`assertValidForwardingEmail`; ungültige werden silent gedroppt
|
||||||
|
und auf `console.debug`-Level geloggt.
|
||||||
|
- **83.2 LOW:** Self-Forward-Schutz (81.1) lief nur im Add-Pfad.
|
||||||
|
Wenn Plesk die eigene Adresse als Mailgroup-Member führte, wäre
|
||||||
|
sie beim Auto-Import in die DB-Liste gerutscht → nach dem
|
||||||
|
Umschalten auf Forwarding Mail-Loop. Fix:
|
||||||
|
`seenKeys.add(canonicalEmailKey(stressfreiEmail.email))` vor
|
||||||
|
der Import-Schleife.
|
||||||
|
- **83.3 INFO:** PII-Log auf `console.debug` umgestellt (statt
|
||||||
|
`console.log` auf Default-Level).
|
||||||
|
- Smoke-Test mit gemischter Plesk-Liste: `karibik61@web.de` (legit)
|
||||||
|
importiert, `attacker@plesk.internal` + `evil@x.local` per 83.1
|
||||||
|
abgelehnt, exakte Self-Mail + Plus-Tag-Variante per 83.2
|
||||||
|
abgelehnt, Customer-Stamm-Mail + Default deduped.
|
||||||
|
|
||||||
- [x] **🐞 Plesk-Sync: Legacy-Mailgroup-Adressen synchronisierten nicht**
|
- [x] **🐞 Plesk-Sync: Legacy-Mailgroup-Adressen synchronisierten nicht**
|
||||||
- Prod-Bug: User trägt zusätzliche Weiterleitung ein, Toast meldet
|
- Prod-Bug: User trägt zusätzliche Weiterleitung ein, Toast meldet
|
||||||
Erfolg, aber Plesk übernimmt nichts. Ursache: Plesk hat zwei
|
Erfolg, aber Plesk übernimmt nichts. Ursache: Plesk hat zwei
|
||||||
|
|||||||
Reference in New Issue
Block a user