ws: Disallow direct URL logins with LoginTo=false

The current documentation of LoginTo= isn't very specific about what
exactly happens with a "false" value; but it is plausible for an admin
to assume that "false" would disallow logging into a remote host
completely -- not merely hide the "Connect to:" field and then allowing
a direct URL login anyway.

It is sometimes important to disallow direct SSH logins from the login
page on publicly exposed bastion hosts, as this functionality allows
unauthenticated remote users to:

 - scan the internal network for existing hosts, which might otherwise
   not be accessible directly from the internet
   (Fixes #18540, https://bugzilla.redhat.com/show_bug.cgi?id=2167006)

 - scan the cockpit-ws host or internal network hosts for open ports
   (Fixes #15077, https://bugzilla.redhat.com/show_bug.cgi?id=2018741)

So change ws to reject direct URL logins with `LoginTo=false`. This
happens most naturally in cockpit_session_launch(), as we still want to
allow remote URLs from the shell's host switcher in already
authenticated sessions. This will not produce a very friendly error
message, but it doesn't have to be -- at that point specifying direct
URLs can be considered hacking anyway.

Clarify the documentation accordingly.
This commit is contained in:
Martin Pitt 2023-04-05 17:03:45 +02:00 committed by Martin Pitt
parent cd86905e45
commit 29500b32c6
3 changed files with 25 additions and 3 deletions

View File

@ -102,9 +102,15 @@ ForwardedForHeader = X-Forwarded-For
<term><option>LoginTo</option></term>
<listitem>
<para>When set to <literal>true</literal> the <emphasis>Connect to</emphasis> option
on the login screen is visible and allows logging into another server. If this
option is not specified then it will be automatically detected based on whether
the <command>cockpit-ssh</command> process is available or not.</para>
on the login screen is visible and allows logging into another server. When set to
<literal>false</literal>, direct remote logins are disallowed. If this option is not specified
then it will be automatically detected based on whether the
<command>cockpit-ssh</command> process is available or not.</para>
<para>If cockpit-ws is exposed to the public internet, and also has access to a private
internal network, it is recommended to explicitly set <literal>LoginTo=false</literal>. This prevents
unauthenticated remote attackers from scanning the internal network for existing machines
and open ports.</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -1047,6 +1047,13 @@ cockpit_session_launch (CockpitAuth *self,
return NULL;
}
/* this might be unset, which means "allow if cockpit-ssh is installed"; if it isn't, this will fail later on */
if (host && !cockpit_conf_bool ("WebService", "LoginTo", TRUE)) {
g_set_error (error, COCKPIT_ERROR, COCKPIT_ERROR_AUTHENTICATION_FAILED,
"Direct remote login is disabled");
return NULL;
}
/* These are the credentials we'll carry around for this session */
g_autoptr(CockpitCreds) creds = build_session_credentials (self, request, application, host, type, authorization);

View File

@ -148,6 +148,15 @@ account required pam_succeed_if.so user ingroup %s""" % m.get_admin_group
b.wait_visible("#login")
b.wait_not_visible("#option-group")
# LoginTo= also disables direct URL
b.open("/=192.168.99.99/")
b.wait_visible("#login")
b.wait_not_visible("#option-group")
# logging in does not go via cockpit-ssh (which would cause a connection failure)
b.try_login()
# this isn't the most helpful error message, but this is essentially hacking
b.wait_text("#login-error-message", "Wrong user name or password")
# Default options be to display these options
m.execute("rm /etc/cockpit/cockpit.conf")
m.restart_cockpit()