0003-Fix-potential-Cross-site-Scripting-XSS-exploits-in-demos.patch 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. From ba166e9adebfe5343f826c6a9e02299d35414ffd Mon Sep 17 00:00:00 2001
  2. From: Lorenzo Miniero <lminiero@gmail.com>
  3. Date: Thu, 25 Nov 2021 17:20:53 +0100
  4. Subject: [PATCH] Fix potential Cross-site Scripting (XSS) exploits in demos
  5. (#2817)
  6. [Retrieved (and backported) from:
  7. https://github.com/meetecho/janus-gateway/commit/ba166e9adebfe5343f826c6a9e02299d35414ffd]
  8. Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
  9. ---
  10. html/audiobridgetest.js | 17 +++++++++++++----
  11. html/recordplaytest.js | 13 +++++++++++--
  12. html/screensharingtest.js | 11 ++++++++++-
  13. html/streamingtest.js | 13 +++++++++++--
  14. html/textroomtest.js | 23 ++++++++++++++---------
  15. html/videocalltest.js | 15 ++++++++++++---
  16. html/videoroomtest.js | 13 +++++++++++--
  17. html/vp9svctest.js | 13 +++++++++++--
  18. 8 files changed, 93 insertions(+), 25 deletions(-)
  19. diff --git a/html/audiobridgetest.js b/html/audiobridgetest.js
  20. index 18e1cc1839..f757789708 100644
  21. --- a/html/audiobridgetest.js
  22. +++ b/html/audiobridgetest.js
  23. @@ -178,7 +178,7 @@ $(document).ready(function() {
  24. Janus.debug("Got a list of participants:", list);
  25. for(var f in list) {
  26. var id = list[f]["id"];
  27. - var display = list[f]["display"];
  28. + var display = escapeXmlTags(list[f]["display"]);
  29. var setup = list[f]["setup"];
  30. var muted = list[f]["muted"];
  31. var spatial = list[f]["spatial_position"];
  32. @@ -222,7 +222,7 @@ $(document).ready(function() {
  33. Janus.debug("Got a list of participants:", list);
  34. for(var f in list) {
  35. var id = list[f]["id"];
  36. - var display = list[f]["display"];
  37. + var display = escapeXmlTags(list[f]["display"]);
  38. var setup = list[f]["setup"];
  39. var muted = list[f]["muted"];
  40. var spatial = list[f]["spatial_position"];
  41. @@ -267,7 +267,7 @@ $(document).ready(function() {
  42. Janus.debug("Got a list of participants:", list);
  43. for(var f in list) {
  44. var id = list[f]["id"];
  45. - var display = list[f]["display"];
  46. + var display = escapeXmlTags(list[f]["display"]);
  47. var setup = list[f]["setup"];
  48. var muted = list[f]["muted"];
  49. var spatial = list[f]["spatial_position"];
  50. @@ -429,7 +429,7 @@ function registerUsername() {
  51. return;
  52. }
  53. var register = { request: "join", room: myroom, display: username };
  54. - myusername = username;
  55. + myusername = escapeXmlTags(username);
  56. mixertest.send({ message: register});
  57. }
  58. }
  59. @@ -448,3 +448,12 @@ function getQueryStringValue(name) {
  60. results = regex.exec(location.search);
  61. return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  62. }
  63. +
  64. +// Helper to escape XML tags
  65. +function escapeXmlTags(value) {
  66. + if(value) {
  67. + var escapedValue = value.replace(new RegExp('<', 'g'), '&lt');
  68. + escapedValue = escapedValue.replace(new RegExp('>', 'g'), '&gt');
  69. + return escapedValue;
  70. + }
  71. +}
  72. diff --git a/html/recordplaytest.js b/html/recordplaytest.js
  73. index 74ee7bed95..52b5ccbc4c 100644
  74. --- a/html/recordplaytest.js
  75. +++ b/html/recordplaytest.js
  76. @@ -423,11 +423,11 @@ function updateRecsList() {
  77. Janus.debug("Got a list of available recordings:", list);
  78. for(var mp in list) {
  79. Janus.debug(" >> [" + list[mp]["id"] + "] " + list[mp]["name"] + " (" + list[mp]["date"] + ")");
  80. - $('#recslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + list[mp]["name"] + " [" + list[mp]["date"] + "]" + "</a></li>");
  81. + $('#recslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + escapeXmlTags(list[mp]["name"]) + " [" + list[mp]["date"] + "]" + "</a></li>");
  82. }
  83. $('#recslist a').unbind('click').click(function() {
  84. selectedRecording = $(this).attr("id");
  85. - selectedRecordingInfo = $(this).text();
  86. + selectedRecordingInfo = escapeXmlTags($(this).text());
  87. $('#recset').html($(this).html()).parent().removeClass('open');
  88. $('#play').removeAttr('disabled').click(startPlayout);
  89. return false;
  90. @@ -545,3 +545,12 @@ function getQueryStringValue(name) {
  91. results = regex.exec(location.search);
  92. return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  93. }
  94. +
  95. +// Helper to escape XML tags
  96. +function escapeXmlTags(value) {
  97. + if(value) {
  98. + var escapedValue = value.replace(new RegExp('<', 'g'), '&lt');
  99. + escapedValue = escapedValue.replace(new RegExp('>', 'g'), '&gt');
  100. + return escapedValue;
  101. + }
  102. +}
  103. diff --git a/html/screensharingtest.js b/html/screensharingtest.js
  104. index 61eac70f43..c64d8dbd67 100644
  105. --- a/html/screensharingtest.js
  106. +++ b/html/screensharingtest.js
  107. @@ -161,7 +161,7 @@ $(document).ready(function() {
  108. if(event === "joined") {
  109. myid = msg["id"];
  110. $('#session').html(room);
  111. - $('#title').html(msg["description"]);
  112. + $('#title').html(escapeXmlTags(msg["description"]));
  113. Janus.log("Successfully joined room " + msg["room"] + " with ID " + myid);
  114. if(role === "publisher") {
  115. // This is our session, publish our stream
  116. @@ -514,3 +514,12 @@ function newRemoteFeed(id, display) {
  117. }
  118. });
  119. }
  120. +
  121. +// Helper to escape XML tags
  122. +function escapeXmlTags(value) {
  123. + if(value) {
  124. + var escapedValue = value.replace(new RegExp('<', 'g'), '&lt');
  125. + escapedValue = escapedValue.replace(new RegExp('>', 'g'), '&gt');
  126. + return escapedValue;
  127. + }
  128. +}
  129. diff --git a/html/streamingtest.js b/html/streamingtest.js
  130. index 7dd2e1f681..3f9937f11c 100644
  131. --- a/html/streamingtest.js
  132. +++ b/html/streamingtest.js
  133. @@ -323,7 +323,7 @@ function updateStreamsList() {
  134. Janus.debug(list);
  135. for(var mp in list) {
  136. Janus.debug(" >> [" + list[mp]["id"] + "] " + list[mp]["description"] + " (" + list[mp]["type"] + ")");
  137. - $('#streamslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + list[mp]["description"] + " (" + list[mp]["type"] + ")" + "</a></li>");
  138. + $('#streamslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + escapeXmlTags(list[mp]["description"]) + " (" + list[mp]["type"] + ")" + "</a></li>");
  139. }
  140. $('#streamslist a').unbind('click').click(function() {
  141. selectedStream = $(this).attr("id");
  142. @@ -345,7 +345,7 @@ function getStreamInfo() {
  143. var body = { request: "info", id: parseInt(selectedStream) || selectedStream };
  144. streaming.send({ message: body, success: function(result) {
  145. if(result && result.info && result.info.metadata) {
  146. - $('#metadata').html(result.info.metadata);
  147. + $('#metadata').html(escapeXmlTags(result.info.metadata));
  148. $('#info').removeClass('hide').show();
  149. }
  150. }});
  151. @@ -394,6 +394,15 @@ function stopStream() {
  152. simulcastStarted = false;
  153. }
  154. +// Helper to escape XML tags
  155. +function escapeXmlTags(value) {
  156. + if(value) {
  157. + var escapedValue = value.replace(new RegExp('<', 'g'), '&lt');
  158. + escapedValue = escapedValue.replace(new RegExp('>', 'g'), '&gt');
  159. + return escapedValue;
  160. + }
  161. +}
  162. +
  163. // Helpers to create Simulcast-related UI, if enabled
  164. function addSimulcastButtons() {
  165. $('#curres').parent().append(
  166. diff --git a/html/textroomtest.js b/html/textroomtest.js
  167. index 082ae44905..3d0697e35a 100644
  168. --- a/html/textroomtest.js
  169. +++ b/html/textroomtest.js
  170. @@ -153,9 +153,7 @@ $(document).ready(function() {
  171. var what = json["textroom"];
  172. if(what === "message") {
  173. // Incoming message: public or private?
  174. - var msg = json["text"];
  175. - msg = msg.replace(new RegExp('<', 'g'), '&lt');
  176. - msg = msg.replace(new RegExp('>', 'g'), '&gt');
  177. + var msg = escapeXmlTags(json["text"]);
  178. var from = json["from"];
  179. var dateString = getDateString(json["date"]);
  180. var whisper = json["whisper"];
  181. @@ -170,9 +168,7 @@ $(document).ready(function() {
  182. }
  183. } else if(what === "announcement") {
  184. // Room announcement
  185. - var msg = json["text"];
  186. - msg = msg.replace(new RegExp('<', 'g'), '&lt');
  187. - msg = msg.replace(new RegExp('>', 'g'), '&gt');
  188. + var msg = escapeXmlTags(json["text"]);
  189. var dateString = getDateString(json["date"]);
  190. $('#chatroom').append('<p style="color: purple;">[' + dateString + '] <i>' + msg + '</i>');
  191. $('#chatroom').get(0).scrollTop = $('#chatroom').get(0).scrollHeight;
  192. @@ -180,7 +176,7 @@ $(document).ready(function() {
  193. // Somebody joined
  194. var username = json["username"];
  195. var display = json["display"];
  196. - participants[username] = display ? display : username;
  197. + participants[username] = escapeXmlTags(display ? display : username);
  198. if(username !== myid && $('#rp' + username).length === 0) {
  199. // Add to the participants list
  200. $('#list').append('<li id="rp' + username + '" class="list-group-item">' + participants[username] + '</li>');
  201. @@ -282,7 +278,7 @@ function registerUsername() {
  202. username: myid,
  203. display: username
  204. };
  205. - myusername = username;
  206. + myusername = escapeXmlTags(username);
  207. transactions[transaction] = function(response) {
  208. if(response["textroom"] === "error") {
  209. // Something went wrong
  210. @@ -312,7 +308,7 @@ function registerUsername() {
  211. if(response.participants && response.participants.length > 0) {
  212. for(var i in response.participants) {
  213. var p = response.participants[i];
  214. - participants[p.username] = p.display ? p.display : p.username;
  215. + participants[p.username] = escapeXmlTags(p.display ? p.display : p.username);
  216. if(p.username !== myid && $('#rp' + p.username).length === 0) {
  217. // Add to the participants list
  218. $('#list').append('<li id="rp' + p.username + '" class="list-group-item">' + participants[p.username] + '</li>');
  219. @@ -418,3 +414,12 @@ function getQueryStringValue(name) {
  220. results = regex.exec(location.search);
  221. return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  222. }
  223. +
  224. +// Helper to escape XML tags
  225. +function escapeXmlTags(value) {
  226. + if(value) {
  227. + var escapedValue = value.replace(new RegExp('<', 'g'), '&lt');
  228. + escapedValue = escapedValue.replace(new RegExp('>', 'g'), '&gt');
  229. + return escapedValue;
  230. + }
  231. +}
  232. diff --git a/html/videocalltest.js b/html/videocalltest.js
  233. index d1c1ab8d07..18ccbc2c47 100644
  234. --- a/html/videocalltest.js
  235. +++ b/html/videocalltest.js
  236. @@ -148,7 +148,7 @@ $(document).ready(function() {
  237. } else if(result["event"]) {
  238. var event = result["event"];
  239. if(event === 'registered') {
  240. - myusername = result["username"];
  241. + myusername = escapeXmlTags(result["username"]);
  242. Janus.log("Successfully registered as " + myusername + "!");
  243. $('#youok').removeClass('hide').show().html("Registered as '" + myusername + "'");
  244. // Get a list of available peers, just for fun
  245. @@ -163,7 +163,7 @@ $(document).ready(function() {
  246. bootbox.alert("Waiting for the peer to answer...");
  247. } else if(event === 'incomingcall') {
  248. Janus.log("Incoming call from " + result["username"] + "!");
  249. - yourusername = result["username"];
  250. + yourusername = escapeXmlTags(result["username"]);
  251. // Notify user
  252. bootbox.hideAll();
  253. incoming = bootbox.dialog({
  254. @@ -213,7 +213,7 @@ $(document).ready(function() {
  255. });
  256. } else if(event === 'accepted') {
  257. bootbox.hideAll();
  258. - var peer = result["username"];
  259. + var peer = escapeXmlTags(result["username"]);
  260. if(!peer) {
  261. Janus.log("Call started!");
  262. } else {
  263. @@ -598,6 +598,15 @@ function getQueryStringValue(name) {
  264. return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  265. }
  266. +// Helper to escape XML tags
  267. +function escapeXmlTags(value) {
  268. + if(value) {
  269. + var escapedValue = value.replace(new RegExp('<', 'g'), '&lt');
  270. + escapedValue = escapedValue.replace(new RegExp('>', 'g'), '&gt');
  271. + return escapedValue;
  272. + }
  273. +}
  274. +
  275. // Helpers to create Simulcast-related UI, if enabled
  276. function addSimulcastButtons(temporal) {
  277. $('#curres').parent().append(
  278. diff --git a/html/videoroomtest.js b/html/videoroomtest.js
  279. index 6a566891d8..5a3ade9be9 100644
  280. --- a/html/videoroomtest.js
  281. +++ b/html/videoroomtest.js
  282. @@ -400,7 +400,7 @@ function registerUsername() {
  283. ptype: "publisher",
  284. display: username
  285. };
  286. - myusername = username;
  287. + myusername = escapeXmlTags(username);
  288. sfutest.send({ message: register });
  289. }
  290. }
  291. @@ -530,7 +530,7 @@ function newRemoteFeed(id, display, audio, video) {
  292. }
  293. }
  294. remoteFeed.rfid = msg["id"];
  295. - remoteFeed.rfdisplay = msg["display"];
  296. + remoteFeed.rfdisplay = escapeXmlTags(msg["display"]);
  297. if(!remoteFeed.spinner) {
  298. var target = document.getElementById('videoremote'+remoteFeed.rfindex);
  299. remoteFeed.spinner = new Spinner({top:100}).spin(target);
  300. @@ -685,6 +685,15 @@ function getQueryStringValue(name) {
  301. return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  302. }
  303. +// Helper to escape XML tags
  304. +function escapeXmlTags(value) {
  305. + if(value) {
  306. + var escapedValue = value.replace(new RegExp('<', 'g'), '&lt');
  307. + escapedValue = escapedValue.replace(new RegExp('>', 'g'), '&gt');
  308. + return escapedValue;
  309. + }
  310. +}
  311. +
  312. // Helpers to create Simulcast-related UI, if enabled
  313. function addSimulcastButtons(feed, temporal) {
  314. var index = feed;
  315. diff --git a/html/vp9svctest.js b/html/vp9svctest.js
  316. index eca0239c32..b22ccf3340 100644
  317. --- a/html/vp9svctest.js
  318. +++ b/html/vp9svctest.js
  319. @@ -387,7 +387,7 @@ function registerUsername() {
  320. ptype: "publisher",
  321. display: username
  322. };
  323. - myusername = username;
  324. + myusername = escapeXmlTags(username);
  325. sfutest.send({ message: register });
  326. }
  327. }
  328. @@ -486,7 +486,7 @@ function newRemoteFeed(id, display, audio, video) {
  329. }
  330. }
  331. remoteFeed.rfid = msg["id"];
  332. - remoteFeed.rfdisplay = msg["display"];
  333. + remoteFeed.rfdisplay = escapeXmlTags(msg["display"]);
  334. if(!remoteFeed.spinner) {
  335. var target = document.getElementById('videoremote'+remoteFeed.rfindex);
  336. remoteFeed.spinner = new Spinner({top:100}).spin(target);
  337. @@ -630,6 +630,15 @@ function newRemoteFeed(id, display, audio, video) {
  338. });
  339. }
  340. +// Helper to escape XML tags
  341. +function escapeXmlTags(value) {
  342. + if(value) {
  343. + var escapedValue = value.replace(new RegExp('<', 'g'), '&lt');
  344. + escapedValue = escapedValue.replace(new RegExp('>', 'g'), '&gt');
  345. + return escapedValue;
  346. + }
  347. +}
  348. +
  349. // Helpers to create SVC-related UI for a new viewer
  350. function addSvcButtons(feed) {
  351. var index = feed;