mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-05 21:42:47 -05:00
Move password-packet padding into the BPP module.
Now when we construct a packet containing sensitive data, we just set a field saying '... and make it take up at least this much space, to disguise its true size', and nothing in the rest of the system worries about that flag until ssh2bpp.c acts on it. Also, I've changed the strategy for doing the padding. Previously, we were following the real packet with an SSH_MSG_IGNORE to make up the size. But that was only a partial defence: it works OK against passive traffic analysis, but an attacker proxying the TCP stream and dribbling it out one byte at a time could still have found out the size of the real packet by noting when the dribbled data provoked a response. Now I put the SSH_MSG_IGNORE _first_, which should defeat that attack. But that in turn doesn't work when we're doing compression, because we can't predict the compressed sizes accurately enough to make that strategy sensible. Fortunately, compression provides an alternative strategy anyway: if we've got zlib turned on when we send one of these sensitive packets, then we can pad out the compressed zlib data as much as we like by adding empty RFC1951 blocks (effectively chaining ZLIB_PARTIAL_FLUSHes). So both strategies should now be dribble-proof.
This commit is contained in:
87
ssh.c
87
ssh.c
@ -342,7 +342,8 @@ static void ssh_comp_none_cleanup(void *handle)
|
||||
{
|
||||
}
|
||||
static void ssh_comp_none_block(void *handle, unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen)
|
||||
unsigned char **outblock, int *outlen,
|
||||
int minlen)
|
||||
{
|
||||
}
|
||||
static int ssh_decomp_none_block(void *handle, unsigned char *block, int len,
|
||||
@ -350,15 +351,11 @@ static int ssh_decomp_none_block(void *handle, unsigned char *block, int len,
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int ssh_comp_none_disable(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const static struct ssh_compress ssh_comp_none = {
|
||||
"none", NULL,
|
||||
ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block,
|
||||
ssh_comp_none_init, ssh_comp_none_cleanup, ssh_decomp_none_block,
|
||||
ssh_comp_none_disable, NULL
|
||||
NULL
|
||||
};
|
||||
extern const struct ssh_compress ssh_zlib;
|
||||
const static struct ssh_compress *const compressions[] = {
|
||||
@ -1327,72 +1324,6 @@ static void ssh_send_outgoing_data(void *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a packet whose length needs to be disguised (typically
|
||||
* passwords or keyboard-interactive responses).
|
||||
*/
|
||||
static void ssh2_pkt_send_with_padding(Ssh ssh, PktOut *pkt, int padsize)
|
||||
{
|
||||
#if 0
|
||||
if (0) {
|
||||
/*
|
||||
* The simplest way to do this is to adjust the
|
||||
* variable-length padding field in the outgoing packet.
|
||||
*
|
||||
* Currently compiled out, because some Cisco SSH servers
|
||||
* don't like excessively padded packets (bah, why's it
|
||||
* always Cisco?)
|
||||
*/
|
||||
pkt->forcepad = padsize;
|
||||
ssh2_pkt_send(ssh, pkt);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* If we can't do that, however, an alternative approach is to
|
||||
* bundle the packet tightly together with an SSH_MSG_IGNORE
|
||||
* such that their combined length is a constant. So first we
|
||||
* construct the final form of this packet and append it to
|
||||
* the outgoing_data bufchain...
|
||||
*/
|
||||
ssh_pkt_write(ssh, pkt);
|
||||
|
||||
/*
|
||||
* ... but before we return from this function (triggering a
|
||||
* call to the outgoing_data_sender), we also construct an
|
||||
* SSH_MSG_IGNORE which includes a string that's an exact
|
||||
* multiple of the cipher block size. (If the cipher is NULL
|
||||
* so that the block size is unavailable, we don't do this
|
||||
* trick at all, because we gain nothing by it.)
|
||||
*/
|
||||
if (!(ssh->remote_bugs & BUG_CHOKES_ON_SSH2_IGNORE)) {
|
||||
int stringlen, i;
|
||||
|
||||
stringlen = (256 - bufchain_size(&ssh->outgoing_data));
|
||||
stringlen += ssh->v2_out_cipherblksize - 1;
|
||||
stringlen -= (stringlen % ssh->v2_out_cipherblksize);
|
||||
|
||||
/*
|
||||
* Temporarily disable actual compression, so we can
|
||||
* guarantee to get this string exactly the length we want
|
||||
* it. The compression-disabling routine should return an
|
||||
* integer indicating how many bytes we should adjust our
|
||||
* string length by.
|
||||
*/
|
||||
stringlen -= ssh2_bpp_temporarily_disable_compression(ssh->bpp);
|
||||
|
||||
pkt = ssh_bpp_new_pktout(ssh->bpp, SSH2_MSG_IGNORE);
|
||||
{
|
||||
strbuf *substr = strbuf_new();
|
||||
for (i = 0; i < stringlen; i++)
|
||||
put_byte(substr, random_byte());
|
||||
put_stringsb(pkt, substr);
|
||||
}
|
||||
ssh_pkt_write(ssh, pkt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send all queued SSH-2 packets.
|
||||
*/
|
||||
@ -9563,7 +9494,8 @@ static void do_ssh2_userauth(void *vctx)
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the response(s) to the server.
|
||||
* Send the response(s) to the server, padding
|
||||
* them to disguise their true length.
|
||||
*/
|
||||
s->pktout = ssh_bpp_new_pktout(
|
||||
ssh->bpp, SSH2_MSG_USERAUTH_INFO_RESPONSE);
|
||||
@ -9572,7 +9504,8 @@ static void do_ssh2_userauth(void *vctx)
|
||||
put_stringz(s->pktout,
|
||||
s->cur_prompt->prompts[i]->result);
|
||||
}
|
||||
ssh2_pkt_send_with_padding(ssh, s->pktout, 256);
|
||||
s->pktout->minlen = 256;
|
||||
ssh2_pkt_send(ssh, s->pktout);
|
||||
|
||||
/*
|
||||
* Free the prompts structure from this iteration.
|
||||
@ -9661,7 +9594,8 @@ static void do_ssh2_userauth(void *vctx)
|
||||
put_stringz(s->pktout, "password");
|
||||
put_bool(s->pktout, FALSE);
|
||||
put_stringz(s->pktout, s->password);
|
||||
ssh2_pkt_send_with_padding(ssh, s->pktout, 256);
|
||||
s->pktout->minlen = 256;
|
||||
ssh2_pkt_send(ssh, s->pktout);
|
||||
logevent("Sent password");
|
||||
s->type = AUTH_TYPE_PASSWORD;
|
||||
|
||||
@ -9797,7 +9731,8 @@ static void do_ssh2_userauth(void *vctx)
|
||||
put_stringz(s->pktout,
|
||||
s->cur_prompt->prompts[1]->result);
|
||||
free_prompts(s->cur_prompt);
|
||||
ssh2_pkt_send_with_padding(ssh, s->pktout, 256);
|
||||
s->pktout->minlen = 256;
|
||||
ssh2_pkt_send(ssh, s->pktout);
|
||||
logevent("Sent new password");
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user