1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-15 20:29:03 +00:00

Fix IPID sequence detection in the case of Random

Reported by Lior Levinsky. As part of r32469, which added IPv6 IPID
sequnce detection, the logic to detect all-zero IPID sequences was
split. get_diffs was returning IPID_SEQ_UNKNOWN, IPID_SEQ_RD, or
1 for all-zeros, but the get_ipid_sequence_* functions were treating
every non-zero return value as indicating all-zeros, which meant that
IPID sequence detection was broken.

http://seclists.org/nmap-dev/2014/q1/287
This commit is contained in:
dmiller
2014-03-15 12:37:54 +00:00
parent 573f9c1a73
commit c4a541ac1e

View File

@@ -249,13 +249,9 @@ int get_initial_ttl_guess(u8 ttl) {
function cannot determine the sequence, IPID_SEQ_UNKNOWN is returned. function cannot determine the sequence, IPID_SEQ_UNKNOWN is returned.
This islocalhost argument is a boolean specifying whether these This islocalhost argument is a boolean specifying whether these
numbers were generated by scanning localhost. */ numbers were generated by scanning localhost. */
int identify_sequence(int numSamples, u32 *ipid_diffs, int islocalhost, int allipideqz) { int identify_sequence(int numSamples, u32 *ipid_diffs, int islocalhost) {
int i, j, k, l; int i, j, k, l;
/* ZERO */
if (allipideqz)
return IPID_SEQ_ZERO;
if (islocalhost) { if (islocalhost) {
int allgto = 1; /* ALL diffs greater than one */ int allgto = 1; /* ALL diffs greater than one */
@@ -331,17 +327,18 @@ int identify_sequence(int numSamples, u32 *ipid_diffs, int islocalhost, int alli
} }
/* Calculate the distances between the ipids and write them /* Calculate the distances between the ipids and write them
into the ipid_diffs array */ into the ipid_diffs array. If the sequence class can be determined
immediately, return it; otherwise return -1 */
int get_diffs(u32 *ipid_diffs, int numSamples, u32 *ipids, int islocalhost) { int get_diffs(u32 *ipid_diffs, int numSamples, u32 *ipids, int islocalhost) {
int i; int i;
int allipideqz = 1; bool allipideqz = true;
if (numSamples < 2) if (numSamples < 2)
return IPID_SEQ_UNKNOWN; return IPID_SEQ_UNKNOWN;
for (i = 1; i < numSamples; i++) { for (i = 1; i < numSamples; i++) {
if (ipids[i - 1] != 0 || ipids[i] != 0) if (ipids[i - 1] != 0 || ipids[i] != 0)
allipideqz = 0; /* All IP.ID values do *NOT* equal zero */ allipideqz = false; /* All IP.ID values do *NOT* equal zero */
ipid_diffs[i - 1] = ipids[i] - ipids[i - 1]; ipid_diffs[i - 1] = ipids[i] - ipids[i - 1];
@@ -350,32 +347,47 @@ int get_diffs(u32 *ipid_diffs, int numSamples, u32 *ipids, int islocalhost) {
return IPID_SEQ_RD; return IPID_SEQ_RD;
} }
return allipideqz; if (allipideqz) {
return IPID_SEQ_ZERO;
}
else {
return -1;
}
} }
/* Indentify the ipid sequence for 32-bit IPID values (IPv6) */ /* Indentify the ipid sequence for 32-bit IPID values (IPv6) */
int get_ipid_sequence_32(int numSamples, u32 *ipids, int islocalhost) { int get_ipid_sequence_32(int numSamples, u32 *ipids, int islocalhost) {
int allipideqz=1; int ipid_seq = IPID_SEQ_UNKNOWN;
u32 ipid_diffs[32]; u32 ipid_diffs[32];
assert(numSamples < (int) (sizeof(ipid_diffs) / 2)); assert(numSamples < (int) (sizeof(ipid_diffs) / 2));
allipideqz = get_diffs(ipid_diffs, numSamples, ipids, islocalhost); ipid_seq = get_diffs(ipid_diffs, numSamples, ipids, islocalhost);
return identify_sequence(numSamples, ipid_diffs, islocalhost, allipideqz); if (ipid_seq < 0) {
return identify_sequence(numSamples, ipid_diffs, islocalhost);
}
else {
return ipid_seq;
}
} }
/* Indentify the ipid sequence for 16-bit IPID values (IPv4) */ /* Indentify the ipid sequence for 16-bit IPID values (IPv4) */
int get_ipid_sequence_16(int numSamples, u32 *ipids, int islocalhost) { int get_ipid_sequence_16(int numSamples, u32 *ipids, int islocalhost) {
int i; int i;
int allipideqz=1; int ipid_seq = IPID_SEQ_UNKNOWN;
u32 ipid_diffs[32]; u32 ipid_diffs[32];
assert(numSamples < (int) (sizeof(ipid_diffs) / 2)); assert(numSamples < (int) (sizeof(ipid_diffs) / 2));
allipideqz = get_diffs(ipid_diffs, numSamples, ipids, islocalhost); ipid_seq = get_diffs(ipid_diffs, numSamples, ipids, islocalhost);
/* AND with 0xffff so that in case the 16 bit counter was /* AND with 0xffff so that in case the 16 bit counter was
* flipped over we still have a continuous sequence */ * flipped over we still have a continuous sequence */
for (i = 0; i < numSamples; i++) { for (i = 0; i < numSamples; i++) {
ipid_diffs[i] = ipid_diffs[i] & 0xffff; ipid_diffs[i] = ipid_diffs[i] & 0xffff;
} }
return identify_sequence(numSamples, ipid_diffs, islocalhost, allipideqz); if (ipid_seq < 0) {
return identify_sequence(numSamples, ipid_diffs, islocalhost);
}
else {
return ipid_seq;
}
} }