Security considerations regarding QLabel and friends

This blog post is a reminder to always sanitise input going into QLabel and similar classes.

Summary:

When creating a QLabel for displaying text information, be aware that the class tries to guess whether the format is plain text or whether it is rich text. Especially if you expect the data to be plain text, but you cannot control its source, e.g. when loading data from the Web, it might be a good idea to set the text format explicitly via setTextFormat() or escape your input via Qt::escape().

More details:

Input to a QLabel (and others, e.g. QMessageBox) can be crafted in such a way that it does not display all the information that the input text contains.
The trigger for this blog post are vulnerabilities reported for some Qt / KDE applications; those can be tricked to display false information in labels:

  • CVE-2011-3365 affecting KSSL
  • CVE-2011-3366 affecting Rekonq
  • CVE-2011-3367 affecting Arora

Example:

Imagine a browser connecting to a server using SSL. When a user wants to view the details of the SSL connection (either upon SSL errors or just out of interest), the browser will show a dialog containing the most descriptive fields of the SSL certificate. Among the most important ones is the Common Name attribute of the subject field, which denotes the host name the certificate was issued for. For instance, the SSL certificate used by https://qt.nokia.com contains the following Subject line with the Common Name (abbreviated CN) field highlighted in bold:

Subject: C=NO, ST=Oslo, L=Oslo, O=Nokia, OU=ASF, CN=qt.nokia.com

Now imagine a server using the following unusual Common Name attribute:

Subject: C=NO, ST=myState, O=myCompany, CN=qt.nokia.com<table>.evilhost.com

When displaying that common name in a QLabel via setText(), the QLabel class will guess that the passed text is rich text, and will not display the "<table>.evilhost.com" portion. Thus, the output will look like the following:

This is obviously not what the QLabel should display. The solution in this case is to set the text format explicitly on the QLabel:
label->setTextFormat(Qt::PlainText);

That way, the label displays the whole information correctly.

So a reader might now say: "Right, make sense, but no Certificate Authority would ever sign a certificate that has HTML tags in its Common Name". However, given that Certificate Authorities (CAs) signed certificates containing NUL bytes, this does not seem too far fetched. (However, the NUL byte case was much worse because SSL implementations could be tricked to accept a different host name than the certificate was issued for; this article is just about displaying the rogue host name.)

When using rich text with untrusted input, you might want to escape it like the following:
label->setText(QString::fromAscii("<b>Common Name:</b> %1").arg(Qt::escape(commonName)));

Summary:

Always be careful about input that you feed into QLabel, QMessageBox and others; a good practice might be to set the text format explicitly or escape the input before feeding it into above classes.

Acknowledgements:

Thanks to Tim Brown from Nth Dimension and Jeff Mitchell from KDE for reporting this issue, and thanks to Rich Moore from KDE for cross-reading this post.


Blog Topics:

Comments