Bug 217464 (CVE-2010-2536) - Universal XSS
Summary: Universal XSS
Status: RESOLVED FIXED
Alias: CVE-2010-2536
Product: rekonq
Classification: Applications
Component: general (show other bugs)
Version: 0.4.0
Platform: unspecified Linux
: NOR crash
Target Milestone: ---
Assignee: Andrea Diamantini
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-12-05 17:52 UTC by Tim Brown
Modified: 2011-11-02 16:47 UTC (History)
4 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
Removes path from URL on error page (778 bytes, patch)
2010-07-23 16:27 UTC, Eelko Berkenpies
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tim Brown 2009-12-05 17:52:42 UTC
Version:           0.2.90 (using 4.3.2 (KDE 4.3.2), Debian packages)
Compiler:          cc
OS:                Linux (x86_64) release 2.6.31-1-amd64

Rekonq is affected by a universal XSS and / or crash.  Opening a fresh instance of Rekonq and entering the following URL causes a crash:

http://thisdomainwillnotresolveandrekonqerrorpagewillbeshownwithfullurlembedded.twitter.com/"><script>alert(document.cookie)</script>

However, if you enter this into a new tab on an existing instance of Rekonq then it will first try and resolve the hostname and then when that fails it will display an error message.  The error message output by Rekonq includes the full URL, including the <script> tags.  Since Rekonq see that the requested URL is part of *.twitter.com and since twitter.com sets wildcard domain'd cookies, the error page will be able to access any cookies that have been set.  Note that this is not unique to twitter.com, cookies can be stole for any site that sets wildcard domain'd cookies.

There are therefore 3 issues:

1) Crash on fresh instance
2) Injection of malicious content into error message
3) Access to cookies when the hostname under which the cookies have been set was not accessible

I believe the root cause of 2 is:

rekonq-mainline/src/webpage.cpp:    msg += "<h2>" + i18nc("%1=an URL, e.g.'kde.org'", "When connecting to: %1", reply->url().toString()) + "</h2>";

Note that there is no sanitisation of reply->url().toString()!  I haven't investigated the others in any depth but I will update the bug with a stack trace for 1 shortly.
Comment 1 Tim Brown 2009-12-05 17:58:37 UTC
Application: rekonq (rekonq), signal: Segmentation fault
[Current thread is 1 (Thread 0x7f2b122b6750 (LWP 3613))]

Thread 3 (Thread 0x7f2af75e1910 (LWP 3614)):
#0  pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:261
#1  0x00007f2b0ec29499 in QWaitCondition::wait(QMutex*, unsigned long) () from /usr/lib/libQtCore.so.4
#2  0x00007f2b113e54ce in ?? () from /usr/lib/libQtWebKit.so.4
#3  0x00007f2b113e5647 in ?? () from /usr/lib/libQtWebKit.so.4
#4  0x00007f2b10ef489b in ?? () from /usr/lib/libQtWebKit.so.4
#5  0x00007f2b0ec284a5 in ?? () from /usr/lib/libQtCore.so.4
#6  0x00007f2b0d08673a in start_thread (arg=<value optimized out>) at pthread_create.c:300
#7  0x00007f2b0d57e69d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
#8  0x0000000000000000 in ?? ()

Thread 2 (Thread 0x7f2af6de0910 (LWP 3618)):
#0  pthread_cond_timedwait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:220
#1  0x00007f2b0ec29477 in QWaitCondition::wait(QMutex*, unsigned long) () from /usr/lib/libQtCore.so.4
#2  0x00007f2b0ec1f2d1 in ?? () from /usr/lib/libQtCore.so.4
#3  0x00007f2b0ec284a5 in ?? () from /usr/lib/libQtCore.so.4
#4  0x00007f2b0d08673a in start_thread (arg=<value optimized out>) at pthread_create.c:300
#5  0x00007f2b0d57e69d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
#6  0x0000000000000000 in ?? ()
The current source language is "auto; currently asm".

Thread 1 (Thread 0x7f2b122b6750 (LWP 3613)):
[KCrash Handler]
#5  0x00007f2b112be094 in ?? () from /usr/lib/libQtWebKit.so.4
#6  0x00007f2b112be952 in ?? () from /usr/lib/libQtWebKit.so.4
#7  0x00007f2b1100b26f in ?? () from /usr/lib/libQtWebKit.so.4
#8  0x00007f2b11000db0 in ?? () from /usr/lib/libQtWebKit.so.4
#9  0x00007f2b1100360a in ?? () from /usr/lib/libQtWebKit.so.4
#10 0x00007f2b11003dc8 in ?? () from /usr/lib/libQtWebKit.so.4
#11 0x00007f2b111e78dd in ?? () from /usr/lib/libQtWebKit.so.4
#12 0x00007f2b111e9836 in ?? () from /usr/lib/libQtWebKit.so.4
#13 0x00007f2b111e9fc7 in ?? () from /usr/lib/libQtWebKit.so.4
#14 0x00007f2b111ea0e9 in ?? () from /usr/lib/libQtWebKit.so.4
#15 0x00007f2b11397d7f in ?? () from /usr/lib/libQtWebKit.so.4
#16 0x00007f2b1139dd39 in QWebPage::event(QEvent*) () from /usr/lib/libQtWebKit.so.4
#17 0x00007f2b1139fc18 in QWebView::mouseMoveEvent(QMouseEvent*) () from /usr/lib/libQtWebKit.so.4
#18 0x00007f2b0e1d7218 in QWidget::event(QEvent*) () from /usr/lib/libQtGui.so.4
#19 0x00007f2b113a01ff in QWebView::event(QEvent*) () from /usr/lib/libQtWebKit.so.4
#20 0x00007f2b0e18701d in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4
#21 0x00007f2b0e18f7ca in QApplication::notify(QObject*, QEvent*) () from /usr/lib/libQtGui.so.4
#22 0x00007f2b104d60db in KApplication::notify(QObject*, QEvent*) () from /usr/lib/libkdeui.so.5
#23 0x00007f2b0ed0dc9c in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/libQtCore.so.4
#24 0x00007f2b0e18ea78 in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&) () from /usr/lib/libQtGui.so.4
#25 0x00007f2b0e18ef9b in QApplicationPrivate::sendSyntheticEnterLeave(QWidget*) () from /usr/lib/libQtGui.so.4
#26 0x00007f2b0e1d57ae in QWidgetPrivate::hideChildren(bool) () from /usr/lib/libQtGui.so.4
#27 0x00007f2b0e1d5771 in QWidgetPrivate::hideChildren(bool) () from /usr/lib/libQtGui.so.4
#28 0x00007f2b0e1d5771 in QWidgetPrivate::hideChildren(bool) () from /usr/lib/libQtGui.so.4
#29 0x00007f2b0e1d5915 in QWidgetPrivate::hide_helper() () from /usr/lib/libQtGui.so.4
#30 0x00007f2b0e1dc860 in QWidget::setVisible(bool) () from /usr/lib/libQtGui.so.4
#31 0x00007f2b1130e028 in ?? () from /usr/lib/libQtWebKit.so.4
#32 0x00007f2b1100fad5 in ?? () from /usr/lib/libQtWebKit.so.4
#33 0x00007f2b10fcd5a4 in ?? () from /usr/lib/libQtWebKit.so.4
#34 0x00007f2b10fcd5a4 in ?? () from /usr/lib/libQtWebKit.so.4
#35 0x00007f2b10fcd5a4 in ?? () from /usr/lib/libQtWebKit.so.4
#36 0x00007f2b10fcd5a4 in ?? () from /usr/lib/libQtWebKit.so.4
#37 0x00007f2b10fcd5a4 in ?? () from /usr/lib/libQtWebKit.so.4
#38 0x00007f2b10fcd5a4 in ?? () from /usr/lib/libQtWebKit.so.4
#39 0x00007f2b10fcd5a4 in ?? () from /usr/lib/libQtWebKit.so.4
#40 0x00007f2b10fdd503 in ?? () from /usr/lib/libQtWebKit.so.4
#41 0x00007f2b111ef06d in ?? () from /usr/lib/libQtWebKit.so.4
#42 0x00007f2b1118cfc2 in ?? () from /usr/lib/libQtWebKit.so.4
#43 0x00007f2b11389011 in ?? () from /usr/lib/libQtWebKit.so.4
#44 0x00007f2b11184adc in ?? () from /usr/lib/libQtWebKit.so.4
#45 0x00007f2b11188311 in ?? () from /usr/lib/libQtWebKit.so.4
#46 0x00007f2b1116aacf in ?? () from /usr/lib/libQtWebKit.so.4
#47 0x00007f2b1116af30 in ?? () from /usr/lib/libQtWebKit.so.4
#48 0x00007f2b111a3339 in ?? () from /usr/lib/libQtWebKit.so.4
#49 0x00007f2b1119b52e in ?? () from /usr/lib/libQtWebKit.so.4
#50 0x00007f2b1119d9e7 in ?? () from /usr/lib/libQtWebKit.so.4
#51 0x00007f2b1119dd76 in ?? () from /usr/lib/libQtWebKit.so.4
#52 0x00007f2b1119d1ba in ?? () from /usr/lib/libQtWebKit.so.4
#53 0x00007f2b1119bde9 in ?? () from /usr/lib/libQtWebKit.so.4
#54 0x00007f2b1119c5af in ?? () from /usr/lib/libQtWebKit.so.4
#55 0x00007f2b1119c795 in ?? () from /usr/lib/libQtWebKit.so.4
#56 0x00007f2b1119e1de in ?? () from /usr/lib/libQtWebKit.so.4
#57 0x00007f2b1116b2ff in ?? () from /usr/lib/libQtWebKit.so.4
#58 0x00007f2b11173530 in ?? () from /usr/lib/libQtWebKit.so.4
#59 0x00007f2b1117ed95 in ?? () from /usr/lib/libQtWebKit.so.4
#60 0x00007f2b1117edde in ?? () from /usr/lib/libQtWebKit.so.4
#61 0x00007f2b11177701 in ?? () from /usr/lib/libQtWebKit.so.4
#62 0x00007f2b1117d7b3 in ?? () from /usr/lib/libQtWebKit.so.4
#63 0x00007f2b1117d963 in ?? () from /usr/lib/libQtWebKit.so.4
#64 0x00007f2b1117da29 in ?? () from /usr/lib/libQtWebKit.so.4
#65 0x00007f2b11395da0 in QWebFrame::setHtml(QString const&, QUrl const&) () from /usr/lib/libQtWebKit.so.4
#66 0x000000000047caa7 in _start ()
The current source language is "auto; currently c".
Comment 2 Tim Brown 2009-12-05 22:18:37 UTC
Looks like QtDemoBrowser is also affected and is more than likely the original source of the bug:

demos/browser/webview.cpp:

    QFile file(QLatin1String(":/notfound.html"));
    bool isOpened = file.open(QIODevice::ReadOnly);
    Q_ASSERT(isOpened);
    Q_UNUSED(isOpened)

    QString title = tr("Error loading page: %1").arg(reply->url().toString());
    QString html = QString(QLatin1String(file.readAll()))
                        .arg(title)
                        .arg(reply->errorString())
                        .arg(reply->url().toString());
Comment 3 Dawit Alemayehu 2009-12-05 22:40:32 UTC
SVN commit 1059140 by adawit:

Do not fall for XSS tricks when loading error pages.
Escaping the output of KUrl::prettyUrl might be sufficient for
khtml, but it does not work for webkit.

NOTE: This only fixes the issue in kwebkitpart, no where else.

CCBUG: 217464


 M  +1 -1      webkitpart.cpp  


WebSVN link: http://websvn.kde.org/?view=rev&revision=1059140
Comment 4 Tim Brown 2009-12-06 13:36:42 UTC
This line from Rekonq's webview.cpp is also problematic:

msg += "<input type=\"button\" id=\"reloadButton\" onClick=\"document.location.href='" + reply->url().path() + "';\" value=\"";
Comment 5 Andrea Diamantini 2009-12-07 13:17:14 UTC
(In reply to comment #0)
> Rekonq is affected by a universal XSS and / or crash.  Opening a fresh instance
> of Rekonq and entering the following URL causes a crash:
> 
> http://thisdomainwillnotresolveandrekonqerrorpagewillbeshownwithfullurlembedded.twitter.com/"><script>alert(document.cookie)</script>
> 
> However, if you enter this into a new tab on an existing instance of Rekonq
> then it will first try and resolve the hostname and then when that fails it
> will display an error message.  The error message output by Rekonq includes the
> full URL, including the <script> tags.  Since Rekonq see that the requested URL
> is part of *.twitter.com and since twitter.com sets wildcard domain'd cookies,
> the error page will be able to access any cookies that have been set.  Note
> that this is not unique to twitter.com, cookies can be stole for any site that
> sets wildcard domain'd cookies.
> 
> There are therefore 3 issues:
> 
> 1) Crash on fresh instance
> 2) Injection of malicious content into error message
> 3) Access to cookies when the hostname under which the cookies have been set
> was not accessible

First of all, thanks for pointing out the issue :)
I'm having here some different behaviour, anyway.
1) rekonq no more crashes (master, rekonq 0.3.19)
2) present
3) uhm... "quite present"

I'm following your suggestions to fix #2 and investigating about #3.
Comment 6 Tim Brown 2009-12-07 13:25:34 UTC
Qt specific elements of this bug are being tracked at:

http://bugreports.qt.nokia.com/browse/QTWEBKIT-22
Comment 7 Tim Brown 2009-12-08 00:48:38 UTC
At the Trolls request, tracking of Qt specific elements of this bug have been moved to:

https://bugs.webkit.org/show_bug.cgi?id=32252
Comment 8 Panagiotis Papadopoulos 2010-02-05 16:55:47 UTC
no crash here with Qt 4.6.1. Entering the URL above throws me an error dialog, telling me that the URL is not valid. Should we close this bug?
Comment 9 Tim Brown 2010-02-06 11:44:13 UTC
Possibly, I would need to build rekonq from git to confirm.  I've seen the changes but I don't know Qt well enough to give you a guaranteed answer without checking.  Unfortunately, Qt in Debian hasn't quite caught up with where Rekonq is at, so for now I can't build it :(.

I have also found further cases of XSS.  When you open a new tab you get a tool bar with favourites, bookmarks, closed tabs and history.  These "about:" views are rendered using webkit's HTML rendering engine and can therefore be used to execute injected Javascript.  For example any HTML including script tags in the title of the page, or the URL will be rendered.  Luckily document.domain for these is not set, so the associated risk is less severe, but still.
Comment 10 Andrea Diamantini 2010-04-13 12:09:37 UTC
Seems fixed now.
rekonq 0.4.60
kde 4.4 compiled from branches
qtwebkit 2.0
Comment 11 Tim Brown 2010-07-14 18:02:45 UTC
Still a problem even on 0.5.  Enter:

http://wwwmail.google.com/"><script>document.body.innerHTML='<h1>Welcome to Google.com</h1>Username: <input type="username" name="text">Password: <input type="password" name="password"><input type="submit" value="Submit">'</script>

into your URL bar and hit enter.  The full URL submitted is used as part of the error page for the "Try again" button.  The good news is that this time, I don't appear to have access to the cookies for the domain this time but as you can see it's still possible to spoof up legitimate loooking URLs.
Comment 12 Tim Brown 2010-07-21 20:20:57 UTC
As discussed in #rekonq, a CVE has been requested and assigned: CVE-2010-2536
Comment 13 Eelko Berkenpies 2010-07-23 16:27:13 UTC
Created attachment 49437 [details]
Removes path from URL on error page

The attached (simple) patch produces a more firefox-like error page and removes the path from the URL, preventing any (XSS) code into being included into the error page.

Please correct me if I'm wrong. :)
Comment 14 Andrea Diamantini 2010-08-02 00:53:52 UTC
commit 1fd48c700abb6d7ff56fded1e39a1418cc573216
Author: Andrea Diamantini <adjam7@gmail.com>
Date:   Sat Jul 31 01:08:41 2010 +0200

    Applying Eelko's patch against XSS vulnerability
    
    Are we yet vulnerable?
    
    CCBUG:217464

diff --git a/src/webpage.cpp b/src/webpage.cpp
index a63940b..ea2add6 100644
--- a/src/webpage.cpp
+++ b/src/webpage.cpp
@@ -577,8 +577,8 @@ QString WebPage::errorPage(QNetworkReply *reply)
         return QString("Couldn't open the rekonqinfo.html file");
     }
 
-    QString title = i18n("Error loading: %1", reply->url().toString());
-    QString urlString = reply->url().toString(QUrl::RemoveUserInfo | QUrl::RemoveQuery);
+    QString title = i18n("There was a problem while loading the page");
+    QString urlString = reply->url().toString(QUrl::RemoveUserInfo | QUrl::RemoveQuery | QUrl::RemovePath);
 
     QString iconPath = QString("file://") + KIconLoader::global()->iconPath("dialog-warning" , KIconLoader::Small);
     iconPath.replace(QL1S("16"), QL1S("128"));
Comment 16 Andrea Diamantini 2010-10-12 18:06:01 UTC
commit 68330c38941be0246716c8035a010d082cf16a9d
Author: Andrea Diamantini <adjam7@gmail.com>
Date:   Tue Oct 12 18:08:03 2010 +0200

    This change to be sure universal XSS bug has been fixed.
    Anyway, from Eelko's patch on, this was no more reproducible, so... :)
    
    Does the CVE request need to be updated??
    
    CCBUG:217464
    CCMAIL:tampakrap@gmail.com

diff --git a/src/webpage.cpp b/src/webpage.cpp
index d481567..61c6a32 100644
--- a/src/webpage.cpp
+++ b/src/webpage.cpp
@@ -68,6 +68,9 @@
 
 // Qt Includes
 #include <QtCore/QFileInfo>
+
+#include <QtGui/QTextDocument>
+
 #include <QtDBus/QDBusConnection>
 #include <QtDBus/QDBusConnectionInterface>
 #include <QtDBus/QDBusInterface>
@@ -599,7 +602,10 @@ QString WebPage::errorPage(QNetworkReply *reply)
     }
 
     QString title = i18n("There was a problem while loading the page");
-    QString urlString = reply->url().toString(QUrl::RemoveUserInfo | QUrl::RemoveQuery | QUrl::RemovePath);
+    
+    // NOTE: 
+    // this, to be sure BUG 217464 (Universal XSS) has been fixed..
+    QString urlString = Qt::escape(reply->url().toString(QUrl::RemoveUserInfo | QUrl::RemoveQuery | QUrl::RemovePath));
 
     QString iconPath = QString("file://") + KIconLoader::global()->iconPath("dialog-warning" , KIconLoader::Small);
     iconPath.replace(QL1S("16"), QL1S("128"));
Comment 17 Andrea Diamantini 2011-01-24 22:44:59 UTC
Git commit 1d83ce109628cf28269a849abec9786b9e920c39 by Andrea Diamantini.
Pushed by adjam into branch 'master'.

This evening I started working again on this bug. I did all the tests against XSS
and it seems ok. Hope it's true.

CCBUG:217464
CCBUG:246355

M  +7    -4    src/webpage.cpp     

http://commits.kde.org/rekonq/1d83ce109628cf28269a849abec9786b9e920c39