summaryrefslogtreecommitdiff
path: root/qutebrowser/browser/webkit/network/webkitqutescheme.py
diff options
context:
space:
mode:
authorFlorian Bruhin <git@the-compiler.org>2018-07-09 23:38:47 +0200
committerFlorian Bruhin <git@the-compiler.org>2018-07-11 17:06:40 +0200
commitff686ff7f395d83e5ac48507ecfae0b0e97a61ef (patch)
tree10465c0cea2939fe9458254968fda49a3e004132 /qutebrowser/browser/webkit/network/webkitqutescheme.py
parent8486efa940d8349176237dec47a5fbd8694e0375 (diff)
downloadqutebrowser-ff686ff7f395d83e5ac48507ecfae0b0e97a61ef.tar.gz
qutebrowser-ff686ff7f395d83e5ac48507ecfae0b0e97a61ef.zip
CVE-2018-10895: Fix CSRF issues with qute://settings/set URLv1.1.x
In ffc29ee043ae7336d9b9dcc029a05bf7a3f994e8 (part of v1.0.0), a qute://settings/set URL was added to change settings. Contrary to what I apparently believed at the time, it *is* possible for websites to access `qute://*` URLs (i.e., neither QtWebKit nor QtWebEngine prohibit such requests, other than the usual cross-origin rules). In other words, this means a website can e.g. have an `<img>` tag which loads a `qute://settings/set` URL, which then sets `editor.command` to a bash script. The result of that is arbitrary code execution. Fixes #4060 See #2332 (cherry picked from commit 43e58ac865ff862c2008c510fc5f7627e10b4660)
Diffstat (limited to 'qutebrowser/browser/webkit/network/webkitqutescheme.py')
-rw-r--r--qutebrowser/browser/webkit/network/webkitqutescheme.py30
1 files changed, 24 insertions, 6 deletions
diff --git a/qutebrowser/browser/webkit/network/webkitqutescheme.py b/qutebrowser/browser/webkit/network/webkitqutescheme.py
index 5413a4a8d..236ebcc0c 100644
--- a/qutebrowser/browser/webkit/network/webkitqutescheme.py
+++ b/qutebrowser/browser/webkit/network/webkitqutescheme.py
@@ -21,7 +21,8 @@
import mimetypes
-from PyQt5.QtNetwork import QNetworkReply
+from PyQt5.QtCore import QUrl
+from PyQt5.QtNetwork import QNetworkReply, QNetworkAccessManager
from qutebrowser.browser import pdfjs, qutescheme
from qutebrowser.browser.webkit.network import schemehandler, networkreply
@@ -32,22 +33,39 @@ class QuteSchemeHandler(schemehandler.SchemeHandler):
"""Scheme handler for qute:// URLs."""
- def createRequest(self, _op, request, _outgoing_data):
+ def createRequest(self, op, request, _outgoing_data, current_url):
"""Create a new request.
Args:
request: const QNetworkRequest & req
- _op: Operation op
+ op: Operation op
_outgoing_data: QIODevice * outgoingData
+ current_url: The page we're on currently.
Return:
A QNetworkReply.
"""
+ if op != QNetworkAccessManager.GetOperation:
+ return networkreply.ErrorNetworkReply(
+ request, "Unsupported request type",
+ QNetworkReply.ContentOperationNotPermittedError)
+
+ url = request.url()
+
+ if ((url.scheme(), url.host(), url.path()) ==
+ ('qute', 'settings', '/set')):
+ if current_url != QUrl('qute://settings/'):
+ log.webview.warning("Blocking malicious request from {} to {}"
+ .format(current_url.toDisplayString(),
+ url.toDisplayString()))
+ return networkreply.ErrorNetworkReply(
+ request, "Invalid qute://settings request",
+ QNetworkReply.ContentAccessDenied)
+
try:
- mimetype, data = qutescheme.data_for_url(request.url())
+ mimetype, data = qutescheme.data_for_url(url)
except qutescheme.NoHandlerFound:
- errorstr = "No handler found for {}!".format(
- request.url().toDisplayString())
+ errorstr = "No handler found for {}!".format(url.toDisplayString())
return networkreply.ErrorNetworkReply(
request, errorstr, QNetworkReply.ContentNotFoundError,
self.parent())