Skip to content

Commit 2874696

Browse files
committed
Fix CVE-2013-4073 - handling of certs with null bytes
1 parent f4dc224 commit 2874696

File tree

4 files changed

+135
-2
lines changed

4 files changed

+135
-2
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ PHP NEWS
101101
. Fixed bug #61387 (NULL valued anonymous column causes segfault in
102102
odbc_fetch_array). (Brandon Kirsch)
103103

104+
- Openssl:
105+
. Fixed handling null bytes in subjectAltName (CVE-2013-4073).
106+
(Christian Heimes)
107+
104108
- PDO:
105109
. Allowed PDO_OCI to compile with Oracle Database 12c client libraries.
106110
(Chris Jones)

ext/openssl/openssl.c

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,74 @@ PHP_FUNCTION(openssl_x509_check_private_key)
13981398
}
13991399
/* }}} */
14001400

1401+
/* Special handling of subjectAltName, see CVE-2013-4073
1402+
* Christian Heimes
1403+
*/
1404+
1405+
static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension)
1406+
{
1407+
GENERAL_NAMES *names;
1408+
const X509V3_EXT_METHOD *method = NULL;
1409+
long i, length, num;
1410+
const unsigned char *p;
1411+
1412+
method = X509V3_EXT_get(extension);
1413+
if (method == NULL) {
1414+
return -1;
1415+
}
1416+
1417+
p = extension->value->data;
1418+
length = extension->value->length;
1419+
if (method->it) {
1420+
names = (GENERAL_NAMES*)(ASN1_item_d2i(NULL, &p, length,
1421+
ASN1_ITEM_ptr(method->it)));
1422+
} else {
1423+
names = (GENERAL_NAMES*)(method->d2i(NULL, &p, length));
1424+
}
1425+
if (names == NULL) {
1426+
return -1;
1427+
}
1428+
1429+
num = sk_GENERAL_NAME_num(names);
1430+
for (i = 0; i < num; i++) {
1431+
GENERAL_NAME *name;
1432+
ASN1_STRING *as;
1433+
name = sk_GENERAL_NAME_value(names, i);
1434+
switch (name->type) {
1435+
case GEN_EMAIL:
1436+
BIO_puts(bio, "email:");
1437+
as = name->d.rfc822Name;
1438+
BIO_write(bio, ASN1_STRING_data(as),
1439+
ASN1_STRING_length(as));
1440+
break;
1441+
case GEN_DNS:
1442+
BIO_puts(bio, "DNS:");
1443+
as = name->d.dNSName;
1444+
BIO_write(bio, ASN1_STRING_data(as),
1445+
ASN1_STRING_length(as));
1446+
break;
1447+
case GEN_URI:
1448+
BIO_puts(bio, "URI:");
1449+
as = name->d.uniformResourceIdentifier;
1450+
BIO_write(bio, ASN1_STRING_data(as),
1451+
ASN1_STRING_length(as));
1452+
break;
1453+
default:
1454+
/* use builtin print for GEN_OTHERNAME, GEN_X400,
1455+
* GEN_EDIPARTY, GEN_DIRNAME, GEN_IPADD and GEN_RID
1456+
*/
1457+
GENERAL_NAME_print(bio, name);
1458+
}
1459+
/* trailing ', ' except for last element */
1460+
if (i < (num - 1)) {
1461+
BIO_puts(bio, ", ");
1462+
}
1463+
}
1464+
sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
1465+
1466+
return 0;
1467+
}
1468+
14011469
/* {{{ proto array openssl_x509_parse(mixed x509 [, bool shortnames=true])
14021470
Returns an array of the fields/values of the CERT */
14031471
PHP_FUNCTION(openssl_x509_parse)
@@ -1494,15 +1562,29 @@ PHP_FUNCTION(openssl_x509_parse)
14941562

14951563

14961564
for (i = 0; i < X509_get_ext_count(cert); i++) {
1565+
int nid;
14971566
extension = X509_get_ext(cert, i);
1498-
if (OBJ_obj2nid(X509_EXTENSION_get_object(extension)) != NID_undef) {
1567+
nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension));
1568+
if (nid != NID_undef) {
14991569
extname = (char *)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(extension)));
15001570
} else {
15011571
OBJ_obj2txt(buf, sizeof(buf)-1, X509_EXTENSION_get_object(extension), 1);
15021572
extname = buf;
15031573
}
15041574
bio_out = BIO_new(BIO_s_mem());
1505-
if (X509V3_EXT_print(bio_out, extension, 0, 0)) {
1575+
if (nid == NID_subject_alt_name) {
1576+
if (openssl_x509v3_subjectAltName(bio_out, extension) == 0) {
1577+
add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1);
1578+
} else {
1579+
zval_dtor(return_value);
1580+
if (certresource == -1 && cert) {
1581+
X509_free(cert);
1582+
}
1583+
BIO_free(bio_out);
1584+
RETURN_FALSE;
1585+
}
1586+
}
1587+
else if (X509V3_EXT_print(bio_out, extension, 0, 0)) {
15061588
BIO_get_mem_ptr(bio_out, &bio_buf);
15071589
add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1);
15081590
} else {

ext/openssl/tests/cve2013_4073.pem

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIE2DCCA8CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBxTELMAkGA1UEBhMCVVMx
3+
DzANBgNVBAgMBk9yZWdvbjESMBAGA1UEBwwJQmVhdmVydG9uMSMwIQYDVQQKDBpQ
4+
eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjEgMB4GA1UECwwXUHl0aG9uIENvcmUg
5+
RGV2ZWxvcG1lbnQxJDAiBgNVBAMMG251bGwucHl0aG9uLm9yZwBleGFtcGxlLm9y
6+
ZzEkMCIGCSqGSIb3DQEJARYVcHl0aG9uLWRldkBweXRob24ub3JnMB4XDTEzMDgw
7+
NzEzMTE1MloXDTEzMDgwNzEzMTI1MlowgcUxCzAJBgNVBAYTAlVTMQ8wDQYDVQQI
8+
DAZPcmVnb24xEjAQBgNVBAcMCUJlYXZlcnRvbjEjMCEGA1UECgwaUHl0aG9uIFNv
9+
ZnR3YXJlIEZvdW5kYXRpb24xIDAeBgNVBAsMF1B5dGhvbiBDb3JlIERldmVsb3Bt
10+
ZW50MSQwIgYDVQQDDBtudWxsLnB5dGhvbi5vcmcAZXhhbXBsZS5vcmcxJDAiBgkq
11+
hkiG9w0BCQEWFXB5dGhvbi1kZXZAcHl0aG9uLm9yZzCCASIwDQYJKoZIhvcNAQEB
12+
BQADggEPADCCAQoCggEBALXq7cn7Rn1vO3aA3TrzA5QLp6bb7B3f/yN0CJ2XFj+j
13+
pHs+Gw6WWSUDpybiiKnPec33BFawq3kyblnBMjBU61ioy5HwQqVkJ8vUVjGIUq3P
14+
vX/wBmQfzCe4o4uM89gpHyUL9UYGG8oCRa17dgqcv7u5rg0Wq2B1rgY+nHwx3JIv
15+
KRrgSwyRkGzpN8WQ1yrXlxWjgI9de0mPVDDUlywcWze1q2kwaEPTM3hLAmD1PESA
16+
oY/n8A/RXoeeRs9i/Pm/DGUS8ZPINXk/yOzsR/XvvkTVroIeLZqfmFpnZeF0cHzL
17+
08LODkVJJ9zjLdT7SA4vnne4FEbAxDbKAq5qkYzaL4UCAwEAAaOB0DCBzTAMBgNV
18+
HRMBAf8EAjAAMB0GA1UdDgQWBBSIWlXAUv9hzVKjNQ/qWpwkOCL3XDALBgNVHQ8E
19+
BAMCBeAwgZAGA1UdEQSBiDCBhYIeYWx0bnVsbC5weXRob24ub3JnAGV4YW1wbGUu
20+
Y29tgSBudWxsQHB5dGhvbi5vcmcAdXNlckBleGFtcGxlLm9yZ4YpaHR0cDovL251
21+
bGwucHl0aG9uLm9yZwBodHRwOi8vZXhhbXBsZS5vcmeHBMAAAgGHECABDbgAAAAA
22+
AAAAAAAAAAEwDQYJKoZIhvcNAQEFBQADggEBAKxPRe99SaghcI6IWT7UNkJw9aO9
23+
i9eo0Fj2MUqxpKbdb9noRDy2CnHWf7EIYZ1gznXPdwzSN4YCjV5d+Q9xtBaowT0j
24+
HPERs1ZuytCNNJTmhyqZ8q6uzMLoht4IqH/FBfpvgaeC5tBTnTT0rD5A/olXeimk
25+
kX4LxlEx5RAvpGB2zZVRGr6LobD9rVK91xuHYNIxxxfEGE8tCCWjp0+3ksri9SXx
26+
VHWBnbM9YaL32u3hxm8sYB/Yb8WSBavJCWJJqRStVRHM1koZlJmXNx2BX4vPo6iW
27+
RFEIPQsFZRLrtnCAiEhyT8bC2s/Njlu6ly9gtJZWSV46Q3ZjBL4q9sHKqZQ=
28+
-----END CERTIFICATE-----

ext/openssl/tests/cve2013_4073.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
CVE 2013-4073: Null-byte certificate handling
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("openssl")) die("skip");
6+
--FILE--
7+
<?php
8+
$cert = file_get_contents(__DIR__ . '/cve2013_4073.pem');
9+
$info = openssl_x509_parse($cert);
10+
var_export($info['extensions']);
11+
12+
--EXPECTF--
13+
array (
14+
'basicConstraints' => 'CA:FALSE',
15+
'subjectKeyIdentifier' => '88:5A:55:C0:52:FF:61:CD:52:A3:35:0F:EA:5A:9C:24:38:22:F7:5C',
16+
'keyUsage' => 'Digital Signature, Non Repudiation, Key Encipherment',
17+
'subjectAltName' => 'DNS:altnull.python.org' . "\0" . 'example.com, email:null@python.org' . "\0" . 'user@example.org, 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
18+
',
19+
)

0 commit comments

Comments
 (0)