Hello all, in order to connect to my SSH servers from untrusted devices like company computers or my smartphone, I set up 2FA with google-authenticator hooked into PAM. However, this is not really 2FA at least for the smartphone, since I use the same device for generating the TANs and it is also at least inconvenient to always require a new TAN for each connection. I do not want to solely rely on SSH keys on these devices since - as I pointed out - I do not really trust them. So, my idea was to use SSH keys but to also require the server's PAM login for these "semi-trusted" keys. But of course, I want to trust the keys on my own laptop and desktop without an additional PAM password. Therefore, I cannot simply use something like AuthenticationMethods publickey,password I want to be able to specify this per key. Right now, I do a work-around by specifying command="/usr/bin/sudo /bin/login myusername" for the "semi-trusted" keys in the login users' authorized_keys, but this has issues when using scp or rsync. (As I understand, they execute some kind of remote shell or remote daemon, which is overwritten by the command-directive. Unfortunately, this is where my expertise finds its limits and therefore, I was wondering whether anyone already had a similar problem and found a solution or whether anyone would have an idea on how to proceed. My thoughts go in the direction of still using authorized_keys and do something like command="/verify/pam/login/or/whatever/via/some/script.sh && $SSH_ORIGINAL_COMMAND" to use a script for external verification (allowing for any kind of additional checking, including PAM, but with a different configuration) and then continue the normal execution. Unfortunately, this has not worked for me. So, is there any solution for this? Might it be as simple as using a different environment variable that I am simply not aware of? Or could there be an entirely different approach? (Again, I want this for normal login, scp and rsync at least.) Thanks to all and best regards, Jan
On 10/21/20 9:05 AM, Jan Bergner wrote:> > Hello all, > > in order to connect to my SSH servers from untrusted devices like company computers or my smartphone, I set up 2FA with > google-authenticator hooked into PAM. > > However, this is not really 2FA at least for the smartphone, since I use the same device for generating the TANs and it > is also at least inconvenient to always require a new TAN for each connection. I do not want to solely rely on SSH keys > on these devices since - as I pointed out - I do not really trust them.Honestly, this is likely a bad idea. Not because the extra layer of authentication is bad, but because you have no idea what those untrusted devices will do. For example, there is nothing to prevent a device from injecting a backdoor into your ~/.ssh/rc or ~/.profile. That could do anything you could, including creating a fake login session. If you use sudo, they could implant a trojan sudo binary in your $PATH and get root access.> So, my idea was to use SSH keys but to also require the server's PAM login for these "semi-trusted" keys. But of course, > I want to trust the keys on my own laptop and desktop without an additional PAM password. Therefore, I cannot simply use > something likeI strongly recommend only allowing devices you trust to use SSH. Why do you need to login from these untrusted devices? There might very well be a safer solution. That said, if you must allow SSH from an untrusted device, I strongly recommend only allowing SFTP and rsync access, and only allowing it as a separate, unprivileged user. This will solve most of the security holes, but you will need to be very careful about local privilege escalation vulnerabilities. If you are on Linux, polyinstantiating /tmp will help a little. If SELinux is in enforcing mode, using a low-privileged account (such as user_u or even guest_u) would help a lot. If you only need to perform monitoring operations, you could use command="some custom script here", where the custom script only allowed various read-only operations. For instance, you could use command="systemctl status </dev/null" to check if your services are running.> Thanks to all and best regards, > > JanYou're welcome, and best of luck to you. Sincerely, Demi -------------- next part -------------- A non-text attachment was scrubbed... Name: OpenPGP_0xB288B55FFF9C22C1.asc Type: application/pgp-keys Size: 3099 bytes Desc: not available URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20201021/dae383a6/attachment-0001.bin> -------------- next part -------------- A non-text attachment was scrubbed... Name: OpenPGP_signature Type: application/pgp-signature Size: 833 bytes Desc: OpenPGP digital signature URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20201021/dae383a6/attachment-0001.asc>
On Wed, Oct 21, 2020 at 03:05:38PM +0200, Jan Bergner <jan.bergner at indurad.com> wrote:> Hello all, > > in order to connect to my SSH servers from untrusted devices like company computers or my smartphone, I set up 2FA with > google-authenticator hooked into PAM. > > However, this is not really 2FA at least for the smartphone, since I use the same device for generating the TANs and it > is also at least inconvenient to always require a new TAN for each connection. I do not want to solely rely on SSH keys > on these devices since - as I pointed out - I do not really trust them. > > So, my idea was to use SSH keys but to also require the server's PAM login for these "semi-trusted" keys. But of course, > I want to trust the keys on my own laptop and desktop without an additional PAM password. Therefore, I cannot simply use > something like > > AuthenticationMethods publickey,password > > I want to be able to specify this per key. Right now, I do a work-around by specifying > > command="/usr/bin/sudo /bin/login myusername" > > for the "semi-trusted" keys in the login users' authorized_keys, but this has issues when using scp or rsync. (As I > understand, they execute some kind of remote shell or remote daemon, which is overwritten by the command-directive. > Unfortunately, this is where my expertise finds its limits and therefore, I was wondering whether anyone already had > a similar problem and found a solution or whether anyone would have an idea on how to proceed. > > My thoughts go in the direction of still using authorized_keys and do something like > > command="/verify/pam/login/or/whatever/via/some/script.sh && $SSH_ORIGINAL_COMMAND" > > to use a script for external verification (allowing for any kind of additional checking, including PAM, but with a > different configuration) and then continue the normal execution. > Unfortunately, this has not worked for me. > > > So, is there any solution for this? Might it be as simple as using a different environment variable that I am simply not > aware of? Or could there be an entirely different approach? (Again, I want this for normal login, scp and rsync at > least.) > > Thanks to all and best regards, > > JanI can't answer your question, but if you do get this working this way, make sure that you don't explicitly use $SSH_ORIGINAL_COMMAND in the command parameter. That's never the right thing to do. If you do, it will be re-evaluated by the user's login shell an extra time before it is finally evaluated and executed, which will often not do what you want. Whatever command you put in the command parameter should just inherit SSH_ORIGINAL_COMMAND in its environment, without an additional round of shell evaluation, and then, if the extra validation passes, perform the equivalent of: execv('/path/to/sh', ['sh', '-c', env('SSH_ORIGINAL_COMMAND')]) where the sh is the user's login shell (or /bin/sh if there isn't a login shell listed in /etc/passwd). This way, the original command will be executed exactly as ssh would have done it, and so will be able to support any original command. cheers, raf P.S. If you only want the semi-trusted keys to be able to execute a particular fixed set of arbitrary commands (e.g. cronjobs), then an ssh command whitelisting tool might meet your needs. Examples are: https://github.com/raforg/sshdo (auto-learn/unlearn, exact commands only) https://github.com/daethnir/authprogs (manual config, supports regexps) But these won't help if those keys need to be used for arbitrary unpredictable commands (e.g. humans).
Hello Demi et al, first of all, thanks for your reply. I will provide some clarification below. TL;DR: Let us rephrase the question to "How can I require an additional layer of authentication for certain SSH keys, but not for all of them?" Am 21.10.20 um 18:25 schrieb Demi M. Obenour:> On 10/21/20 9:05 AM, Jan Bergner wrote: >> >> Hello all, >> >> in order to connect to my SSH servers from untrusted devices like company computers or my smartphone, I set up 2FA with >> google-authenticator hooked into PAM. >> >> However, this is not really 2FA at least for the smartphone, since I use the same device for generating the TANs and it >> is also at least inconvenient to always require a new TAN for each connection. I do not want to solely rely on SSH keys >> on these devices since - as I pointed out - I do not really trust them. > > Honestly, this is likely a bad idea. Not because the extra layer > of authentication is bad, but because you have no idea what those > untrusted devices will do. > > For example, there is nothing to prevent a device from injecting a > backdoor into your ~/.ssh/rc or ~/.profile. That could do anything you > could, including creating a fake login session. If you use sudo, they > could implant a trojan sudo binary in your $PATH and get root access.Normally, you would be right, of course, but the devices are not completely untrusted, either. Basically, I have three categories of devices: 1. My smartphone Of course, I do not entirely distrust my smartphone. Otherwise I could not really use it for anything. To be concrete, my concern is the backup. In order to reliably backup your complete smartphone, you need root (which has other disadvantages) or you backup using your Google/Samsung/whatever-Account. And I distrust _them_. Think of "The Fappening". It is not inconceivable, that someone could get his hands on my private key. Then, the last layer of protection is the key's passphrase. Thus, I thought that requiring the second password (PAM) is a reasonable compromise between security and convenience. (On the other hand, using a generalized approach like the pseudo-coded command="/some/script.sh && $SSH_ORIGINAL_COMMAND" would also allow for stronger authentication requirements. 2. The company laptop with Linux I have set up this one myself. Therefore, I am also satisfied that it won't do anything nasty. However, the LUKS password is also known to the other company admins - whom I trust, but who knows, who will enter the company in the future. The bigger issue is, again, the backup which is going to onedrive. Therefore, I have the same issue as with my smartphone. 3. The company laptop with Windows This one is obviously the worst. I was not planning on using my "semi-trusted" keys here. To sum this up, I am probably more paranoid than I would need to be considering my setup. On the other hand, I enjoyed giving this issue some thought and in order to get it running to my satisfaction, everything boils down to the question in my TL;DR: How can I require an additional layer of authentication for certain SSH keys, but not for all of them? I think this is an interesting question in general, as well.> >> So, my idea was to use SSH keys but to also require the server's PAM login for these "semi-trusted" keys. But of course, >> I want to trust the keys on my own laptop and desktop without an additional PAM password. Therefore, I cannot simply use >> something like > > I strongly recommend only allowing devices you trust to use SSH. > Why do you need to login from these untrusted devices? There might > very well be a safer solution. > > That said, if you must allow SSH from an untrusted device, I strongly > recommend only allowing SFTP and rsync access, and only allowing it as > a separate, unprivileged user. This will solve most of the security > holes, but you will need to be very careful about local privilege > escalation vulnerabilities. If you are on Linux, polyinstantiating > /tmp will help a little. If SELinux is in enforcing mode, using a > low-privileged account (such as user_u or even guest_u) would help > a lot. > > If you only need to perform monitoring operations, you could use > command="some custom script here", where the custom script only > allowed various read-only operations. For instance, you could use > command="systemctl status </dev/null" to check if your services > are running.That won't do it for me. One use-case is supporting my family with IT problems. (I could not really get rid of that job but I managed to bring all of them to Linux. So, the pain is not that bad.) I don't have issues every week, but sometimes, I really need a shell, SSH-port-forwarding or a file transfer. (Be it config or whatever.) But then, their problems are usually solved within minutes. Second, in my company, it can be very exhausting to get something as simple as a webserver to provide a file to a system or something like this. On such occasions - and if it is not private or classified data, of course - I can save up to hours if I can just place something on my private server and use that for testing. It is also often helpful for debugging connection issues for my company, when I can access a second device (like my server) inside an independent network and do the ping/nmap/traceroute-magic from there for comparison.> >> Thanks to all and best regards, >> >> Jan > > You're welcome, and best of luck to you. > > Sincerely, > > DemiBest, Jan> > > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev >-- *Jan Bergner, M.Sc. * Senior IT Administrator *indurad GmbH* *The Industrial Radar Company* Belvedereallee 5 52070 Aachen, Germany Office: + 49 241 538070-61 Front Desk: + 49 241 538070-0 Fax: + 49 241 538070-99 jan.bergner at indurad.com www.indurad.com <http://www.indurad.com/>
On Wed, 21 Oct 2020, Jan Bergner wrote:> > Hello all, > > in order to connect to my SSH servers from untrusted devices like company computers or my smartphone, I set up 2FA with > google-authenticator hooked into PAM. > > However, this is not really 2FA at least for the smartphone, since I use the same device for generating the TANs and it > is also at least inconvenient to always require a new TAN for each connection. I do not want to solely rely on SSH keys > on these devices since - as I pointed out - I do not really trust them. > > So, my idea was to use SSH keys but to also require the server's PAM login for these "semi-trusted" keys. But of course, > I want to trust the keys on my own laptop and desktop without an additional PAM password. Therefore, I cannot simply use > something like > > AuthenticationMethods publickey,passwordSince the main difference here is how much you trust the originating host, you might want to consider setting up host-based authentication for those hosts and using a config like: AuthenticationMethods publickey,password publickey,hostbased This would allow users to log in with (public key AND password) OR (public key and host-based). -d
Thanks for the tip with environment inheritance; that was helpful in understanding what is actually going on. I have done some testing and it seems, this is not the way to go. If you do just plain "ssh user at host", the SSH_ORIGINAL_COMMAND is empty, while doing scp or rsync fails with an error from the shell. Thus, I would probably need to "intercept" at an earlier point, right? Jan Am 22.10.20 um 00:47 schrieb raf:> On Wed, Oct 21, 2020 at 03:05:38PM +0200, Jan Bergner <jan.bergner at indurad.com> wrote: > >> Hello all, >> >> in order to connect to my SSH servers from untrusted devices like company computers or my smartphone, I set up 2FA with >> google-authenticator hooked into PAM. >> >> However, this is not really 2FA at least for the smartphone, since I use the same device for generating the TANs and it >> is also at least inconvenient to always require a new TAN for each connection. I do not want to solely rely on SSH keys >> on these devices since - as I pointed out - I do not really trust them. >> >> So, my idea was to use SSH keys but to also require the server's PAM login for these "semi-trusted" keys. But of course, >> I want to trust the keys on my own laptop and desktop without an additional PAM password. Therefore, I cannot simply use >> something like >> >> AuthenticationMethods publickey,password >> >> I want to be able to specify this per key. Right now, I do a work-around by specifying >> >> command="/usr/bin/sudo /bin/login myusername" >> >> for the "semi-trusted" keys in the login users' authorized_keys, but this has issues when using scp or rsync. (As I >> understand, they execute some kind of remote shell or remote daemon, which is overwritten by the command-directive. >> Unfortunately, this is where my expertise finds its limits and therefore, I was wondering whether anyone already had >> a similar problem and found a solution or whether anyone would have an idea on how to proceed. >> >> My thoughts go in the direction of still using authorized_keys and do something like >> >> command="/verify/pam/login/or/whatever/via/some/script.sh && $SSH_ORIGINAL_COMMAND" >> >> to use a script for external verification (allowing for any kind of additional checking, including PAM, but with a >> different configuration) and then continue the normal execution. >> Unfortunately, this has not worked for me. >> >> >> So, is there any solution for this? Might it be as simple as using a different environment variable that I am simply not >> aware of? Or could there be an entirely different approach? (Again, I want this for normal login, scp and rsync at >> least.) >> >> Thanks to all and best regards, >> >> Jan > > I can't answer your question, but if you do get this > working this way, make sure that you don't explicitly > use $SSH_ORIGINAL_COMMAND in the command parameter. > That's never the right thing to do. If you do, it will > be re-evaluated by the user's login shell an extra time > before it is finally evaluated and executed, which will > often not do what you want. > > Whatever command you put in the command parameter > should just inherit SSH_ORIGINAL_COMMAND in its > environment, without an additional round of shell > evaluation, and then, if the extra validation passes, > perform the equivalent of: > > execv('/path/to/sh', ['sh', '-c', env('SSH_ORIGINAL_COMMAND')]) > > where the sh is the user's login shell (or /bin/sh if > there isn't a login shell listed in /etc/passwd). > > This way, the original command will be executed exactly > as ssh would have done it, and so will be able to > support any original command. > > cheers, > raf > > P.S. If you only want the semi-trusted keys to be able > to execute a particular fixed set of arbitrary commands > (e.g. cronjobs), then an ssh command whitelisting tool > might meet your needs. Examples are: > > https://github.com/raforg/sshdo (auto-learn/unlearn, exact commands only) > https://github.com/daethnir/authprogs (manual config, supports regexps) > > But these won't help if those keys need to be used for > arbitrary unpredictable commands (e.g. humans). > > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev >-- *Jan Bergner, M.Sc. * Senior IT Administrator *indurad GmbH* *The Industrial Radar Company* Belvedereallee 5 52070 Aachen, Germany Office: + 49 241 538070-61 Front Desk: + 49 241 538070-0 Fax: + 49 241 538070-99 jan.bergner at indurad.com www.indurad.com <http://www.indurad.com/>
Hello Damien, Brian and all, thanks for the suggestions. I actually had not considered host-based authentication and looked it up. As I understand from my first quick reading, I would need to specify the clients which are allowed to use host-based auth on the server with a DNS name or an IP, which would not work for a client behind a CG NAT or in a cellular network. Or did I get this wrong? So, this is also an answer to Brian. Right now, I cannot simply use IPs. (However, it would not be out of reach to simply put all clients on a private VPN. But I would consider that more of a work-around to the original problem.) Thanks and best, Jan Am 22.10.20 um 01:31 schrieb Damien Miller:> On Wed, 21 Oct 2020, Jan Bergner wrote: > >> >> Hello all, >> >> in order to connect to my SSH servers from untrusted devices like company computers or my smartphone, I set up 2FA with >> google-authenticator hooked into PAM. >> >> However, this is not really 2FA at least for the smartphone, since I use the same device for generating the TANs and it >> is also at least inconvenient to always require a new TAN for each connection. I do not want to solely rely on SSH keys >> on these devices since - as I pointed out - I do not really trust them. >> >> So, my idea was to use SSH keys but to also require the server's PAM login for these "semi-trusted" keys. But of course, >> I want to trust the keys on my own laptop and desktop without an additional PAM password. Therefore, I cannot simply use >> something like >> >> AuthenticationMethods publickey,password > > Since the main difference here is how much you trust the originating host, > you might want to consider setting up host-based authentication for those > hosts and using a config like: > > AuthenticationMethods publickey,password publickey,hostbased > > This would allow users to log in with (public key AND password) OR > (public key and host-based). > > -d >-- *Jan Bergner, M.Sc. * Senior IT Administrator *indurad GmbH* *The Industrial Radar Company* Belvedereallee 5 52070 Aachen, Germany Office: + 49 241 538070-61 Front Desk: + 49 241 538070-0 Fax: + 49 241 538070-99 jan.bergner at indurad.com www.indurad.com <http://www.indurad.com/>