QLabel及其朋友的安全性思考

作者:Debao Zhang | Oct 13, 2011 12:14:52 PM

原文链接: Peter Hartmann Security considerations regarding QLabel and friends

本篇博客旨在提醒,要始终保持QLabel以及其它相似类中输入内容的清洁。

摘要:

当创建一个QLabel来显示文字信息时,要意识到该类将会尝试猜测其格式是纯文本还是富文本。特别是,如果你希望数据是纯文本,但你无法控制它的来源,比如当下载Web中数据时,通过setTextFormat()显式地设置文本的格式或使用Qt::escape()来进行转义或许是个很好的主意。

更多细节:

通过对QLabel(以及其他,比如QMessageBox)的输入的精心构建可以使得其不能显示输入文本中的全部信息。

本文写作动机源于对一些Qt/KDE应用程序的漏洞报告;它们会被欺骗并在标签中显示虚假的信息。

  • CVE-2011-3365影响到KSSL
  • CVE-2011-3366影响到Rekonq
  • CVE-2011-3367影响到Arora

例子:

考虑一个使用SSL连接到服务器的浏览器。当用户想要查看SSL连接(无论是由于SSL错误还是仅出于兴趣)的细节时,浏览器将显示一个包含了SSL证书中多数描述性字段(field)的对话框。其中最重要的是主题(subject)字段的通用名称属性(Common Name attribute),它表示该证书被授予到的主机名。例如,https://qt.nokia.com使用的SSL证书包含以下的主题行,其中通用名称(简称CN)字段以黑体高亮:


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

现在想象一个使用了下列不常用的通用名称属性的服务器:


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

当通过setText()在一个QLabel中显示这个通用名称时,该QLabel将会认为传递进的文本是富文本,并且不显示"<table>.evilhost.com"部分。这样一来,输出看起来像下面这样:

这显然不是QLabel应该显示的。这种情况下的解决方案是在该QLabel上显式地设置文本格式:

label->setTextFormat(Qt::PlainText);

这样一来,标签将会正确显示完整的信息。

所以读者现在可能会说:“对,有道理,但是没有证书颁发机构会签发在通用名称中包含HTML标记的证书”。尽管如此,考虑到证书颁发机构(CAs)签发包含NUL字节的证书,这种情况也不是遥不可及的。(然而,NUL字节的情况更糟,因为SSL的实现可能会被欺骗并接受其他主机名而不是证书被颁发到的主机;本文只是涉及流氓主机名的显示。)

当在不被信任的输入中使用富文本时,你可能愿意像下面这样来转义它:

label->setText(QString::fromAscii("<b>Common Name:</b> %1").arg(Qt::escape(commonName)));

小结:

对要送入QLabel、QMessageBox以及其他控件的输入,要务必谨慎;一个很好的做法可能是,显式地设置文本的格式或者在送入上述类之前先转义它。

致谢:

感谢来自Nth Dimension的Tim Brown和来自KDE的Jeff Mitchell提交了这个问题,感谢来自KDE的Rich Moore审阅(cross-reading)了本文。