Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PHP Bug #81713 - Patches
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index aa819be422..334728732f 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -1738,7 +1738,10 @@ static X509 * php_openssl_x509_from_zval(zval * val, int makeresource, zend_reso
}
if (Z_STRLEN_P(val) > 7 && memcmp(Z_STRVAL_P(val), "file://", sizeof("file://") - 1) == 0) {
-
+ if (CHECK_ZVAL_NULL_PATH(val)) {
+ php_error_docref(NULL, E_WARNING, "Argument #1 must not contain any null bytes when file:// is used");
+ return NULL;
+ }
if (php_openssl_open_base_dir_chk(Z_STRVAL_P(val) + (sizeof("file://") - 1))) {
return NULL;
}
@@ -3325,6 +3328,10 @@ static X509_REQ * php_openssl_csr_from_zval(zval * val, int makeresource, zend_r
filename = Z_STRVAL_P(val) + (sizeof("file://") - 1);
}
if (filename) {
+ if (CHECK_NULL_PATH(filename, Z_STRLEN_P(val) - sizeof("file://") + 1)) {
+ php_error_docref(NULL, E_WARNING, "Argument #1 must not contain any null bytes when file:// is used");
+ return NULL;
+ }
if (php_openssl_open_base_dir_chk(filename)) {
return NULL;
}
@@ -3911,6 +3918,10 @@ static EVP_PKEY * php_openssl_evp_from_zval(
if (Z_STRLEN_P(val) > 7 && memcmp(Z_STRVAL_P(val), "file://", sizeof("file://") - 1) == 0) {
filename = Z_STRVAL_P(val) + (sizeof("file://") - 1);
+ if (CHECK_NULL_PATH(filename, Z_STRLEN_P(val) - sizeof("file://") + 1)) {
+ php_error_docref(NULL, E_WARNING, "Argument #1 must not contain any null bytes when file:// is used");
+ TMP_CLEAN;
+ }
if (php_openssl_open_base_dir_chk(filename)) {
TMP_CLEAN;
}
diff --git a/ext/openssl/tests/bug81713.phpt b/ext/openssl/tests/bug81713.phpt
new file mode 100644
index 0000000000..e5809f7416
--- /dev/null
+++ b/ext/openssl/tests/bug81713.phpt
@@ -0,0 +1,54 @@
+--TEST--
+OpenSSL functions null byte injection
+--SKIPIF--
+<?php if (!extension_loaded("openssl")) die("skip openssl extension not available"); ?>
+--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--
+resource(4) of type (OpenSSL key)
+
+Warning: openssl_pkey_get_public(): Argument #1 must not contain any null bytes when file:// is used in %s on line %d
+bool(false)
+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"
+}
+
+Warning: openssl_csr_get_subject(): Argument #1 must not contain any null bytes when file:// is used in %s on line %d
+bool(false)
+string(40) "6e6fd1ea10a5a23071d61c728ee9b40df6dbc33c"
+
+Warning: openssl_x509_fingerprint(): Argument #1 must not contain any null bytes when file:// is used in %s on line %d
+
+Warning: openssl_x509_fingerprint(): cannot get cert from parameter 1 in %s on line %d
+bool(false)
\ No newline at end of file
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 506074172a..9dcad366d4 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -1402,6 +1402,10 @@ static X509 *php_openssl_x509_from_str(zend_string *cert_str) {
BIO *in;
if (ZSTR_LEN(cert_str) > 7 && memcmp(ZSTR_VAL(cert_str), "file://", sizeof("file://") - 1) == 0) {
+ 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;
+ }
if (php_openssl_open_base_dir_chk(ZSTR_VAL(cert_str) + (sizeof("file://") - 1))) {
return NULL;
}
@@ -3002,6 +3006,10 @@ static X509_REQ *php_openssl_csr_from_str(zend_string *csr_str)
}
if (filename) {
+ 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;
+ }
if (php_openssl_open_base_dir_chk(filename)) {
return NULL;
}
@@ -3568,6 +3576,10 @@ static EVP_PKEY *php_openssl_pkey_from_zval(zval *val, int public_key, char *pas
if (Z_STRLEN_P(val) > 7 && memcmp(Z_STRVAL_P(val), "file://", sizeof("file://") - 1) == 0) {
filename = Z_STRVAL_P(val) + (sizeof("file://") - 1);
+ 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;
+ }
if (php_openssl_open_base_dir_chk(filename)) {
TMP_CLEAN;
}
diff --git a/ext/openssl/tests/bug81713.phpt b/ext/openssl/tests/bug81713.phpt
new file mode 100644
index 0000000000..914fd48ab7
--- /dev/null
+++ b/ext/openssl/tests/bug81713.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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment