2

In bash (and other shells) it is possible to insert the result of a command into a command line using something like $() and `` (backticks).

Now it would be nice if you had something like that but for ssh sessions. So you are in an ssh session and need some information from your own computer and want to put it into the inner command line on the machine you are connected to.

E.g. say you want to directly access a mysql console. You could use a command like that:

ssh [email protected] "mysql -u blub -pmypass"

That works but the problem is, that you can see the password in the command line of the ssh shell process.

To solve this security problem I would like to have something like that:

ssh [email protected] "mysql -u blub -p\$(ssh-on-client 'cat pass-file')"

which would execute cat passfile on the ssh client and not on the server. Is there anything known like that? Do you have any other tricks how to do that?

UPDATE: I appreciate answers which refer to my example, but I will not accept them unless they answer the real question. That is, wether it is possible to communicate to the ssh client computer from within an ssh session. (I know this may constitute a possible security problem)

Possible solutions:

  • Having an ssh server on the client to connect back to. (sweimann) The problem is how to get the credentials for connecting back to the server.
  • Creating a tunnel with ssh and using some netcat script/telnet to execute commands on the server and send the result back.
  • Use expect to script the shell. (Zac Thompson)
  • Use a custom wrapper around ssh on the client watching the console and taking action accordingly. (sapporo)
  • Patch SSH to support this. There is similar patch on the mailing list available.
  • There's an option 'SendEnv' to ssh which sets environment variables on the remote computer. This has to be enabled on the remote sshd, though.
2
  • Would xclip be able to do this? Jul 10, 2009 at 16:06
  • I chose Zac's solution ('expect') because it seems like the most general solution to the problem.
    – JohannesR
    Jul 17, 2009 at 11:34

12 Answers 12

3

You want to use expect for this. It's probably already on your machine. It's the standard tool for any kind of interactive command-line automation. It's a Tcl library, so you'll get some Tcl skills along the way for free. Beware; it's addictive.

#!/path/to/expect
spawn ssh [email protected] "mysql -u blub"
expect "*ssword:*"
send -- "mypass\r"
interact
5

Try using a <.

ssh [email protected] "mysql -u blub -p" < file

If the first line in "file" is your password, it "should" use that for the password prompt, then the rest will be used for the sql portion.

If you are simply executing an sql file on the remote server, try:

ssh [email protected] "mysql -u blub -p < file.sql" < password

1
  • Very nice, that works perfect for my example.
    – JohannesR
    Jul 14, 2009 at 14:11
2

I've been looking into the underlying problem a few years ago. I wanted to trigger a SCP download from inside a SSH session. Like your problem, this requires communication from inside the SSH session back to some process on the client.

So here's a third possible solution: Connect using a wrapper around SSH, which scans SSH's output and triggers certain commands locally when it recognizes a pattern. It's clearly a hack, but it might do the trick.

I ended up with a modified version of /usr/bin/script that would remember my SSH connection (e.g. me@somehost), and whenever my ssh session printed ###/some/absulte/path/to/file/on/host.txt###, it would locally execute scp me@somehost:/some/absulte/path/to/file/on/host.txt .

A simple shell script was used to conveniently produce the pattern and absolute path on the server.

(My code actually did a little more: It opened a local text editor on the downloaded file, and would re-upload it using SCP when the file was modified. Let me know if you want the code.)

I've been looking for a nicer implementation of this ever since, but haven't found one so far.

Maybe this technique could be implemented as a SSH proxy command (think connect.c) instead of a wrapper around SSH.

4
  • Isn't that what expect is doing actually?
    – JohannesR
    Jul 14, 2009 at 14:13
  • A similar patch is available on the openssh mailing list, patching this directly into the openssh client program.
    – JohannesR
    Jul 14, 2009 at 14:47
  • Not sure whether expect can scan for patterns while the user is interacting with the target process. I'm not the biggest fan of TCL, so I never investigated this further. Patching the openssh binary is definitely not an option in my work environment, but I'd like to learn more about how this patch works. Where do I find some info about it (aside from the openssh mailing list, of course)? Jul 14, 2009 at 15:44
  • JohannesR, I cannot find that patch on the openssh mailing list. What's the subject of the announcement mail? I would really like to have a look at it. Thanks. Jul 23, 2009 at 8:40
1

For this specific problem, maybe you can just put the password in your ~/my.cnf file on the server?

For your idea: You have to use escaping to make that work:

ssh dba@db "echo \`ssh [email protected] \"cat echofile\" \`"

Edit again: You will neeed passwordless login from the server to the client, meaning a private key for your client box on the server, which is even less secure than my.cnf.

2
  • Right, I could. But then I would link the security of the Mysql account to the ssh account what I'm just trying to avoid.
    – JohannesR
    Jul 10, 2009 at 10:03
  • Hehe, right, I had a similar idea, but as you mentioned yourself it is not really practical. My example is probably not the best, since you always tie both accounts while you are connected. If the ssh account would be compromised an attacker could just connect to the server at the same time as you are and spy into the mysql process to find the password or intercept or change commands sent to the mysql server (with some non-neglectible effort, of course).
    – JohannesR
    Jul 10, 2009 at 14:18
1

You have to emulate terminal session:

ssh -t [email protected] "mysql -u blub -p"

In this case you will be asked for password which travel the network through encrypted ssh-channel and it will be not displayed in console.

1
  • This is real solution to my example but then again, scripting is about automatizing manual work and avoiding interactivity.
    – JohannesR
    Jul 10, 2009 at 14:12
0

You would need to execute a shell first, something like

ssh [email protected] bash -c 'mysql -u user -p$(cat /root/pass_file)'
2
  • That doesn't help, because it reads the password first and then connects to the ssh server and calls the bash with the plain password, which is the thing I'm trying to avoid.
    – JohannesR
    Jul 10, 2009 at 10:07
  • Oh, I just figured out, you want to read the file from the local machine... The only mechanism i can think of that avoids having the plain password in the cmdline is through stdin, but you obviously need it to interact with mysql. Try forwarding the mysql socket to the local machine over ssh, then connect to it (TCP forwarding is a bit more straightforward than unix socket, but the latter can be done as well, after jumping through a few hoops like socat). I feel complied to say that you probably need to take a step back and rethink what you need so the black magicks are avoided.
    – rpetre
    Jul 10, 2009 at 10:40
0

You use ssh instead of telnet but still send password through the command, to be freely executed on the remote machine in clear text (visible on a ps listing there).

Please read through this SecurityFocus article on Securing MySQL.

1
  • Right, this was my concern. So what is the solution?
    – JohannesR
    Jul 10, 2009 at 14:11
0

OK, I think I can with some certainty say that what you wan't to do is not possible in a general way, there are only workarounds for this that are dependent on the actual problem you want to solve.

Having thought about it a bit more, I would solve the "example problem" you gave simply by doing a port forwarding via ssh from the client to the server and then using a local mysql client with a local my.cnf, which actually is the way I always work with mysql.

0

You could use environment variables on your local machine. It would open security vulnerbilities if someone on your local machine can see your enviroment. and anyone on the server can see the password.

PASSWORD=$(cat pass-file) ssh [email protected] "mysql -u blub -p$PASSWORD"
1
  • 1
    That's not a solution, because the password will be shown in plaintext on a process list on the remote server.
    – JohannesR
    Jul 17, 2009 at 11:29
0

I think by using single quotation marks, the value for the environment variable will be taken from remote machine. So you can set PASSWORD=value in the .bashrc on remote machine. Then on your local machine run ssh [email protected] '. ~/.bashrc; mysql -u blub -p$PASSWORD'

1
  • Thx for this suggestion. I would rather have no file with the password on the remote end...
    – JohannesR
    Jul 21, 2009 at 10:25
0

Install sshpass (yum install)

sshpass -p password ssh [email protected]

If you do not want to worry about fingerprint keys add

sshpass -p password ssh -o StrictHostKeyChecking=no [email protected]

0

You can have bash interpret the parameter as a command and load your password before sending it over SSH

MY_PASSWORD=abcde ssh [email protected] `echo mysql -p$MY_PASSWORD`
1
  • Isn't that the same as Rory's answer?
    – JohannesR
    Sep 3, 2012 at 11:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .