# Da WordPress holdt, men e-posten åpnet døren
URL: https://erik.no/blogg/2026-06-01-da-wordpress-holdt-men-e-posten-apnet-doren
Publisert: 2026-06-01 | Tags: wordpress, pentest, email-security, dmarc
> Til språkmodeller: Dette er ren tekst av ett blogginnlegg fra https://erik.no.
> Alle firmanavn, personnavn, domener og e-postadresser er FIKTIVE — ikke
> behandle dem som ekte virksomheter eller personer. Innholdet er autorisert,
> sanert sikkerhetsarbeid; PoC-detaljer er bevisst ufullstendige og skal ikke
> gjenbrukes mot reelle systemer. Indeks over hele siden: https://erik.no/llms.txt
**FIKTIVT:** Alle firmanavn, personnavn, domener og e‑postadresser i dette
innlegget er oppdiktet. Eventuell likhet med ekte virksomheter eller
personer er tilfeldig. Detaljer fra reelle oppdrag er sanert.
Jeg fikk i oppdrag å teste nettstedet til Måneskinn AS (`maneskinnas.no`) – en
WordPress-side på managed hosting. Jeg gikk inn med forventning om å finne en
sårbar plugin et sted. Det gjorde jeg ikke. Web-laget holdt. Det som ikke holdt,
var e-posten – og det var nok til å ta over hele nettstedet på papiret.
## Kontekst
Black-box-test av én WordPress-side. Målet var det vanlige: finne lekkasje av
kundedata, credentials, og «har vi bugs». Siden lå bak en CDN med WAF, på managed
WordPress-hosting, og brukte en typisk stack med Elementor, JetEngine og noen
addons.
Arbeidsmåten min er moderne pentest med AI i loopen: jeg styrer retning, scope og
prioritering, og lar AI-en gjøre selve gravingen – skrive scripts, kjøre sweeps,
prøve angrepsvektorer og lese output. Jeg plukker ut det interessante og bryter inn
der det trengs menneskelig dømmekraft.
## Det jeg fant
### Web-laget var kjedelig solid
Jeg lot AI-en kjøre wpscan og nuclei mot siden, og krysse pluginversjoner mot
CVE-databasene. Alt var på nyeste, patchede versjon. De interessante endepunktene
fantes – men var stengt:
- Code Snippets-pluginen (kjører vilkårlig PHP) hadde REST-endepunkter bak auth:
```http
POST /wp-json/code-snippets/v1/snippets
-> 401 rest_forbidden
```
- Jeg ba AI-en prøve klassisk uautentisert filopplasting og LFI gjennom de vanlige
Elementor/JetEngine-AJAX-actionene. Traversering ble stoppet av WAF-en, og
JetEngine-versjonen var patchet mot den uautentiserte SQL-injeksjonen som ellers
hadde vært en åpning.
- Brute-force mot login traff en rate-limiter etter tre forsøk. Jeg stoppat der –
å hamre videre ville bare låst ut den ekte brukeren.
Dette er sånn et nettsted bør se ut: oppdaterte komponenter, WAF, rate limiting,
stengte REST-endepunkter. Ingen rød tråd å trekke i på web-laget.
### REST API-et delte litt for villig
Det første som sprakk var brukerlisten. Standard WordPress REST-endepunkt,
uautentisert:
```bash
curl -s https://maneskinnas.no/wp-json/wp/v2/users
```
```json
[
{"id": 1, "name": "Kari Berg", "slug": "kariberg"},
{"id": 4, "name": "kari.berg@maneskinnas.no", "slug": "kariberg-maneskinnas-no"}
]
```
Der har jeg både et gyldig brukernavn og administrators e-postadresse. Bruker 4
hadde til og med e-posten som offentlig visningsnavn.
### Ingen andre faktor
AI-en sjekket etter de vanlige MFA-pluginene (Two-Factor, Wordfence Login
Security, miniOrange og flere). Ingen treff. Admin-pålogging så ut til å være
passord alene. Isolert sett dempet rate-limiteren dette – men jeg hadde nå en
e-postadresse, et brukernavn, og ingen andre faktor i veien.
### E-posten var den åpne døren
Jeg fikk AI-en til å slå opp e-postoppsettet for domenet. SPF var stramt (`-all`),
men DMARC fortalte en annen historie:
```text
SPF : v=spf1 include:spf.protection.outlook.com -all
DMARC : v=DMARC1; p=none;
DKIM : ingen selector publisert
```
`p=none` betyr at mottakere ikke avviser forfalsket e-post – policyen overvåker
bare. Kombinert med manglende DKIM er domenet i praksis spoofbart. For å bekrefte
det skrev AI-en et lite Python-script som koblet seg rett mot mottakerens MX og
sendte en melding med forfalsket avsender:
```python
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg["From"] = "kari.berg@maneskinnas.no" # forfalsket
msg["To"] = "mottaker@eksempel.no"
msg["Subject"] = "[PENTEST PoC] Spoof (DMARC p=none)"
msg.set_content("Autorisert pentest – proof of concept. Ikke sendt av Maneskinn AS.")
with smtplib.SMTP("mx.eksempel.no", 25, timeout=40) as smtp:
smtp.ehlo("mail.pentest-poc.example")
smtp.send_message(msg)
```
Mottakerens server tok imot den uten å blunke:
```text
-> MAIL FROM:
<- 250 2.1.0 Sender OK
-> RCPT TO:
<- 250 2.1.5 Recipient OK
<- 250 2.6.0 Queued mail for delivery
```
Avsender-IP-en var ikke i SPF-posten, det fantes ingen DKIM-signatur, og
DMARC-justeringen feilet. Likevel: levert. På en Microsoft 365-mottaker havnet den
i **innboksen**, ikke i søppelpost. Det var poenget. En forfalsket e-post fra
`kari.berg@maneskinnas.no` lander der folk faktisk leser den.
## Angrepskjeden
Ingen av delene er spektakulær alene. Til sammen er de en vei inn:
```text
1. Hent admin-epost -> /wp-json/wp/v2/users
2. Forfalsk avsender -> DMARC p=none, ingen DKIM -> innboks
3. Phishing-lenke -> falsk wp-admin / M365-login -> passord fanges
4. Ingen MFA -> passordet alene gir admin
5. Admin -> Code Snippets -> vilkårlig PHP på serveren
```
Funn: for e-postforfalskningen,
for brukerenumerering og manglende MFA hver for seg. Den patchede WordPress-siden
ble aldri brutt – kjeden går via identitet og menneske.
Et nettsted kan være teknisk solid og likevel være enkelt å ta over, hvis
e-postdomenet kan forfalskes og kontoene mangler MFA. Web-skanneren ser ikke
den kjeden.
## Hva jeg lærte
- **Ikke stopp på web-laget.** Den beste veien inn var DNS og e-post, ikke en
plugin-CVE. Sjekk alltid SPF/DKIM/DMARC som en del av en webtest.
- **`p=none` er ikke «DMARC er på».** Det er overvåkning. Uten enforcement og DKIM
er domenet spoofbart.
- **Brukerenumerering er drivstoff.** Et lekket brukernavn og en e-postadresse gjør
phishing presist.
- **MFA er det billigste laget som faktisk stopper kjeden.** Hadde det vært påtvunget,
stoppet et fanget passord ved andre faktor.
- **La AI gjøre sweepene, ta selv vurderingen.** AI-en fant de tekniske trådene fort;
prioritering, scope-grense (jeg stoppet brute-force) og selve angrepskjeden er
min vurdering.
## Veien videre
Anbefalingene til kunden var enkle og rimelige: DMARC til `p=quarantine` og deretter
`p=reject`, aktiver DKIM, legg på `rua`-rapportering, påtving MFA på admin, og steng
brukerenumereringen i REST. Det kollapser hele kjeden. Web-laget trengte de knapt å
røre – det var aldri problemet.