 |
|
 |
by Tan Chew Keong
Release Date: 08 May 2005
Orenosv HTTP/FTP Server
is a stable, reliable and high performance HTTP/FTP/FTPS server that can operate 24H/365D. Orenosp runs on
Windows platforms (NT, 2000, XP and 2003) and Linux x86.
A remote buffer overflow vulnerability was found in Orenosv's FTP server. This vulnerability may be exploited
by a malicious user to crash the server. A buffer overflow vulnerability also exists in the SSI module of Orenosv's
HTTP server. This overflow may be triggered using a specially crafted SSI file (.shtml).
Orenosv HTTP/FTP Server Version 0.8.1 on English Win2K SP4.
A remote buffer overflow vulnerability was found in Orenosv's FTP server. This vulnerability may be exploited
by a malicious user to crash the server. A buffer overflow vulnerability also exists in the SSI module of Orenosv's
HTTP server. This overflow may be triggered using a specially crafted SSI file (.shtml).
1. Multiple FTP Commands Buffer Overflow Vulnerability.
This buffer overflow is triggered when the server receives a FTP file/directory manipulation command with a filename
that is 249 or 250
bytes long. For 4-character FTP file/directory commands, 249-bytes filenames will cause the overflow. Examples of
4-character FTP commands include LIST, DELE, RETR etc. For 3-character FTP commands, 250-bytes filenames will cause the
overflow. 3-character FTP commands include MKD, RMD, CWD, etc.
The server restricts the maximum length of each input line, hence using a filename that is longer than 250
will not trigger the vulnerable function. This is illustrated below.
MKD AAAAAAAA.... // 250 bytes filename
RMD AAAAAAAA.... // 250 bytes filename
DELE AAAAAAAA... // 249 bytes filename
Reversing orenosv.exe shows that the problem lies in the unbounded copy that occurs within the ftp_xlate_path() and
the ftp_is_canonial() functions. These two functions are called whenever FTP file/directory manipulation commands
are received. The following paragraphs explain the cause of the overflow using the MKD and RMD commands as examples.
Upon receiving the MKD or RMD FTP commands, the function ftp_do_dele() will be called. In this function,
two character arrays of 256 bytes each is allocated on the stack. The second array (let's call it
buffer2_from_ftp_do_delete), which lies next to the saved EIP, is passed to the function ftp_find_fpath().
Subsquently, this array is passed to the ftp_xlate_path() function.
In ftp_xlate_path(), the string containing the FTP root (assume "C:\ftproot") is copied into
buffer2_from_ftp_do_delete. This takes up 10 bytes, excluding NULL,
assuming the FTP root is "C:\ftproot". Next, the received filename (250 bytes), with a forward slash added in front
(251 bytes), is concatenated to buffer2_from_ftp_do_delete. This overwrites the saved EIP with a value that we
can control when function ftp_do_delete() returns. Unfortunately, other overflows may occur before ftp_do_delete()
returns, preventing us from controlling the EIP using this buffer.
After returning from ftp_xlate_path(), there will be a call to ftp_acl_check() to check
whether the user has the privilege to do a MKD or RMD. If this check fails, sprintf() will be called to format
the error message. This sprintf() call will overflow the local sprintf_buffer buffer and overwrite the
saved EIP, but not with values that we can control. i.e. EIP will be overwritten with bytes from "access denied".
If the user is allowed to perform MKD or RMD, there will be a call to ftp_is_canonical().
An unsafe copy of overlapping arrays will occur in this
function, causing an exception to occur due to writing beyond the bottom of the stack. This allows us to control EIP
via an overwritten SEH.
Exploitation is complicated by the fact that the buffer is limited to 250 bytes. Orenosv runs in two separate processes.
(1) the monitoring process, (2) the server process. The monitoring process will restart the server process if it
crashes due to the overflow. On our test system, we were able to cause a DoS on the server by sending the overflow
buffer in quick successions to the server. This causes both the server and monitor process to crash, thus preventing
any automatic restarts.
The vulnerable functions are shown below in pseudo-C.
ftp_do_delete(arg1, arg2)
{
char buffer1[256];
char buffer2[256];
...
// received_file is AAAAAAAAAA.... (250 bytes)
ftp_find_fpath(arg1, arg2, received_filename, buffer2, some_buffer, 4);
...
}
ftp_find_fpath(arg1, arg2, received_filename, buffer2_from_ftp_do_delete[256], arg3, arg4)
{
char unknown[40];
char sprintf_buffer[256];
// this will copy received_filename (250 bytes) to arg3, adding a forward slash in front.
// (i.e. /AAAAAA... 251 bytes)
ftp_build_vpath(arg1, received_filename, arg3);
...
ftp_xlate_path(arg1, arg3, buffer2_from_ftp_do_delete[256]); // buffer2_from_ftp_do_delete will be overflowed
...
if(ftp_acl_check(arg1, arg4, arg3, buffer2_from_ftp_do_delete))
{
// sprintf OVERFLOW, arg3 is "/AAAA..." 251 bytes + " access denied" > 256 bytes!!!
sprintf(sprintf_buffer[256], "%s access denied", arg3);
ftp_msg_write_rc(....);
return;
}
....
ftp_is_canonical(buffer2_from_ftp_do_delete, ..); // the stack will be overrun.
...
}
ftp_xlate_path(arg1, arg2, buffer2_from_ftp_do_delete[256])
{
// arg2 contains "/AAAAAA...." (251 bytes)
...
...
strcpy(buffer2_from_ftp_do_delete, FTPROOT); // assume FTPROOT is c:/ftproot (10 bytes)
...
strcat(buffer2_from_ftp_do_delete, arg2); // buffer2_from_ftp_do_delete is now overflowed
// (10 + 251 = 261 bytes) excluding NULL
}
ftp_is_canonical(buffer2_from_ftp_do_delete, arg1)
{
DWORD dword_var;
char buf1[256];
char buf2[256];
char buf3[256];
..
...
// This will do a NULL terminated unsafe copy from buffer2_from_ftp_do_delete to buf1,
// character 0x2f will be dropped if it is the last character in the buffer.
// Since the string in buffer2_from_ftp_do_delete is 261 bytes, its contents will overrun into buf2.
strcpy_droplast(buf1, buffer2_from_ftp_do_delete, 0x2f);
// buf1 now holds "c:/ftproot/AAAA...", with the last few bytes overrun into buf2.
...
...
while(...)
{
// unsafe NULL terminated copy
// EAX points to "AAAA..." within buf1
ptr = buf2;
while(*EAX) // copying the filename within buf1 to buf2
{
// Since the contents of buf1 overlaps into buf2, the NULL termination condition
// will not be met. i.e. The copying will continue until it hits the bottom of the stack.
// A write exception will occur and the SEH will be executed. This allows us to control
// EIP via an overwritten SEH.
*ptr++ = *EAX++;
}
}
}
The following Ollydbg capture shows the SEH being overwritten by a LIST command with 249-bytes filename.
2. cgissi.exe Overly Long SSI Command Buffer Overflow Vulnerability.
Orenosv supports the use of SSI (.shtml). This supported is provided by cgissi.exe. A buffer overflow vulnerability
exists in cgissi.exe when processing an overly long SSI command name. An example SSI tag that will trigger
this overflow is shown below.
<!--#aaaaa... -->
Approx. 120 bytes of aaaaaa...
The overflow occurs in the parse_cmd() function. In this function, a loop performs an unsafe copy of the
SSI command name "aaaaaa..." to a local stack buffer. This copy loop is terminated by the space character. The EIP
is overwritten as shown below. Exploitation may be limited since the SSI command name is limited to less than 128 bytes.
- Upgrade to version 0.8.1a or later.
26 Apr 05 - Vulnerability Discovered.
28 Apr 05 - Initial Author Notification.
29 Apr 05 - Initial Author Reply.
01 May 05 - Author Provided Fix for Testing.
01 May 05 - Informed Author that Overflow will still occur in os_fn_nativize().
01 May 05 - Author Provided Another Fix for Testing.
01 May 05 - Informed Author that Overflow will still occur due to several unsafe sprintf().
05 May 05 - Author Provided Another Fix for Testing.
05 May 05 - Informed Author of Potential Problem in STOU command.
06 May 05 - Author Provided Auother Fix for Testing.
07 May 05 - Author Released Patch.
08 May 05 - Public Release.
For further questions and enquries, email them to the following.
Overall-in-charge: Tan Chew Keong
webmaster@security.org.sg
|
 |