The Slow Accumulation of Overlooked Misconfigurations
A Case Study of How A Wordpress Security Audit Revealed Backup Exposure, Misrouted Forms, & Broken Authentication
Part One: The Routine Audit
A nonprofit media organization had built a successful WordPress site over several years. Traffic was growing, they were planning to expand their digital presence, and they wanted to make sure their foundation was solid before building on it. A formal security assessment seemed like the right time.
The pre-engagement reconnaissance painted a familiar picture: WordPress 6.9 (current), SiteGround hosting, Google Workspace for email, Wordfence for security…A handful of outdated plugins, some missing email authentication records…In short, nothing screamed urgency.
Then I connected via SSH and started poking around.
The Backup Directory
My external scans had flagged a potential backup directory at /wp-content/backup-db/. When I checked the filesystem, that directory didn’t exist—a false positive from the scanner. But the presence of the All-in-One WP Migration plugin caught my eye, so I went looking for its default backup location.
Two complete site backups. The older one had been sitting there for nearly six months. These .wpress archives contain everything: the complete database with user credentials, wp-config.php with database passwords and authentication keys, all uploaded media, and every line of plugin and theme code.
My first thought was: these should be protected. All-in-One WP Migration creates a .htaccess file in the backup directory specifically to prevent public access. I checked—the protection was there, with proper Apache directives to deny all requests.
So why did I have a bad feeling?
The Architecture Gap
SiteGround uses a hybrid server setup: nginx as a reverse proxy in front of Apache. Apache handles PHP processing and reads .htaccess rules. But here’s the catch—by default, SiteGround enables “NGINX Direct Delivery,” which serves static files directly through nginx without ever touching Apache.
The .wpress backup files are static content. With NGINX Direct Delivery enabled, requests for those files go straight through nginx, which doesn’t read .htaccess files. The protection rules were there, but the requests never reached the server component that would enforce them.
It was like posting a guard at the back door while everyone walked in through the front.
I tested with curl and got HTTP 200. Downloadable. A 270MB complete site backup, including database credentials, sitting on the public internet for six months.
Technical Note: SiteGround’s NGINX Direct Delivery is a performance feature that serves static content (images, CSS, JS, and other non-PHP files) directly from nginx, bypassing Apache. This is faster, but it means .htaccess rules only apply to requests that actually reach Apache. Static file protection requires server-level nginx configuration, not directory-level .htaccess rules.
Immediate Remediation
I notified the client immediately and got approval to act. The fix was straightforward—move the backups outside the web-accessible directory entirely. After relocating the files, a fresh curl request returned HTTP 404.
The invisible door was finally closed. But I couldn’t shake the question: had anyone walked through it while it was open?
Part Two: The Phantom Logins
During log analysis, I found something that made me sit up straight:
[23-Jan-2026] wp_auto_login: trying to login user_id==1 loginusername=[redacted]
[26-Jan-2026] wp_auto_login: trying to login user_id==1 loginusername=[redacted]
[27-Jan-2026] wp_auto_login: trying to login user_id==1 loginusername=[redacted]
Auto-login attempts over multiple days and a function called wp_auto_login that I’d never seen in core WordPress. This looked like either malware or unauthorized automation.
So, I started hunting.
The Search
I grepped the entire codebase for the function name. Nothing in the plugins, nothing in the themes; I checked mu-plugins (WordPress’s “must-use” plugins directory that loads automatically)—it didn’t exist. I checked for drop-in files like advanced-cache.php or db.php that can execute arbitrary code—none present.
I searched the database for any reference to the function or the log message…empty results.
I checked for recently modified PHP files during the window when these login attempts occurred—nothing suspicious. I reviewed every installed plugin looking for rogue entries. I examined SiteGround’s hosting infrastructure paths. All empty.
The code generating these log entries simply didn’t exist anywhere I could access.
The Discrepancy
Then I noticed something odd in the logs themselves. They referenced “user_id==1” but the username belonged to user ID 2. I pulled up the user table and confirmed: user ID 1 was a different account entirely. The log was claiming to login one user ID using a different user’s username.
That inconsistency ruled out a standard WordPress login attempt—something else was happening.
The Answer
I asked the client about the account mentioned in the logs. Their response: “Oh, that’s the account SiteGround uses for their auto-login feature.”
SiteGround’s hosting control panel includes a “Login to WordPress” button that authenticates users without requiring credentials. The wp_auto_login function exists in their hosting infrastructure—outside the WordPress installation entirely—at the server level where my grep commands couldn’t reach.
The phantom was the hosting provider all along.
But this investigation revealed something worth documenting: SiteGround’s auto-login feature has no configuration interface. It doesn’t let you choose which WordPress account to use. Instead, it automatically selects the first administrator account alphabetically by username.
This means if someone creates an admin account named “admin” or “aardvark,” SiteGround’s auto-login will silently start using that account instead—with no notification. A quirky platform behavior worth knowing about.
Part Three: 609 608
With the backup exposure remediated and the phantom logins explained, Phase 2 moved into hardening. Plugin updates, security headers, email authentication—standard remediation work.
While reviewing the admin dashboard, I noticed something odd: two numbers displayed in the upper-left corner, just before the first admin notice element.
609 608
No context, no label, not wrapped in any HTML tags…just raw text floating between elements. Small anomalies like this can sometimes point to bigger problems: debug output that reveals internal state, error messages that expose paths, or artifacts from injected code. It warranted investigation.
The Hunt
My first thought: post IDs. WordPress stores everything as “posts” internally, so maybe something was echoing object IDs. I checked the database—no posts with those IDs existed.
I reviewed the Code Snippets plugin—three active snippets for reCAPTCHA, RSS version removal, and security headers. All clean, no stray echo statements.
I used the browser inspector to find the exact HTML location. The numbers appeared immediately before an Elementor admin notice div. I searched the Elementor codebase but found nothing relevant.
Dead end.
Brute Force
When surgical approaches fail, sometimes you need a hammer. I started deactivating plugins one by one, checking the dashboard after each change.
Elementor—numbers still there; sitekit—still there; wordfence—still there.
Ad-Inserter Pro…numbers gone.
I reactivated it; numbers came back.
Now I had a target. Ad-Inserter Pro was a plugin for managing Google AdSense placement, but the client’s license had expired. I started tracing through its code, looking for anything that might output numbers to the dashboard.
The plugin hooked into WordPress’s admin notices system. When a license expires, it displays a warning. I traced the code path: expired license triggers a specific status code, which loads a version-check file. Inside that file:
$wp_check = intval(get_bloginfo('version') * 100);
$wp_last = get_option('ai_wp_version', 0);
echo $wp_check, ' ', $wp_last; // <-- There it is
A debug statement. Left in production code. The numbers were WordPress version calculations:
| Value | Calculation | Meaning |
|---|---|---|
| 609 | 6.9 × 100 | Current WP version |
| 608 | 6.8 × 100 | Last cached version check |
Some developer had added an echo statement for debugging, presumably to troubleshoot version comparison logic, and never removed it. Because the output only appeared when the license was expired, it probably passed QA testing.
More importantly, the investigation revealed that the plugin was redundant—ads were actually being served by Google Site Kit’s Auto Ads feature, and Ad-Inserter Pro wasn’t contributing anything. We deactivated it entirely.
Part Four: The Email Trail
The pre-engagement reconnaissance had flagged email authentication issues: missing SPF, weak DMARC. When I dug in, the situation was more tangled than expected, and it went beyond just DNS records.
The Contact Form
While reviewing the site’s email configuration, I checked where contact form submissions were being sent. The routing stopped me cold:
TO: Tech News <[redacted]@[redated].com> via [redacted].siteground.biz
The contact form had been sending every submission to what appeared to be a previous developer’s email address, not to anyone at the organization. Every inquiry, every potential partnership, every reader reaching out—routed to a stranger.
How long had this been happening? Impossible to say. But the fix was immediate: submissions now route to the organization’s actual staff.
The Authentication Puzzle
I ran a test: sent an email from the client’s Google Workspace account and examined the headers. SPF failed. DKIM passed but wasn’t aligned. DMARC failed.
Emails were being delivered only because the DMARC policy was set to “none” (monitor only). But sender reputation was taking hits, and spoofing protection was nonexistent.
Here’s the thing: from the client’s perspective, email “worked.” Messages sent, messages received. If you don’t know what SPF, DKIM, and DMARC are supposed to do, there’s no visible indication that anything is wrong. The authentication failures were invisible—until they eventually cause deliverability problems or someone spoofs your domain.
The Wrong Subdomain
When I pulled the DNS records, I found the SPF record. It was just in the wrong place:
www.example.org TXT "v=spf1 include:_spf.google.com ~all"
example.org TXT (nothing)
SPF records must be at the root domain (the “naked” domain), not the www subdomain. The record existed but was completely ineffective.
The DMARC record had the same problem—configured on _dmarc.www instead of _dmarc. Someone had set everything up on the www subdomain. A simple mistake that broke the entire authentication chain.
There were also orphaned DNS records from Mailgun—MX records, a CNAME, SPF includes—for a service the client couldn’t even access anymore. Leftover from a previous developer, adding clutter and potential confusion.
Rebuilding Authentication
The fix required coordinated DNS changes: SPF created at the root domain with proper includes for Google Workspace and SiteGround (Mailgun removed since the account was inaccessible); DMARC created at the correct location with a reporting address; DKIM key generated in Google Admin and the corresponding TXT record added; orphaned Mailgun records cleaned up.
After DNS propagation, a fresh test showed all checks passing. The client now had proper email authentication, and a reporting address to monitor for spoofing attempts.
Technical Note: Email authentication relies on three mechanisms working together. SPF specifies which servers can send mail for your domain. DKIM cryptographically signs messages. DMARC tells receiving servers what to do when checks fail and where to send reports. All three records must be at the correct DNS locations to function—and “email works” isn’t the same as “email is authenticated.”
Part Five: The Spam Folder
A week after remediation wrapped up, the client reached out. An important email—a pitch to a local hotel for advertising—had landed in the recipient’s spam folder. The reply came back with the subject line:
Re: [EX][Spam] Featuring [redacted] Hotel on [Client Website]
The [EX] tag is standard enterprise labeling for external senders. The [Spam] tag meant their mail system had flagged the original message. But authentication was now passing, so why was email still landing in spam?
Three Factors
Factor 1: DMARC is still in monitoring mode. The policy was still set to p=none, which means receiving servers get no instruction to trust properly-authenticated mail or reject spoofed mail. Enterprise mail filters at large organizations treat domains without DMARC enforcement as less trustworthy. When their system decides whether an email is legitimate, a strong DMARC policy is a major trust signal—and theirs wasn’t providing one yet.
That said, the monitoring phase is intentional. DMARC aggregate reports need to be reviewed to confirm all legitimate mail sources are properly authenticated before tightening the policy. Moving to enforcement prematurely risks blocking the organization’s own emails (horror stories abound). The goal is to move through this phase as quickly as possible: p=none → p=quarantine → p=reject.
Factor 2: SPF soft fail. The SPF record ends with ~all (soft fail), which tells receiving servers to be suspicious of unauthorized senders but not reject them outright. The stronger setting, -all (hard fail), instructs receivers to reject unauthorized senders. Soft fail is another signal to spam filters that the domain owner isn’t fully asserting control over their email.
Like the DMARC setup though, this ~all is intentional during verification. Once all legitimate sending sources are confirmed through DMARC reports, SPF will be tightened to a hard fail.
Factor 3: Domain reputation and sending volume. Large organizations that send thousands of emails build a track record with mail providers over time. Low-volume senders don’t have that luxury, which means the authentication signals above carry even more weight. When a low-volume domain also has weak policy enforcement, spam filters tend to err on the side of caution.
The Path Forward
Even with authentication passing, email deliverability is a longer game. The steps are:
- Monitor DMARC reports to confirm all legitimate sources are authenticated
- Tighten DMARC from
p=nonetop=quarantinetop=reject - Tighten SPF from
~allto-all - Build reputation through consistent sending with proper authentication in place
But you’re still not done even after full enforcement, because individual emails can still occasionally land in spam—particularly with enterprise filters that apply their own internal scoring. To be clear, proper authentication provides the strongest possible foundation, and without it you’re asking recipients to trust you on faith. For clients who wan to take the next step though and strengthen their domation / email reputation score, that’s where the concept of email warming comes in.
Part Six: The Loose Ends
Security work rarely ends with a clean break. In the days following remediation, a few more items surfaced.
The Caching Conflict
The client reported formatting issues on the site one evening: the homepage layout was broken, and the styles weren’t loading correctly. If you’ve worked with WordPress for any length of time, your first instinct is probably the same as mine: caching.
Caching is supposed to make sites faster by storing copies of pages, stylesheets, and scripts so they don’t need to be regenerated on every visit. But caching is also responsible for a disproportionate share of WordPress display problem, and the reasons are worth understanding.
Why caching breaks things: When you update a theme, plugin, or page content, the changes exist in the database and on the filesystem. But if a caching layer is serving a stored copy of the old CSS or JavaScript, visitors see a mismatch: new HTML structure trying to use old styles, or new functionality expecting scripts that haven’t been refreshed. The result is broken layouts, missing elements, or JavaScript errors.
Why it’s hard to diagnose: Modern WordPress sites often have multiple caching layers stacked on top of each other:
- Browser cache — Your visitor’s browser stores files locally
- CDN cache — If you use Cloudflare or similar, they cache at the edge
- Server-level cache — Many hosts (including SiteGround) provide their own caching
- Plugin cache — WordPress caching plugins like WP Fastest Cache, W3 Total Cache, or LiteSpeed Cache
Each layer has its own expiration rules, its own purge mechanisms, and its own quirks. When something goes wrong, you’re hunting through multiple systems trying to figure out which one is serving stale content.
The specific problem: This site had WP Fastest Cache (a WordPress plugin) running alongside SiteGround’s SuperCacher (host-level caching). I cleared SiteGround’s SuperCacher, and the display problem resolved immediately. But that raised the question: why now? The site had been running this combination for a while without visible issues.
My hypothesis: the recent Elementor and Astra updates introduced something that didn’t interact well with the dual-caching setup. Maybe a new CSS file that one cache recognized and the other didn’t, maybe a change in how assets are loaded. Honestly, it’s hard to pin down exactly—that’s the nature of WordPress. The combinations of plugins, themes, hosting providers, and server configurations are endless, and sometimes those combinations interact in ways that cause unexpected issues only under specific conditions.
The troubleshooting approach: If the problem returned, the plan was to diff the source code of the broken page against a correctly rendered version—compare the raw HTML, see exactly what’s different, and trace backward to figure out which caching layer is responsible for the discrepancy. Sometimes that’s the only way to isolate these issues.
I disabled WP Fastest Cache to eliminate the variable. Over the following days, the display issue didn’t return. The conflict was confirmed: running a WordPress caching plugin on top of SiteGround’s built-in caching created unpredictable behavior that only manifested after certain updates.
The lesson: If your host provides caching (and most modern WordPress hosts do), you probably don’t need a caching plugin. Running both creates more opportunities for conflicts than benefits. And when display issues appear—especially after updates—clearing every cache layer you can find is usually step one.
The Orphaned SVG
During a performance check, an externally hosted SVG file was identified loading on every page via custom CSS. It served no visible purpose and was slowing down page loads. The client didn’t recognize it—likely leftover from the original theme setup. Removed.
(A side effect: removing the SVG also removed a gradient background behind one section, since both were defined in the same CSS block. Caught by the client and restored the same day. Careful cleanup sometimes has unintended consequences.)
The Redundant Plugin
With ads confirmed working through Google Site Kit, the deactivated Ad-Inserter Pro remained in limbo. Fewer plugins means a smaller attack surface and fewer update obligations. If the current ad placements continue working, full removal is the recommendation.
Lessons for Site Owners
Know Your Server Architecture
The backup exposure happened because a plugin assumed one server configuration when reality was different. Before trusting any security mechanism, verify it actually works in your specific environment. SiteGround’s hybrid nginx/Apache setup is common among modern hosts—and it means .htaccess rules don’t protect static files by default.
Check Where Your Forms Actually Send
The contact form had been routing submissions to a previous developer for an unknown period of time. When you inherit a site, or even if you’ve been running one for years, verify that forms, notifications, and automated emails are going where you think they’re going.
Small Anomalies Matter
Random numbers appearing in the admin dashboard turned out to be a forgotten debug statement—not malware, not a security issue. But it could have been. Unexplained output, unexpected behavior, things that “weren’t there before” are worth investigating. The cost of checking is low; the cost of ignoring something that matters is high.
“Working” Isn’t “Configured Correctly”
Email was working; messages sent and received. But authentication was broken, reputation was degrading, and spoofing protection was nonexistent. Many configuration problems are invisible until they cause a crisis. Periodic audits catch these issues before they compound.
Authentication Is the Floor, Not the Ceiling
Passing SPF, DKIM, and DMARC doesn’t guarantee inbox placement. It proves you are who you claim to be—but inbox providers still decide whether they trust you. For low-volume senders especially, the policy settings matter as much as the records themselves. p=none and ~all are temporary states, not destinations.
Conclusion
What started as a routine audit revealed a critical six-month backup exposure, untangled phantom login entries that led to hosting infrastructure documentation, solved mysterious debug output from forgotten code, discovered a contact form sending submissions to a stranger, rebuilt broken email authentication, and navigated the ongoing challenge of email deliverability for a low-volume sender.
The invisible door is now closed, the contact form reaches the right people, email is properly authenticated and on a path toward full enforcement, and the site is hardened and documented.
But the real lesson spans the entire engagement: security isn’t a moment, it’s a posture. The backup exposure existed because no one tested an assumption. The contact form routed elsewhere because no one checked. The email authentication was broken because the records “looked right.” Each gap persisted because there was no visible symptom—until there was.
Proactive review found these issues before they became crises. That’s the point.
Confidentiality Note: Identifying details including the organization name, location, and specific configurations have been redacted to protect client confidentiality. Technical details have been preserved for educational purposes.
Related Reading
-
Case Study: The Anatomy of an E-Commerce Breach
When attackers get in, they don't just take — they build infrastructure to stay. -
The Invisible Score: Why Your Emails Disappear Even When You've Done Everything Right
SPF, DKIM, and DMARC prove who you are — but inbox providers decide if they trust you. -
Email Warm-Up & Reputation Recovery
Authentication alone won't fix spam placement for new or damaged domains.