Mercurial > p > roundup > code
comparison doc/upgrading.txt @ 8062:28aa76443f58
fix(security): fix CVE-2024-39124, CVE-2024-39124, and CVE-2024-39125
Directions for fixing:
* `CVE-2024-39124`_ - :ref:`classhelpers (_generic.help.html) are
vulnerable to an XSS attack. <CVE-2024-39124>` Requires fixing
tracker homes.
* `CVE-2024-39125`_ - :ref:`if Referer header is set to a script
tag, it will be executed. <CVE-2024-39125>` Fixed in release 2.4.0,
directions available for fixing in prior versions.
* `CVE-2024-39126`_ - :ref:`PDF, XML and SVG files downloaded from
an issue can contain embedded JavaScript which is
executed. <CVE-2024-39126>` Fixed in release 2.4.0, directions
available for fixing in prior versions.
prior to 2.4.0 release this weekend that fixes the last two CVE's.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Tue, 09 Jul 2024 09:07:09 -0400 |
| parents | 0e382e97f0e3 |
| children | d6b447de4f59 |
comparison
equal
deleted
inserted
replaced
| 8061:b1d384d23cdb | 8062:28aa76443f58 |
|---|---|
| 120 This will insert the bad API login rate limiting settings. | 120 This will insert the bad API login rate limiting settings. |
| 121 | 121 |
| 122 Also if you have ``html_version`` set to ``xhtml``, you will get | 122 Also if you have ``html_version`` set to ``xhtml``, you will get |
| 123 an error. | 123 an error. |
| 124 | 124 |
| 125 Use of xhtml html_version disabled (required) | 125 .. comment: _CVE-2024-39124: |
| 126 --------------------------------------------- | 126 |
| 127 | 127 Fix for CVE-2024-39124 in help/calendar popups (recommended) |
| 128 If you enabled xhtml formatted templates, you will need to | 128 ------------------------------------------------------------ |
| 129 change them to html (html4) format. Also change the value of | 129 |
| 130 ``html_version`` from ``xhtml`` to ``html``. | 130 Classhelper components accessed via URL using ``@template=help``, |
| 131 ``@template=calendar`` or other template frame in the classhelper | |
| 132 can run JavaScript embedded in the URL. If user clicks on a | |
| 133 malicious URL that: | |
| 134 | |
| 135 * arrives in an email, | |
| 136 * is embedded in a note left on a ticket [#markdown-note]_, | |
| 137 * left on some other web page | |
| 138 | |
| 139 the JavaScript code will be executed. This vulnerability seems to | |
| 140 be limited to manually crafted URL's. It has not been generated | |
| 141 by using Roundup's mechanism for generating classhelper URLs. | |
| 142 | |
| 143 The files that need to be changed to fix this depend on the | |
| 144 template used to create the tracker. Check the | |
| 145 TEMPLATE-INFO.txt file in your tracker home. The template | |
| 146 name is the first component of the ``Name`` field. For | |
| 147 example trackers with Names like:: | |
| 148 | |
| 149 Name: classic-bugtracker | |
| 150 | |
| 151 Name: devel-mytracker | |
| 152 | |
| 153 were derived from the ``classic`` and ``devel`` templates | |
| 154 respectively. If your tracker is derived from the jinja2 | |
| 155 template, you may not be affected as it doesn't provide | |
| 156 classhelpers by default. If you aren't sure which tracker | |
| 157 template was used to create your tracker home, check the | |
| 158 ``html/help.html`` file for the word ``Javascript``. If your | |
| 159 help.html is missing the word ``Javascript``, follow the | |
| 160 directions for the classic template. | |
| 161 | |
| 162 If you have not modified the original tracker html | |
| 163 templates, you can copy replacement files from the new | |
| 164 templates supplied with release 2.4.0. If you install 2.4.0 | |
| 165 in a `new virtual environment | |
| 166 <installation.html#standard-installation>`_, you can use the | |
| 167 command ``roundup-admin templates`` to find the installation | |
| 168 path of the default templates. | |
| 169 | |
| 170 If your template was based on the classic template, replace the | |
| 171 following files in your tracker: | |
| 172 | |
| 173 * html/_generic.calendar.html | |
| 174 * html/_generic.help-list.html | |
| 175 * html/_generic.help-submit.html | |
| 176 * html/_generic.help.html | |
| 177 * html/user.help-search.html | |
| 178 * html/user.help.html | |
| 179 | |
| 180 If your template was based on the minimal template, replace the | |
| 181 following files in your tracker: | |
| 182 | |
| 183 * html/_generic.calendar.html | |
| 184 * html/_generic.help.html | |
| 185 | |
| 186 If your template was based on the responsive or devel templates, | |
| 187 replace the following files in your tracker: | |
| 188 | |
| 189 * html/_generic.calendar.html | |
| 190 * html/_generic.help-submit.html | |
| 191 * html/help.html | |
| 192 * html/user.help-search.html | |
| 193 * html/user.help.html | |
| 194 | |
| 195 As an example, assume Roundup's virtual environment is | |
| 196 ``/tools/roundup``. The classic tracker's default template will | |
| 197 be in ``/tools/roundup/share/roundup/templates/classic``. | |
| 198 Copy | |
| 199 ``/tools/roundup/share/roundup/templates/classic/html/_generic.calendar.html`` | |
| 200 to ``html/_generic.calendar.html`` in your tracker's home | |
| 201 directory. Repeat for every one of the files that needs to | |
| 202 be replaced. | |
| 203 | |
| 204 If you have made local changes to your popup/classhelper | |
| 205 files or have created new help templates based on the | |
| 206 existing ones, don't copy the default files. Instead, follow | |
| 207 the directions below to modify each file as needed for your | |
| 208 template. | |
| 209 | |
| 210 In the examples below, your script tag may differ. For | |
| 211 example it could include:: | |
| 212 | |
| 213 tal:attributes="nonce request/client/client_nonce" | |
| 214 | |
| 215 If it does, keep the differences. You want to make changes | |
| 216 to remove the structure option but keep the rest of the | |
| 217 valid attributes. | |
| 218 | |
| 219 Most files have a small script that sets a few variables | |
| 220 from the settings in the URL. You should change:: | |
| 221 | |
| 222 <script language="Javascript" type="text/javascript" | |
| 223 tal:content="structure string: | |
| 224 // this is the name of the field in the original form that we're working on | |
| 225 form = window.opener.document.${request/form/form/value}; | |
| 226 field = '${request/form/property/value}';"> | |
| 227 | |
| 228 to:: | |
| 229 | |
| 230 <script language="Javascript" type="text/javascript" | |
| 231 tal:content="string: | |
| 232 // this is the name of the field in the original form that we're working on | |
| 233 form = window.opener.document.${request/form/form/value}; | |
| 234 field = '${request/form/property/value}';"> | |
| 235 | |
| 236 by removing the ``structure`` keyword from the tal:content | |
| 237 block. This will html escape the settings in the URL. This | |
| 238 neutralizes an attempt to execute JavaScript by manipulating | |
| 239 the URL. Most of the files use code similar to this. | |
| 240 | |
| 241 A few files have more extensive JavaScript embedded in the same | |
| 242 script tag. To handle this you should split it into two scripts | |
| 243 and encode the replaced strings. For example, change:: | |
| 244 | |
| 245 <script language="Javascript" type="text/javascript" | |
| 246 tal:content="structure string:<!-- | |
| 247 // this is the name of the field in the original form that we're working on | |
| 248 form = parent.opener.document.${request/form/form/value}; | |
| 249 callingform=form | |
| 250 field = '${request/form/property/value}'; | |
| 251 var listform = null | |
| 252 function listPresent() { | |
| 253 return document.frm_help.cb_listpresent.checked | |
| 254 [more code skipped] | |
| 255 | |
| 256 to:: | |
| 257 | |
| 258 <script language="Javascript" type="text/javascript" | |
| 259 tal:content="string: | |
| 260 // this is the name of the field in the original form that we're working on | |
| 261 form = parent.opener.document.${request/form/form/value}; | |
| 262 callingform=form | |
| 263 field = '${request/form/property/value}';"> | |
| 264 </script> | |
| 265 <script language="Javascript" type="text/javascript" | |
| 266 tal:content="string: | |
| 267 var listform = null | |
| 268 function listPresent() { | |
| 269 return document.frm_help.cb_listpresent.checked | |
| 270 [...] | |
| 271 | |
| 272 modifying the original by: | |
| 273 | |
| 274 1. removing the ``structure`` keyword and the HTML comment | |
| 275 marker ``<!--``. This encodes the replaced strings. | |
| 276 2. adding ``">`` at the end of the line that sets ``field`` closes | |
| 277 the script tag. | |
| 278 3. adding:: | |
| 279 | |
| 280 </script> | |
| 281 <script language="Javascript" type="text/javascript" | |
| 282 tal:content="string: | |
| 283 | |
| 284 after the line used in step 2, to ends the first script and | |
| 285 starts a new script. | |
| 286 | |
| 287 Just removing the ``structure`` directive is enough to fix the | |
| 288 bug. Splitting the large script into two parts: | |
| 289 | |
| 290 1. one that has replaced strings with values taken from the URL | |
| 291 2. one that has no replaced strings | |
| 292 | |
| 293 allows use of ``structure`` on the script with no replaced | |
| 294 strings should it be required for your tracker. | |
| 295 | |
| 296 .. [#markdown-note] If you are using markdown formatting for your tracker's notes, | |
| 297 the user will see the markdown label rather than the long | |
| 298 (suspicious) URL. You may want to add something like:: | |
| 299 | |
| 300 a[href*=\@template]::after { | |
| 301 content: ' [' attr(href) ']'; | |
| 302 } | |
| 303 | |
| 304 to your css. This displays the URL inside square brackets if | |
| 305 the href has ``@template`` in it. It is placed after the link | |
| 306 label. | |
| 307 | |
| 308 Fix CVE in earlier versions of Roundup (recommended) | |
| 309 ---------------------------------------------------- | |
| 310 | |
| 311 If you are upgrading to version 2.4.0, you can skip this | |
| 312 section. These fixes are already present in 2.4.0. | |
| 313 | |
| 314 This section is for people who can not upgrade yet, and want | |
| 315 to fix the issues. | |
| 316 | |
| 317 .. comment: _CVE-2024-39125: | |
| 318 | |
| 319 Referer value not escaped CVE-2024-39125 | |
| 320 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 321 | |
| 322 Malicious JavaScript inserted into a page can change the value of | |
| 323 the Referer header to include a script. If a link on that page | |
| 324 points to a Roundup tracker, that script will be executed. The | |
| 325 technique to change the header will result in a change of the URL | |
| 326 in the browser's address bar, but this is easily missed. | |
| 327 | |
| 328 Fix this by editing ``cgi/client.py``, and change:: | |
| 329 | |
| 330 except (UsageError, Unauthorised) as msg: | |
| 331 csrf_ok = False | |
| 332 self.form_wins = True | |
| 333 self._error_message = msg.args | |
| 334 | |
| 335 to:: | |
| 336 | |
| 337 except (UsageError, Unauthorised) as msg: | |
| 338 csrf_ok = False | |
| 339 self.form_wins = True | |
| 340 self.add_error_message(' '.join(msg.args)) | |
| 341 | |
| 342 This escapes the Referer value an prevents it from being | |
| 343 executed. | |
| 344 | |
| 345 .. comment: _CVE-2024-39126: | |
| 346 | |
| 347 Stop JavaScript execution from attached files CVE-2024-39126 | |
| 348 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| 349 | |
| 350 If an SVG, XML or PDF file that includes malicious JavaScript is | |
| 351 attached to an issue, downloading the file will cause the | |
| 352 JavaScript to run. | |
| 353 | |
| 354 In ``cgi/client.py`` add the Content-Security-Policy line | |
| 355 after the existing ``nosniff`` line so it looks like:: | |
| 356 | |
| 357 # exception handlers. | |
| 358 self.determine_language() | |
| 359 self.db.i18n = self.translator | |
| 360 self.setHeader("X-Content-Type-Options", "nosniff") | |
| 361 self.setHeader("Content-Security-Policy", "script-src 'none'") | |
| 362 self.serve_file(designator) | |
| 363 | |
| 364 (the example is reindented for display). | |
| 365 | |
| 366 This should prevent SVG and XML files with embedded scripts | |
| 367 from running. | |
| 368 | |
| 369 If your version of Roundup is old enough that the ``nosniff`` | |
| 370 line is missing, search for ``serve_file(designator)`` and add | |
| 371 both setHeader lines. | |
| 372 | |
| 373 .. warning:: | |
| 374 | |
| 375 If your users use older browsers that don't support Content | |
| 376 Security Policies (e.g. Internet Explorer), you must | |
| 377 remove ``text/xml`` and ``image/svg`` from | |
| 378 ``mime_type_allowlist`` as explained below for | |
| 379 ``application/pdf``. | |
| 380 | |
| 381 PDF files can also embed JavaScript. Many browsers include | |
| 382 PDF viewers that may not support disabling scripting. The | |
| 383 safest way to handle this is to force a download of the PDF | |
| 384 file and use a PDF viewer with scripting disabled. To force | |
| 385 downloading, look in ``cgi/client.py`` for | |
| 386 ``mime_type_allowlist`` and remove the line for | |
| 387 ``application/pdf``. | |
| 388 | |
| 389 Version 2.4.0 allows you to `modify the mime_type_allowlist | |
| 390 using interfaces.py | |
| 391 <admin_guide.html#controlling-browser-handling-of-attached-files>`_. | |
| 392 This will allow you to enable in-browser reading of PDF | |
| 393 files when you upgrade to 2.4.0 if you wish. | |
| 394 | |
| 395 Note that a `Content Security Policy as documented in the admin | |
| 396 guide | |
| 397 <admin_guide.html#adding-a-web-content-security-policy-csp>`_ is | |
| 398 not applied it to a direct download. This requires adding an | |
| 399 explicit CSP header as above. | |
| 400 | |
| 401 .. comment: end of CVE include marker | |
| 402 | |
| 403 XHTML no longer supported (required) | |
| 404 ------------------------------------ | |
| 405 | |
| 406 If your ``config.ini`` sets ``html_version`` to ``xhtml``, | |
| 407 you need to change it to ``html``. Then you need to change | |
| 408 your tracker's templates to html from xhtml. | |
| 131 | 409 |
| 132 Note that the default Roundup templates use html4 so it is | 410 Note that the default Roundup templates use html4 so it is |
| 133 unlikely that your templates are xhtml based. See | 411 unlikely that your templates are xhtml based. See |
| 134 `issue2551323 | 412 `issue2551323 |
| 135 <https://issues.roundup-tracker.org/issue2551323>`_ for | 413 <https://issues.roundup-tracker.org/issue2551323>`_ for |
