Skip to content

Commit

Permalink
Deny remote user login with default credentials
Browse files Browse the repository at this point in the history
Apparently there are users exposing the webui client to the internet
without changing the default credentials. And apparently there are
attackers out there scanning for exposed clients and then logging
in with the default credentials and running code (crypto miners).

Closes qbittorrent#13833
Closes qbittorrent#16529
Closes qbittorrent#18731
  • Loading branch information
sledgehammer999 committed Mar 22, 2023
1 parent b922e1a commit 24cad44
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 5 deletions.
14 changes: 14 additions & 0 deletions src/webui/api/authcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ void AuthController::loginAction()

const QString username {pref->getWebUiUsername()};
const QByteArray secret {pref->getWebUIPassword()};
if (!m_sessionManager->isLocalClient()
&& (username == u"admin"_qs)
&& (secret == QByteArrayLiteral("ARQ77eY1NUZaQsuDHbIMCA==:0WMRkYTUWVT9wVvdDtHAjU9b3b7uB8NR1Gur2hmQCvCDpm39Q+PsJRJPaCU51dEiz+dTzh8qbPsL8WkFljQYFQ==")))
{
if (Preferences::instance()->getWebUIMaxAuthFailCount() > 0)
increaseFailedAttempts();
LogMsg(tr("WebAPI login failure. Reason: Remote connection with the default credentials is prohibited.")
, Log::WARNING);
throw APIError(APIErrorType::AccessDenied
, tr("Remote connection with the default credentials is prohibited. Change the default credentials by connecting from %1."
, "Remote connection with the default credentials is prohibited. Change the default credentials by connecting from localhost.")
.arg(u"localhost"_qs));
}

const bool usernameEqual = Utils::Password::slowEquals(usernameFromWeb.toUtf8(), username.toUtf8());
const bool passwordEqual = Utils::Password::PBKDF2::verify(secret, passwordFromWeb);

Expand Down
1 change: 1 addition & 0 deletions src/webui/api/isessionmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct ISessionManager
{
virtual ~ISessionManager() = default;
virtual QString clientId() const = 0;
virtual bool isLocalClient() const = 0;
virtual ISession *session() = 0;
virtual void sessionStart() = 0;
virtual void sessionEnd() = 0;
Expand Down
7 changes: 6 additions & 1 deletion src/webui/webapplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,11 @@ QString WebApplication::clientId() const
return m_clientAddress.toString();
}

bool WebApplication::isLocalClient() const
{
return Utils::Net::isLoopbackAddress(m_clientAddress);
}

void WebApplication::sessionInitialize()
{
Q_ASSERT(!m_currentSession);
Expand Down Expand Up @@ -638,7 +643,7 @@ QString WebApplication::generateSid() const

bool WebApplication::isAuthNeeded()
{
if (!m_isLocalAuthEnabled && Utils::Net::isLoopbackAddress(m_clientAddress))
if (!m_isLocalAuthEnabled && isLocalClient())
return false;
if (m_isAuthSubnetWhitelistEnabled && Utils::Net::isIPInSubnets(m_clientAddress, m_authSubnetWhitelist))
return false;
Expand Down
1 change: 1 addition & 0 deletions src/webui/webapplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class WebApplication final
Http::Response processRequest(const Http::Request &request, const Http::Environment &env) override;

QString clientId() const override;
bool isLocalClient() const override;
WebSession *session() override;
void sessionStart() override;
void sessionEnd() override;
Expand Down
17 changes: 13 additions & 4 deletions src/webui/www/public/scripts/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,25 @@ document.addEventListener('DOMContentLoaded', function() {

function submitLoginForm() {
const errorMsgElement = document.getElementById('error_msg');
errorMsgElement.textContent = "";

const xhr = new XMLHttpRequest();
xhr.open('POST', 'api/v2/auth/login', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8');
xhr.addEventListener('readystatechange', function() {
if (xhr.readyState === 4) { // DONE state
if ((xhr.status === 200) && (xhr.responseText === "Ok."))
location.reload(true);
else
errorMsgElement.textContent = 'QBT_TR(Invalid Username or Password.)QBT_TR[CONTEXT=HttpServer]';
if (xhr.status === 200) {
if (xhr.responseText === "Ok.")
location.reload(true);
else
errorMsgElement.textContent = 'QBT_TR(Invalid Username or Password.)QBT_TR[CONTEXT=HttpServer]';
}
else if ((xhr.status === 403) && xhr.responseText) {
errorMsgElement.textContent = xhr.responseText;
}
else {
errorMsgElement.textContent = 'QBT_TR(Generic login error.)QBT_TR[CONTEXT=HttpServer]';
}
}
});
xhr.addEventListener('error', function() {
Expand Down

0 comments on commit 24cad44

Please sign in to comment.