|
1 Fix for CVE-2013-4248 |
|
2 Patch: |
|
3 http://git.php.net/?p=php-src.git;a=patch;h=2874696a5a8d46639d261571f915c493cd875897 |
|
4 Code: |
|
5 http://git.php.net/?p=php-src.git;a=commit;h=2874696a5a8d46639d261571f915c493cd875897 |
|
6 This patch is for php 5.4 code but works well enough on php 5.2 code. |
|
7 Verified by hand that it patches the correct code. |
|
8 |
|
9 |
|
10 |
|
11 From 2874696a5a8d46639d261571f915c493cd875897 Mon Sep 17 00:00:00 2001 |
|
12 From: Stanislav Malyshev <[email protected]> |
|
13 Date: Tue, 13 Aug 2013 22:20:33 -0700 |
|
14 Subject: [PATCH] Fix CVE-2013-4073 - handling of certs with null bytes |
|
15 |
|
16 --- |
|
17 NEWS | 4 ++ |
|
18 ext/openssl/openssl.c | 86 ++++++++++++++++++++++++++++++++++++- |
|
19 ext/openssl/tests/cve2013_4073.pem | 28 ++++++++++++ |
|
20 ext/openssl/tests/cve2013_4073.phpt | 19 ++++++++ |
|
21 4 files changed, 135 insertions(+), 2 deletions(-) |
|
22 create mode 100644 ext/openssl/tests/cve2013_4073.pem |
|
23 create mode 100644 ext/openssl/tests/cve2013_4073.phpt |
|
24 |
|
25 diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c |
|
26 index d7ac117..c32748c 100644 |
|
27 --- a/ext/openssl/openssl.c |
|
28 +++ b/ext/openssl/openssl.c |
|
29 @@ -1398,6 +1398,74 @@ PHP_FUNCTION(openssl_x509_check_private_key) |
|
30 } |
|
31 /* }}} */ |
|
32 |
|
33 +/* Special handling of subjectAltName, see CVE-2013-4073 |
|
34 + * Christian Heimes |
|
35 + */ |
|
36 + |
|
37 +static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension) |
|
38 +{ |
|
39 + GENERAL_NAMES *names; |
|
40 + const X509V3_EXT_METHOD *method = NULL; |
|
41 + long i, length, num; |
|
42 + const unsigned char *p; |
|
43 + |
|
44 + method = X509V3_EXT_get(extension); |
|
45 + if (method == NULL) { |
|
46 + return -1; |
|
47 + } |
|
48 + |
|
49 + p = extension->value->data; |
|
50 + length = extension->value->length; |
|
51 + if (method->it) { |
|
52 + names = (GENERAL_NAMES*)(ASN1_item_d2i(NULL, &p, length, |
|
53 + ASN1_ITEM_ptr(method->it))); |
|
54 + } else { |
|
55 + names = (GENERAL_NAMES*)(method->d2i(NULL, &p, length)); |
|
56 + } |
|
57 + if (names == NULL) { |
|
58 + return -1; |
|
59 + } |
|
60 + |
|
61 + num = sk_GENERAL_NAME_num(names); |
|
62 + for (i = 0; i < num; i++) { |
|
63 + GENERAL_NAME *name; |
|
64 + ASN1_STRING *as; |
|
65 + name = sk_GENERAL_NAME_value(names, i); |
|
66 + switch (name->type) { |
|
67 + case GEN_EMAIL: |
|
68 + BIO_puts(bio, "email:"); |
|
69 + as = name->d.rfc822Name; |
|
70 + BIO_write(bio, ASN1_STRING_data(as), |
|
71 + ASN1_STRING_length(as)); |
|
72 + break; |
|
73 + case GEN_DNS: |
|
74 + BIO_puts(bio, "DNS:"); |
|
75 + as = name->d.dNSName; |
|
76 + BIO_write(bio, ASN1_STRING_data(as), |
|
77 + ASN1_STRING_length(as)); |
|
78 + break; |
|
79 + case GEN_URI: |
|
80 + BIO_puts(bio, "URI:"); |
|
81 + as = name->d.uniformResourceIdentifier; |
|
82 + BIO_write(bio, ASN1_STRING_data(as), |
|
83 + ASN1_STRING_length(as)); |
|
84 + break; |
|
85 + default: |
|
86 + /* use builtin print for GEN_OTHERNAME, GEN_X400, |
|
87 + * GEN_EDIPARTY, GEN_DIRNAME, GEN_IPADD and GEN_RID |
|
88 + */ |
|
89 + GENERAL_NAME_print(bio, name); |
|
90 + } |
|
91 + /* trailing ', ' except for last element */ |
|
92 + if (i < (num - 1)) { |
|
93 + BIO_puts(bio, ", "); |
|
94 + } |
|
95 + } |
|
96 + sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); |
|
97 + |
|
98 + return 0; |
|
99 +} |
|
100 + |
|
101 /* {{{ proto array openssl_x509_parse(mixed x509 [, bool shortnames=true]) |
|
102 Returns an array of the fields/values of the CERT */ |
|
103 PHP_FUNCTION(openssl_x509_parse) |
|
104 @@ -1494,15 +1562,29 @@ PHP_FUNCTION(openssl_x509_parse) |
|
105 |
|
106 |
|
107 for (i = 0; i < X509_get_ext_count(cert); i++) { |
|
108 + int nid; |
|
109 extension = X509_get_ext(cert, i); |
|
110 - if (OBJ_obj2nid(X509_EXTENSION_get_object(extension)) != NID_undef) { |
|
111 + nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension)); |
|
112 + if (nid != NID_undef) { |
|
113 extname = (char *)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(extension))); |
|
114 } else { |
|
115 OBJ_obj2txt(buf, sizeof(buf)-1, X509_EXTENSION_get_object(extension), 1); |
|
116 extname = buf; |
|
117 } |
|
118 bio_out = BIO_new(BIO_s_mem()); |
|
119 - if (X509V3_EXT_print(bio_out, extension, 0, 0)) { |
|
120 + if (nid == NID_subject_alt_name) { |
|
121 + if (openssl_x509v3_subjectAltName(bio_out, extension) == 0) { |
|
122 + add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1); |
|
123 + } else { |
|
124 + zval_dtor(return_value); |
|
125 + if (certresource == -1 && cert) { |
|
126 + X509_free(cert); |
|
127 + } |
|
128 + BIO_free(bio_out); |
|
129 + RETURN_FALSE; |
|
130 + } |
|
131 + } |
|
132 + else if (X509V3_EXT_print(bio_out, extension, 0, 0)) { |
|
133 BIO_get_mem_ptr(bio_out, &bio_buf); |
|
134 add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1); |
|
135 } else { |
|
136 diff --git a/ext/openssl/tests/cve2013_4073.pem b/ext/openssl/tests/cve2013_4073.pem |
|
137 new file mode 100644 |
|
138 index 0000000..7ebb994 |
|
139 --- /dev/null |
|
140 +++ b/ext/openssl/tests/cve2013_4073.pem |
|
141 @@ -0,0 +1,28 @@ |
|
142 +-----BEGIN CERTIFICATE----- |
|
143 +MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx |
|
144 +DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ |
|
145 +eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg |
|
146 +RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y |
|
147 +ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw |
|
148 +NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI |
|
149 +DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv |
|
150 +ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt |
|
151 +ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq |
|
152 +hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB |
|
153 +BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j |
|
154 +pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P |
|
155 +vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv |
|
156 +KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA |
|
157 +oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL |
|
158 +08LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV |
|
159 +HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E |
|
160 +BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu |
|
161 +Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251 |
|
162 +bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA |
|
163 +AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9 |
|
164 +i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j |
|
165 +HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk |
|
166 +kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx |
|
167 +VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW |
|
168 +RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ= |
|
169 +-----END CERTIFICATE----- |
|
170 diff --git a/ext/openssl/tests/cve2013_4073.phpt b/ext/openssl/tests/cve2013_4073.phpt |
|
171 new file mode 100644 |
|
172 index 0000000..e676ddf |
|
173 --- /dev/null |
|
174 +++ b/ext/openssl/tests/cve2013_4073.phpt |
|
175 @@ -0,0 +1,19 @@ |
|
176 +--TEST-- |
|
177 +CVE 2013-4073: Null-byte certificate handling |
|
178 +--SKIPIF-- |
|
179 +<?php |
|
180 +if (!extension_loaded("openssl")) die("skip"); |
|
181 +--FILE-- |
|
182 +<?php |
|
183 +$cert = file_get_contents(__DIR__ . '/cve2013_4073.pem'); |
|
184 +$info = openssl_x509_parse($cert); |
|
185 +var_export($info['extensions']); |
|
186 + |
|
187 +--EXPECTF-- |
|
188 +array ( |
|
189 + 'basicConstraints' => 'CA:FALSE', |
|
190 + 'subjectKeyIdentifier' => '88:5A:55:C0:52:FF:61:CD:52:A3:35:0F:EA:5A:9C:24:38:22:F7:5C', |
|
191 + 'keyUsage' => 'Digital Signature, Non Repudiation, Key Encipherment', |
|
192 + 'subjectAltName' => 'DNS:altnull.python.org' . "\0" . 'example.com, email:[email protected]' . "\0" . '[email protected], URI:http://null.python.org' . "\0" . 'http://example.org, IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1 |
|
193 +', |
|
194 +) |
|
195 -- |
|
196 1.8.4.3 |
|
197 |
|
198 |