Be more strict about opening URLs.

In the proto tree, copy URLs instead of opening them.

In the export dialog, enable previews only if the advertised MIME type
*and* the contents of the file are plain text, GIF, JPEG, or PNG.

Add warnings to the wslua browser_open_url and browser_open_data_file
documentation.

Fixes #17232.
This commit is contained in:
Gerald Combs 2021-02-12 11:54:54 -08:00 committed by Wireshark GitLab Utility
parent 270c8ed746
commit e99c9afce8
4 changed files with 49 additions and 7 deletions

View File

@ -1103,7 +1103,16 @@ WSLUA_FUNCTION wslua_reload_lua_plugins(lua_State* L) { /* Reload all Lua plugin
} }
WSLUA_FUNCTION wslua_browser_open_url(lua_State* L) { /* Opens an URL in a web browser. Requires a GUI. */ WSLUA_FUNCTION wslua_browser_open_url(lua_State* L) { /*
Opens an URL in a web browser. Requires a GUI.
[WARNING]
====
Do not pass an untrusted URL to this function.
It will be passed to the system's URL handler, which might execute malicious code, switch on your Bluetooth-connected foghorn, or any of a number of unexpected or harmful things.
====
*/
#define WSLUA_ARG_browser_open_url_URL 1 /* The url. */ #define WSLUA_ARG_browser_open_url_URL 1 /* The url. */
const char* url = luaL_checkstring(L,WSLUA_ARG_browser_open_url_URL); const char* url = luaL_checkstring(L,WSLUA_ARG_browser_open_url_URL);
@ -1121,6 +1130,13 @@ WSLUA_FUNCTION wslua_browser_open_data_file(lua_State* L) { /*
Open a file located in the data directory (specified in the Wireshark preferences) in the web browser. Open a file located in the data directory (specified in the Wireshark preferences) in the web browser.
If the file does not exist, the function silently ignores the request. If the file does not exist, the function silently ignores the request.
Requires a GUI. Requires a GUI.
[WARNING]
====
Do not pass an untrusted URL to this function.
It will be passed to the system's URL handler, which might execute malicious code, switch on your Bluetooth-connected foghorn, or any of a number of unexpected or harmful things.
====
*/ */
#define WSLUA_ARG_browser_open_data_file_FILENAME 1 /* The file name. */ #define WSLUA_ARG_browser_open_data_file_FILENAME 1 /* The file name. */
const char* file = luaL_checkstring(L,WSLUA_ARG_browser_open_data_file_FILENAME); const char* file = luaL_checkstring(L,WSLUA_ARG_browser_open_data_file_FILENAME);

View File

@ -17,9 +17,11 @@
#include "ui/qt/widgets/wireshark_file_dialog.h" #include "ui/qt/widgets/wireshark_file_dialog.h"
#include <ui/qt/widgets/export_objects_view.h> #include <ui/qt/widgets/export_objects_view.h>
#include <ui/qt/models/export_objects_model.h> #include <ui/qt/models/export_objects_model.h>
#include <ui/qt/utils/qt_ui_utils.h>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QMessageBox> #include <QMessageBox>
#include <QMimeDatabase>
#include <QPushButton> #include <QPushButton>
#include <QComboBox> #include <QComboBox>
#include <QDir> #include <QDir>
@ -95,14 +97,27 @@ void ExportObjectDialog::currentHasChanged(QModelIndex current)
QModelIndex sibl = current.sibling(current.row(), ExportObjectModel::colPacket); QModelIndex sibl = current.sibling(current.row(), ExportObjectModel::colPacket);
if (eo_ui_->buttonBox->button(QDialogButtonBox::Open)) if (eo_ui_->buttonBox->button(QDialogButtonBox::Open))
{ {
QString cont = sibl.sibling(current.row(), ExportObjectModel::colContent).data().toString(); QString mime_type = sibl.sibling(current.row(), ExportObjectModel::colContent).data().toString();
/* For security reasons application and unknown are disabled */ eo_ui_->buttonBox->button(QDialogButtonBox::Open)->setEnabled(mimeTypeIsPreviewable(mime_type));
eo_ui_->buttonBox->button(QDialogButtonBox::Open)->setEnabled(! cont.startsWith("application/") && ! cont.startsWith("unknown/"));
} }
wsApp->gotoFrame(sibl.data().toInt()); wsApp->gotoFrame(sibl.data().toInt());
} }
} }
bool ExportObjectDialog::mimeTypeIsPreviewable(QString mime_type)
{
// XXX This excludes everything except HTTP. Maybe that's a good thing?
// Take care when adding to this, e.g. text/html or image/svg might contain JavaScript.
QStringList previewable_mime_types = QStringList()
<< "text/plain"
<< "image/gif" << "image/jpeg" << "image/png";
if (previewable_mime_types.contains(mime_type)) {
return true;
}
return false;
}
void ExportObjectDialog::modelDataChanged(const QModelIndex&, int from, int to) void ExportObjectDialog::modelDataChanged(const QModelIndex&, int from, int to)
{ {
bool contentTypes_changed = false; bool contentTypes_changed = false;
@ -203,8 +218,16 @@ void ExportObjectDialog::on_buttonBox_clicked(QAbstractButton *button)
QString temp; QString temp;
saveCurrentEntry(&temp); saveCurrentEntry(&temp);
if (temp.length() > 0) if (temp.length() > 0) {
QDesktopServices::openUrl(QUrl(QString("file:///").append(temp), QUrl::TolerantMode)); QMimeDatabase mime_db;
QMimeType mime_type = mime_db.mimeTypeForFile(temp, QMimeDatabase::MatchContent);
if (mimeTypeIsPreviewable(mime_type.name())) {
QDesktopServices::openUrl(QUrl(QString("file:///").append(temp), QUrl::TolerantMode));
} else {
desktop_show_in_folder(temp);
}
}
break; break;
} }
default: // Help, Cancel default: // Help, Cancel

View File

@ -55,6 +55,7 @@ private slots:
void currentHasChanged(QModelIndex current); void currentHasChanged(QModelIndex current);
private: private:
bool mimeTypeIsPreviewable(QString mime_type);
void saveCurrentEntry(QString *tempFile = Q_NULLPTR); void saveCurrentEntry(QString *tempFile = Q_NULLPTR);
void saveAllEntries(); void saveAllEntries();

View File

@ -614,7 +614,9 @@ void ProtoTree::itemDoubleClicked(const QModelIndex &index)
} else { } else {
QString url = finfo.url(); QString url = finfo.url();
if (!url.isEmpty()) { if (!url.isEmpty()) {
QDesktopServices::openUrl(QUrl(url)); QApplication::clipboard()->setText(url);
QString push_msg = tr("Copied ") + url;
wsApp->pushStatus(WiresharkApplication::TemporaryStatus, push_msg);
} }
} }
} }