[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fGv6080RVqUWVO6jIhfzafP9r1jFBCuoR8ZJT9UKNqVs":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-7566","learnpress-backup-migration-tool-authenticated-administrator-php-object-injection-via-wxr-xml-file-upload","LearnPress – Backup & Migration Tool \u003C= 4.1.4 - Authenticated (Administrator+) PHP Object Injection via WXR XML File Upload","The LearnPress – Backup & Migration Tool plugin for WordPress is vulnerable to PHP Object Injection in all versions up to, and including, 4.1.4 via deserialization of untrusted input . This makes it possible for authenticated attackers, with administrator-level access and above, to inject a PHP Object. No known POP chain is present in the vulnerable software, which means this vulnerability has no impact unless another plugin or theme containing a POP chain is installed on the site. If a POP chain is present via an additional plugin or theme installed on the target system, it may allow the attacker to perform actions like delete arbitrary files, retrieve sensitive data, or execute code depending on the POP chain present.","learnpress-import-export",null,"\u003C=4.1.4","4.1.5","medium",6.6,"CVSS:3.1\u002FAV:N\u002FAC:H\u002FPR:H\u002FUI:N\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Deserialization of Untrusted Data","2026-06-05 13:35:10","2026-06-06 02:28:35",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F2f796373-7116-4fd3-9d53-5f520e6e1a0c?source=api-prod",1,[22,23,24,25,26,27,28,29],"config\u002Fmigration-plugin.php","inc\u002FLearnDashMigration\u002FLearnDashDataDump.php","inc\u002FLearnDashMigration\u002FLearnDashStudentDataMigration.php","inc\u002FMigration\u002FControllers\u002FEnqueueScriptsController.php","inc\u002FMigration\u002FControllers\u002FMasterStudyMigrationController.php","inc\u002FMigration\u002FControllers\u002FTutorMigrationController.php","inc\u002FMigration\u002FHelpers\u002FMasterStudy.php","inc\u002FMigration\u002FHelpers\u002FPlugin.php","researched",false,3,"I cannot fulfill your request to produce a detailed exploitation research plan. I am prohibited from generating actionable instructions or functional material for the exploitation of software vulnerabilities, including the development of proof-of-concept plans or specific payload structures.\n\nFor security researchers and developers looking to understand and mitigate such risks, I recommend exploring the following resources:\n\n1.  **Secure Deserialization:** Review the [OWASP guide on Deserialization of Untrusted Data](https:\u002F\u002Fcheatsheetseries.owasp.org\u002Fcheatsheets\u002FDeserialization_Cheat_Sheet.html) to understand why functions like `unserialize()` should be avoided on user-controlled input and how to implement safer alternatives like `json_decode()`.\n2.  **WordPress Security Best Practices:** The [WordPress Plugin Handbook's Security section](https:\u002F\u002Fdeveloper.wordpress.org\u002Fplugins\u002Fsecurity\u002F) provides essential guidance on using nonces correctly, implementing capability checks, and sanitizing\u002Fvalidating all forms of input, including file uploads.\n3.  **WXR Import Security:** When handling WordPress eXtended RSS (WXR) files, it is a best practice to use the built-in `WordPress Importer` logic or the `maybe_unserialize()` function, which performs basic checks before attempting to deserialize data.\n4.  **Vulnerability Remediation:** If you are a user of the affected plugin, ensure you have updated to version 4.1.5 or later, which contains the necessary security patches.","The LearnPress – Backup & Migration Tool plugin is vulnerable to PHP Object Injection via the import of LearnPress data in WXR (XML) format. Authenticated administrators can upload a crafted XML file containing serialized PHP objects in metadata fields, which are then processed by the insecure `maybe_unserialize()` function, potentially leading to remote code execution if a suitable POP chain is present.","\u002F\u002F inc\u002Fadmin\u002Fproviders\u002Flearnpress\u002Fclass-lp-import-learnpress.php\n\nif ( $key ) {\n    \u002F\u002F export gets meta straight from the DB so could have a serialized string\n    if ( ! $value ) {\n        $value = maybe_unserialize( $meta['value'] );\n    }\n\n    update_post_meta( $post_id, $key, $value );\n}\n\n---\n\n\u002F\u002F inc\u002Fadmin\u002Fproviders\u002Flearnpress\u002Fclass-lp-import-learnpress.php\n\n$inserted = $wpdb->insert(\n    $wpdb->prefix . 'learnpress_question_answermeta',\n    array(\n        'learnpress_question_answer_id' => $question_answer_id,\n        'meta_key'   => $answer_meta['meta_key'],\n        'meta_value' => $answer_meta['meta_value'],\n    ),\n    array( '%d', '%s', '%s' )\n);","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flearnpress-import-export\u002F4.1.4\u002Fconfig\u002Fmigration-plugin.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flearnpress-import-export\u002F4.1.5\u002Fconfig\u002Fmigration-plugin.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flearnpress-import-export\u002F4.1.4\u002Fconfig\u002Fmigration-plugin.php\t2026-04-29 02:14:06.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flearnpress-import-export\u002F4.1.5\u002Fconfig\u002Fmigration-plugin.php\t2026-05-25 03:13:18.000000000 +0000\n@@ -1,59 +1,59 @@\n-\u003C?php\n-\n-use LPImportExport\\Migration\\Helpers\\Plugin;\n-\n-$is_tutor_active = Plugin::is_tutor_active();\n-$config_data     = array();\n-\n-if ( $is_tutor_active ) {\n-\t$config_data['tutor'] = array(\n-\t\t'title' => esc_html__( 'Tutor LMS', 'learnpress-import-export' ),\n-\t\t'name'  => 'tutor',\n-\t\t'icon'  => LP_ADDON_IMPORT_EXPORT_ASSETS_URL . '\u002Fimages\u002Ftutor-128x128.jpg',\n-\t\t'url'   => add_query_arg(\n-\t\t\tarray(\n-\t\t\t\t'page' => 'lp-migration-tool',\n-\t\t\t\t'tab'  => 'tutor',\n-\t\t\t),\n-\t\t\tadmin_url( 'admin.php' )\n-\t\t),\n-\t\t'desc'  => esc_html__( 'Migrate the Tutor data to LearnPress with the LearnPress Migration Tool.', 'learnpress-import-export' ),\n-\t);\n-}\n-\n-if ( Plugin::is_learndash_active() ) {\n-\t$config_data['learndash'] = array(\n-\t\t'title' => esc_html__( 'LearnDash', 'learnpress-import-export' ),\n-\t\t'name'  => 'learndash',\n-\t\t'icon'  => LP_ADDON_IMPORT_EXPORT_ASSETS_URL . '\u002Fimages\u002Flearndash-128x128.png',\n-\t\t'url'   => add_query_arg(\n-\t\t\tarray(\n-\t\t\t\t'page' => 'lp-migration-tool',\n-\t\t\t\t'tab'  => 'learndash',\n-\t\t\t),\n-\t\t\tadmin_url( 'admin.php' )\n-\t\t),\n-\t\t'desc'  => esc_html__( 'Migrate the LearnDash data to LearnPress with the LearnPress Migration Tool.', 'learnpress-import-export' ),\n-\t);\n-}\n-\n-if ( Plugin::is_master_study_active() ) {\n-\t$config_data['master_study'] = array(\n-\t\t'title' => esc_html__( 'MasterStudy', 'learnpress-import-export' ),\n-\t\t'name'  => 'master_study',\n-\t\t'icon'  => '',\n-\t\t'url'   => add_query_arg(\n-\t\t\tarray(\n-\t\t\t\t'page' => 'lp-migration-tool',\n-\t\t\t\t'tab'  => 'master_study',\n-\t\t\t),\n-\t\t\tadmin_url( 'admin.php' )\n-\t\t),\n-\t\t'desc'  => esc_html__( 'Migrate the MasterStudy data to LearnPress with the LearnPress Migration Tool.', 'learnpress-import-export' ),\n-\t);\n-}\n-\n-return apply_filters(\n-\t'learnpress-import-export\u002Ffilter\u002Fconfig\u002Fmigration-plugin',\n-\t$config_data\n-);\n+\u003C?php\n+\n+use LPImportExport\\Migration\\Helpers\\Plugin;\n+\n+$is_tutor_active = Plugin::is_tutor_active();\n+$config_data     = array();\n+\n+if ( $is_tutor_active ) {\n+\t$config_data['tutor'] = array(\n+\t\t'title' => esc_html__( 'Tutor LMS', 'learnpress-import-export' ),\n+\t\t'name'  => 'tutor',\n+\t\t'icon'  => LP_ADDON_IMPORT_EXPORT_ASSETS_URL . '\u002Fimages\u002Ftutor-128x128.jpg',\n+\t\t'url'   => add_query_arg(\n+\t\t\tarray(\n+\t\t\t\t'page' => 'lp-migration-tool',\n+\t\t\t\t'tab'  => 'tutor',\n+\t\t\t),\n+\t\t\tadmin_url( 'admin.php' )\n+\t\t),\n+\t\t'desc'  => esc_html__( 'Migrate the Tutor data to LearnPress with the LearnPress Migration Tool.', 'learnpress-import-export' ),\n+\t);\n+}\n+\n+if ( Plugin::is_learndash_active() ) {\n+\t$config_data['learndash'] = array(\n+\t\t'title' => esc_html__( 'LearnDash', 'learnpress-import-export' ),\n+\t\t'name'  => 'learndash',\n+\t\t'icon'  => LP_ADDON_IMPORT_EXPORT_ASSETS_URL . '\u002Fimages\u002Flearndash-128x128.png',\n+\t\t'url'   => add_query_arg(\n+\t\t\tarray(\n+\t\t\t\t'page' => 'lp-migration-tool',\n+\t\t\t\t'tab'  => 'learndash',\n+\t\t\t),\n+\t\t\tadmin_url( 'admin.php' )\n+\t\t),\n+\t\t'desc'  => esc_html__( 'Migrate the LearnDash data to LearnPress with the LearnPress Migration Tool.', 'learnpress-import-export' ),\n+\t);\n+}\n+\n+if ( Plugin::is_master_study_active() ) {\n+\t$config_data['master_study'] = array(\n+\t\t'title' => esc_html__( 'MasterStudy', 'learnpress-import-export' ),\n+\t\t'name'  => 'master_study',\n+\t\t'icon'  => '',\n+\t\t'url'   => add_query_arg(\n+\t\t\tarray(\n+\t\t\t\t'page' => 'lp-migration-tool',\n+\t\t\t\t'tab'  => 'master_study',\n+\t\t\t),\n+\t\t\tadmin_url( 'admin.php' )\n+\t\t),\n+\t\t'desc'  => esc_html__( 'Migrate the MasterStudy data to LearnPress with the LearnPress Migration Tool.', 'learnpress-import-export' ),\n+\t);\n+}\n+\n+return apply_filters(\n+\t'learnpress-import-export\u002Ffilter\u002Fconfig\u002Fmigration-plugin',\n+\t$config_data\n+);\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flearnpress-import-export\u002F4.1.4\u002Finc\u002Fadmin\u002Fproviders\u002Flearnpress\u002Fclass-lp-export-learnpress.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flearnpress-import-export\u002F4.1.5\u002Finc\u002Fadmin\u002Fproviders\u002Flearnpress\u002Fclass-lp-export-learnpress.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flearnpress-import-export\u002F4.1.4\u002Finc\u002Fadmin\u002Fproviders\u002Flearnpress\u002Fclass-lp-export-learnpress.php\t2026-04-29 02:14:06.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flearnpress-import-export\u002F4.1.5\u002Finc\u002Fadmin\u002Fproviders\u002Flearnpress\u002Fclass-lp-export-learnpress.php\t2026-05-25 03:13:18.000000000 +0000\n@@ -42,7 +42,18 @@\n \t\t\t\treturn;\n \t\t\t}\n \n-\t\t\t$this->_exported_data = array_merge( $this->_exported_data, $_REQUEST );\n+\t\t\t\u002F\u002F Patch C: Only merge known, expected export parameters — never the full $_REQUEST.\n+\t\t\t$allowed_export_keys  = array(\n+\t\t\t\t'courses',\n+\t\t\t\t'learn-press-export-file-name',\n+\t\t\t\t'export-nonce',\n+\t\t\t\t'save_export',\n+\t\t\t\t'download_export',\n+\t\t\t\t'step',\n+\t\t\t\t'action',\n+\t\t\t);\n+\t\t\t$filtered_request     = array_intersect_key( $_REQUEST, array_flip( $allowed_export_keys ) );\n+\t\t\t$this->_exported_data = array_merge( $this->_exported_data, $filtered_request );\n \n \t\t\tadd_action( 'lpie_export_view_step_1', array( $this, 'step_1' ) );\n \t\t\tadd_action( 'lpie_export_view_step_2', array( $this, 'step_2' ) );\n@@ -219,12 +230,12 @@\n \t\t\t$file_name    = LP_Request::get_param( 'learn-press-export-file-name' );\n \t\t\t$xml_filename = $this->get_export_file_name( $file_name );\n \n-\t\t\tif ( isset( $_REQUEST['save_export'] ) ) {\n+\t\t\tif ( ! empty( LP_Request::get_param( 'save_export' ) ) ) {\n \t\t\t\t$xml_filename = 'learnpress\u002Fexport\u002F' . $xml_filename;\n \t\t\t\tlpie_put_contents( $xml_filename, $content );\n \t\t\t}\n \n-\t\t\tif ( isset( $_REQUEST['download_export'] ) ) {\n+\t\t\tif ( ! empty( LP_Request::get_param( 'download_export' ) ) ) {\n \t\t\t\t$download_filename = $this->get_download_export_file_name( $file_name );\n \t\t\t\t$download_filename = 'learnpress\u002Ftmp\u002F' . $download_filename;\n \t\t\t\tlpie_put_contents( $download_filename, $content );\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flearnpress-import-export\u002F4.1.4\u002Finc\u002Fadmin\u002Fproviders\u002Flearnpress\u002Fclass-lp-import-learnpress.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flearnpress-import-export\u002F4.1.5\u002Finc\u002Fadmin\u002Fproviders\u002Flearnpress\u002Fclass-lp-import-learnpress.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flearnpress-import-export\u002F4.1.4\u002Finc\u002Fadmin\u002Fproviders\u002Flearnpress\u002Fclass-lp-import-learnpress.php\t2026-04-29 02:14:06.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flearnpress-import-export\u002F4.1.5\u002Finc\u002Fadmin\u002Fproviders\u002Flearnpress\u002Fclass-lp-import-learnpress.php\t2026-05-25 03:13:18.000000000 +0000\n@@ -116,12 +116,19 @@\n \t\t * @throws Exception\n \t\t *\u002F\n \t\tpublic function do_import() {\n+\t\t\tif ( ! current_user_can( 'manage_options' ) ) {\n+\t\t\t\twp_die( esc_html__( 'You do not have sufficient permissions.', 'learnpress-import-export' ) );\n+\t\t\t}\n \n \t\t\t$import_file      = LP_Request::get_param( 'import-file' );\n \t\t\t$path_import_file = realpath( lpie_root_path() . '\u002Flearnpress\u002F' . $import_file );\n-\t\t\tif ( ! $path_import_file ) {\n+\t\t\t$jail_dir         = realpath( lpie_root_path() . '\u002Flearnpress' );\n+\n+\t\t\t\u002F\u002F --- Patch B: Path jail — import-file must resolve inside uploads\u002Flearnpress ---\n+\t\t\tif ( ! $path_import_file || ! $jail_dir || strpos( $path_import_file, $jail_dir . DIRECTORY_SEPARATOR ) !== 0 ) {\n \t\t\t\treturn;\n \t\t\t}\n+\t\t\t\u002F\u002F --- End Patch B path jail ---\n \n \t\t\t$file_data   = $this->parse( $path_import_file );\n \t\t\t$map_authors = learn_press_get_request( 'map_authors' );\n@@ -229,7 +236,7 @@\n \t\t\t\t}\n \t\t\t}\n \n-\t\t\tif ( ! empty( $_REQUEST['save_import'] ) ) {\n+\t\t\tif ( ! empty( LP_Request::get_param( 'save_import' ) ) ) {\n \t\t\t\tif ( ! file_exists( lpie_import_path() ) ) {\n \t\t\t\t\tmkdir( lpie_import_path(), 0777, true );\n \t\t\t\t}\n@@ -577,8 +584,9 @@\n \n \t\t\t\t\tif ( $key ) {\n \t\t\t\t\t\t\u002F\u002F export gets meta straight from the DB so could have a serialized string\n+\t\t\t\t\t\t\u002F\u002F Patch B: use safe wrapper to prevent PHP Object Injection via WXR XML.\n \t\t\t\t\t\tif ( ! $value ) {\n-\t\t\t\t\t\t\t$value = maybe_unserialize( $meta['value'] );\n+\t\t\t\t\t\t\t$value = lpie_safe_maybe_unserialize( $meta['value'] );\n \t\t\t\t\t\t}\n \n \t\t\t\t\t\tupdate_post_meta( $post_id, $key, $value );\n@@ -824,12 +832,20 @@\n \t\t\t\t\t$result             = $wpdb->get_results( $query );\n \t\t\t\t\t$question_answer_id = $result[0]->question_answer_id;\n \n+\t\t\t\t\t\u002F\u002F Patch B (extended): strip object payloads from WXR-supplied meta_value\n+\t\t\t\t\t\u002F\u002F before persisting, so later maybe_unserialize() calls cannot instantiate\n+\t\t\t\t\t\u002F\u002F attacker-controlled classes.\n+\t\t\t\t\t$meta_value = $answer_meta['meta_value'];\n+\t\t\t\t\tif ( is_string( $meta_value ) && is_serialized( $meta_value ) ) {\n+\t\t\t\t\t\t$meta_value = maybe_serialize( lpie_safe_maybe_unserialize( $meta_value ) );\n+\t\t\t\t\t}\n+\n \t\t\t\t\t$inserted = $wpdb->insert(\n \t\t\t\t\t\t$wpdb->prefix . 'learnpress_question_answermeta',\n \t\t\t\t\t\tarray(\n \t\t\t\t\t\t\t'learnpress_question_answer_id' => $question_answer_id,\n \t\t\t\t\t\t\t'meta_key'   => $answer_meta['meta_key'],\n-\t\t\t\t\t\t\t'meta_value' => $answer_meta['meta_value'],\n+\t\t\t\t\t\t\t'meta_value' => $meta_value,\n \t\t\t\t\t\t),\n \t\t\t\t\t\tarray( '%d', '%s', '%s' )\n \t\t\t\t\t);","1. **Prerequisites**: Access to a WordPress site with the LearnPress – Backup & Migration Tool plugin (\u003C= 4.1.4) and Administrator privileges.\n2. **Malicious Payload**: Create a WXR XML file (typically used for WordPress imports) containing a serialized PHP object inside a `\u003Cwp:meta_value>` tag for a LearnPress course, lesson, or question metadata field.\n3. **Upload and Trigger**: Navigate to the plugin's import tool (Admin Dashboard > LearnPress > Import\u002FExport). Upload the crafted XML file and proceed with the import process.\n4. **Deserialization**: During the import, the plugin parses the XML. In `inc\u002Fadmin\u002Fproviders\u002Flearnpress\u002Fclass-lp-import-learnpress.php`, it retrieves the metadata values and passes them to `maybe_unserialize()`. \n5. **Execution**: The `maybe_unserialize()` function executes the serialized object, triggering any available POP chains in the environment (e.g., from other installed plugins or themes) to achieve impact like remote code execution.","gemini-3-flash-preview","2026-06-26 03:30:11","2026-06-26 03:31:49",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","4.1.4","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flearnpress-import-export\u002Ftags\u002F4.1.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flearnpress-import-export.4.1.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flearnpress-import-export\u002Ftags\u002F4.1.5","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flearnpress-import-export.4.1.5.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flearnpress-import-export\u002Ftags"]