mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-28 15:34:16 +00:00
[WebUI]: Implement CSRF defense
Bump API version
This commit is contained in:
parent
34c7465009
commit
087856d3d8
@ -43,8 +43,12 @@ namespace Http
|
||||
const char HEADER_CONTENT_SECURITY_POLICY[] = "Content-Security-Policy";
|
||||
const char HEADER_CONTENT_TYPE[] = "Content-Type";
|
||||
const char HEADER_DATE[] = "Date";
|
||||
const char HEADER_HOST[] = "host";
|
||||
const char HEADER_ORIGIN[] = "origin";
|
||||
const char HEADER_REFERER[] = "referer";
|
||||
const char HEADER_SET_COOKIE[] = "Set-Cookie";
|
||||
const char HEADER_X_CONTENT_TYPE_OPTIONS[] = "X-Content-Type-Options";
|
||||
const char HEADER_X_FORWARDED_HOST[] = "x-forwarded-host";
|
||||
const char HEADER_X_FRAME_OPTIONS[] = "X-Frame-Options";
|
||||
const char HEADER_X_XSS_PROTECTION[] = "X-XSS-Protection";
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <QNetworkCookie>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
|
||||
#include "base/preferences.h"
|
||||
#include "base/utils/fs.h"
|
||||
@ -113,6 +114,12 @@ Http::Response AbstractWebApplication::processRequest(const Http::Request &reque
|
||||
header(Http::HEADER_X_CONTENT_TYPE_OPTIONS, "nosniff");
|
||||
header(Http::HEADER_CONTENT_SECURITY_POLICY, "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; script-src 'self' 'unsafe-inline'; object-src 'none';");
|
||||
|
||||
// block cross-site requests
|
||||
if (isCrossSiteRequest(request_)) {
|
||||
status(401, "Unauthorized");
|
||||
return response();
|
||||
}
|
||||
|
||||
sessionInitialize();
|
||||
if (!sessionActive() && !isAuthNeeded())
|
||||
sessionStart();
|
||||
@ -368,6 +375,38 @@ QString AbstractWebApplication::saveTmpFile(const QByteArray &data)
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool AbstractWebApplication::isCrossSiteRequest(const Http::Request &request) const
|
||||
{
|
||||
// https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Verifying_Same_Origin_with_Standard_Headers
|
||||
|
||||
const auto isSameOrigin = [](const QUrl &left, const QUrl &right) -> bool
|
||||
{
|
||||
// [rfc6454] 5. Comparing Origins
|
||||
return ((left.port() == right.port())
|
||||
// && (left.scheme() == right.scheme()) // not present in this context
|
||||
&& (left.host() == right.host()));
|
||||
};
|
||||
|
||||
const QString targetOrigin = request.headers.value(Http::HEADER_X_FORWARDED_HOST, request.headers[Http::HEADER_HOST]);
|
||||
const QString originValue = request.headers.value(Http::HEADER_ORIGIN);
|
||||
const QString refererValue = request.headers.value(Http::HEADER_REFERER);
|
||||
|
||||
if (originValue.isEmpty() && refererValue.isEmpty()) {
|
||||
if ((request.path == QLatin1String("/")) || (request.path == QLatin1String("/favicon.ico")))
|
||||
return false; // normal request
|
||||
return true;
|
||||
}
|
||||
|
||||
// sent with CORS requests, as well as with POST requests
|
||||
if (!originValue.isEmpty())
|
||||
return !isSameOrigin(QUrl::fromUserInput(targetOrigin), originValue);
|
||||
|
||||
if (!refererValue.isEmpty())
|
||||
return !isSameOrigin(QUrl::fromUserInput(targetOrigin), refererValue);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const QStringMap AbstractWebApplication::CONTENT_TYPE_BY_EXT = {
|
||||
{ "htm", Http::CONTENT_TYPE_HTML },
|
||||
{ "html", Http::CONTENT_TYPE_HTML },
|
||||
|
@ -101,6 +101,7 @@ private:
|
||||
bool sessionInitialize();
|
||||
|
||||
QStringMap parseCookie(const Http::Request &request) const;
|
||||
bool isCrossSiteRequest(const Http::Request &request) const;
|
||||
|
||||
static void translateDocument(QString &data);
|
||||
|
||||
|
@ -50,7 +50,7 @@
|
||||
#include "webapplication.h"
|
||||
|
||||
static const int API_VERSION = 14;
|
||||
static const int API_VERSION_MIN = 13;
|
||||
static const int API_VERSION_MIN = 14;
|
||||
|
||||
const QString WWW_FOLDER = ":/www/public/";
|
||||
const QString PRIVATE_FOLDER = ":/www/private/";
|
||||
|
Loading…
x
Reference in New Issue
Block a user