CVE-2020-11054 (published 2020-05-07T21:15Z)

In qutebrowser versions less than 1.11.1, reloading a page with certificate errors shows a green URL. After a certificate error was overridden by the user, qutebrowser displays the URL as yellow (colors.statusbar.url.warn.fg). However, when the affected website was subsequently loaded again, the URL was mistakenly displayed as green (colors.statusbar.url.success_https). While the user already has seen a certificate error prompt at this point (or set content.ssl_strict to false, which is not recommended), this could still provide a false sense of security. This has been fixed in 1.11.1 and 1.12.0. All versions of qutebrowser are believed to be affected, though versions before v0.11.x couldn't be tested. Backported patches for older versions (greater than or equal to 1.4.0 and less than or equal to 1.10.2) are available, but no further releases are planned.

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:P/I:N/A:N)
CVSS v3 base score: 3.5, LOW (CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:L/I:N/A:N)

Weakness information:
cwe_id: CWE-684
cwe_name: Incorrect Provision of Specified Functionality
description: The code does not function according to its published specifications, potentially leading to incorrect usage.
extended_description: When providing functionality to an external party, it is important that the product behaves in accordance with the details specified. When requirements of nuances are not documented, the functionality may produce unintended behaviors for the caller, possibly leading to an exploitable state.
         

Fix information:
repo_url: https://github.com/qutebrowser/qutebrowser
commit_details: repo_url: https://github.com/qutebrowser/qutebrowser
author: Florian Bruhin
author_date: 2020-05-02 18:54:05+02:00
msg: Security: Remember hosts with ignored cert errors for load status

Without this change, we only set a flag when a certificate error occurred.
However, when the same certificate error then happens a second time (e.g.
because of a reload or opening the same URL again), we then colored the URL as
success_https (i.e. green) again.

See #5403
repository: repo_url: https://github.com/qutebrowser/qutebrowser
repo_name: qutebrowser/qutebrowser
description: A keyboard-driven, vim-like browser based on Python and Qt.
repo_language: Python
owner: qutebrowser
file_changes: filename: browsertab.py
change_type: ModificationType.MODIFY
diff: @@ -869,6 +869,13 @@ class AbstractTab(QWidget):
     # arg 1: The exit code.
     renderer_process_terminated = pyqtSignal(TerminationStatus, int)
 
+    # Hosts for which a certificate error happened. Shared between all tabs.
+    #
+    # Note that we remember hosts here, without scheme/port:
+    # QtWebEngine/Chromium also only remembers hostnames, and certificates are
+    # for a given hostname anyways.
+    _insecure_hosts = set()  # type: typing.Set[str]
+
     def __init__(self, *, win_id: int, private: bool,
                  parent: QWidget = None) -> None:
         self.is_private = private
@@ -886,7 +893,6 @@ class AbstractTab(QWidget):
         self._layout = miscwidgets.WrapperLayout(self)
         self._widget = typing.cast(QWidget, None)
         self._progress = 0
-        self._has_ssl_errors = False
         self._load_status = usertypes.LoadStatus.none
         self._tab_event_filter = eventfilter.TabEventFilter(
             self, parent=self)
@@ -973,7 +979,6 @@ class AbstractTab(QWidget):
     @pyqtSlot()
     def _on_load_started(self) -> None:
         self._progress = 0
-        self._has_ssl_errors = False
         self.data.viewing_source = False
         self._set_load_status(usertypes.LoadStatus.loading)
         self.load_started.emit()
@@ -1032,9 +1037,12 @@ class AbstractTab(QWidget):
         Needs to be called by subclasses to trigger a load status update, e.g.
         as a response to a loadFinished signal.
         """
-        if ok and not self._has_ssl_errors:
+        if ok:
             if self.url().scheme() == 'https':
-                self._set_load_status(usertypes.LoadStatus.success_https)
+                if self.url().host() in self._insecure_hosts:
+                    self._set_load_status(usertypes.LoadStatus.warn)
+                else:
+                    self._set_load_status(usertypes.LoadStatus.success_https)
             else:
                 self._set_load_status(usertypes.LoadStatus.success)
         elif ok:

programming_language: Python
filename: webenginetab.py
change_type: ModificationType.MODIFY
diff: @@ -1549,9 +1549,9 @@ class WebEngineTab(browsertab.AbstractTab):
 
     @pyqtSlot(certificateerror.CertificateErrorWrapper)
     def _on_ssl_errors(self, error):
-        self._has_ssl_errors = True
-
         url = error.url()
+        self._insecure_hosts.add(url.host())
+
         log.webview.debug("Certificate error: {}".format(error))
 
         if error.is_overridable():

programming_language: Python
filename: webkittab.py
change_type: ModificationType.MODIFY
diff: @@ -849,9 +849,9 @@ class WebKitTab(browsertab.AbstractTab):
         if navigation.is_main_frame:
             self.settings.update_for_url(navigation.url)
 
-    @pyqtSlot()
-    def _on_ssl_errors(self):
-        self._has_ssl_errors = True
+    @pyqtSlot('QNetworkReply*')
+    def _on_ssl_errors(self, reply):
+        self._insecure_hosts.add(reply.url().host())
 
     def _connect_signals(self):
         view = self._widget

programming_language: Python
repo_url: https://github.com/qutebrowser/qutebrowser
commit_details: repo_url: https://github.com/qutebrowser/qutebrowser
author: Florian Bruhin
author_date: 2020-05-02 19:03:20+02:00
msg: Update changelog
repository: repo_url: https://github.com/qutebrowser/qutebrowser
repo_name: qutebrowser/qutebrowser
description: A keyboard-driven, vim-like browser based on Python and Qt.
repo_language: Python
owner: qutebrowser
file_changes: filename: changelog.asciidoc
change_type: ModificationType.MODIFY
diff: @@ -45,7 +45,16 @@ Fixed
 v1.11.1 (unreleased)
 --------------------
 
-No changes yet.
+Security
+~~~~~~~~
+
+- After a certificate error was overridden by the user, qutebrowser displays
+  the URL as yellow (`colors.statusbar.url.warn.fg`). However, when the
+  affected website was subsequently loaded again, the URL was mistakenly
+  displayed as green (`colors.statusbar.url.success_https`). While the user
+  already has seen a certificate error prompt at this point (or set
+  `content.ssl_strict` to `false` which is not recommended), this could still
+  provide a false sense of security. This is now fixed.
 
 v1.11.0 (2020-04-27)
 --------------------

programming_language: Markdown