]>
Commit | Line | Data |
---|---|---|
820a8c3b GKH |
1 | From foo@baz Wed Mar 19 23:28:23 Local time zone must be set--see zic manual page 2014 |
2 | From: Daniel Borkmann <dborkman@redhat.com> | |
3 | Date: Mon, 3 Mar 2014 17:23:04 +0100 | |
4 | Subject: net: sctp: fix sctp_sf_do_5_1D_ce to verify if we/peer is AUTH capable | |
5 | ||
6 | From: Daniel Borkmann <dborkman@redhat.com> | |
7 | ||
8 | [ Upstream commit ec0223ec48a90cb605244b45f7c62de856403729 ] | |
9 | ||
10 | RFC4895 introduced AUTH chunks for SCTP; during the SCTP | |
11 | handshake RANDOM; CHUNKS; HMAC-ALGO are negotiated (CHUNKS | |
12 | being optional though): | |
13 | ||
14 | ---------- INIT[RANDOM; CHUNKS; HMAC-ALGO] ----------> | |
15 | <------- INIT-ACK[RANDOM; CHUNKS; HMAC-ALGO] --------- | |
16 | -------------------- COOKIE-ECHO --------------------> | |
17 | <-------------------- COOKIE-ACK --------------------- | |
18 | ||
19 | A special case is when an endpoint requires COOKIE-ECHO | |
20 | chunks to be authenticated: | |
21 | ||
22 | ---------- INIT[RANDOM; CHUNKS; HMAC-ALGO] ----------> | |
23 | <------- INIT-ACK[RANDOM; CHUNKS; HMAC-ALGO] --------- | |
24 | ------------------ AUTH; COOKIE-ECHO ----------------> | |
25 | <-------------------- COOKIE-ACK --------------------- | |
26 | ||
27 | RFC4895, section 6.3. Receiving Authenticated Chunks says: | |
28 | ||
29 | The receiver MUST use the HMAC algorithm indicated in | |
30 | the HMAC Identifier field. If this algorithm was not | |
31 | specified by the receiver in the HMAC-ALGO parameter in | |
32 | the INIT or INIT-ACK chunk during association setup, the | |
33 | AUTH chunk and all the chunks after it MUST be discarded | |
34 | and an ERROR chunk SHOULD be sent with the error cause | |
35 | defined in Section 4.1. [...] If no endpoint pair shared | |
36 | key has been configured for that Shared Key Identifier, | |
37 | all authenticated chunks MUST be silently discarded. [...] | |
38 | ||
39 | When an endpoint requires COOKIE-ECHO chunks to be | |
40 | authenticated, some special procedures have to be followed | |
41 | because the reception of a COOKIE-ECHO chunk might result | |
42 | in the creation of an SCTP association. If a packet arrives | |
43 | containing an AUTH chunk as a first chunk, a COOKIE-ECHO | |
44 | chunk as the second chunk, and possibly more chunks after | |
45 | them, and the receiver does not have an STCB for that | |
46 | packet, then authentication is based on the contents of | |
47 | the COOKIE-ECHO chunk. In this situation, the receiver MUST | |
48 | authenticate the chunks in the packet by using the RANDOM | |
49 | parameters, CHUNKS parameters and HMAC_ALGO parameters | |
50 | obtained from the COOKIE-ECHO chunk, and possibly a local | |
51 | shared secret as inputs to the authentication procedure | |
52 | specified in Section 6.3. If authentication fails, then | |
53 | the packet is discarded. If the authentication is successful, | |
54 | the COOKIE-ECHO and all the chunks after the COOKIE-ECHO | |
55 | MUST be processed. If the receiver has an STCB, it MUST | |
56 | process the AUTH chunk as described above using the STCB | |
57 | from the existing association to authenticate the | |
58 | COOKIE-ECHO chunk and all the chunks after it. [...] | |
59 | ||
60 | Commit bbd0d59809f9 introduced the possibility to receive | |
61 | and verification of AUTH chunk, including the edge case for | |
62 | authenticated COOKIE-ECHO. On reception of COOKIE-ECHO, | |
63 | the function sctp_sf_do_5_1D_ce() handles processing, | |
64 | unpacks and creates a new association if it passed sanity | |
65 | checks and also tests for authentication chunks being | |
66 | present. After a new association has been processed, it | |
67 | invokes sctp_process_init() on the new association and | |
68 | walks through the parameter list it received from the INIT | |
69 | chunk. It checks SCTP_PARAM_RANDOM, SCTP_PARAM_HMAC_ALGO | |
70 | and SCTP_PARAM_CHUNKS, and copies them into asoc->peer | |
71 | meta data (peer_random, peer_hmacs, peer_chunks) in case | |
72 | sysctl -w net.sctp.auth_enable=1 is set. If in INIT's | |
73 | SCTP_PARAM_SUPPORTED_EXT parameter SCTP_CID_AUTH is set, | |
74 | peer_random != NULL and peer_hmacs != NULL the peer is to be | |
75 | assumed asoc->peer.auth_capable=1, in any other case | |
76 | asoc->peer.auth_capable=0. | |
77 | ||
78 | Now, if in sctp_sf_do_5_1D_ce() chunk->auth_chunk is | |
79 | available, we set up a fake auth chunk and pass that on to | |
80 | sctp_sf_authenticate(), which at latest in | |
81 | sctp_auth_calculate_hmac() reliably dereferences a NULL pointer | |
82 | at position 0..0008 when setting up the crypto key in | |
83 | crypto_hash_setkey() by using asoc->asoc_shared_key that is | |
84 | NULL as condition key_id == asoc->active_key_id is true if | |
85 | the AUTH chunk was injected correctly from remote. This | |
86 | happens no matter what net.sctp.auth_enable sysctl says. | |
87 | ||
88 | The fix is to check for net->sctp.auth_enable and for | |
89 | asoc->peer.auth_capable before doing any operations like | |
90 | sctp_sf_authenticate() as no key is activated in | |
91 | sctp_auth_asoc_init_active_key() for each case. | |
92 | ||
93 | Now as RFC4895 section 6.3 states that if the used HMAC-ALGO | |
94 | passed from the INIT chunk was not used in the AUTH chunk, we | |
95 | SHOULD send an error; however in this case it would be better | |
96 | to just silently discard such a maliciously prepared handshake | |
97 | as we didn't even receive a parameter at all. Also, as our | |
98 | endpoint has no shared key configured, section 6.3 says that | |
99 | MUST silently discard, which we are doing from now onwards. | |
100 | ||
101 | Before calling sctp_sf_pdiscard(), we need not only to free | |
102 | the association, but also the chunk->auth_chunk skb, as | |
103 | commit bbd0d59809f9 created a skb clone in that case. | |
104 | ||
105 | I have tested this locally by using netfilter's nfqueue and | |
106 | re-injecting packets into the local stack after maliciously | |
107 | modifying the INIT chunk (removing RANDOM; HMAC-ALGO param) | |
108 | and the SCTP packet containing the COOKIE_ECHO (injecting | |
109 | AUTH chunk before COOKIE_ECHO). Fixed with this patch applied. | |
110 | ||
111 | Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk") | |
112 | Signed-off-by: Daniel Borkmann <dborkman@redhat.com> | |
113 | Cc: Vlad Yasevich <yasevich@gmail.com> | |
114 | Cc: Neil Horman <nhorman@tuxdriver.com> | |
115 | Acked-by: Vlad Yasevich <vyasevich@gmail.com> | |
116 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
117 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
118 | --- | |
119 | net/sctp/sm_statefuns.c | 7 +++++++ | |
120 | 1 file changed, 7 insertions(+) | |
121 | ||
122 | --- a/net/sctp/sm_statefuns.c | |
123 | +++ b/net/sctp/sm_statefuns.c | |
124 | @@ -765,6 +765,13 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(st | |
125 | struct sctp_chunk auth; | |
126 | sctp_ierror_t ret; | |
127 | ||
128 | + /* Make sure that we and the peer are AUTH capable */ | |
129 | + if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) { | |
130 | + kfree_skb(chunk->auth_chunk); | |
131 | + sctp_association_free(new_asoc); | |
132 | + return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | |
133 | + } | |
134 | + | |
135 | /* set-up our fake chunk so that we can process it */ | |
136 | auth.skb = chunk->auth_chunk; | |
137 | auth.asoc = chunk->asoc; |