Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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 user@example.com "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 user@example.com "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.
share|improve this question
    
Would xclip be able to do this? –  Brad Gilbert Jul 10 '09 at 16:06
    
I chose Zac's solution ('expect') because it seems like the most general solution to the problem. –  JohannesR Jul 17 '09 at 11:34

12 Answers 12

up vote 3 down vote accepted

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 user@example.com "mysql -u blub"
expect "*ssword:*"
send -- "mypass\r"
interact
share|improve this answer

Try using a <.

ssh user@example.com "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 user@example.com "mysql -u blub -p < file.sql" < password

share|improve this answer
    
Very nice, that works perfect for my example. –  JohannesR Jul 14 '09 at 14:11

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.

share|improve this answer
    
Isn't that what expect is doing actually? –  JohannesR Jul 14 '09 at 14:13
    
A similar patch is available on the openssh mailing list, patching this directly into the openssh client program. –  JohannesR Jul 14 '09 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)? –  otto.poellath Jul 14 '09 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. –  otto.poellath Jul 23 '09 at 8:40

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 sven@192.168.2.10 \"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.

share|improve this answer
    
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 '09 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 '09 at 14:18

You have to emulate terminal session:

ssh -t user@example.com "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.

share|improve this answer
    
This is real solution to my example but then again, scripting is about automatizing manual work and avoiding interactivity. –  JohannesR Jul 10 '09 at 14:12

You would need to execute a shell first, something like

ssh user@exampl.com bash -c 'mysql -u user -p$(cat /root/pass_file)'
share|improve this answer
    
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 '09 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 '09 at 10:40

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.

share|improve this answer
    
Right, this was my concern. So what is the solution? –  JohannesR Jul 10 '09 at 14:11

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.

share|improve this answer

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 user@example.com "mysql -u blub -p$PASSWORD"
share|improve this answer
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 '09 at 11:29

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 user@example.com '. ~/.bashrc; mysql -u blub -p$PASSWORD'

share|improve this answer
    
Thx for this suggestion. I would rather have no file with the password on the remote end... –  JohannesR Jul 21 '09 at 10:25

Install sshpass (yum install)

sshpass -p password ssh user@host.com

If you do not want to worry about fingerprint keys add

sshpass -p password ssh -o StrictHostKeyChecking=no user@host.com

share|improve this answer

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

MY_PASSWORD=abcde ssh user@example.com `echo mysql -p$MY_PASSWORD`
share|improve this answer
    
Isn't that the same as Rory's answer? –  JohannesR Sep 3 '12 at 11:53

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.