Correct multiple vulnerabilities in OpenSSH.

Security:	FreeBSD-SA-06:22.openssh
Approved by:	re (kensmith)
This commit is contained in:
simon 2006-09-30 19:50:57 +00:00
parent 2c92928f9d
commit 0202bc32c2
14 changed files with 62 additions and 12 deletions

View File

@ -50,6 +50,7 @@ typedef struct KbdintDevice KbdintDevice;
struct Authctxt {
int success;
int authenticated; /* authenticated and alarms cancelled */
int postponed; /* authentication needs another step */
int valid; /* user exists and is allowed to login */
int attempt;

View File

@ -27,6 +27,24 @@ RCSID("$OpenBSD: deattack.c,v 1.19 2003/09/18 08:49:45 markus Exp $");
#include "xmalloc.h"
#include "deattack.h"
/*
* CRC attack detection has a worst-case behaviour that is O(N^3) over
* the number of identical blocks in a packet. This behaviour can be
* exploited to create a limited denial of service attack.
*
* However, because we are dealing with encrypted data, identical
* blocks should only occur every 2^35 maximally-sized packets or so.
* Consequently, we can detect this DoS by looking for identical blocks
* in a packet.
*
* The parameter below determines how many identical blocks we will
* accept in a single packet, trading off between attack detection and
* likelihood of terminating a legitimate connection. A value of 32
* corresponds to an average of 2^40 messages before an attack is
* misdetected
*/
#define MAX_IDENTICAL 32
/* SSH Constants */
#define SSH_MAXBLOCKS (32 * 1024)
#define SSH_BLOCKSIZE (8)
@ -87,7 +105,7 @@ detect_attack(u_char *buf, u_int32_t len, u_char *IV)
static u_int16_t *h = (u_int16_t *) NULL;
static u_int32_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
u_int32_t i, j;
u_int32_t l;
u_int32_t l, same;
u_char *c;
u_char *d;
@ -133,7 +151,7 @@ detect_attack(u_char *buf, u_int32_t len, u_char *IV)
if (IV)
h[HASH(IV) & (n - 1)] = HASH_IV;
for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) {
for (c = buf, same = j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) {
for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED;
i = (i + 1) & (n - 1)) {
if (h[i] == HASH_IV) {
@ -144,6 +162,8 @@ detect_attack(u_char *buf, u_int32_t len, u_char *IV)
break;
}
} else if (!CMP(c, buf + h[i] * SSH_BLOCKSIZE)) {
if (++same > MAX_IDENTICAL)
return (DEATTACK_DOS_DETECTED);
if (check_crc(c, buf, len, IV))
return (DEATTACK_DETECTED);
else

View File

@ -25,6 +25,7 @@
/* Return codes */
#define DEATTACK_OK 0
#define DEATTACK_DETECTED 1
#define DEATTACK_DOS_DETECTED 2
int detect_attack(u_char *, u_int32_t, u_char[8]);
#endif

View File

@ -540,6 +540,11 @@ struct winsize {
# undef HAVE_UPDWTMPX
#endif
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) && \
defined(SYSLOG_R_SAFE_IN_SIGHAND)
# define DO_LOG_SAFE_IN_SIGHAND
#endif
#if !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY)
# define memmove(s1, s2, n) bcopy((s2), (s1), (n))
#endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */

View File

@ -130,6 +130,20 @@ error(const char *fmt,...)
va_end(args);
}
void
sigdie(const char *fmt,...)
{
va_list args;
#ifdef DO_LOG_SAFE_IN_SIGHAND
va_start(args, fmt);
do_log(SYSLOG_LEVEL_FATAL, fmt, args);
va_end(args);
#endif
_exit(1);
}
/* Log this message (information that usually should go to the log). */
void

View File

@ -64,6 +64,7 @@ LogLevel log_level_number(char *);
void fatal(const char *, ...) __dead __attribute__((format(printf, 1, 2)));
void error(const char *, ...) __attribute__((format(printf, 1, 2)));
void sigdie(const char *, ...) __attribute__((format(printf, 1, 2)));
void logit(const char *, ...) __attribute__((format(printf, 1, 2)));
void verbose(const char *, ...) __attribute__((format(printf, 1, 2)));
void debug(const char *, ...) __attribute__((format(printf, 1, 2)));

View File

@ -978,9 +978,16 @@ packet_read_poll1(void)
* (C)1998 CORE-SDI, Buenos Aires Argentina
* Ariel Futoransky(futo@core-sdi.com)
*/
if (!receive_context.plaintext &&
detect_attack(buffer_ptr(&input), padded_len, NULL) == DEATTACK_DETECTED)
packet_disconnect("crc32 compensation attack: network attack detected");
if (!receive_context.plaintext) {
switch (detect_attack(buffer_ptr(&input), padded_len, NULL)) {
case DEATTACK_DETECTED:
packet_disconnect("crc32 compensation attack: "
"network attack detected");
case DEATTACK_DOS_DETECTED:
packet_disconnect("deattack denial of "
"service detected");
}
}
/* Decrypt data to incoming_packet. */
buffer_clear(&incoming_packet);

View File

@ -2472,7 +2472,7 @@ do_cleanup(Authctxt *authctxt)
return;
called = 1;
if (authctxt == NULL)
if (authctxt == NULL || !authctxt->authenticated)
return;
#ifdef KRB5
if (options.kerberos_ticket_cleanup &&

View File

@ -38,4 +38,4 @@
# Cipher 3des
# Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc
# EscapeChar ~
# VersionAddendum FreeBSD-20050903
# VersionAddendum FreeBSD-20060930

View File

@ -900,7 +900,7 @@ Note that this option applies to protocol version 2 only.
Specifies a string to append to the regular version string to identify
OS- or site-specific modifications.
The default is
.Dq FreeBSD-20050903 .
.Dq FreeBSD-20060930 .
.It Cm XAuthLocation
Specifies the full pathname of the
.Xr xauth 1

View File

@ -317,7 +317,7 @@ grace_alarm_handler(int sig)
kill(pmonitor->m_pid, SIGALRM);
/* Log error and exit. */
fatal("Timeout before authentication for %s", get_remote_ipaddr());
sigdie("Timeout before authentication for %s", get_remote_ipaddr());
}
/*
@ -1730,6 +1730,7 @@ main(int ac, char **av)
}
authenticated:
authctxt->authenticated = 1;
#ifdef SSH_AUDIT_EVENTS
audit_event(SSH_AUTH_SUCCESS);
#endif

View File

@ -14,7 +14,7 @@
# Note that some of FreeBSD's defaults differ from OpenBSD's, and
# FreeBSD has a few additional options.
#VersionAddendum FreeBSD-20050903
#VersionAddendum FreeBSD-20060930
#Port 22
#Protocol 2

View File

@ -725,7 +725,7 @@ The default is
Specifies a string to append to the regular version string to identify
OS- or site-specific modifications.
The default is
.Dq FreeBSD-20050903 .
.Dq FreeBSD-20060930 .
.It Cm X11DisplayOffset
Specifies the first display number available for
.Nm sshd Ns 's

View File

@ -6,7 +6,7 @@
#define SSH_VERSION (ssh_version_get())
#define SSH_RELEASE (ssh_version_get())
#define SSH_VERSION_BASE "OpenSSH_4.2p1"
#define SSH_VERSION_ADDENDUM "FreeBSD-20050903"
#define SSH_VERSION_ADDENDUM "FreeBSD-20060930"
const char *ssh_version_get(void);
void ssh_version_set_addendum(const char *add);