4

My ssh access is restricted to a Google Authenticator verification code prompt. I'd like to have a script that programmatically answers that prompt.

Context:

  • The variable ($1) passes correctly to the script - it's the verification code.
  • The sshfs command works in terminal.
  • The prompt Verification code: comes with space and a key symbol at the end.

[EDIT] Just to make sure we don't switch to security discussions here, please note that of course I also use SSH keys, additionally to this Google Authenticator. As the Authenticator verification code expires every x seconds it does not matter that others could intercept it.

Result:

The disk mounts (I can see it with df -h), but is empty... Kind of same behavior as when the Verification code is wrong, or maybe it doesn't have the time to execute?

Shell script:

    #!/bin/bash

    expect_sh=$(expect -c "
        spawn /usr/local/bin/sshfs username@123.123.1.123:/path/to/folder/RAID1 /Users/username/Desktop/RAID1 -o defer_permissions -o volname=RAID1
        expect \"Verification code:\"
        send \"$1\r\";
    ")

    echo "$expect_sh"

Thanks

Uddhav P. Gautam
  • 7,362
  • 3
  • 47
  • 64
  • Did you see `Verification code:` in `$expect_sh`? –  Feb 13 '18 at 16:05
  • Thx @EmilyE. , how would you echo inside expect_sh in order to verify this plz? –  Feb 14 '18 at 10:35
  • Wondering does my answer solve your problem? –  Feb 14 '18 at 11:00
  • @EmilyE. Unfortunately not. In the meantime, I can confirm that the variable goes trough as I had `send: spawn id exp6 not open while executing "send "432941\r""` when deactivating authenticator. Currently, the script executes, I can see the commands and Verification code: that get executed but then nothing, no mounted volume, no error message. How could I expect anything? Maybe it's because Verification code comes with a space after it, and a key symbol? –  Feb 15 '18 at 08:29
  • Have a look [there: Trying to get SSH with public key (no password) + google authenticator working on...](https://serverfault.com/a/632197/142978) – F. Hauri - Give Up GitHub Feb 24 '18 at 13:54
  • @F.Hauri Why do you send me there? Did you even read the description of my issue? –  Feb 24 '18 at 20:24
  • 1
    I'm trying to help: *using `expect` with `ssh` is a wrong good idea*! Nota `ssh` and `sftp` use direct `tty` dialog for passwords! Not regular `STDIO`! This could be an issue with `expect`. – F. Hauri - Give Up GitHub Feb 26 '18 at 06:06
  • Have you tried simple sleep before delivering your passkey? You could also try using sshpass. – Stacking For Heap Mar 02 '18 at 06:52

3 Answers3

3

I'm afraid, I have to answer no.

There are some issues:

  1. Having password has argument could reveal your password to other users with a simple

    ps axw
    
  2. Having password stored into a variable could reveal your password to other users with a simple

    ps axeww
    
  3. Having passord transmited via STDIN could be easy to trace.

For this and a lot of other reason, ssh (and sftp) refuse to trasnsmit secrets via arguments, variables or STDIO.

Before asking for password, there is a lot of verification, then the use of a secured dialog (working with direct TTY or with some boxes on X DISPLAY).

So using expect or passing secret as arguments is not directly possible with ssh.

But.

You could connect ssh server by using secret key:

ssh-keygen -b 4096
Enter file in which to save the key (/home/user/.ssh/id_rsa): 
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:q/2fX/Hello/World/Lorem/Ipsum/Dolor/Sit/Amet user@localhst
The key's randomart image is:
+---[RSA 4096]----+
|          .=o=E.o|
|      .. o= o    |
|     o+ +=...    |
|     .o+ o+o.    |
|   . +.oS.oo     |
|  . *.= .  ...   |
|   o =.     oo.  |
|  ...        +o. |
| .ooo       oooo.|
+----[SHA256]-----+

Then now, you have to send your /home/user/.ssh/id_rsa.pub to be stored in authorized_keys file in the server you try to connect to (this files is located in $HOME/.ssh/ or in /etc, but could be located elsewhere, depending on sshd.conf in server).

F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
  • Thanks for your security concerns but unfortunately that's out of the question's context. Of course I use ssh additionally to the Google Authenticator verification code. –  Feb 27 '18 at 08:40
  • The thing is: because of this security concerns, regular tools like `ssh` and `sftp` are built in a way that make use of standard redirection not possible for secrets. – F. Hauri - Give Up GitHub Feb 27 '18 at 09:31
  • Did you alreasy read [this answer to: Use expect in bash script to provide password to SSH command](https://stackoverflow.com/q/4780893/1765658) – F. Hauri - Give Up GitHub Mar 03 '18 at 09:30
2

The reason this isn't working is that you are running expect in a subshell inside the command substitution.

This would be a regular harmless useless use of echo if it weren't for the fact that you hope and expect the process to remain alive.

Just take out the variable capture and run expect as a direct descendant of your current script. If you really require your output to be available as a variable when it's done, maybe try something like

#!/bin/bash

t=$(mktemp -t gauthssh.XXXXXXXXXX) || exit
trap 'rm -f "$t"' EXIT ERROR INT HUP TERM  # clean up temp file when done
expect -c "
    spawn /usr/local/bin/sshfs username@123.123.1.123:/path/to/folder/RAID1 /Users/username/Desktop/RAID1 -o defer_permissions -o volname=RAID1
    expect \"Verification code:\"
    send \"$1\r\";
" | tee "$t"
expect_sh=$(<"$t")
tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Thanks, this seems very interesting, I'll try this asap and accept the answer that works. –  Mar 02 '18 at 09:41
  • You're welcome, but I fail to see how this comment is useful or necessary. If you *don't* plan to do that maybe we would need to know. – tripleee Mar 02 '18 at 09:48
  • Sorry, it's just that it may take a couple of days so I wanted to show my gratitude instead of silence... cheers –  Mar 02 '18 at 10:09
  • The bounty ends in 12 hours so you really need to get that done within a day or so. – tripleee Mar 02 '18 at 10:50
0

You can construct a solution with screen(1)

I tested the script below. It's not especially robust, and you'll need to make some changes according to your enviroment.

#!/bin/sh

screen -d -m -S sshtest sh -c "ssh -l postgres localhost id > output"

pass="77c94046"
ret="$(printf '\n')"

while true; do
        screen -S sshtest -X hardcopy
        grep -q 'password:' hardcopy.0 && break
        sleep 1
done

grep -v '^$' hardcopy.0
echo -n "$passenter" | xxd
screen -S sshtest -X stuff "$pass"
screen -S sshtest -X stuff "$(printf '\r')"
sleep 1
cat output

The idea is to set up a screen running your command that redirects its output to a local file. Then you take screen grabs in a loop and look for your expected prompt with grep. Once you find it, use the 'stuff' command in screen to push your password into the terminal input (i.e. screen's pty). Then you wait a bit and collect your output if needed. This is just proof of concept code, a robust solution would do more error checking and cleanup, and wait for the screen to actually exit.

user464502
  • 2,203
  • 11
  • 14