CVE-2025-14793

DK PDF – WordPress PDF Generator <= 2.3.0 - Authenticated (Author+) Server-Side Request Forgery

mediumServer-Side Request Forgery (SSRF)
5.0
CVSS Score
5.0
CVSS Score
medium
Severity
2.3.1
Patched in
4d
Time to patch

Description

The DK PDF – WordPress PDF Generator plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 2.3.0 via the 'addContentToMpdf' function. This makes it possible for authenticated attackers, author level and above, to make web requests to arbitrary locations originating from the web application and can be used to query and modify information from internal services.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.3.0
PublishedJanuary 15, 2026
Last updatedJanuary 19, 2026
Affected plugindk-pdf

Source Code

WordPress.org SVN
Research Plan
Unverified

## 1. Vulnerability Summary The **DK PDF – WordPress PDF Generator** plugin (<= 2.3.0) is vulnerable to **Authenticated Server-Side Request Forgery (SSRF)**. The vulnerability exists in the `addContentToMpdf` function located in `includes/class-dk-pdf-functions.php`. The plugin uses the **mPDF** l…

Show full research plan

1. Vulnerability Summary

The DK PDF – WordPress PDF Generator plugin (<= 2.3.0) is vulnerable to Authenticated Server-Side Request Forgery (SSRF). The vulnerability exists in the addContentToMpdf function located in includes/class-dk-pdf-functions.php.

The plugin uses the mPDF library to generate PDF files from WordPress posts. When a PDF is generated, the plugin processes the post's content and attempts to resolve or fetch remote resources (like images) to include them in the PDF. Because the plugin does not properly validate or sanitize these resource URLs, an authenticated attacker with Author permissions (who can create and edit posts) can embed malicious URLs (e.g., targeting internal metadata services or internal network IPs) within a post. When the PDF generation is triggered for that post, the server makes a request to the attacker-specified location.

2. Attack Vector Analysis

  • Endpoint: Frontend post URL with specific query parameters or the PDF export trigger.
  • Trigger Parameter: dk_pdf_to_pdf=1 (Query string) and pdf_id (Post ID).
  • Vulnerable Function: addContentToMpdf in includes/class-dk-pdf-functions.php.
  • Authentication: Authenticated, Author level or above (capability edit_posts).
  • Payload Location: The post_content field of a WordPress post.
  • Vector: HTML <img> tags or CSS @import rules containing internal/restricted URLs.

3. Code Flow

  1. The plugin registers a template_redirect hook in includes/class-dk-pdf.php that points to dk_pdf_template_redirect.
  2. dk_pdf_template_redirect checks if the dk_pdf_to_pdf parameter is set in the $_GET array.
  3. If set, it retrieves the pdf_id from $_GET['pdf_id'].
  4. It instantiates the DK_PDF_Functions class and calls methods to set up the mPDF object.
  5. The flow reaches DK_PDF_Functions::addContentToMpdf( $mpdf, $post_id ).
  6. Inside addContentToMpdf, the plugin retrieves the post content using get_post_field( 'post_content', $post_id ).
  7. The plugin (or the mPDF library it invokes) parses the HTML content.
  8. To ensure images are rendered in the PDF, the plugin or mPDF's configuration attempts to fetch external assets using wp_remote_get() or PHP's stream wrappers.
  9. Sink: A wp_remote_get() call is made to a URL sourced directly from an <img> tag's src attribute within the post content without validation against internal IP ranges or restricted protocols.

4. Nonce Acquisition Strategy

The PDF generation trigger in DK PDF is typically designed as a "Download PDF" button available on the frontend or post editor.

  • Frontend Trigger: The URL /?dk_pdf_to_pdf=1&pdf_id=[ID] is often accessible without a specific DK PDF-specific nonce because it acts as a public-facing conversion tool for authorized post types.
  • Bypass Check: If the plugin uses check_admin_referer or wp_verify_nonce, it is likely only on the admin settings page. The conversion logic in template_redirect usually relies on the user's capability to read the post.
  • Verification: If a nonce is required, it is typically localized in the dkpdf_ajax object.
    1. Create a post as the Author.
    2. Navigate to the post's view page.
    3. Use browser_eval to check for any localized nonces: browser_eval("window.dkpdf_ajax?.nonce").

Note: For this vulnerability, the primary "nonce" is simply the session cookie of the Author user and the knowledge of a valid pdf_id they have permission to edit/view.

5. Exploitation Strategy

Step 1: Authentication

Authenticate as a user with the Author role.

Step 2: Create a Malicious Post

Create a new post containing an <img> tag pointing to an internal service (e.g., AWS Metadata endpoint or a local port).

  • Request: POST /wp-admin/post.php
  • Parameters:
    • action: editpost
    • post_type: post
    • post_title: SSRF Test
    • content: <img src="http://169.254.169.254/latest/meta-data/">
    • publish: Publish

Step 3: Identify Post ID

Capture the post_ID from the response or the URL after the post is created.

Step 4: Trigger the SSRF

Trigger the PDF generation for the created post.

  • Request: GET /?dk_pdf_to_pdf=1&pdf_id=[POST_ID]
  • Headers: Include the Author's session cookies.
  • Expected Response: The server will return a PDF file (Content-Type: application/pdf).

Step 5: Observe Request

During the generation of the PDF, the server will attempt to fetch the image from http://169.254.169.254/latest/meta-data/. If using a collaborator/listener, observe the incoming request from the WordPress server's IP.

6. Test Data Setup

  1. User: Create a user attacker_author with the author role.
  2. Plugin Config: Ensure "DK PDF" is enabled for the post post type in Settings > DK PDF > General. (This is usually the default).
  3. Listener: Have an internal or external listener ready (e.g., http://127.0.0.1:8080/ssrf_callback if testing internal access).

7. Expected Results

  • The http_request to /?dk_pdf_to_pdf=1&pdf_id=[ID] should trigger an outbound HTTP request from the WordPress server.
  • If the internal service is active and returns data, mPDF may attempt to embed the raw response into the PDF (often resulting in a broken image in the PDF, but confirming the request was made).
  • The logs of the target internal service will show a request originating from the WordPress server's IP with a User-Agent identifying as WordPress/X.X or mPDF.

8. Verification Steps

  1. Check Outbound Traffic: Use a tool like tcpdump or an HTTP listener to confirm the server reached out to the target IP.
  2. WP-CLI Check: Verify the post content exists and contains the payload:
    wp post get [POST_ID] --field=post_content
  3. PDF Content: Check the generated PDF for any error messages related to the image fetch which might leak internal information:
    strings output.pdf | grep -i "http"

9. Alternative Approaches

  • CSS SSRF: Instead of an <img> tag, use a <style> block with @import 'http://internal-service';. mPDF processes CSS and will attempt to fetch the imported stylesheet.
  • Background Images: Use <div style="background-image: url('http://internal-service');">.
  • Gopher Protocol: If the underlying PHP curl or wrappers allow it, attempt gopher:// to interact with internal services like Redis or Memcached.
  • Metadata Templates: If the Author cannot edit posts but can edit "DK PDF Templates" (Custom Post Type dkpdf-template), apply the same payload to the template content.

Check if your site is affected.

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