AudioIgniter Music Player <= 2.0.2 - Unauthenticated Insecure Direct Object Reference to 'audioigniter_playlist_id' Parameter
Description
The AudioIgniter plugin for WordPress is vulnerable to Insecure Direct Object Reference in versions up to, and including, 2.0.2. This is due to the handle_playlist_endpoint() function (hooked to template_redirect) accepting a user-controlled playlist ID via the audioigniter_playlist_id query var or the /audioigniter/playlist/{id}/ rewrite rule and returning playlist track data without performing any authentication, capability, or post_status check — only the post_type is validated. This makes it possible for unauthenticated attackers to view track metadata (titles, artists, audio URLs, buy links, download URLs, and cover images) of any playlist on the site, including those in draft, private, pending, or trash status.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NTechnical Details
What Changed in the Fix
Changes introduced in v2.0.3
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-8679 (AudioIgniter Music Player) ## 1. Vulnerability Summary The **AudioIgniter Music Player** plugin (<= 2.0.2) contains an **Insecure Direct Object Reference (IDOR)** vulnerability within its playlist data endpoint. The function `handle_playlist_endpoint()`,…
Show full research plan
Exploitation Research Plan: CVE-2026-8679 (AudioIgniter Music Player)
1. Vulnerability Summary
The AudioIgniter Music Player plugin (<= 2.0.2) contains an Insecure Direct Object Reference (IDOR) vulnerability within its playlist data endpoint. The function handle_playlist_endpoint(), which is hooked to template_redirect, allows unauthenticated users to retrieve metadata for any playlist by providing its ID. Because the function only validates that the requested ID corresponds to the ai_playlist post type and fails to verify the post_status (e.g., draft, private, trash) or user permissions, it exposes sensitive track information (URLs, titles, download links) that should not be publicly accessible.
2. Attack Vector Analysis
- Endpoints:
/?audioigniter_playlist_id=[ID](Query parameter)/audioigniter/playlist/[ID]/(Rewrite rule)
- Parameter:
audioigniter_playlist_id - Authentication: None required (Unauthenticated).
- Preconditions:
- The plugin must be active.
- A playlist must exist (even if it is a draft, private, or in the trash).
- Severity: High (7.5) - This allows full disclosure of track metadata and audio source URLs for restricted content.
3. Code Flow
- Registration: In
audioigniter.php, the methodinit()(line 144) callsregister_playlist_endpoint(), which registers theaudioigniter_playlist_idquery variable and a corresponding rewrite rule. - Hooking: In
audioigniter.php, the methodfrontend_init()(line 197) hookshandle_playlist_endpoint()to thetemplate_redirectaction. - Processing (Inferred): When a request is made:
template_redirecttriggershandle_playlist_endpoint().- The function retrieves the ID from
get_query_var( 'audioigniter_playlist_id' ). - It calls
get_post( $id ). - It checks
if ( $post->post_type === 'ai_playlist' ). - Vulnerability: It proceeds to output the playlist's track data (stored in post meta) as JSON and
exits, without checking ifpost_statusis'publish'.
4. Nonce Acquisition Strategy
According to the vulnerability description, the handle_playlist_endpoint() function performs no authentication or capability checks. This includes a lack of nonce verification.
- Nonce Requirement: None. The endpoint is intended to be a public data source for the player's JavaScript component, but it fails to restrict access to non-public playlists.
5. Exploitation Strategy
The goal is to retrieve track metadata from a Draft playlist as an unauthenticated user.
- Preparation: Identify or create a playlist in
draftstatus. - Request: Send a GET request to the site using the
audioigniter_playlist_idparameter. - Extraction: Parse the JSON response to confirm track titles, audio URLs, and download links are present.
Targeted Request
GET /?audioigniter_playlist_id=[PLAYLIST_ID] HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0
Accept: application/json
6. Test Data Setup
Use wp-cli to create the vulnerable state:
Create a Draft Playlist:
wp post create --post_type=ai_playlist --post_status=draft --post_title="Secret Album 2026" --post_content="Draft content"Note the returned ID (e.g.,
123).Add Track Metadata:
The plugin stores tracks in serialized post meta. Based on the source fields (lines 540-622), the metadata usually resides in a key like_audioigniter_tracks.wp post meta update 123 _audioigniter_tracks '[{"title":"Unreleased Track","artist":"The Attacker","audio":"https://example.com/secret.mp3","download_url":"https://example.com/download-secret"}]' --format=json
7. Expected Results
A successful exploit will return a 200 OK response with a JSON body similar to:
[
{
"title": "Unreleased Track",
"artist": "The Attacker",
"audio": "https://example.com/secret.mp3",
"download_url": "https://example.com/download-secret",
...
}
]
The response confirms that metadata for a draft post is leaked.
8. Verification Steps
- Confirm Post Status: Use WP-CLI to verify the playlist is indeed not published.
wp post get [PLAYLIST_ID] --field=post_status # Expected: draft - Verify Unauthenticated Access: Ensure the HTTP request was made without any session cookies or Authorization headers.
9. Alternative Approaches
If the query parameter method fails due to specific server configurations:
- Rewrite Rule: Try the pretty permalink structure:
GET /audioigniter/playlist/[ID]/ HTTP/1.1 - Internal Query: If the endpoint is restricted by security plugins, try accessing via
admin-ajax.phpif the plugin registered an alternative handler there (though the description points specifically totemplate_redirect). - Metadata Hunting: If track data isn't in the response, check if the response returns a list of attachment IDs, which could then be queried individually. (The description implies metadata is returned directly).
Summary
The AudioIgniter plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) via its playlist data endpoint. Unauthenticated attackers can retrieve sensitive track metadata, including audio URLs and download links, for playlists that are in draft, private, or trash status by providing a numeric ID through the 'audioigniter_playlist_id' parameter.
Vulnerable Code
// audioigniter.php:1266 public function handle_playlist_endpoint() { $playlist_id = get_query_var( 'audioigniter_playlist_id' ); if ( empty( $playlist_id ) ) { return; } $playlist_id = intval( $playlist_id ); $post = get_post( $playlist_id ); if ( empty( $post ) || $post->post_type !== $this->post_type ) { wp_send_json_error( __( "ID doesn't match a playlist", 'audioigniter' ) ); } $response = array(); $tracks = $this->get_post_meta( $playlist_id, '_audioigniter_tracks', array() ); // ... [processing tracks] ... wp_send_json( $response ); } --- // audioigniter.php:1217 $post = get_post( $id ); $params = apply_filters( 'audioigniter_shortcode_data_attributes_array', $this->get_playlist_data_attributes_array( $id ), $id, $post, $atts );
Security Fix
@@ -6,7 +6,7 @@ * Author: The CSSIgniter Team * Author URI: https://www.cssigniter.com * License: GPLv2 or later - * Version: 2.0.2 + * Version: 2.0.3 * Text Domain: audioigniter * Domain Path: /languages * @@ -1208,7 +1208,7 @@ 'class' => '', ), $atts, $tag ); - $id = intval( $atts['id'] ); + $id = (int) $atts['id']; $class_name = $atts['class']; if ( ! $this->is_playlist( $id ) ) { @@ -1217,6 +1217,13 @@ $post = get_post( $id ); + if ( $post->post_status == 'trash' || + ( ! is_user_logged_in() && 'publish' !== $post->post_status ) || + ( is_user_logged_in() && ! current_user_can( 'read_post', $id ) ) ) { + return ''; + } + + $params = apply_filters( 'audioigniter_shortcode_data_attributes_array', $this->get_playlist_data_attributes_array( $id ), $id, $post, $atts ); $params = array_filter( $params, array( $this->sanitizer, 'array_filter_empty_null' ) ); $params = $this->sanitizer->html_data_attributes_array( $params ); @@ -1266,12 +1273,17 @@ return; } - $playlist_id = intval( $playlist_id ); + $playlist_id = (int) $playlist_id; $post = get_post( $playlist_id ); if ( empty( $post ) || $post->post_type !== $this->post_type ) { wp_send_json_error( __( "ID doesn't match a playlist", 'audioigniter' ) ); } + if ( ( ! is_user_logged_in() && 'publish' !== $post->post_status ) || + ( is_user_logged_in() && ! current_user_can( 'read_post', $playlist_id ) ) + ) { + wp_send_json_error( __( 'Sorry, you are not allowed to access this playlist.', 'audioigniter' ) ); + } $response = array(); $tracks = $this->get_post_meta( $playlist_id, '_audioigniter_tracks', array() );
Exploit Outline
To exploit this vulnerability, an unauthenticated attacker can perform the following steps: 1. Identify the target site using the AudioIgniter plugin. 2. Craft a GET request to the site's root using the query parameter 'audioigniter_playlist_id' followed by the ID of a suspected non-public playlist (e.g., `/?audioigniter_playlist_id=123`). Alternatively, use the permalink structure `/audioigniter/playlist/[ID]/` if rewrite rules are active. 3. No authentication, nonces, or cookies are required for this request. 4. Analyze the JSON response, which will contain the serialized track metadata (including audio source URLs, download links, and artist names) even if the playlist's post status is 'draft', 'private', or 'pending'.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.