|
Lines 30-35
Link Here
|
| 30 |
#include "crc32.h" |
30 |
#include "crc32.h" |
| 31 |
#include "misc.h" |
31 |
#include "misc.h" |
| 32 |
|
32 |
|
|
|
33 |
/* |
| 34 |
* CRC attack detection has a worst-case behaviour that is O(N^3) over |
| 35 |
* the number of identical blocks in a packet. This behaviour can be |
| 36 |
* exploited to create a limited denial of service attack. |
| 37 |
* |
| 38 |
* However, because we are dealing with encrypted data, identical |
| 39 |
* blocks should only occur every 2^35 maximally-sized packets or so. |
| 40 |
* Consequently, we can detect this DoS by looking for identical blocks |
| 41 |
* in a packet. |
| 42 |
* |
| 43 |
* The parameter below determines how many identical blocks we will |
| 44 |
* accept in a single packet, trading off between attack detection and |
| 45 |
* likelihood of terminating a legitimate connection. A value of 32 |
| 46 |
* corresponds to an average of 2^40 messages before an attack is |
| 47 |
* misdetected |
| 48 |
*/ |
| 49 |
#define MAX_IDENTICAL 32 |
| 50 |
|
| 33 |
/* SSH Constants */ |
51 |
/* SSH Constants */ |
| 34 |
#define SSH_MAXBLOCKS (32 * 1024) |
52 |
#define SSH_MAXBLOCKS (32 * 1024) |
| 35 |
#define SSH_BLOCKSIZE (8) |
53 |
#define SSH_BLOCKSIZE (8) |
|
Lines 85-91
Link Here
|
| 85 |
static u_int16_t *h = (u_int16_t *) NULL; |
103 |
static u_int16_t *h = (u_int16_t *) NULL; |
| 86 |
static u_int32_t n = HASH_MINSIZE / HASH_ENTRYSIZE; |
104 |
static u_int32_t n = HASH_MINSIZE / HASH_ENTRYSIZE; |
| 87 |
u_int32_t i, j; |
105 |
u_int32_t i, j; |
| 88 |
u_int32_t l; |
106 |
u_int32_t l, same; |
| 89 |
u_char *c; |
107 |
u_char *c; |
| 90 |
u_char *d; |
108 |
u_char *d; |
| 91 |
|
109 |
|
|
Lines 122-132
Link Here
|
| 122 |
if (IV) |
140 |
if (IV) |
| 123 |
h[HASH(IV) & (n - 1)] = HASH_IV; |
141 |
h[HASH(IV) & (n - 1)] = HASH_IV; |
| 124 |
|
142 |
|
| 125 |
for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) { |
143 |
for (c = buf, same = j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) { |
| 126 |
for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED; |
144 |
for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED; |
| 127 |
i = (i + 1) & (n - 1)) { |
145 |
i = (i + 1) & (n - 1)) { |
| 128 |
if (h[i] == HASH_IV) { |
146 |
if (h[i] == HASH_IV) { |
| 129 |
if (!CMP(c, IV)) { |
147 |
if (!CMP(c, IV)) { |
|
|
148 |
if (++same > MAX_IDENTICAL) |
| 149 |
return (DEATTACK_DOS_DETECTED); |
| 130 |
if (check_crc(c, buf, len, IV)) |
150 |
if (check_crc(c, buf, len, IV)) |
| 131 |
return (DEATTACK_DETECTED); |
151 |
return (DEATTACK_DETECTED); |
| 132 |
else |
152 |
else |
|
Lines 991-999
Link Here
|
| 991 |
* (C)1998 CORE-SDI, Buenos Aires Argentina |
991 |
* (C)1998 CORE-SDI, Buenos Aires Argentina |
| 992 |
* Ariel Futoransky(futo@core-sdi.com) |
992 |
* Ariel Futoransky(futo@core-sdi.com) |
| 993 |
*/ |
993 |
*/ |
| 994 |
if (!receive_context.plaintext && |
994 |
if (!receive_context.plaintext) { |
| 995 |
detect_attack(buffer_ptr(&input), padded_len, NULL) == DEATTACK_DETECTED) |
995 |
switch (detect_attack(buffer_ptr(&input), padded_len, NULL)) { |
| 996 |
packet_disconnect("crc32 compensation attack: network attack detected"); |
996 |
case DEATTACK_DETECTED: |
|
|
997 |
packet_disconnect("crc32 compensation attack: " |
| 998 |
"network attack detected"); |
| 999 |
case DEATTACK_DOS_DETECTED: |
| 1000 |
packet_disconnect("deattack denial of " |
| 1001 |
"service detected"); |
| 1002 |
} |
| 1003 |
} |
| 997 |
|
1004 |
|
| 998 |
/* Decrypt data to incoming_packet. */ |
1005 |
/* Decrypt data to incoming_packet. */ |
| 999 |
buffer_clear(&incoming_packet); |
1006 |
buffer_clear(&incoming_packet); |
|
Lines 25-30
Link Here
|
| 25 |
/* Return codes */ |
25 |
/* Return codes */ |
| 26 |
#define DEATTACK_OK 0 |
26 |
#define DEATTACK_OK 0 |
| 27 |
#define DEATTACK_DETECTED 1 |
27 |
#define DEATTACK_DETECTED 1 |
|
|
28 |
#define DEATTACK_DOS_DETECTED 2 |
| 28 |
|
29 |
|
| 29 |
int detect_attack(u_char *, u_int32_t); |
30 |
int detect_attack(u_char *, u_int32_t); |
| 30 |
#endif |
31 |
#endif |