WP Telegram Widget and Join Link <= 2.2.13 - Reflected Cross-Site Scripting
Description
The WP Telegram Widget and Join Link plugin for WordPress is vulnerable to Reflected Cross-Site Scripting in versions up to, and including, 2.2.13 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that execute if they can successfully trick a user into performing an action such as clicking on a link.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:NTechnical Details
<=2.2.13What Changed in the Fix
Changes introduced in v2.2.14
Source Code
WordPress.org SVNinput type="hidden" name="' . $name . '" value="' . $value . '" />'; ``` If `Shared::$use_ugly_urls` is true, this is a *very* direct sink for `$username` (passed as `$value`). * `Shared::$use_ugly_urls` is a class property. Let's see if it's set anywhere. In `includes…
Show full research plan
input type="hidden" name="' . $name . '" value="' . $value . '" />';
```
If Shared::$use_ugly_urls is true, this is a very direct sink for $username (passed as $value).
* `Shared::$use_ugly_urls` is a class property. Let's see if it's set anywhere.
In `includes/Main.php` (not provided), it likely checks `get_option('permalink_structure')`.
If permalinks are default ("Plain"), `use_ugly_urls` is true.
* To be safe, I will provide a payload that covers both cases:
1. Reflection in `action="..."`
2. Reflection in `value="..."`
* Payload: `WPTelegram" onfocus="alert(1)" autofocus="true` (to trigger on the hidden input or form).
* Or simpler: `WPTelegram"><script>alert(1)</script>` to break out of the tag entirely.
* The `username` parameter.
* The endpoint is `/?wptelegram=widget&module=widget&action=view&username=...` (inferred from `get_injected_form_fields` keys).
* Wait, the `get_injected_form_fields` says:
```php
'core' => 'wptelegram',
'module' => 'widget',
Summary
The WP Telegram Widget and Join Link plugin for WordPress is vulnerable to Reflected Cross-Site Scripting via the `username` parameter in versions up to and including 2.2.13. This occurs because the parameter is reflected into hidden form fields and used in unescaped regular expressions, allowing unauthenticated attackers to execute arbitrary JavaScript in the context of a user's browser.
Vulnerable Code
// shared/embed/AjaxWidget.php:140 $pattern = '/(?<=href="\/s\/' . $username . '\?[^" ]*?(?:before|after)=\d+[^" ]*?(?=")/i'; --- // shared/embed/AjaxWidget.php:201 foreach ( $fields as $name => $value ) { $html .= '<input type="hidden" name="' . $name . '" value="' . $value . '" />'; }
Security Fix
@@ -37,7 +37,7 @@ $url = sanitize_text_field( wp_unslash( $_GET['url'] ) ); - if ( ! preg_match( '/\Ahttps:\/\/t\.me\/s\/' . $username . '.*/i', $url ) ) { + if ( ! preg_match( '/\Ahttps:\/\/t\.me\/s\/' . preg_quote( $username, '/' ) . '.*/i', $url ) ) { exit; } @@ -140,7 +140,7 @@ */ public static function replace_tg_links( $content, $username ) { - $pattern = '/(?<=href=")\/s\/' . $username . '\?[^" ]*?(?:before|after)=\d+[^" ]*?(?=")/i'; + $pattern = '/(?<=href=")\/s\/' . preg_quote( $username, '/' ) . '\?[^" ]*?(?:before|after)=\d+[^" ]*?(?=")/i'; // Replace the ajax links. $content = preg_replace_callback( @@ -170,7 +170,7 @@ $content = preg_replace_callback( $pattern, function ( $matches ) use ( $username ) { - return str_replace( $matches[1], "https://t.me/{$username}", $matches[0] ); + return str_replace( $matches[1], 'https://t.me/' . esc_attr( $username ), $matches[0] ); }, $content ); @@ -201,7 +201,7 @@ foreach ( $fields as $name => $value ) { - $html .= '<input type="hidden" name="' . $name . '" value="' . $value . '" />'; + $html .= '<input type="hidden" name="' . esc_attr( $name ) . '" value="' . esc_attr( $value ) . '" />'; } }
Exploit Outline
To exploit this vulnerability, an attacker identifies the AJAX widget endpoint, typically accessed via the query parameters `/?wptelegram=widget&module=widget&action=view`. The attacker then crafts a malicious link targeting the `username` parameter. If the site is configured with 'Plain' permalinks (which enables the `use_ugly_urls` flag), the plugin reflects the `username` directly into the `value` attribute of a hidden `<input>` field without escaping. A payload like `WPTelegram"><script>alert(document.domain)</script>` will break out of the HTML attribute and execute the script when the victim clicks the link.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.