Multiple XSS Vulnerabilities in Queue Condition in osticket/osticket

Valid

Reported on

Dec 12th 2022


Description

Cross-Site Scripting (XSS) vulnerabilities arise when data is copied from a request and echoed into the application's immediate response in an unsafe way. An attacker can use the vulnerability to construct a request that, if issued by another application user, will cause JavaScript code supplied by the attacker to execute within the user's browser in the context of that user's session with the application.

In this specific case, following agent authentication and regardless of administrative privileges, an attacker might take advantage of the Queue Condition functionality widely used within the web application in multiple instances, invoking add and addProperty to execute client-side malicious javascript code by exploiting the unsanitized vulnerable GET parameters prop, condition and id.

Later were found and included also further URL-based XSS vulnerabilities affecting scp/ajax.php in staff/change-department and kb/faq/1/access.

Proof of Concept (exploiting prop GET parameter in /addProperty):

http://<TARGET>/osTicket/scp/ajax.php/queue/condition/addProperty?prop=background-colorvximw%22%3e%3cscript%3ealert(1)%3c%2fscript%3edhvmt&condition=1001

Proof of Concept (exploiting condition GET parameter in /addProperty):

http://<TARGET>/osTicket/scp/ajax.php/queue/condition/addProperty?prop=color&condition=1001ljos2%22%3E%3Cscript%3Ealert(1)%3C%2fscript%3Emui2bt(1)%3C%2fscript%3Edhvmt

Proof of Concept (exploiting id GET parameter in /add):

http://<TARGET>/osTicket/scp/ajax.php/queue/condition/add?field=isassigned&object_id=9&id=1001lr5is%22%3e%3cscript%3ealert(1)%3c%2fscript%3euoq07

Proof of Concept (exploiting Reflected XSS in osTicket/scp/ajax.php/staff/change-department):

http://<TARGET>/osTicket/scp/ajax.php/staff/change-departmenthpwc8%22%3e%3cscript%3ealert(1)%3c/script%3em7dak

Proof of Concept (exploiting Reflected XSS in osTicket/scp/ajax.php/kb/faq/1/access):

http://<TARGET>/osTicket/scp/ajax.php/kb/faq/1/accessmztvw%22%3e%3cscript%3ealert(1)%3c/script%3ez2p1d

Impact

If an attacker can control a script that is executed in the victim's browser, then they can typically fully compromise that user. Amongst other things, the attacker can perform any action within the application that the user can perform, view any information that the user is able to view, modify any information that the user is able to modify or initiate interactions with other application users, including malicious attacks, that will appear to originate from the initial victim user.

Ideally, in this practical example, the victim user of this attack is represented by another osTicket agent, regardless of administrative privileges. Thus, the impact would be considered higher in the case where a malicious agent succeeds in getting a second agent, the victim, who instead possesses higher privileges, to execute malicious javascript code.

We are processing your report and will contact the osticket team within 24 hours. 3 months ago
We have contacted a member of the osticket team and are waiting to hear back 3 months ago
Samuele Gugliotta modified the report
3 months ago
Samuele
3 months ago

Researcher


Included further URL-based XSS vulnerabilities affecting osTicket/scp/ajax.php in staff/change-department and kb/faq/1/access along with the related PoCs and code occurrences.

JediKev
2 months ago

Maintainer


@indevi0us

Could you please test the following patch and let us know if it mitigates all the vulnerabilities reported above?

diff --git a/include/ajax.search.php b/include/ajax.search.php
index 56c0f332..18fb9ac1 100644
--- a/include/ajax.search.php
+++ b/include/ajax.search.php
@@ -346,17 +346,16 @@ class SearchAjaxAPI extends AjaxController {
     function addCondition() {
         global $thisstaff;
 
-        if (!$thisstaff) {
+        if (!$thisstaff)
             Http::response(403, 'Agent login is required');
-        }
         elseif (!isset($_GET['field']) || !isset($_GET['id'])
-            || !isset($_GET['object_id'])
-        ) {
+                || !isset($_GET['object_id']))
             Http::response(400, '`field`, `id`, and `object_id` parameters required');
-        }
-        elseif (!is_numeric($_GET['object_id'])) {
+        elseif (!is_numeric($_GET['object_id']))
             Http::response(400, '`object_id` should be an integer');
-        }
+        elseif (!is_numeric($_GET['id']))
+            Http::response(400, '`id` should be an integer');
+
         $fields = SavedSearch::getSearchableFields('Ticket');
         if (!isset($fields[$_GET['field']])) {
             Http::response(400, sprintf('%s: No such searchable field'),
@@ -382,8 +381,8 @@ class SearchAjaxAPI extends AjaxController {
             Http::response(400, '`prop` and `condition` parameters required');
         }
 
-        $prop = $_GET['prop'];
-        $id = $_GET['condition'];
+        $prop = Format::htmlchars($_GET['prop']);
+        $id = Format::htmlchars($_GET['condition']);
         include STAFFINC_DIR . 'templates/queue-column-condition-prop.tmpl.php';
     }
 
diff --git a/include/class.osticket.php b/include/class.osticket.php
index 8e70a27f..26568072 100644
--- a/include/class.osticket.php
+++ b/include/class.osticket.php
@@ -366,10 +366,10 @@ class osTicket {
 
     static function get_path_info() {
         if(isset($_SERVER['PATH_INFO']))
-            return $_SERVER['PATH_INFO'];
+            return htmlentities($_SERVER['PATH_INFO']);
 
         if(isset($_SERVER['ORIG_PATH_INFO']))
-            return $_SERVER['ORIG_PATH_INFO'];
+            return htmlentities($_SERVER['ORIG_PATH_INFO']);
 
         //TODO: conruct possible path info.
 

Cheers.

Samuele
2 months ago

Researcher


Hi @JediKev. I've just applied the changes to the code and tried to reproduce all the PoCs listed above. None of them worked anymore. That's great!

JediKev validated this vulnerability 12 days ago
Samuele Gugliotta has been awarded the disclosure bounty
The fix bounty is now up for grabs
The researcher's credibility has increased: +7
JediKev marked this as fixed in v1.16.6 with commit 343a2b 12 days ago
JediKev has been awarded the fix bounty
This vulnerability has been assigned a CVE
JediKev published this vulnerability 12 days ago
to join this conversation