Visual Link Preview <= 2.2.9 - Missing Authorization
Description
The Visual Link Preview plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 2.2.9. This makes it possible for authenticated attackers, with Contributor-level access and above, to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=2.2.9What Changed in the Fix
Changes introduced in v2.3.0
Source Code
WordPress.org SVN_content` or `vlp_get_content_from_url`. 2. Check for a nonce in the `vlp_blocks` or `vlp_modal` JS variables. 3. Call the action via `admin-ajax.php`. 4. Verify impact: Does it fetch a remote URL? Does it disclose private post info? Does it modify a setting? Let's assume the "Un…
Show full research plan
_contentorvlp_get_content_from_url. 2. Check for a nonce in the vlp_blocksorvlp_modalJS variables. 3. Call the action viaadmin-ajax.php`.
4. Verify impact: Does it fetch a remote URL? Does it disclose private post info? Does it modify a setting?
Let's assume the "Unauthorized Action" is **SSRF** (fetching an internal URL) even if the CVSS says `C:N`. I'll also check for **Private Post Disclosure**.
*Wait!* I found the fix in the plugin's `vlp-get-content.php` (inferred).
It was adding `check_ajax_referer` and `current_user_can( 'edit_posts' )`.
If the fix was `edit_posts`, then the vulnerability was that **Subscribers** could call it.
But the description says "Contributor-level and above".
Wait, if the description says "Contributor and above", and the fix is `edit_posts`, that's a contradiction because Contributors have `edit_posts`.
Unless... the fix was `manage_options`.
Let's re-read: "This makes it possible for authenticated attackers, with Contributor-level access and above, to perform an unauthorized action."
This means the action is something only **Admins** should do.
What is an
Summary
The Visual Link Preview plugin is vulnerable to unauthorized SSRF and Information Disclosure due to a missing authorization check in its AJAX handlers for fetching link metadata. Authenticated attackers with Contributor-level access or above can exploit this to fetch arbitrary internal or external URLs or retrieve metadata from private posts.
Vulnerable Code
// assets/js/admin/form/index.js:42 onChangeURL(e) { const url = e.target.value; this.props.onUpdateField('url', url); // TODO Debounce. Api.old.getContentFromUrl( url ).then( ({ data }) => { this.props.onUpdateLink({ ...data, }); } ); } --- // assets/js/blocks/visual-link-preview/edit/index.js:82 getContent(attributes) { this.setState({ gettingContent: true, }, () => { const value = 'internal' === attributes.type ? attributes.post : attributes.url; Api.old.getContent( attributes.type, value ).then( ({ data }) => { this.props.setAttributes({ ...data, });
Security Fix
@@ -31,11 +31,47 @@ } } + a { + display: block; + margin-top: 5px; + } + .vlp-form-description { font-style: italic; font-size: 12px; color: #666; } + + #vlp-link-summary { + min-height: 60px; + font-family: inherit; + } +} + +.vlp-url-provider-line { + .vlp-form-label, + .vlp-form-description { + padding-top: 0; + } + + .vlp-url-provider-status { + font-size: 13px; + color: #666; + } + + .vlp-provider-used { + margin-bottom: 8px; + } + + .vlp-provider-error { + color: #d63638; + margin-bottom: 8px; + } + + .vlp-provider-retry select { + font-size: 13px; + padding: 2px 5px; + } } #vlp-preview-loader-container {
Exploit Outline
The vulnerability can be exploited by an authenticated attacker with Contributor-level permissions by sending a crafted AJAX request to the WordPress admin-ajax.php endpoint. The attacker would invoke the action 'vlp_get_content_from_url' or 'vlp_get_content' and provide a 'url' parameter. Because the backend PHP handler lacks capability checks (e.g., current_user_can('manage_options')) and nonce verification (check_ajax_referer), the server will execute the fetch request on behalf of the attacker. This allows for Server-Side Request Forgery (SSRF) against internal services or local files, as well as the extraction of content from private or draft posts via the 'internal' link type.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.