Page MenuHomePhabricator

XSS in Wikidata Query Service UI (entity labels) - CVE-2019-19328
Closed, ResolvedPublic

Description

TL;DR: entity labels (editable by anyone) included directly as HTML on query.wikidata.org (not CORS-whitelisted)

The Wikidata Query Service UI (wikidata/query/gui in Gerrit) directly includes entity labels as HTML in the tooltip when hovering over an entity ID.

wikibase/queryService/ui/editor/tooltip/Rdf.js
$( '<div class="panel-body">' ).html( text ).css( 'padding', '10px' ) )

To reproduce, open [SELECT (wd:Q43981055 AS ?x) {}](https://query.wikidata.org/#SELECT%20%28wd%3AQ43981055%20AS%20%3Fx%29%20%7B%7D) or a similar query, then hover your mouse over the item ID. The label of the item (“<script>alert("!Mediengruppe Bitnik");</script>” – yes, that’s the actual title of a book) will be injected as HTML into the popup. Users can add almost arbitrary other HTML to the labels of other entities (subject to a limit of, I believe, some 500 characters), though of course this will show up in the history of that item, in recent changes, etc.

Event Timeline

Also found by grepping for .html( (cf. T238822#5681271). Result 7 out of 25.

Edit: No further vulnerabilities found in the remaining results.

The fix for this is almost embarassingly trivial:

diff --git a/wikibase/queryService/ui/editor/tooltip/Rdf.js b/wikibase/queryService/ui/editor/tooltip/Rdf.js
index 028ac68..b1383bc 100644
--- a/wikibase/queryService/ui/editor/tooltip/Rdf.js
+++ b/wikibase/queryService/ui/editor/tooltip/Rdf.js
@@ -108,7 +108,7 @@ wikibase.queryService.ui.editor.tooltip.Rdf = ( function( CodeMirror, $, _ ) {
 					top: pos.y + 2,
 					left: pos.x + 2
 				} ).addClass( 'wikibaseRDFtoolTip' ).append(
-						$( '<div class="panel-body">' ).html( text ).css( 'padding', '10px' ) )
+						$( '<div class="panel-body">' ).text( text ).css( 'padding', '10px' ) )
 				.appendTo( 'body' ).fadeIn( 'slow' );
 	};

Going to do coordination of patching and releasing in the other ticket T238822#5681528 (so as the avoid duplication and keep everything in one place)

sbassett added a project: Security-Team.
sbassett moved this task from Incoming to Watching on the Security-Team board.

Better fix:

diff --git a/wikibase/queryService/ui/editor/tooltip/Rdf.js b/wikibase/queryService/ui/editor/tooltip/Rdf.js
index 028ac68..9c8120d 100644
--- a/wikibase/queryService/ui/editor/tooltip/Rdf.js
+++ b/wikibase/queryService/ui/editor/tooltip/Rdf.js
@@ -98,8 +98,8 @@ wikibase.queryService.ui.editor.tooltip.Rdf = ( function( CodeMirror, $, _ ) {
         $( '.wikibaseRDFtoolTip' ).remove();
     };
 
-    SELF.prototype._showToolTip = function( text, pos ) {
-        if ( !text || !pos ) {
+    SELF.prototype._showToolTip = function( $content, pos ) {
+        if ( !$content || !pos ) {
             return;
         }
 
@@ -108,7 +108,7 @@ wikibase.queryService.ui.editor.tooltip.Rdf = ( function( CodeMirror, $, _ ) {
                     top: pos.y + 2,
                     left: pos.x + 2
                 } ).addClass( 'wikibaseRDFtoolTip' ).append(
-                        $( '<div class="panel-body">' ).html( text ).css( 'padding', '10px' ) )
+                        $( '<div class="panel-body">' ).append( $content ).css( 'padding', '10px' ) )
                 .appendTo( 'body' ).fadeIn( 'slow' );
     };
 
@@ -137,8 +137,12 @@ wikibase.queryService.ui.editor.tooltip.Rdf = ( function( CodeMirror, $, _ ) {
         this._api.searchEntities( term, type ).done(
                 function( data ) {
                     $.each( data.search, function( key, value ) {
-                        entityList.push( value.label + ' (' + value.id + ')<br/><small>' +
-                            ( value.description || '' ) + '</small>' );
+                        entityList.push(
+                            $()
+                                .add( document.createTextNode( value.label + ' (' + value.id + ')' ) )
+                                .add( $( '<br>' ) )
+                                .add( $( '<small>' ).text( value.description || '' ) )
+                        );
                     } );
 
                     deferred.resolve( entityList );

(Side note, this creates a jQuery collection for up to fifty search results, only to then throw away all but the first one… but that can be improved later.)

In Gerrit:

Docker image rebuild https://travis-ci.org/wmde/wikibase-docker/builds/617703004

latest: digest: sha256:6570acb916b429f10ccb3bf3479b66aa6697b3fb3982166a09aba87eeaba7c90
legacy: digest: sha256:4503257bbe1744ce389f07f6dcbaf53db7569cc3e570e30dd5a85c8d0073a39d

CVE just requested via https://cveform.mitre.org/

Great, when the CVE ID is available (typically in a day or two from my personal experience) we should add it to the title of this task and make this task public as I don't think there's any PII or other sensitive information here. Same for T233213 and T238822.

Addshore renamed this task from XSS in Wikidata Query Service UI (entity labels) to XSS in Wikidata Query Service UI (entity labels) - CVE-2019-19328.Nov 28 2019, 9:59 AM
Addshore changed the visibility from "Custom Policy" to "Public (No Login Required)".