php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #81713
Patch patch-openssl-null-byte-injection-v1 revision 2022-03-10 11:30 UTC by thomas dot chauchefoin at sonarsource dot com

Patch patch-openssl-null-byte-injection-v1 for OpenSSL related Bug #81713

Patch version 2022-03-10 11:30 UTC

Return to Bug #81713 | Download this patch
Patch Revisions:

Developer: thomas.chauchefoin@sonarsource.com

diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 506074172a..52fd6ac41d 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -1405,6 +1405,10 @@ static X509 *php_openssl_x509_from_str(zend_string *cert_str) {
 		if (php_openssl_open_base_dir_chk(ZSTR_VAL(cert_str) + (sizeof("file://") - 1))) {
 			return NULL;
 		}
+		if (CHECK_NULL_PATH(ZSTR_VAL(cert_str), ZSTR_LEN(cert_str))) {
+			zend_argument_value_error(1, "must not contain any null bytes when file:// is used");
+			return NULL;
+		}
 
 		in = BIO_new_file(ZSTR_VAL(cert_str) + (sizeof("file://") - 1), PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY));
 		if (in == NULL) {
@@ -3005,6 +3009,10 @@ static X509_REQ *php_openssl_csr_from_str(zend_string *csr_str)
 		if (php_openssl_open_base_dir_chk(filename)) {
 			return NULL;
 		}
+		if (CHECK_NULL_PATH(filename, ZSTR_LEN(csr_str) - sizeof("file://") + 1)) {
+			zend_argument_value_error(1, "must not contain any null bytes when file:// is used");
+			return NULL;
+		}
 		in = BIO_new_file(filename, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY));
 	} else {
 		in = BIO_new_mem_buf(ZSTR_VAL(csr_str), (int) ZSTR_LEN(csr_str));
@@ -3571,6 +3579,10 @@ static EVP_PKEY *php_openssl_pkey_from_zval(zval *val, int public_key, char *pas
 			if (php_openssl_open_base_dir_chk(filename)) {
 				TMP_CLEAN;
 			}
+			if (CHECK_NULL_PATH(filename, Z_STRLEN_P(val) - sizeof("file://") + 1)) {
+				zend_argument_value_error(1, "must not contain any null bytes when file:// is used");
+				TMP_CLEAN;
+			}
 		}
 		/* it's an X509 file/cert of some kind, and we need to extract the data from that */
 		if (public_key) {
diff --git a/ext/openssl/tests/openssl_functions_null_byte_injection.phpt b/ext/openssl/tests/openssl_functions_null_byte_injection.phpt
new file mode 100644
index 0000000000..cbf9f03306
--- /dev/null
+++ b/ext/openssl/tests/openssl_functions_null_byte_injection.phpt
@@ -0,0 +1,49 @@
+--TEST--
+OpenSSL functions null byte injection
+--EXTENSIONS--
+openssl
+--FILE--
+<?php
+$crt_file = __DIR__ . '/cert.crt';
+$csr_file = __DIR__ . '/cert.csr';
+$tests = [
+    ["openssl_pkey_get_public", "file:///$crt_file"],
+    ["openssl_pkey_get_public", "file:///$crt_file\x00foo"],
+    ["openssl_csr_get_subject", "file:///$csr_file"],
+    ["openssl_csr_get_subject", "file:///$csr_file\x00foo"],
+    ["openssl_x509_fingerprint", "file:///$crt_file"],
+    ["openssl_x509_fingerprint", "file:///$crt_file\x00foo"],
+];
+foreach ($tests as $test) {
+    try {
+        $key = $test[0]($test[1]);
+        var_dump($key);
+    }
+    catch (ValueError $e) {
+        echo $e->getMessage() . PHP_EOL;
+    }
+}
+?>
+--EXPECTF--
+object(OpenSSLAsymmetricKey)#1 (0) {
+}
+openssl_pkey_get_public(): Argument #1 ($public_key) must not contain any null bytes when file:// is used
+array(6) {
+  ["C"]=>
+  string(2) "NL"
+  ["ST"]=>
+  string(13) "Noord Brabant"
+  ["L"]=>
+  string(4) "Uden"
+  ["O"]=>
+  string(10) "Triconnect"
+  ["OU"]=>
+  string(10) "Triconnect"
+  ["CN"]=>
+  string(15) "*.triconnect.nl"
+}
+openssl_csr_get_subject(): Argument #1 ($csr) must not contain any null bytes when file:// is used
+string(40) "6e6fd1ea10a5a23071d61c728ee9b40df6dbc33c"
+
+Warning: openssl_x509_fingerprint(): X.509 Certificate cannot be retrieved in %s on line %d
+openssl_x509_fingerprint(): Argument #1 ($certificate) must not contain any null bytes when file:// is used
\ No newline at end of file
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 26 08:01:30 2024 UTC