CVE-2026-2569

Dear Flipbook <= 2.4.20 - Authenticated (Auhtor+) Stored Cross-Site Scripting via PDF Page Labels

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
2.4.27
Patched in
1d
Time to patch

Description

The Dear Flipbook – PDF Flipbook, 3D Flipbook, PDF embed, PDF viewer plugin for WordPress is vulnerable to Stored Cross-Site Scripting via PDF page labels in all versions up to, and including, 2.4.20 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with Author-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.4.20
PublishedMarch 10, 2026
Last updatedMarch 10, 2026
Affected plugin3d-flipbook-dflip-lite

What Changed in the Fix

Changes introduced in v2.4.27

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the **Dear Flipbook** plugin (<= 2.4.20). Authenticated Authors can inject arbitrary scripts through the "Page Labels" configuration of a flipbook. --- ### 1. Vulnerability Summary * **Vulnerabi…

Show full research plan

This research plan outlines the steps to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the Dear Flipbook plugin (<= 2.4.20). Authenticated Authors can inject arbitrary scripts through the "Page Labels" configuration of a flipbook.


1. Vulnerability Summary

  • Vulnerability: Stored Cross-Site Scripting (XSS)
  • Affected Parameter: PDF Page Labels (stored in _dflip_settings post meta).
  • Vulnerability Mechanism: The plugin allows users to define custom labels for PDF pages (e.g., mapping page 1 to "Cover"). These labels are stored in the database without sufficient sanitization. When the flipbook is rendered on the frontend, the dflip.js script processes these labels and inserts them into the DOM (typically in the thumbnail view or page selector) using unsafe methods like .innerHTML or jQuery's .html(), leading to script execution.
  • Auth Requirement: Authenticated user with Author role or higher (privileged enough to create/edit dflip posts).

2. Attack Vector Analysis

  • Endpoint: wp-admin/post.php
  • Action: editpost (Update a dflip custom post type).
  • Vulnerable Parameter: _dflip_settings[page_labels] (or similar field within the settings array).
  • Preconditions: The plugin must be active, and a flipbook post must be created. The XSS triggers when any user (including Administrators) views a page where that flipbook is embedded via shortcode.

3. Code Flow

  1. Input: An Author submits a dflip post update via wp-admin/post.php.
  2. Storage: The plugin captures settings and saves them into the wp_postmeta table under the key _dflip_settings.
  3. Initialization: When a page containing [dflip id="123"] is loaded, the plugin's PHP code retrieves the _dflip_settings meta for post 123.
  4. Frontend Delivery: The settings are localized or embedded into the HTML, often as a JSON string in a data attribute (e.g., <div class="dflip-container" data-options="{...}">).
  5. Execution (Sink): assets/js/dflip.js parses the data-options. When it builds the UI (like page thumbnails or the page navigation dropdown), it retrieves the pageLabels object. It uses the l.prototype.html or l.prototype.append functions (defined in dflip.js as wrappers for innerHTML or appendChild) to insert the labels into the UI, triggering the XSS.

4. Nonce Acquisition Strategy

This is an authenticated vulnerability. To update a post via HTTP, we need the _wpnonce found on the post edit screen.

  1. Login: Authenticate as an Author user.
  2. Navigate: Go to wp-admin/post-new.php?post_type=dflip to create a new flipbook or wp-admin/edit.php?post_type=dflip to find an existing one.
  3. Extract Nonce:
    Use browser_eval to extract the required nonces and post ID from the edit page:
    • Post ID: document.getElementById('post_ID').value
    • Update Nonce: document.getElementById('_wpnonce').value

5. Exploitation Strategy

The goal is to update a dflip post with a malicious page label and then view it.

Step 1: Create/Identify a Flipbook Post
Create a flipbook post using WP-CLI for efficiency.

wp post create --post_type=dflip --post_title="XSS Flipbook" --post_status=publish --post_author=AUTHOR_ID

Step 2: Inject the XSS Payload via Post Update
The _dflip_settings meta key stores a serialized array. We will update the page_labels field.

  • Payload: 1:One, 2:<img src=x onerror=alert(document.domain)>
  • HTTP Request (as Author):
    POST /wp-admin/post.php HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    action=editpost
    &post_ID=TARGET_POST_ID
    &_wpnonce=EXTRACTED_NONCE
    &_dflip_settings[page_labels]=1:One, 2:<img src=x onerror=alert(document.domain)>
    &_dflip_settings[source_type]=pdf
    

Step 3: Trigger the XSS

  1. Create a public page with the flipbook shortcode:
    wp post create --post_type=page --post_title="Flipbook Viewer" --post_status=publish --post_content='[dflip id="TARGET_POST_ID"]'
    
  2. Navigate to the URL of the newly created page.
  3. Observe the alert box when the flipbook initializes (the XSS may trigger when the thumbnail gallery is opened or the page navigation is used).

6. Test Data Setup

  1. Plugin: Install and activate 3d-flipbook-dflip-lite version 2.4.20.
  2. User: Create an Author user.
  3. Post: Create a dflip post and a standard page to host the shortcode.
  4. PDF (Optional): Some versions may require a valid PDF URL in the _dflip_settings[pdf_source] field to initialize the viewer. Use any sample PDF URL.

7. Expected Results

  • The page_labels value will be stored in wp_postmeta exactly as provided.
  • The frontend HTML will contain the payload within the data-options attribute of the flipbook container.
  • When the JavaScript processes the labels, it will inject the <img> tag into the DOM, executing the onerror script.

8. Verification Steps

  1. Database Check:
    wp post meta get TARGET_POST_ID _dflip_settings
    
    Confirm the page_labels string contains the payload.
  2. Frontend Check:
    Use http_request to fetch the viewer page and search for the payload in the raw HTML.
  3. DOM Check:
    Use browser_eval on the viewer page to check if the malicious tag exists:
    document.querySelectorAll('img[onerror]').length > 0
    

9. Alternative Approaches

  • Setting-based XSS: If page_labels is not the only vulnerable field, check other text_... fields in the defaults array found in 3d-flipbook-dflip-lite.php (e.g., text_loading, text_goto_first_page).
  • Direct Meta Injection: If the post.php update is complex, use a direct AJAX request if the plugin registers a specific save handler.
  • PDF Metadata: If the plugin extracts labels directly from a PDF file using PDF.js without escaping, the attack would involve uploading a PDF with a malicious PageLabel metadata field. However, the "Author+" requirement and "insufficient sanitization" point more towards the plugin's own settings.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Dear Flipbook plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'Page Labels' configuration field. Authenticated attackers with Author-level permissions or higher can inject malicious scripts into flipbook settings, which are later rendered on the frontend using unsafe JavaScript sinks like insertAdjacentHTML or innerHTML without proper sanitization.

Vulnerable Code

// assets/js/dflip.min.js
// The plugin uses a custom jQuery-like wrapper 'l' that uses unsafe DOM insertion methods
l.prototype.append = function(e) {
    return e && this._getElements().forEach(function(t) {
        "string" == typeof e ? t.insertAdjacentHTML("beforeend", e) : e instanceof l ? e._getElements().forEach(function(e) {
            t.contains(e) || t.appendChild(e)
        }) : e.nodeType && t.appendChild(e)
    }), this
}

---

// 3d-flipbook-dflip-lite.php
// Settings are handled as a serialized array in post meta without specific sanitization for page labels
public function init() {
    $this->defaults = array(
        'text_toggle_sound'      => __( "Turn on/off Sound", '3d-flipbook-dflip-lite' ),
        // ... other settings ...
        'text_loading'           => __( "DearFlip: Loading ", '3d-flipbook-dflip-lite' ),
        // Settings are stored in the _dflip_settings meta key
    );

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/3d-flipbook-dflip-lite/2.4.20/3d-flipbook-dflip-lite.php /home/deploy/wp-safety.org/data/plugin-versions/3d-flipbook-dflip-lite/2.4.27/3d-flipbook-dflip-lite.php
--- /home/deploy/wp-safety.org/data/plugin-versions/3d-flipbook-dflip-lite/2.4.20/3d-flipbook-dflip-lite.php	2026-03-03 12:35:50.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/3d-flipbook-dflip-lite/2.4.27/3d-flipbook-dflip-lite.php	2026-03-03 12:35:50.000000000 +0000
@@ -4,7 +4,7 @@
  * Plugin Name: 3D FlipBook : DearFlip Lite
  * Description: Realistic 3D Flip-books for WordPress <a href="https://dearflip.com/go/wp-lite-full-version" >Get Full Version Here</a><strong> NOTE : Deactivate this lite version before activating Full Version</strong>
  *
- * Version: 2.4.20
+ * Version: 2.4.27
  * Text Domain: 3d-flipbook-dflip-lite
  * Author: DearHive
  * Author URI: https://dearflip.com/go/wp-lite-author
@@ -45,7 +45,7 @@
      *
      * @var string
      */
-    public $version = '2.4.20';
+    public $version = '2.4.27';
 
     /**
      * The name of the plugin.
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/3d-flipbook-dflip-lite/2.4.20/assets/css/dflip.css /home/deploy/wp-safety.org/data/plugin-versions/3d-flipbook-dflip-lite/2.4.27/assets/css/dflip.css
--- /home/deploy/wp-safety.org/data/plugin-versions/3d-flipbook-dflip-lite/2.4.20/assets/css/dflip.css	2026-03-03 12:35:50.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/3d-flipbook-dflip-lite/2.4.27/assets/css/dflip.css	2026-03-03 12:35:50.000000000 +0000
@@ -1256,7 +1256,7 @@
 .df-reader-scroll-page-number.df-active {
   display: block;
 }
-.df-reader-scroll-page-number div {
+.df-reader-scroll-page-number .df-reader-scroll-page-number-total {
   margin-top: 6px;
   padding-top: 6px;
   border-top: 1px solid #aaa;

Exploit Outline

The exploit targets the flipbook configuration settings. An attacker with Author privileges performs the following steps: 1. Authenticates to the WordPress dashboard. 2. Navigates to the 'dFlip Books' menu and creates a new flipbook post or edits an existing one. 3. In the flipbook settings, identifies the 'Page Labels' field (which maps page numbers to custom display text). 4. Injects an XSS payload into the Page Labels field, for example: `1:First, 2:<img src=x onerror=alert(document.domain)>`. 5. Saves the post, which stores the payload in the `_dflip_settings` post meta. 6. Embeds the flipbook into a public-facing post or page using the `[dflip id="..."]` shortcode. 7. When any user views the page, the plugin's frontend JavaScript library (`dflip.js`) parses the settings and uses the malicious label string to build the UI elements (such as page selectors or thumbnails) using unsafe methods like `insertAdjacentHTML`, triggering the script execution.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.