]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/NISCC/TLS_SSL/README.txt
Security-57031.30.12.tar.gz
[apple/security.git] / SecurityTests / clxutils / NISCC / TLS_SSL / README.txt
1 Testing the NISCC SSL Certs
2 Last Update 12 Nov 2003 by dmitch
3
4 Introduction
5 ------------
6 Per 3479950, the British NISCC has discovered a vulnerability in almost
7 all existing SSL implementation which can result in a Denial of Service
8 attack when certain badly formatted DER elements are sent by the client
9 the the server. Specifically the badly formatted element is the client
10 cert. NISCC has provided a huge array of test certs to verify this
11 problem. They've distrubuted this set of certs on a CD.
12
13 This directory contains some of that CD, plus some X-specific tools
14 to test and verify. The bulk of the CD is in the form of 6 large tarred
15 and zipped bundles of bad certs. Those .tar.gz files are not in the
16 CVS repositoty because they are so big. When those files are expanded,
17 they result in hundreds of thousands of (bad) certs. Those certs are
18 not in the CVS repository either.
19
20 Details of the failures we're testing for
21 -----------------------------------------
22 As of this writing, there are three specific bugs in the SecurityNssAsn1
23 library which can all cause crashes when an app attempts to decode
24 certain badly formatted DER. All bugs are in
25 SecurityNssAsn1/nssDER/Source/secasn1d.c.
26
27 First, when doing an SEC_ASN1_SAVE operation (e.g., saving the
28 still-encoded subject and issuer names in NSS_TBSCertificate.derIssuer and
29 NSS_TBSCertificate.derSubject), the code allocates a SECItem for the
30 whole blob solely based upon the length of the blob indicated in its
31 enclosing DER sequence or set. However when traversing the actual bits
32 being saved, each element is copied to the pre-allocated buffer according
33 to the length field of that element. Corruption and crash can result if
34 those inner length fields are bad and end up adding up to a size larger than
35 the preallocated SECItem buffer. The solution is to track the allocated size
36 of the buffer in sec_asn1d_state_struct.dest_alloc_len, which gets inherited
37 from parent to child state as does the dest field itself. Whenever an item
38 is appended to the dest SECItem, possible overflow is checked and the op
39 aborts if an overflow would result.
40
41 Second, the sec_asn1d_reuse_encoding() routine is called after a
42 (successful) SEC_ASN1_SAVE op to "back up" to the forked location and
43 resume decoding it "for real", using the saved-off buffer - NOT the
44 caller's input. There was a bug here in that a "needBytes" error in the
45 sec_asn1d_reuse_encoding()'s call to SEC_ASN1DecoderUpdate() was ignored
46 and thrown out by the calling SEC_ASN1DecoderUpdate(), and processing
47 proceeds, with possibly hazardous and unpredicatable results. However
48 a "needBytes" error in the SEC_ASN1DecoderUpdate actually
49 called by sec_asn1d_reuse_encoding() must be fatal since all the data
50 is already present - we're not streaming when that update is called
51 because all of the data is already present in the saved-off buffer. The
52 solution is for sec_asn1d_reuse_encoding to detect the needBytes status and
53 convert it into decodeError, thus aborting the caller immediately. (Note
54 that this generally did not result in a crash, but in undetected decoding
55 errors.)
56
57 The third bug involved the behavior of the decoding engine if incoming
58 encoded data claimed to have a very large length. Two problems can occur
59 in sec_asn1d_prepare_for_contents() in such a case. First of course is the
60 result of trying to malloc the large size. If state->contents_length is
61 2**32-1, for example, that malloc will almost certainly either fail or
62 take much longer than is appropriate. Then there is some arithmetic
63 involving appending subitems to the alloc_len which can result in
64 integer overflow:
65
66 for (subitem = state->subitems_head;
67 subitem != NULL; subitem = subitem->next)
68 alloc_len += subitem->len;
69 }
70
71 This bug is avoided by placing a somewhat arbitrary, but perfectly reasonable,
72 restriction in sec_asn1d_parse_more_length() - the routine which parses
73 such a huge length - that a 32-bit length value with the m.s. bit set is
74 invalid.
75
76
77 Testing overview
78 ----------------
79 There are two flavors of testing provided here. One uses a custom SSL
80 client, nisccSimpleClient, which performs actual SSL transactions with
81 an SSL server. The SSL server uses a good cert and requires client
82 authentication. The SSL client uses a bad cert. Both are based on
83 SecureTransport. A failure is indicated by the server crashing and
84 failing to respond to any more client requests.
85
86 The other method of testing focusses exlusively on the failure mode,
87 which is the decoding and parsing of the bad certs. (The gross failure
88 mode in an SSL server noted in the previous paragraph is always caused
89 by the server crashing during the decoding of the client cert.) This testing
90 is performed by a program called certDecode which simply attempts to decode
91 every cert in cwd. This is way, way faster than setting up actual SSL
92 clients and doing SSL transactions. As a result, the entire suite of
93 "bad" client certs provided by NISCC (about 200,000 certs) has in fact
94 been verified by this program. Resources to perform 200,000 SSL client
95 trasnactions have not been marshalled as of this writing. In the opinion
96 of this author, simply verifying that a process can attempt to decode the
97 bad certs, without crashing, is sufficient for verifying that the
98 problem has been solved.
99
100 Building the test programs
101 --------------------------
102 The nisccSimpleClient program requires the presence of both the
103 clxutils/clAppUtils directory and the library it builds. The other
104 programs - certDecode and skipThisNisccCert - just link against
105 libCdsaUtils.a. None of these build in a way which is compatible with
106 Jasper Makefiles or PB project files. All you need to do is to set the
107 LOCAL_BUILD_DIR environment variable to point to the place where the
108 executables go. YOu can build each program individually by cd'ing to
109 the program directory and typing 'make', or just do a 'make' from
110 here (which is assumed to be clxutils/NISCC/TLS_SSL), which builds
111 all three.
112
113 Testing using certDecode
114 ------------------------
115 The certDecode program is a standalone executable which uses the
116 SecurityNssAsn1 library to simply attempt to decode either every cert
117 in cwd, or the single cert specified in the cmd line. Build it by
118 doing 'make' in its directory. You must have the $LOCAL_BUILD_DIR
119 environment set.
120
121 You need to obtain and untar one of the NISCC cert bundles. The two
122 of main concern are simple_client.tar.gz and resigned_client.tar.gz.
123 Each one of these explodes into about 100,000 certs taking up about
124 200 MB of disk space. To run the test, cd to the directory containing
125 100,000 certs and just run "certDecode" with no args. THe result will look
126 something like this:
127
128 % tower.local:simple_client> certDecode
129 ....00000001...00000002...00000003...00000004...00000005...
130 00000006...00000007...00000008...00000009...00000010...00000011...
131 00000012...00000013...00000014...00000015...00000016...00000017...
132 ...etc....
133
134 It takes about 30 minutes to run thru all 100000 certs. Two things
135 will happen: either the program will crash, or you'll see this at the
136 end:
137
138 00106148...00106149...00106150...00106151...00106152...00106153...
139 00106154...00106155...00106156...00106157...00106158...00106159...
140 00106160
141 certDecode did not crash.
142 %
143
144 Test using nisccSimpleClient
145 ----------------------------
146
147 WARNING this hasn't been tested in a long time (as of 7/18/06). The
148 nisccSimpleClient builds as of this date but the status of rest of this
149 is unknown. Stick to the certDecode test, above, which was verified as
150 of 7/18/06.
151
152 This is much more complicated and takes way longer than the certDecode
153 test - so long that I still haven't run it with all 200,000 NISCC certs.
154 But to get started here's what you need to do.
155
156 First you need to build the sslServer program, in clxutils/sslServer. See
157 the README in clxutils for build instructions.
158
159 You also need the cspxutils/dbTool program. Your PATH variable needs
160 to include the directory where its executable lives (generally, this is
161 the same as your LOCAL_BUILD_DIR env var.)
162
163 Then you need to build a custom Security.framework because certain errors
164 introduced by this test will cause the stock SecureTransport library to
165 (properly) abort client-side transactions before you get started due to
166 badly formatted certs. The tag for this Security.framework NISCC_ASN1;
167 that's a branch off of the PantherGM Security tree. Build the tree and
168 either install it or make sure your DYLD_FRAMEWORK_PATH env var points
169 to it for all subsequent testing.
170
171 Now set up the SSL server keychain using the (good) NISCC-supplied server
172 cert and key. In the NISCC/TLS_SSL/testcases directory do the following:
173
174 % rm -f ~/Library/Keychains/nisccServer
175 % certtool i server_crt.pem k=nisccServer r=server_key.pem c
176
177 Run the sslServer app from the NISCC/TLS_SSL/testcases directory:
178
179 % sslServer l k=nisccServer P=1200 a rootca.crt u=t
180
181 The "a rootca.crt" tells SecureTransport that the cert which signed the
182 server's cert is a trusted root cert. The "u=t" tells the server to
183 request client authentication. If all is well, this program just keeps
184 on running, serving SSL requests, spewing forth to stdout (do not have
185 an unlimited scrollback buffer in your Terminal window or your root disk
186 will fill up.)
187
188 Assuming that you'cve cd'd to the directory containing the nisccSslTest
189 script (clxutils/NISCC/TLS_SSL/) and that the directory containing the
190 untarred simple_client certs is in ./testcases/simple_client, just run
191 the nisccSslTest script with one argument, the port number you supplied
192 to the sslServer program above:
193
194 % nisccSslTest 1200
195
196 This assumes that the following executables are accessible via your
197 PATH variable: dbTool, nisccSimpleClient, and skipThisNisccCert.
198
199 When this is running OK you'll see an endless spew on stdout like this:
200
201 cert 00001012...
202 ...DB /Volumes/Data_and_Apps/home/dmitch/Library/Keychains/nisccClient wiped clean
203 Starting nisccSimpleClient; args: localhost 1200 nisccClient
204 ===== nisccSimpleClient test PASSED =====
205 cert 00001013...
206 ...DB /Volumes/Data_and_Apps/home/dmitch/Library/Keychains/nisccClient wiped clean
207 Starting nisccSimpleClient; args: localhost 1200 nisccClient
208 ===== nisccSimpleClient test PASSED =====
209 cert 00001014...
210 ...DB /Volumes/Data_and_Apps/home/dmitch/Library/Keychains/nisccClient wiped clean
211 Starting nisccSimpleClient; args: localhost 13 1200 01 nisccClient
212
213 ...again, do not have an unlimited scrollback buffer in your Terminal
214 window or your root disk will fill up.