CVE-2023-37901 (published 2023-07-21T19:15Z)

Indico is an open source a general-purpose, web based event management tool. There is a Cross-Site-Scripting vulnerability in confirmation prompts commonly used when deleting content from Indico. Exploitation requires someone with at least submission privileges (such as a speaker) and then someone else to attempt to delete this content. Considering that event organizers may want to delete suspicious-looking content when spotting it, there is a non-negligible risk of such an attack to succeed. The risk of this could be further increased when combined with some some social engineering pointing the victim towards this content. Users need to update to Indico 3.2.6 as soon as possible. See the docs for instructions on how to update. Users who cannot upgrade should only let trustworthy users manage categories, create events or upload materials ("submission" privileges on a contribution/event). This should already be the case in a properly-configured setup when it comes to category/event management. Note that a conference doing a Call for Abstracts actively invites external speakers (who the organizers may not know and thus cannot fully trust) to submit content, hence the need to update to a a fixed version ASAP in particular when using such workflows.

CVSS v3 base score: 5.4, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N)

Weakness information:
cwe_id: CWE-79
cwe_name: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
extended_description: 
            Cross-site scripting (XSS) vulnerabilities occur when:
            
               Untrusted data enters a web application, typically from a web request.
               The web application dynamically generates a web page that contains this untrusted data.
               During page generation, the application does not prevent the data from containing content that is executable by a web browser, such as JavaScript, HTML tags, HTML attributes, mouse events, Flash, ActiveX, etc.
               A victim visits the generated web page through a web browser, which contains malicious script that was injected using the untrusted data.
               Since the script comes from a web page that was sent by the web server, the victim's web browser executes the malicious script in the context of the web server's domain.
               This effectively violates the intention of the web browser's same-origin policy, which states that scripts in one domain should not be able to access resources or run code in a different domain.
            
            There are three main kinds of XSS:
            
               
                  Type 1: Reflected XSS (or Non-Persistent) - 
         			The server reads data directly from the HTTP request and reflects it back in the HTTP response. Reflected XSS exploits occur when an attacker causes a victim to supply dangerous content to a vulnerable web application, which is then reflected back to the victim and executed by the web browser. The most common mechanism for delivering malicious content is to include it as a parameter in a URL that is posted publicly or e-mailed directly to the victim. URLs constructed in this manner constitute the core of many phishing schemes, whereby an attacker convinces a victim to visit a URL that refers to a vulnerable site. After the site reflects the attacker's content back to the victim, the content is executed by the victim's browser.
               
                  Type 2: Stored XSS (or Persistent) - 
               The application stores dangerous data in a database, message forum, visitor log, or other trusted data store. At a later time, the dangerous data is subsequently read back into the application and included in dynamic content. From an attacker's perspective, the optimal place to inject malicious content is in an area that is displayed to either many users or particularly interesting users. Interesting users typically have elevated privileges in the application or interact with sensitive data that is valuable to the attacker. If one of these users executes malicious content, the attacker may be able to perform privileged operations on behalf of the user or gain access to sensitive data belonging to the user. For example, the attacker might inject XSS into a log message, which might not be handled properly when an administrator views the logs.
            
               
                  Type 0: DOM-Based XSS - 
               In DOM-based XSS, the client performs the injection of XSS into the page; in the other types, the server performs the injection. DOM-based XSS generally involves server-controlled, trusted script that is sent to the client, such as Javascript that performs sanity checks on a form before the user submits it. If the server-supplied script processes user-supplied data and then injects it back into the web page (such as with dynamic HTML), then DOM-based XSS is possible.
            
            
            Once the malicious script is injected, the attacker can perform a variety of malicious activities. The attacker could transfer private information, such as cookies that may include session information, from the victim's machine to the attacker. The attacker could send malicious requests to a web site on behalf of the victim, which could be especially dangerous to the site if the victim has administrator privileges to manage that site. Phishing attacks could be used to emulate trusted web sites and trick the victim into entering a password, allowing the attacker to compromise the victim's account on that web site. Finally, the script could exploit a vulnerability in the web browser itself possibly taking over the victim's machine, sometimes referred to as "drive-by hacking."
            In many cases, the attack can be launched without the victim even being aware of it. Even with careful users, attackers frequently use a variety of methods to encode the malicious portion of the attack, such as URL encoding or Unicode, so the request looks less suspicious.
         
         

Fix information:
repo_url: https://github.com/indico/indico
commit_details: repo_url: https://github.com/indico/indico
author: Adrian Moennich
author_date: 2023-07-18 22:47:26+02:00
msg: Fix XSS in confirmation prompts

Also update some confirmation prompts to not use HTML in the message as
this is no longer supported.
repository: repo_url: https://github.com/indico/indico
repo_name: indico/indico
description: Indico - A feature-rich event management system, made @ CERN, the place where the Web was born.
repo_language: Python
owner: indico
file_changes: filename: CHANGES.rst
change_type: ModificationType.MODIFY
diff: @@ -7,6 +7,17 @@ Version 3.2.6
 
 *Unreleased*
 
+Security fixes
+^^^^^^^^^^^^^^
+
+- Fix an XSS vulnerability in various confirmation prompts commonly used when deleting
+  things. Exploitation requires someone with at least submission privileges (such as a
+  speaker) and then rely on someone else to attempt to delete this content. However,
+  considering that event organizers may indeed delete suspicious-looking content when
+  encountering it, there is a non-negligible risk of such an attack to succeed. Because
+  of this it is strongly recommended to upgrade as soon as possible (:pr:`5862`,
+  :cve:`CVE-2023-37901`)
+
 Internationalization
 ^^^^^^^^^^^^^^^^^^^^
 

programming_language: Markdown
filename: _attachments.html
change_type: ModificationType.MODIFY
diff: @@ -54,7 +54,7 @@
                    data-title="{% trans name=attachment.title %}Remove {{ name }}?{% endtrans %}"
                    title="{% trans %}Remove{% endtrans %}"
                    data-confirm="{% trans name=attachment.title -%}
-                       Are you sure you want to remove &quot;{{ name }}&quot;?<br>
+                       Are you sure you want to remove &quot;{{ name }}&quot;?
                        This will remove the attachment permanently.
                        {%- endtrans %}">
                 </a>
@@ -94,7 +94,7 @@
                    data-title="{% trans name=folder.title %}Remove {{ name }}?{% endtrans %}"
                    title="{% trans %}Remove{% endtrans %}"
                    data-confirm="{% trans name=folder.title -%}
-                       Are you sure you want to remove &quot;{{ name }}&quot;?<br>
+                       Are you sure you want to remove &quot;{{ name }}&quot;?
                        This will remove the folder and its contents permanently.
                    {%- endtrans %}">
                 </a>

programming_language: HTML
filename: base.html
change_type: ModificationType.MODIFY
diff: @@ -2,7 +2,9 @@
 
 {% macro delete_category_button(category, classes="i-button") %}
     {% set confirmation_message -%}
-        {% trans category=category.title %}Do you really want to delete the category "{{ category }}"?{% endtrans %}
+        {% trans category=category.title %}
+            Do you really want to delete the category &quot;{{ category }}&quot;?
+        {% endtrans %}
     {%- endset %}
     {% if category.is_empty %}
         {% set tooltip -%}
@@ -16,7 +18,7 @@
     {% endif %}
     <a class="{{ classes }} icon-remove js-delete-category"
        title="{{ tooltip|forceescape }}"
-       data-confirm="{{ confirmation_message|forceescape }}"
+       data-confirm="{{ confirmation_message }}"
        data-title="{% trans %}Delete category{% endtrans %}"
        data-href="{{ url_for('categories.delete', category) }}"
        data-method="POST"></a>

programming_language: HTML
filename: public.html
change_type: ModificationType.MODIFY
diff: @@ -19,12 +19,10 @@
                         {% set message %}
                             {% trans %}Do you really want to withdraw this abstract?{% endtrans %}
                             {% if abstract.contribution %}
-                                <br>
                                 {%- trans -%}
                                     Withdrawing this abstract will permanently delete its corresponding contribution.
                                 {%- endtrans -%}
                             {% elif not can_manage %}
-                                <br>
                                 {% trans %}This operation is irreversible.{% endtrans %}
                             {% endif %}
                         {% endset %}

programming_language: HTML
filename: _menu.html
change_type: ModificationType.MODIFY
diff: @@ -37,7 +37,7 @@
                          title="{% trans %}Remove the menu entry{% endtrans %}"
                          data-confirm="
                             {%- if not entry.is_separator -%}
-                                {%- trans name='&quot;%s&quot;'|format(entry.localized_title) -%}
+                                {%- trans name='"%s"'|format(entry.localized_title) -%}
                                     Are you sure you want to remove {{ name }}?
                                 {%- endtrans -%}
                             {% else %}

programming_language: HTML
filename: _action_menu.html
change_type: ModificationType.MODIFY
diff: @@ -1,6 +1,6 @@
 {% macro _change_type_confirmation(type) %}
     {% trans -%}
-        Changing the event type to <strong>{{ type }}</strong> will change the look of the event page
+        Changing the event type to {{ type }} will change the look of the event page
         and may disable some features not available for the new event type.
     {%- endtrans %}
 {% endmacro %}

programming_language: HTML
filename: static_sites.html
change_type: ModificationType.MODIFY
diff: @@ -11,7 +11,7 @@
                         data-method="post"
                         data-href="{{ url_for('static_site.build', event) }}"
                         data-title="{% trans %}Build an offline copy{% endtrans %}"
-                        data-confirm="{% trans %}Are you sure you want to build an offline copy of this event?<br>Beware that it is a heavy operation, especially for large events, and it might take some time to finish.{% endtrans %}">
+                        data-confirm="{% trans %}Are you sure you want to build an offline copy of this event? Beware that it is a heavy operation, especially for large events, and it might take some time to finish.{% endtrans %}">
                     {%- trans %}Build offline copy{% endtrans -%}
                 </button>
             </div>

programming_language: HTML
filename: survey.html
change_type: ModificationType.MODIFY
diff: @@ -194,8 +194,10 @@
             {% set data_confirm %}
                 {% trans %}Are you sure you want to remove this submission?{% endtrans %}
                 {% if submission.is_anonymous %}
-                    <br><br>
-                    {% trans %}Note: Authenticated users will not be able to submit an anonymous survey again even if you delete their submission.{% endtrans %}
+                    {% trans %}
+                        Note: Authenticated users will not be able to submit an anonymous survey again
+                        even if you delete their submission.
+                    {% endtrans %}
                 {% endif %}
             {% endset %}
             <a href="#" class="icon-remove right js-delete-submission hide-if-locked"

programming_language: HTML
filename: user_apps.html
change_type: ModificationType.MODIFY
diff: @@ -36,7 +36,7 @@
                             <button class="ui negative small button"
                                     data-href="{{ url_for('.user_app_revoke', auth.application) }}"
                                     data-method="POST"
-                                    data-confirm="{% trans app_name=auth.application.name %}{{ app_name }} will no longer have access to your Indico data.<br>
+                                    data-confirm="{% trans app_name=auth.application.name %}{{ app_name }} will no longer have access to your Indico data.
                                     Are you sure you want to revoke its access?{% endtrans %}">
                                 {%- trans %}Revoke{% endtrans -%}
                             </button>

programming_language: HTML
filename: user_tokens.html
change_type: ModificationType.MODIFY
diff: @@ -109,13 +109,10 @@
                                             You cannot undo this action.
                                             {% endtrans %}
                                             {% if not can_manage %}
-                                                <br><br>
-                                                <strong>
                                                 {% trans %}
                                                 Warning: You will not be able to create a new API token since only Indico
                                                 admins can create API tokens.
                                                 {% endtrans %}
-                                                </strong>
                                             {% endif %}
                                             ">
                                         <i aria-hidden="true" class="trash icon"></i>

programming_language: HTML
filename: personal_data.html
change_type: ModificationType.MODIFY
diff: @@ -14,7 +14,7 @@
                                 <button class="ui negative small button"
                                         data-href="{{ url_for('.user_block') }}"
                                         data-method="PUT"
-                                        data-confirm="{% trans %}This user will no longer have access to Indico.<br>
+                                        data-confirm="{% trans %}This user will no longer have access to Indico.
                                         Are you sure you want to revoke their access?{% endtrans %}"
                                         data-reload-after
                                         {% if user == session.user %}disabled{% endif %}>
@@ -25,7 +25,7 @@
                             <button class="ui small button"
                                     data-href="{{ url_for('.user_block') }}"
                                     data-method="DELETE"
-                                    data-confirm="{% trans %}This user will regain access to Indico.<br>
+                                    data-confirm="{% trans %}This user will regain access to Indico.
                                     Are you sure you want to restore their access?{% endtrans %}"
                                     data-reload-after>
                                 {% trans %}Unblock User{% endtrans %}

programming_language: HTML
filename: misc.js
change_type: ModificationType.MODIFY
diff: @@ -12,7 +12,7 @@ import Palette from '../../utils/palette';
 (function(global) {
   global.confirmPrompt = function confirmPrompt(message, title) {
     var dfd = $.Deferred();
-    message = $('<div>', {width: 400, html: message});
+    message = $('<div>', {width: 400, text: message});
     new ConfirmPopup(title || $T('Please confirm'), message, function(confirmed) {
       if (confirmed) {
         dfd.resolve();

programming_language: JavaScript