[Buildroot] [PATCH 1/1] package/janus-gateway: fix CVE-2021-4020
Yann E. MORIN
yann.morin.1998 at free.fr
Sat Dec 4 11:29:29 UTC 2021
Fabrice, All,
On 2021-12-03 22:04 +0100, Fabrice Fontaine spake thusly:
> Fix CVE-2021-4020: janus-gateway is vulnerable to Improper
> Neutralization of Input During Web Page Generation ('Cross-site
> Scripting')
>
> Signed-off-by: Fabrice Fontaine <fontaine.fabrice at gmail.com>
Applied to master, thanks.
Gregory, what about updating to a newer version with the fix ? ;-)
Regards,
Yann E. MORIN.
> ---
> ...site-Scripting-XSS-exploits-in-demos.patch | 357 ++++++++++++++++++
> package/janus-gateway/janus-gateway.mk | 3 +
> 2 files changed, 360 insertions(+)
> create mode 100644 package/janus-gateway/0003-Fix-potential-Cross-site-Scripting-XSS-exploits-in-demos.patch
>
> diff --git a/package/janus-gateway/0003-Fix-potential-Cross-site-Scripting-XSS-exploits-in-demos.patch b/package/janus-gateway/0003-Fix-potential-Cross-site-Scripting-XSS-exploits-in-demos.patch
> new file mode 100644
> index 0000000000..9f3adfcc8e
> --- /dev/null
> +++ b/package/janus-gateway/0003-Fix-potential-Cross-site-Scripting-XSS-exploits-in-demos.patch
> @@ -0,0 +1,357 @@
> +From ba166e9adebfe5343f826c6a9e02299d35414ffd Mon Sep 17 00:00:00 2001
> +From: Lorenzo Miniero <lminiero at gmail.com>
> +Date: Thu, 25 Nov 2021 17:20:53 +0100
> +Subject: [PATCH] Fix potential Cross-site Scripting (XSS) exploits in demos
> + (#2817)
> +
> +[Retrieved (and backported) from:
> +https://github.com/meetecho/janus-gateway/commit/ba166e9adebfe5343f826c6a9e02299d35414ffd]
> +Signed-off-by: Fabrice Fontaine <fontaine.fabrice at gmail.com>
> +---
> + html/audiobridgetest.js | 17 +++++++++++++----
> + html/recordplaytest.js | 13 +++++++++++--
> + html/screensharingtest.js | 11 ++++++++++-
> + html/streamingtest.js | 13 +++++++++++--
> + html/textroomtest.js | 23 ++++++++++++++---------
> + html/videocalltest.js | 15 ++++++++++++---
> + html/videoroomtest.js | 13 +++++++++++--
> + html/vp9svctest.js | 13 +++++++++++--
> + 8 files changed, 93 insertions(+), 25 deletions(-)
> +
> +diff --git a/html/audiobridgetest.js b/html/audiobridgetest.js
> +index 18e1cc1839..f757789708 100644
> +--- a/html/audiobridgetest.js
> ++++ b/html/audiobridgetest.js
> +@@ -178,7 +178,7 @@ $(document).ready(function() {
> + Janus.debug("Got a list of participants:", list);
> + for(var f in list) {
> + var id = list[f]["id"];
> +- var display = list[f]["display"];
> ++ var display = escapeXmlTags(list[f]["display"]);
> + var setup = list[f]["setup"];
> + var muted = list[f]["muted"];
> + var spatial = list[f]["spatial_position"];
> +@@ -222,7 +222,7 @@ $(document).ready(function() {
> + Janus.debug("Got a list of participants:", list);
> + for(var f in list) {
> + var id = list[f]["id"];
> +- var display = list[f]["display"];
> ++ var display = escapeXmlTags(list[f]["display"]);
> + var setup = list[f]["setup"];
> + var muted = list[f]["muted"];
> + var spatial = list[f]["spatial_position"];
> +@@ -267,7 +267,7 @@ $(document).ready(function() {
> + Janus.debug("Got a list of participants:", list);
> + for(var f in list) {
> + var id = list[f]["id"];
> +- var display = list[f]["display"];
> ++ var display = escapeXmlTags(list[f]["display"]);
> + var setup = list[f]["setup"];
> + var muted = list[f]["muted"];
> + var spatial = list[f]["spatial_position"];
> +@@ -429,7 +429,7 @@ function registerUsername() {
> + return;
> + }
> + var register = { request: "join", room: myroom, display: username };
> +- myusername = username;
> ++ myusername = escapeXmlTags(username);
> + mixertest.send({ message: register});
> + }
> + }
> +@@ -448,3 +448,12 @@ function getQueryStringValue(name) {
> + results = regex.exec(location.search);
> + return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
> + }
> ++
> ++// Helper to escape XML tags
> ++function escapeXmlTags(value) {
> ++ if(value) {
> ++ var escapedValue = value.replace(new RegExp('<', 'g'), '<');
> ++ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>');
> ++ return escapedValue;
> ++ }
> ++}
> +diff --git a/html/recordplaytest.js b/html/recordplaytest.js
> +index 74ee7bed95..52b5ccbc4c 100644
> +--- a/html/recordplaytest.js
> ++++ b/html/recordplaytest.js
> +@@ -423,11 +423,11 @@ function updateRecsList() {
> + Janus.debug("Got a list of available recordings:", list);
> + for(var mp in list) {
> + Janus.debug(" >> [" + list[mp]["id"] + "] " + list[mp]["name"] + " (" + list[mp]["date"] + ")");
> +- $('#recslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + list[mp]["name"] + " [" + list[mp]["date"] + "]" + "</a></li>");
> ++ $('#recslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + escapeXmlTags(list[mp]["name"]) + " [" + list[mp]["date"] + "]" + "</a></li>");
> + }
> + $('#recslist a').unbind('click').click(function() {
> + selectedRecording = $(this).attr("id");
> +- selectedRecordingInfo = $(this).text();
> ++ selectedRecordingInfo = escapeXmlTags($(this).text());
> + $('#recset').html($(this).html()).parent().removeClass('open');
> + $('#play').removeAttr('disabled').click(startPlayout);
> + return false;
> +@@ -545,3 +545,12 @@ function getQueryStringValue(name) {
> + results = regex.exec(location.search);
> + return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
> + }
> ++
> ++// Helper to escape XML tags
> ++function escapeXmlTags(value) {
> ++ if(value) {
> ++ var escapedValue = value.replace(new RegExp('<', 'g'), '<');
> ++ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>');
> ++ return escapedValue;
> ++ }
> ++}
> +diff --git a/html/screensharingtest.js b/html/screensharingtest.js
> +index 61eac70f43..c64d8dbd67 100644
> +--- a/html/screensharingtest.js
> ++++ b/html/screensharingtest.js
> +@@ -161,7 +161,7 @@ $(document).ready(function() {
> + if(event === "joined") {
> + myid = msg["id"];
> + $('#session').html(room);
> +- $('#title').html(msg["description"]);
> ++ $('#title').html(escapeXmlTags(msg["description"]));
> + Janus.log("Successfully joined room " + msg["room"] + " with ID " + myid);
> + if(role === "publisher") {
> + // This is our session, publish our stream
> +@@ -514,3 +514,12 @@ function newRemoteFeed(id, display) {
> + }
> + });
> + }
> ++
> ++// Helper to escape XML tags
> ++function escapeXmlTags(value) {
> ++ if(value) {
> ++ var escapedValue = value.replace(new RegExp('<', 'g'), '<');
> ++ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>');
> ++ return escapedValue;
> ++ }
> ++}
> +diff --git a/html/streamingtest.js b/html/streamingtest.js
> +index 7dd2e1f681..3f9937f11c 100644
> +--- a/html/streamingtest.js
> ++++ b/html/streamingtest.js
> +@@ -323,7 +323,7 @@ function updateStreamsList() {
> + Janus.debug(list);
> + for(var mp in list) {
> + Janus.debug(" >> [" + list[mp]["id"] + "] " + list[mp]["description"] + " (" + list[mp]["type"] + ")");
> +- $('#streamslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + list[mp]["description"] + " (" + list[mp]["type"] + ")" + "</a></li>");
> ++ $('#streamslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + escapeXmlTags(list[mp]["description"]) + " (" + list[mp]["type"] + ")" + "</a></li>");
> + }
> + $('#streamslist a').unbind('click').click(function() {
> + selectedStream = $(this).attr("id");
> +@@ -345,7 +345,7 @@ function getStreamInfo() {
> + var body = { request: "info", id: parseInt(selectedStream) || selectedStream };
> + streaming.send({ message: body, success: function(result) {
> + if(result && result.info && result.info.metadata) {
> +- $('#metadata').html(result.info.metadata);
> ++ $('#metadata').html(escapeXmlTags(result.info.metadata));
> + $('#info').removeClass('hide').show();
> + }
> + }});
> +@@ -394,6 +394,15 @@ function stopStream() {
> + simulcastStarted = false;
> + }
> +
> ++// Helper to escape XML tags
> ++function escapeXmlTags(value) {
> ++ if(value) {
> ++ var escapedValue = value.replace(new RegExp('<', 'g'), '<');
> ++ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>');
> ++ return escapedValue;
> ++ }
> ++}
> ++
> + // Helpers to create Simulcast-related UI, if enabled
> + function addSimulcastButtons() {
> + $('#curres').parent().append(
> +diff --git a/html/textroomtest.js b/html/textroomtest.js
> +index 082ae44905..3d0697e35a 100644
> +--- a/html/textroomtest.js
> ++++ b/html/textroomtest.js
> +@@ -153,9 +153,7 @@ $(document).ready(function() {
> + var what = json["textroom"];
> + if(what === "message") {
> + // Incoming message: public or private?
> +- var msg = json["text"];
> +- msg = msg.replace(new RegExp('<', 'g'), '<');
> +- msg = msg.replace(new RegExp('>', 'g'), '>');
> ++ var msg = escapeXmlTags(json["text"]);
> + var from = json["from"];
> + var dateString = getDateString(json["date"]);
> + var whisper = json["whisper"];
> +@@ -170,9 +168,7 @@ $(document).ready(function() {
> + }
> + } else if(what === "announcement") {
> + // Room announcement
> +- var msg = json["text"];
> +- msg = msg.replace(new RegExp('<', 'g'), '<');
> +- msg = msg.replace(new RegExp('>', 'g'), '>');
> ++ var msg = escapeXmlTags(json["text"]);
> + var dateString = getDateString(json["date"]);
> + $('#chatroom').append('<p style="color: purple;">[' + dateString + '] <i>' + msg + '</i>');
> + $('#chatroom').get(0).scrollTop = $('#chatroom').get(0).scrollHeight;
> +@@ -180,7 +176,7 @@ $(document).ready(function() {
> + // Somebody joined
> + var username = json["username"];
> + var display = json["display"];
> +- participants[username] = display ? display : username;
> ++ participants[username] = escapeXmlTags(display ? display : username);
> + if(username !== myid && $('#rp' + username).length === 0) {
> + // Add to the participants list
> + $('#list').append('<li id="rp' + username + '" class="list-group-item">' + participants[username] + '</li>');
> +@@ -282,7 +278,7 @@ function registerUsername() {
> + username: myid,
> + display: username
> + };
> +- myusername = username;
> ++ myusername = escapeXmlTags(username);
> + transactions[transaction] = function(response) {
> + if(response["textroom"] === "error") {
> + // Something went wrong
> +@@ -312,7 +308,7 @@ function registerUsername() {
> + if(response.participants && response.participants.length > 0) {
> + for(var i in response.participants) {
> + var p = response.participants[i];
> +- participants[p.username] = p.display ? p.display : p.username;
> ++ participants[p.username] = escapeXmlTags(p.display ? p.display : p.username);
> + if(p.username !== myid && $('#rp' + p.username).length === 0) {
> + // Add to the participants list
> + $('#list').append('<li id="rp' + p.username + '" class="list-group-item">' + participants[p.username] + '</li>');
> +@@ -418,3 +414,12 @@ function getQueryStringValue(name) {
> + results = regex.exec(location.search);
> + return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
> + }
> ++
> ++// Helper to escape XML tags
> ++function escapeXmlTags(value) {
> ++ if(value) {
> ++ var escapedValue = value.replace(new RegExp('<', 'g'), '<');
> ++ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>');
> ++ return escapedValue;
> ++ }
> ++}
> +diff --git a/html/videocalltest.js b/html/videocalltest.js
> +index d1c1ab8d07..18ccbc2c47 100644
> +--- a/html/videocalltest.js
> ++++ b/html/videocalltest.js
> +@@ -148,7 +148,7 @@ $(document).ready(function() {
> + } else if(result["event"]) {
> + var event = result["event"];
> + if(event === 'registered') {
> +- myusername = result["username"];
> ++ myusername = escapeXmlTags(result["username"]);
> + Janus.log("Successfully registered as " + myusername + "!");
> + $('#youok').removeClass('hide').show().html("Registered as '" + myusername + "'");
> + // Get a list of available peers, just for fun
> +@@ -163,7 +163,7 @@ $(document).ready(function() {
> + bootbox.alert("Waiting for the peer to answer...");
> + } else if(event === 'incomingcall') {
> + Janus.log("Incoming call from " + result["username"] + "!");
> +- yourusername = result["username"];
> ++ yourusername = escapeXmlTags(result["username"]);
> + // Notify user
> + bootbox.hideAll();
> + incoming = bootbox.dialog({
> +@@ -213,7 +213,7 @@ $(document).ready(function() {
> + });
> + } else if(event === 'accepted') {
> + bootbox.hideAll();
> +- var peer = result["username"];
> ++ var peer = escapeXmlTags(result["username"]);
> + if(!peer) {
> + Janus.log("Call started!");
> + } else {
> +@@ -598,6 +598,15 @@ function getQueryStringValue(name) {
> + return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
> + }
> +
> ++// Helper to escape XML tags
> ++function escapeXmlTags(value) {
> ++ if(value) {
> ++ var escapedValue = value.replace(new RegExp('<', 'g'), '<');
> ++ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>');
> ++ return escapedValue;
> ++ }
> ++}
> ++
> + // Helpers to create Simulcast-related UI, if enabled
> + function addSimulcastButtons(temporal) {
> + $('#curres').parent().append(
> +diff --git a/html/videoroomtest.js b/html/videoroomtest.js
> +index 6a566891d8..5a3ade9be9 100644
> +--- a/html/videoroomtest.js
> ++++ b/html/videoroomtest.js
> +@@ -400,7 +400,7 @@ function registerUsername() {
> + ptype: "publisher",
> + display: username
> + };
> +- myusername = username;
> ++ myusername = escapeXmlTags(username);
> + sfutest.send({ message: register });
> + }
> + }
> +@@ -530,7 +530,7 @@ function newRemoteFeed(id, display, audio, video) {
> + }
> + }
> + remoteFeed.rfid = msg["id"];
> +- remoteFeed.rfdisplay = msg["display"];
> ++ remoteFeed.rfdisplay = escapeXmlTags(msg["display"]);
> + if(!remoteFeed.spinner) {
> + var target = document.getElementById('videoremote'+remoteFeed.rfindex);
> + remoteFeed.spinner = new Spinner({top:100}).spin(target);
> +@@ -685,6 +685,15 @@ function getQueryStringValue(name) {
> + return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
> + }
> +
> ++// Helper to escape XML tags
> ++function escapeXmlTags(value) {
> ++ if(value) {
> ++ var escapedValue = value.replace(new RegExp('<', 'g'), '<');
> ++ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>');
> ++ return escapedValue;
> ++ }
> ++}
> ++
> + // Helpers to create Simulcast-related UI, if enabled
> + function addSimulcastButtons(feed, temporal) {
> + var index = feed;
> +diff --git a/html/vp9svctest.js b/html/vp9svctest.js
> +index eca0239c32..b22ccf3340 100644
> +--- a/html/vp9svctest.js
> ++++ b/html/vp9svctest.js
> +@@ -387,7 +387,7 @@ function registerUsername() {
> + ptype: "publisher",
> + display: username
> + };
> +- myusername = username;
> ++ myusername = escapeXmlTags(username);
> + sfutest.send({ message: register });
> + }
> + }
> +@@ -486,7 +486,7 @@ function newRemoteFeed(id, display, audio, video) {
> + }
> + }
> + remoteFeed.rfid = msg["id"];
> +- remoteFeed.rfdisplay = msg["display"];
> ++ remoteFeed.rfdisplay = escapeXmlTags(msg["display"]);
> + if(!remoteFeed.spinner) {
> + var target = document.getElementById('videoremote'+remoteFeed.rfindex);
> + remoteFeed.spinner = new Spinner({top:100}).spin(target);
> +@@ -630,6 +630,15 @@ function newRemoteFeed(id, display, audio, video) {
> + });
> + }
> +
> ++// Helper to escape XML tags
> ++function escapeXmlTags(value) {
> ++ if(value) {
> ++ var escapedValue = value.replace(new RegExp('<', 'g'), '<');
> ++ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>');
> ++ return escapedValue;
> ++ }
> ++}
> ++
> + // Helpers to create SVC-related UI for a new viewer
> + function addSvcButtons(feed) {
> + var index = feed;
> diff --git a/package/janus-gateway/janus-gateway.mk b/package/janus-gateway/janus-gateway.mk
> index 40652d802a..98e00aeeb8 100644
> --- a/package/janus-gateway/janus-gateway.mk
> +++ b/package/janus-gateway/janus-gateway.mk
> @@ -11,6 +11,9 @@ JANUS_GATEWAY_LICENSE_FILES = COPYING
> JANUS_GATEWAY_CPE_ID_VENDOR = meetecho
> JANUS_GATEWAY_CPE_ID_PRODUCT = janus
>
> +# 0003-Fix-potential-Cross-site-Scripting-XSS-exploits-in-demos.patch
> +JANUS_GATEWAY_IGNORE_CVES += CVE-2021-4020
> +
> # ding-libs provides the ini_config library
> JANUS_GATEWAY_DEPENDENCIES = host-pkgconf jansson libnice \
> libsrtp host-gengetopt libglib2 openssl libconfig \
> --
> 2.33.0
>
> _______________________________________________
> buildroot mailing list
> buildroot at buildroot.org
> https://lists.buildroot.org/mailman/listinfo/buildroot
--
.-----------------.--------------------.------------------.--------------------.
| Yann E. MORIN | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software Designer | \ / CAMPAIGN | ___ |
| +33 561 099 427 `------------.-------: X AGAINST | \e/ There is no |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL | v conspiracy. |
'------------------------------^-------^------------------^--------------------'
More information about the buildroot
mailing list