~/f4n6 $ grep -r "A phishing email that borrowed SurveyMonkey's reputation" ./investigations/ --include="*.md"
Phishing-Tracker

A phishing email that borrowed SurveyMonkey's reputation

Jeff Davies 24 Oct 2026 7 min read

One seed email, forty passive queries, 1,081 candidates, four live surveys, and a shortlink that resolved to a Klarna kit on a compromised WordPress host. Including the false positive the tool produced.


The email authenticated. SPF passed for the envelope sender and DKIM passed for the signing domain. That is not a sign the message is safe, and here it is a sign of the opposite: it was sent from infrastructure the brand owns and operates for its customers.

The sample is a 25,795-byte message with a single text/html part, no attachment and no form. The subject reads "Important Update Regarding Your 3-Installment Payment." and the body opens with "You have received a new important message in your secure messaging center." It then promises "updated information about your purchase into 3 interest-free", and stops. The sentence is missing its noun. One link leaves the message. Everything else is branding.

I ran it through a passive-only pipeline, then resolved the one link through a private urlscan scan. This is what came back, including a false positive of my own making that is more instructive than the finding.

The headers do the work

Header Value
Envelope from survey-noreply@hr[.]surveymonkeyuser[.]com
Visible from display name …@afw[.]fr[.]nf via SurveyMonkey, address member@surveymonkeyuser[.]com
Reply-To 21-digit local part at afw[.]fr[.]nf
SPF pass, sender IP 192[.]174[.]81[.]47
DKIM pass, header.i=@surveymonkeyuser[.]com, selector scph0816
Relay i-0e43f671a64e70b84.mta2vsmtp.sd.prd.sparkpost
CTA hxxps://rebrand[.]ly/k9f2028

Two details separate this from a spoof. The first is the reply path. The display name is the attacker's Reply-To address, so a client that shows the friendly name shows their mailbox instead of the sender's. Replying goes to them, not to the platform.

The second is X-MSFBL, a header the platform adds. Base64-decoded it is a JSON object with tenant_id: surveymonkey, customer_id: 1, subaccount_id: 102 and a message ID. The body also carries a collector ID and a message ID that belong to the send. The unsubscribe link points at fr[.]surveymonkey[.]com.

The footer gives it away. Under the English lure sit three lines of French: "Commencer le sondage", "Ce lien vers un sondage vous est propre, veuillez ne pas transférer cet email", and "Optimisé par". Start the survey. This survey link is unique to you, do not forward it. Powered by. Nobody writing a bank notification leaves that in. The sender took a French-language survey-invitation template and pasted a payment message into it.

Put together, these say the message was not forged. An account on SurveyMonkey's platform composed and sent it, from a survey template, through the platform's own mail vendor, and every authentication check passed because everything was authentic except the intent. The abuse sits at account level, not at infrastructure level. That distinction decides where the report goes.

Passive pivots returned nothing

Forty queries across urlscan.io, urlquery.net, crt.sh, Wayback and a search engine produced 1,775 raw results. None of them touched the two indicators that matter:

  • The Reply-To domain, afw[.]fr[.]nf, is a free subdomain provider. Domain-scoped queries return zero on urlscan and urlquery. crt.sh has no certificate and Wayback has no capture. Plain-text hits exist, but they are tokenisation noise from unrelated sites.
  • The shortlink returned zero across ten query forms on both sandboxes: exact URL, path token alone, wildcard, domain plus path, and the quoted form. Nobody had submitted it, so neither engine held a destination for it.

Absence is not safety. A shortener exists to make a URL used once and never seen again, and it worked.

What the pipeline did find

The run scored 1,081 candidates from 40 queries:

Confirmed High Probable Candidate Total
0 4 0 1,077 1,081

The four high-confidence results are worth reading closely, because three of them are not the campaign this email belongs to. They are live SurveyMonkey surveys dressed as Spectrum, a US telecoms brand:

hxxps://www[.]surveymonkey[.]com/r/K9WPYHV
hxxps://www[.]surveymonkey[.]com/r/NDHNNBP
hxxps://www[.]surveymonkey[.]com/r/9MVSPNK

Vision analysis of the screenshots describes a Spectrum logo, headings like "Mailbox Validation" and buttons reading "CLICK HERE TO SIGN IN". The pages are hosted on the legitimate surveymonkey[.]com domain, and the domain itself is not malicious. The survey paths are.

That is the triage trap in this whole class. Blocking the domain breaks a service thousands of customers use. A rule has to key on the path or on page content, and a regex on the brand name without anchoring to the registrable domain will bury four real pages under a thousand legitimate ones.

All four findings are unattributed. The pipeline requires a qualifying published IOC, a campaign backend, a source or hash match or analyst-confirmed linkage before it attributes, and none of that was present. Shared Amazon hosting and nginx are correlative at best.

The false positive I would rather publish than hide

The fourth high-confidence result was surveymonkeyuser[.]com, scored as brand impersonation at high confidence, with the page title "SurveyMonkey: The World's Most Popular Survey Platform".

That title is the real homepage. So is the content. The vision stage was describing a genuine site, because the mirror had followed an HTTP 301 chain off the candidate host:

hxxp://surveymonkeyuser[.]com/  →  hxxps://surveymonkeyuser[.]com/  →  hxxps://www[.]surveymonkey[.]com/

The mirror record reported the content as the candidate's own source, with no note that the bytes came from a different host. The domain is registered through MarkMonitor, the registrar brand owners use to hold defensive domains, and the canonical URL in the page metadata is the vendor's.

The same mirror also produced 62 strings that look like IPv4 addresses. None of them is one. They come from SVG path data, where coordinates are written without a leading zero. The offending fragment runs four coordinates, -0.005, 0.247, 0.3 and 0.3, back to back with nothing between them but their decimal points, and the pattern read those three points as octet separators. The zero that follows each point then became an octet prefix, which is where the leading zeros came from.

A strict parser rejects all of them. Python's ipaddress refuses every one. A permissive one does not, which is why the looseness matters beyond cosmetics: glibc's inet_aton reads 005[.]247[.]3[.]3 as 5[.]247[.]3[.]3, treating a leading zero as octal. That is the same parser differential that breaks SSRF denylists, arriving here as noise instead of a bypass.

Nothing downstream filtered them, so they reached the IOC extractor, the CSV and the report.

Two lessons, both filed as fixes. A mirror that leaves the host is not evidence about the host, and a record that hides where its bytes came from invites exactly this error. The first pattern fix took the count from 62 to 3; the survivors are the same path data with their coordinate chain ending at a space, which is filed too. Patterns that read numbers out of markup need to be tighter than the markup.

The useful part: the email's own sending domain was never suspicious. The thing the pipeline graded highest was the one thing that could not be malicious. If I had shipped that report without checking, it would have contained a takedown draft against the vendor whose platform carried the lure.

The pipeline refuses to touch a candidate host, so the link stayed unresolved. I submitted it to urlscan as a private scan. That is urlscan's scanner fetching it, not our infrastructure, and the result stays private.

Submitted hxxps://rebrand[.]ly/k9f2028
Landed on hxxps://nbs[.]tgs[.]mybluehost[.]me/wp-content/eu/klarna/index.php?key=2837400374
IP / ASN 50[.]6[.]61[.]137, ORACLE-BMC-31898
Server Apache
Status 503 Service Unavailable
Screenshot the 503 error page

A 503 does not mean the infrastructure is gone. The www host on the same IP serves its root page with a 200 and the placeholder text "Welcome — Coming Soon", and the scan captured exactly two requests, both to the kit path. The hosting is alive, and the kit directory is not.

The path is the interesting part: /wp-content/eu/klarna/. That is a WordPress content directory with a locale segment and a brand name under it. It is also not unique. Pivoting the same pattern found a family:

nbs[.]tgs[.]mybluehost[.]me/wp-content/eu/klarna/index.php  503
www[.]seniortime[.]com/wp-content/klarna/mobi.htm          500
www[.]seniortime[.]com/wp-content/klarna/OIDCClient.htm    500
phoenixdeluxespa[.]com/wp-content/no/klarna/track.htm      404

Compromised WordPress sites, the same four filenames, locale variants eu and no. The filenames tell you what the kit does after it captures a login: mobi.htm is a mobile variant, OIDCClient.htm is a step that hands the victim to an identity provider, track.htm is instrumentation. The same hosting also serves a Canada Post lure under /wp-content/canadapost/, so this operator runs at least two themes from the same reseller space.

Every page in that family is dead or erroring now, which is normal for kits dropped on sites their owners do not monitor.

The shortener fits the same window. Searches for rebrand[.]ly in the days around this send return recent scans of links carrying rb.routing.mode=proxy, several already answering 404 with the title "Stop! Deceptive page ahead!". Whatever the operator is doing, they are burning links within days. Our slug is an opaque token rather than a keyword string, which may mean a different operator or simply a more careful one. There is nothing here to attribute.

What this means for detection

Domain blocklists will not catch this. The sending domain belongs to the brand and the CTA is a shortener that rotates.

At the mail gateway, the signal is the mismatch inside an authenticated message: a Reply-To on a free subdomain provider, and a display name that is itself the reply address. Both are cheap to spot and neither depends on reputation.

For the survey abuse, key on the path. Survey paths under /r/ that appear in inbound mail from external senders are worth a content check. The three paths above are the known-bad set from this run.

For the kit family, alert on requests to /wp-content/<two-letter-locale>/<brand>/ where the brand is a payment or logistics company. Legitimate WordPress plugins do not install themselves into a locale-named bank directory.

At the host level, a compromised WordPress site is the unit of failure. The kit lives in a content directory the owner can see, if anyone looks.

Limits

Nothing in this run is attributed to a named actor, and I am not going to infer one from shared hosting.

The kit was already returning 503 when it was captured, so I have no page from it, no form, and no exfiltration endpoint. Whether anyone submitted credentials to it is unknown, and will stay unknown without the operator's logs or a victim report.

The Spectrum surveys are live and are a different campaign. They came out of the same pivots, not out of this email.

One sample proves a lure reached one mailbox. The numbers here describe how noisy passive pivoting is on a brand name, not how widespread the campaign is.

Indicators

Defanged, as everything leaving this machine is.

Type Value Note
Sending domain surveymonkeyuser[.]com vendor-owned, authenticated, used by a platform account
Reply-To domain afw[.]fr[.]nf free subdomain provider, no passive footprint
Shortlink rebrand[.]ly/k9f2028 resolves to the kit below
Kit host nbs[.]tgs[.]mybluehost[.]me Bluehost shared hosting
Kit IP 50[.]6[.]61[.]137 ORACLE-BMC-31898
Kit path /wp-content/eu/klarna/index.php locale + brand directory
Survey paths /r/K9WPYHV, /r/NDHNNBP, /r/9MVSPNK on www[.]surveymonkey[.]com, live
Post this to LinkedIn
Formatting is converted automatically — headings, bullets, a link back & hashtags. Paste straight in.
J
Jeff Davies
// read next

Related