Passing parameters to a SSH client to execute a ForceCommand with parameters - shell

I'm having trouble passing command parameters remotely to a "ForceCommand" program in ssh.
In my remote server I have this configuration in sshd_config:
Match User user_1
ForceCommand /home/user_1/user_1_shell
The user_1_shell program limits the commands the user can execute, in this case, I only allow the user to execute "set_new_mode param1 param2". Any other commands will be ignored.
So I expect that when a client logs in via ssh such as this one:
ssh user_1#remotehost "set_new_mode param1 param2"
The user_1_shell program seems to be executed, but the parameter string doesn't seem to be passed.
Maybe, I should be asking, does ForceCommand actually support this?
If yes, any suggestions on how I could make it work?
Thanks.

I found the answer. The remote server captures the parameter string and saves it in "$SSH_ORIGINAL_COMMAND" environment variable.

As already answered, the commandline sent from the ssh client is put into the SSH_ORIGINAL_COMMAND environment variable, only the ForcedCommand is executed.
If you use the information in SSH_ORIGINAL_COMMAND in your ForcedCommand you must take care of security implications. An attacker can augment your command with arbitrary additional commands by sending e.g. ; rm -rf / at the end of the commandline.
This article shows a generic script which can be used to lock down allowed parameters. It also contains links to relevant information.
The described method (the 'only' script) works as follows:
Make the 'only' script the ForcedCommand, and give it the allowed
command as its parameter. Note that more then one allowed command may be used.
Put a .onlyrules files into the home directory of user_1 and fill it with rules (regular expressions) which are matched against the
commandline sent by the ssh client.
Your example would look like:
Match User user_1
ForceCommand /usr/local/bin/only /home/user_1/user_1_shell
and if, for example, you want to allow as parameters only 'set_new_mode' with exactly two alphanumeric arbitrary parameters the .onlyrules file would look like this:
\:^/home/user_1/user_1_shell set_new_mode [[:alnum:]]\{1,\} [[:alnum:]]\{1,\}$:{p;q}
Note that for sending the command to the server you must use the whole commandline:
/home/user_1/user_1_shell set_new_mode param1 param2
'only' looks up the command on the server and uses its name for matching the rules. If any of these checks fail, the command is not run.

[Disclosure: I wrote sshdo which is described below]
There's a program called sshdo for doing this. It controls which commands may be executed via incoming ssh connections. It's available for download at:
http://raf.org/sshdo/ (read manual pages here)
https://github.com/raforg/sshdo/
It has a learning mode to allow all commands that are attempted, and a --learn option to produce the configuration needed to allow learned commands permanently. Then learning mode can be turned off and any other commands will not be executed.
It also has an --unlearn option to stop allowing commands that are no longer in use so as to maintain strict least privilege as requirements change over time.
It can also be configured manually.
It is very fussy about what it allows. It won't allow a command with any arguments. Only complete shell commands can be allowed. But it does support simple patterns to represent similar commands that vary only in the digits that appear on the command line (e.g. sequence numbers or date/time stamps).
It's like a firewall or whitelisting control for ssh commands.

Related

Creating a GUI to interact with Putty

I have to build one application which on button click starts passing command with putty.exe how can it be done with process.start ?
Process.start(#"C:\putty.exe")
ProcessStartInfo startinfo = new ProcessStartInfo();
startInfo.FileName=#"C:\putty.exe"
startInfo.Arguments = "some load session";
this is my current code but i want to push certain script and commands to putty terminal as well
It looks like PuTTY's command line support is rather minimal, but the -m option may work:
From http://the.earth.li/~sgtatham/putty/0.67/htmldoc/Chapter3.html#using-cmdline
3.8.3.6 -m: read a remote command or script from a file
The -m option performs a similar function to the ‘Remote command’ box in the SSH panel of the PuTTY configuration box (see section 4.18.1). However, the -m option expects to be given a local file name, and it will read a command from that file.
With some servers (particularly Unix systems), you can even put multiple lines in this file and execute more than one command in sequence, or a whole shell script; but this is arguably an abuse, and cannot be expected to work on all servers. In particular, it is known not to work with certain ‘embedded’ servers, such as Cisco routers.
You'll have to put your command(s) in a file before and pass that to PuTTY, but for simple tasks, it could work.
As mentioned in a comment on the question, Plink sounds much more amenable to what you're trying to do, as it (appears to) support a fully interactive session via the StandardInput and StandardOutput properties on the object you'll get back from Process.Start().

How Secure is using execFile for Bash Scripts?

I have a node.js app which is using the child_process.execFile command to run a command-line utility.
I'm worried that it would be possible for a user to run commands locally (a rm / -rf horror scenario comes to mind).
How secure is using execFile for Bash scripts? Any tips to ensure that flags I pass to execFile are escaped by the unix box hosting the server?
Edit
To be more precise, I'm more wondering if the arguments being sent to the file could be interpreted as a command and executed.
The other concern is inside the bash script itself, which is technically outside the scope of this question.
Using child_process.execFile by itself is perfectly safe as long as the user doesn't get to specify the command name.
It does not run the command in a shell (like child_process.exec does), so there is no need to escape anything.
child_process.execFile will execute commands with the user id of the node process, so it can do anything that user could do, which includes removing all the server files.
Not a good idea to let user pass in command as you seem to be implying by your question.
You could consider running the script in a sandbox by using chroot, and limiting the commands and what resides on the available file system, but this could get complet in a hurry.
The command you pass will get executed directly via some flavor of exec, so unless what you trying to execute is a script, it does not need to be escaped in any way.

Automatically decrypt and run an encrypted bash script without saving decrypted file to file system

I have a shell script that produces sensitive content when run. It sits on a box that only a few users have permissions to access. However, I have also added layered obfuscation to prevent unauthorized usage, via the following:
script must be run as root
script must be passed specific command line arguments to produce any output
script has been encoded by the shell compiler "shc" to mask facts #1 and #2 from normal users (those who would not know to use TRACE or STRINGS to still view the actual code).
To then add a layer of actual security to protect again more advanced users and system admins, I have also encrypted the script with gpg.
My question is -- Is there a gpg command (or other encryption method) that I could run which prompts for the decryption passphrase, and decrypts the script and runs it in memory only (without saving the decrypted version of the file to the file system)?
I realize that sensitive information may still exist in unprotected memory while being executed, I'll address that separately.
You can capture the output of decrypting by
decrypted=$(gpg -d ...)
You can then eval the result
eval "$decrypted"
Another simple option to contrast with choroba's answer:
Save the decrypted output to a file in /dev/shm/. (It's an in-ram tmpfs filesystem there by default on virtually all Linux distros.) Setup a trap to delete the file when your script exits.
It's very possible I could refine this, but here's another idea where you execute the script rather than evaluate it like in choroba's example. It allows you to pass arguments...
bash <( gpg -d ... ) arg1 arg2
...it 'overrides' the interpreter, though. I.e. I'd run my scripts with bash -ue. May or may not be a problem depending on the scripts and whether you are writing them yourself or not :)

Run only the first Bash command of multiple inline commands

I have a program which runs certain commands over SSH. Some of the commands are static (always the same) and others have arguments which change between runs. The program uses a private key to connect to the server, and the authorized key is locked down to force the command "sh run_script.sh".
run_script.sh will only run $SSH_ORIGINAL_COMMAND if it matches a set of static commands, or if it begins in a certain way (for non-static commands).
The problem is that something like
allowedCommand arg1 arg2 && rm -r ~/
would probably slip through.
Is it possible to have bash only run the first command, and ignore anything after a pipe or &&?
You might be able to set a wrapper script as the login shell (instead of /bin/bash) and have it use sed or something to strip the unwanted parts off. It would be subject to possible false positives and may fail for arguments that contain whitespace and in other situations (see BashFAQ/050).
There might be unforeseen security issues that are introduced by this approach.
It would be better to use the security features provided by ssh, sudo, a restricted shell such as rbash and other security facilities provided by the operating system in combination.

Escape sequence <ESC>]0;

I am currently trying to write a script that uses expect to logon to SSH. Logging on to a server every prompt appears as [user#host]~/directory$ when I use a xterm color terminal. However, if I read the output from SSH directly with expect I see the following <ESC>]0;user#host:~/directory[user#host]~/directory$. Using export PS1="#-->" changes the result to <ESC>]0;user#host:~/directory#-->.
My question is: What does the sequence <ESC>]0;do? And which class of terminals does it belong to? I could not find it for neither VT52 nor VT100.
by default, the label of each tab is the name of the job that's running in that session. some systems are configured to augment this with additional information such as the hostname you're logged in to or your current directory; this is done by sending a special code of:
ESC]0;<string>^G
such as, ESC]0;david#Scott:~^G, would put "david#Scott:~" in my tab title
this is referred to as the XTERM hardstatus hack.

Resources