MAS Videos <= 1.3.2 - Missing Authorization
Description
The MAS Videos plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.3.2. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=1.3.2What Changed in the Fix
Changes introduced in v1.3.3
Source Code
WordPress.org SVNcalls `wp_verify_nonce`. If I'm unauthenticated, I can still get a nonce if it's rendered on a page I can see. Let's look at the "Unauthorized Action" again. Integrity: Low. It's probably importing a movie. Let's check `includes/admin/importers/class-masvideos-tmdb-importer-co…
Show full research plan
calls wp_verify_nonce.
If I'm unauthenticated, I can still get a nonce if it's rendered on a page I can see.
Let's look at the "Unauthorized Action" again.
Integrity: Low.
It's probably importing a movie.
Let's check `includes/admin/importers/class-masvideos-tmdb-importer-controller.php` for clues on the response.
It doesn't show the end of `fetch_form_handler`.
But it likely outputs HTML or JSON with "Found X movies".
Final plan structure:
1. Vulnerability Summary: Missing cap check in TMDB fetch.
2. Vector: `admin-ajax.php` with `action=masvideos_tmdb_fetch_data`.
3. Flow: AJAX -> Handler -> `fetch_form_handler`.
4. Nonce: Find shortcode, extract `masvideos-tmdb-fetch-data`.
5. Exploit: POST request to trigger the fetch.
Wait, one more thing. The plugin *might* not even check the nonce if I use the `masvideos-ajax` endpoint.
`do_masvideos_ajax` in `includes/class-masvideos-ajax.php` calls `do_action( 'masvideos_ajax_' . $action )`.
This bypasses the standard `admin-ajax.php` flow.
Summary
The MAS Videos plugin for WordPress is vulnerable to unauthorized playlist modification due to missing authentication and authorization checks in several AJAX endpoints. This allows unauthenticated attackers to add or remove videos, movies, and TV shows from any existing playlist by sending a crafted request with the target playlist ID.
Vulnerable Code
// includes/class-masvideos-ajax.php:1502 public static function toggle_tv_show_playlist() { ob_start(); $playlist_id = absint( $_POST['playlist_id'] ); $tv_show_id = absint( $_POST['tv_show_id'] ); $delete = isset( $_POST['delete'] ) ? masvideos_string_to_bool( $_POST['delete'] ) : false; if( $delete ) { $tv_show_playlist = masvideos_remove_tv_show_from_playlist( $playlist_id, $tv_show_id ); } else { $tv_show_playlist = masvideos_add_tv_show_to_playlist( $playlist_id, $tv_show_id ); } --- // includes/class-masvideos-ajax.php:1532 public static function toggle_video_playlist() { ob_start(); $playlist_id = absint( $_POST['playlist_id'] ); $video_id = absint( $_POST['video_id'] ); $delete = isset( $_POST['delete'] ) ? masvideos_string_to_bool( $_POST['delete'] ) : false; if( $delete ) { $video_playlist = masvideos_remove_video_from_playlist( $playlist_id, $video_id ); } else { $video_playlist = masvideos_add_video_to_playlist( $playlist_id, $video_id ); } --- // includes/class-masvideos-ajax.php:1562 public static function toggle_movie_playlist() { ob_start(); $playlist_id = absint( $_POST['playlist_id'] ); $movie_id = absint( $_POST['movie_id'] ); $delete = isset( $_POST['delete'] ) ? masvideos_string_to_bool( $_POST['delete'] ) : false; if( $delete ) { $movie_playlist = masvideos_remove_movie_from_playlist( $playlist_id, $movie_id ); } else { $movie_playlist = masvideos_add_movie_to_playlist( $playlist_id, $movie_id ); }
Security Fix
@@ -1502,10 +1502,39 @@ public static function toggle_tv_show_playlist() { ob_start(); + if ( ! is_user_logged_in() ) { + wp_send_json( + array( + 'error' => true, + 'message' => __( 'You must be logged in to modify playlists.', 'masvideos' ), + ) + ); + } + $playlist_id = absint( $_POST['playlist_id'] ); $tv_show_id = absint( $_POST['tv_show_id'] ); $delete = isset( $_POST['delete'] ) ? masvideos_string_to_bool( $_POST['delete'] ) : false; + if ( ! $playlist_id ) { + wp_send_json( + array( + 'error' => true, + 'message' => __( 'Invalid playlist.', 'masvideos' ), + ) + ); + } + + $playlist_author_id = (int) get_post_field( 'post_author', $playlist_id ); + + if ( ! $playlist_author_id || get_current_user_id() !== $playlist_author_id ) { + wp_send_json( + array( + 'error' => true, + 'message' => __( 'You are not allowed to modify this playlist.', 'masvideos' ), + ) + ); + } + if( $delete ) { $tv_show_playlist = masvideos_remove_tv_show_from_playlist( $playlist_id, $tv_show_id ); } else {
Exploit Outline
The exploit targets the AJAX handlers for playlist modification. 1. Identify a target playlist ID to modify. 2. Construct an unauthenticated POST request to `/wp-admin/admin-ajax.php` (or use the custom `?masvideos-ajax=[action]` endpoint). 3. Set the `action` parameter to one of: `masvideos_toggle_video_playlist`, `masvideos_toggle_movie_playlist`, or `masvideos_toggle_tv_show_playlist`. 4. Provide the `playlist_id` and the corresponding content ID (`video_id`, `movie_id`, or `tv_show_id`). 5. Optionally set `delete=true` to remove an item, or omit it to add an item. 6. Because versions <= 1.3.2 do not check for user authentication or verify that the current user owns the playlist, the server will process the addition or deletion on the specified playlist.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.