mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-27 02:02:26 +00:00
Update to password length traffic analysis: one Cisco router can
apparently not deal with SSH1_MSG_IGNORE _or_ padded passwords, so we must fall back to sending an undefended password. [originally from svn r1332]
This commit is contained in:
parent
3dfaf08a0a
commit
6c9cdbe29f
84
ssh.c
84
ssh.c
@ -159,6 +159,8 @@ static const char *const ssh2_disconnect_reasons[] = {
|
|||||||
*/
|
*/
|
||||||
#define BUG_CHOKES_ON_SSH1_IGNORE 1
|
#define BUG_CHOKES_ON_SSH1_IGNORE 1
|
||||||
#define BUG_SSH2_HMAC 2
|
#define BUG_SSH2_HMAC 2
|
||||||
|
#define BUG_NEEDS_SSH1_PLAIN_PASSWORD 4
|
||||||
|
|
||||||
|
|
||||||
#define GET_32BIT(cp) \
|
#define GET_32BIT(cp) \
|
||||||
(((unsigned long)(unsigned char)(cp)[0] << 24) | \
|
(((unsigned long)(unsigned char)(cp)[0] << 24) | \
|
||||||
@ -1418,17 +1420,15 @@ static void ssh_detect_bugs(char *vstring)
|
|||||||
char *imp; /* pointer to implementation part */
|
char *imp; /* pointer to implementation part */
|
||||||
imp = vstring;
|
imp = vstring;
|
||||||
imp += strcspn(imp, "-");
|
imp += strcspn(imp, "-");
|
||||||
if (*imp)
|
if (*imp) imp++;
|
||||||
imp++;
|
|
||||||
imp += strcspn(imp, "-");
|
imp += strcspn(imp, "-");
|
||||||
if (*imp)
|
if (*imp) imp++;
|
||||||
imp++;
|
|
||||||
|
|
||||||
ssh_remote_bugs = 0;
|
ssh_remote_bugs = 0;
|
||||||
|
|
||||||
if (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") ||
|
if (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") ||
|
||||||
!strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") ||
|
!strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") ||
|
||||||
!strcmp(imp, "1.2.22")) {
|
!strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25")) {
|
||||||
/*
|
/*
|
||||||
* These versions don't support SSH1_MSG_IGNORE, so we have
|
* These versions don't support SSH1_MSG_IGNORE, so we have
|
||||||
* to use a different defence against password length
|
* to use a different defence against password length
|
||||||
@ -1438,6 +1438,16 @@ static void ssh_detect_bugs(char *vstring)
|
|||||||
logevent("We believe remote version has SSH1 ignore bug");
|
logevent("We believe remote version has SSH1 ignore bug");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(imp, "Cisco-1.25")) {
|
||||||
|
/*
|
||||||
|
* These versions need a plain password sent; they can't
|
||||||
|
* handle having a null and a random length of data after
|
||||||
|
* the password.
|
||||||
|
*/
|
||||||
|
ssh_remote_bugs |= BUG_NEEDS_SSH1_PLAIN_PASSWORD;
|
||||||
|
logevent("We believe remote version needs a plain SSH1 password");
|
||||||
|
}
|
||||||
|
|
||||||
if (!strncmp(imp, "2.1.0", 5) || !strncmp(imp, "2.0.", 4) ||
|
if (!strncmp(imp, "2.1.0", 5) || !strncmp(imp, "2.0.", 4) ||
|
||||||
!strncmp(imp, "2.2.0", 5) || !strncmp(imp, "2.3.0", 5) ||
|
!strncmp(imp, "2.2.0", 5) || !strncmp(imp, "2.3.0", 5) ||
|
||||||
!strncmp(imp, "2.1 ", 4)) {
|
!strncmp(imp, "2.1 ", 4)) {
|
||||||
@ -1479,8 +1489,8 @@ static int do_ssh_init(unsigned char c)
|
|||||||
crReturn(1); /* get another character */
|
crReturn(1); /* get another character */
|
||||||
}
|
}
|
||||||
|
|
||||||
vstring = smalloc(16);
|
|
||||||
vstrsize = 16;
|
vstrsize = 16;
|
||||||
|
vstring = smalloc(vstrsize);
|
||||||
strcpy(vstring, "SSH-");
|
strcpy(vstring, "SSH-");
|
||||||
vslen = 4;
|
vslen = 4;
|
||||||
i = 0;
|
i = 0;
|
||||||
@ -1506,10 +1516,10 @@ static int do_ssh_init(unsigned char c)
|
|||||||
|
|
||||||
vstring[vslen] = 0;
|
vstring[vslen] = 0;
|
||||||
vlog = smalloc(20 + vslen);
|
vlog = smalloc(20 + vslen);
|
||||||
|
vstring[strcspn (vstring, "\r\n")] = '\0'; /* remove end-of-line chars */
|
||||||
sprintf(vlog, "Server version: %s", vstring);
|
sprintf(vlog, "Server version: %s", vstring);
|
||||||
ssh_detect_bugs(vstring);
|
|
||||||
vlog[strcspn(vlog, "\r\n")] = '\0';
|
|
||||||
logevent(vlog);
|
logevent(vlog);
|
||||||
|
ssh_detect_bugs(vstring);
|
||||||
sfree(vlog);
|
sfree(vlog);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2405,26 +2415,13 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
|
|||||||
* use of the fact that the password is interpreted
|
* use of the fact that the password is interpreted
|
||||||
* as a C string: so we can append a NUL, then some
|
* as a C string: so we can append a NUL, then some
|
||||||
* random data.
|
* random data.
|
||||||
|
*
|
||||||
|
* One server (a Cisco one) can deal with neither
|
||||||
|
* SSH1_MSG_IGNORE _nor_ a padded password string.
|
||||||
|
* For this server we are left with no defences
|
||||||
|
* against password length sniffing.
|
||||||
*/
|
*/
|
||||||
if (ssh_remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE) {
|
if (!(ssh_remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE)) {
|
||||||
char string[64];
|
|
||||||
char *s;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
len = strlen(password);
|
|
||||||
if (len < sizeof(string)) {
|
|
||||||
s = string;
|
|
||||||
strcpy(string, password);
|
|
||||||
len++; /* cover the zero byte */
|
|
||||||
while (len < sizeof(string)) {
|
|
||||||
string[len++] = (char) random_byte();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s = password;
|
|
||||||
}
|
|
||||||
send_packet(pwpkt_type, PKT_INT, len,
|
|
||||||
PKT_DATA, s, len, PKT_END);
|
|
||||||
} else {
|
|
||||||
int bottom, top, pwlen, i;
|
int bottom, top, pwlen, i;
|
||||||
char *randomstr;
|
char *randomstr;
|
||||||
|
|
||||||
@ -2456,8 +2453,41 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt)
|
|||||||
PKT_STR, randomstr, PKT_END);
|
PKT_STR, randomstr, PKT_END);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
logevent("Sending password with camouflage packets");
|
||||||
ssh_pkt_defersend();
|
ssh_pkt_defersend();
|
||||||
}
|
}
|
||||||
|
else if (!(ssh_remote_bugs & BUG_NEEDS_SSH1_PLAIN_PASSWORD)) {
|
||||||
|
char string[64];
|
||||||
|
char *s;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = strlen(password);
|
||||||
|
if (len < sizeof(string)) {
|
||||||
|
s = string;
|
||||||
|
strcpy(string, password);
|
||||||
|
len++; /* cover the zero byte */
|
||||||
|
while (len < sizeof(string)) {
|
||||||
|
string[len++] = (char) random_byte();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s = password;
|
||||||
|
}
|
||||||
|
logevent("Sending length-padded password");
|
||||||
|
send_packet(pwpkt_type, PKT_INT, len,
|
||||||
|
PKT_DATA, s, len, PKT_END);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* The server has _both_
|
||||||
|
* BUG_CHOKES_ON_SSH1_IGNORE and
|
||||||
|
* BUG_NEEDS_SSH1_PLAIN_PASSWORD. There is
|
||||||
|
* therefore nothing we can do.
|
||||||
|
*/
|
||||||
|
int len;
|
||||||
|
len = strlen(password);
|
||||||
|
logevent("Sending unpadded password");
|
||||||
|
send_packet(pwpkt_type, PKT_INT, len,
|
||||||
|
PKT_DATA, password, len, PKT_END);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
send_packet(pwpkt_type, PKT_STR, password, PKT_END);
|
send_packet(pwpkt_type, PKT_STR, password, PKT_END);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user