https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2012-0057 http://git.php.net/?p=php-src.git;a=commitdiff;h=b2287a42a0dfd8fe392051d8f25531051cd86322 http://git.php.net/?p=php-src.git;a=commitdiff;h=192511f75d915c723384da17b6ca265971727132 http://git.php.net/?p=php-src.git;a=commitdiff;h=c9b5d92821db7335632f8578871e2b75ac018f2a http://git.php.net/?p=php-src.git;a=commitdiff;h=777a29fce22a741fedb69c83c3e7c2129372ee0e --- php-5.3.3/ext/xsl/php_xsl.c.cve0057 +++ php-5.3.3/ext/xsl/php_xsl.c @@ -141,6 +141,13 @@ zend_object_value xsl_objects_new(zend_c } /* }}} */ +PHP_INI_BEGIN() +/* Default is not allowing any write operations. + XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_WRITE_FILE == 44 +*/ +PHP_INI_ENTRY("xsl.security_prefs", "44", PHP_INI_ALL, NULL) +PHP_INI_END() + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(xsl) @@ -167,6 +174,14 @@ PHP_MINIT_FUNCTION(xsl) REGISTER_LONG_CONSTANT("XSL_CLONE_NEVER", -1, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XSL_CLONE_ALWAYS", 1, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("XSL_SECPREF_NONE", XSL_SECPREF_NONE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("XSL_SECPREF_READ_FILE", XSL_SECPREF_READ_FILE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("XSL_SECPREF_WRITE_FILE", XSL_SECPREF_WRITE_FILE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("XSL_SECPREF_CREATE_DIRECTORY", XSL_SECPREF_CREATE_DIRECTORY, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("XSL_SECPREF_READ_NETWORK", XSL_SECPREF_READ_NETWORK, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("XSL_SECPREF_WRITE_NETWORK", XSL_SECPREF_WRITE_NETWORK, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("XSL_SECPREF_DEFAULT", XSL_SECPREF_DEFAULT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("LIBXSLT_VERSION", LIBXSLT_VERSION, CONST_CS | CONST_PERSISTENT); REGISTER_STRING_CONSTANT("LIBXSLT_DOTTED_VERSION", LIBXSLT_DOTTED_VERSION, CONST_CS | CONST_PERSISTENT); @@ -175,6 +190,8 @@ PHP_MINIT_FUNCTION(xsl) REGISTER_STRING_CONSTANT("LIBEXSLT_DOTTED_VERSION", LIBEXSLT_DOTTED_VERSION, CONST_CS | CONST_PERSISTENT); #endif + REGISTER_INI_ENTRIES(); + return SUCCESS; } /* }}} */ @@ -258,6 +275,8 @@ PHP_MSHUTDOWN_FUNCTION(xsl) xsltCleanupGlobals(); + UNREGISTER_INI_ENTRIES(); + return SUCCESS; } /* }}} */ --- php-5.3.3/ext/xsl/php_xsl.h.cve0057 +++ php-5.3.3/ext/xsl/php_xsl.h @@ -32,6 +32,7 @@ extern zend_module_entry xsl_module_entr #include #include #include +#include #if HAVE_XSL_EXSLT #include #include @@ -43,6 +44,15 @@ extern zend_module_entry xsl_module_entr #include #include +#define XSL_SECPREF_NONE 0 +#define XSL_SECPREF_READ_FILE 2 +#define XSL_SECPREF_WRITE_FILE 4 +#define XSL_SECPREF_CREATE_DIRECTORY 8 +#define XSL_SECPREF_READ_NETWORK 16 +#define XSL_SECPREF_WRITE_NETWORK 32 +/* Default == disable all write access == XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_FILE */ +#define XSL_SECPREF_DEFAULT 44 + typedef struct _xsl_object { zend_object std; void *ptr; --- php-5.3.3/ext/xsl/tests/bug54446.phpt.cve0057 +++ php-5.3.3/ext/xsl/tests/bug54446.phpt @@ -0,0 +1,95 @@ +--TEST-- +Bug #54446 (Arbitrary file creation via libxslt 'output' extension) +--SKIPIF-- + +--FILE-- + + + + + + + + + +EOT; + +$xsl->loadXML( $sXsl ); + +# START XSLT +$proc->importStylesheet( $xsl ); + +# TRASNFORM & PRINT +print $proc->transformToXML( $dom ); + + +if (file_exists($outputfile)) { + print "$outputfile exists, but shouldn't!\n"; +} else { + print "OK, no file created\n"; +} + +#SET NO SECURITY PREFS +ini_set("xsl.security_prefs", XSL_SECPREF_NONE); + +# TRASNFORM & PRINT +print $proc->transformToXML( $dom ); + + +if (file_exists($outputfile)) { + print "OK, file exists\n"; +} else { + print "$outputfile doesn't exist, but should!\n"; +} + +unlink($outputfile); + +#SET SECURITY PREFS AGAIN +ini_set("xsl.security_prefs", XSL_SECPREF_WRITE_FILE | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_CREATE_DIRECTORY); + +# TRASNFORM & PRINT +print $proc->transformToXML( $dom ); + +if (file_exists($outputfile)) { + print "$outputfile exists, but shouldn't!\n"; +} else { + print "OK, no file created\n"; +} + + +--EXPECTF-- +Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %s element output in %s on line %d + +Warning: XSLTProcessor::transformToXml(): File write for %s/bug54446test.txt refused in %s on line %s + +Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element output in %s on line %d + +Warning: XSLTProcessor::transformToXml(): xsltDocumentElem: write rights for %s/bug54446test.txt denied in %s on line %d +OK, no file created +OK, file exists + +Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %s element output in %s on line %d + +Warning: XSLTProcessor::transformToXml(): File write for %s/bug54446test.txt refused in %s on line %s + +Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element output in %s on line %d + +Warning: XSLTProcessor::transformToXml(): xsltDocumentElem: write rights for %s/bug54446test.txt denied in %s on line %d +OK, no file created +--CREDITS-- +Christian Stocker, chregu@php.net + --- php-5.3.3/ext/xsl/tests/bug54446_with_ini.phpt.cve0057 +++ php-5.3.3/ext/xsl/tests/bug54446_with_ini.phpt @@ -0,0 +1,95 @@ +--TEST-- +Bug #54446 (Arbitrary file creation via libxslt 'output' extension with php.ini setting) +--SKIPIF-- + +--FILE-- + + + + + + + + + +EOT; + +$xsl->loadXML( $sXsl ); + +# START XSLT +$proc->importStylesheet( $xsl ); + +# TRASNFORM & PRINT +print $proc->transformToXML( $dom ); + + +if (file_exists($outputfile)) { + print "$outputfile exists, but shouldn't!\n"; +} else { + print "OK, no file created\n"; +} + +#SET NO SECURITY PREFS +ini_set("xsl.security_prefs", XSL_SECPREF_NONE); + +# TRASNFORM & PRINT +print $proc->transformToXML( $dom ); + + +if (file_exists($outputfile)) { + print "OK, file exists\n"; +} else { + print "$outputfile doesn't exist, but should!\n"; +} + +unlink($outputfile); + +#SET SECURITY PREFS AGAIN +ini_set("xsl.security_prefs", XSL_SECPREF_WRITE_FILE | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_CREATE_DIRECTORY); + +# TRASNFORM & PRINT +print $proc->transformToXML( $dom ); + +if (file_exists($outputfile)) { + print "$outputfile exists, but shouldn't!\n"; +} else { + print "OK, no file created\n"; +} + + +--EXPECTF-- +Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %s element output in %s on line %d + +Warning: XSLTProcessor::transformToXml(): File write for %s/bug54446test.txt refused in %s on line %s + +Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element output in %s on line %d + +Warning: XSLTProcessor::transformToXml(): xsltDocumentElem: write rights for %s/bug54446test.txt denied in %s on line %d +OK, no file created +OK, file exists + +Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %s element output in %s on line %d + +Warning: XSLTProcessor::transformToXml(): File write for %s/bug54446test.txt refused in %s on line %s + +Warning: XSLTProcessor::transformToXml(): runtime error: file %s line %d element output in %s on line %d + +Warning: XSLTProcessor::transformToXml(): xsltDocumentElem: write rights for %s/bug54446test.txt denied in %s on line %d +OK, no file created +--CREDITS-- +Christian Stocker, chregu@php.net + --- php-5.3.3/ext/xsl/xsltprocessor.c.cve0057 +++ php-5.3.3/ext/xsl/xsltprocessor.c @@ -475,6 +475,9 @@ static xmlDocPtr php_xsl_apply_styleshee zval *doXInclude, *member; zend_object_handlers *std_hnd; FILE *f; + int secPrefsError = 0; + int secPrefsValue; + xsltSecurityPrefsPtr secPrefs = NULL; node = php_libxml_import_node(docp TSRMLS_CC); @@ -531,11 +534,56 @@ static xmlDocPtr php_xsl_apply_styleshee } efree(member); - newdocp = xsltApplyStylesheetUser(style, doc, (const char**) params, NULL, f, ctxt); + + secPrefsValue = INI_INT("xsl.security_prefs"); + + /* if securityPrefs is set to NONE, we don't have to do any checks, but otherwise... */ + if (secPrefsValue != XSL_SECPREF_NONE) { + secPrefs = xsltNewSecurityPrefs(); + if (secPrefsValue & XSL_SECPREF_READ_FILE ) { + if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid)) { + secPrefsError = 1; + } + } + if (secPrefsValue & XSL_SECPREF_WRITE_FILE ) { + if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid)) { + secPrefsError = 1; + } + } + if (secPrefsValue & XSL_SECPREF_CREATE_DIRECTORY ) { + if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid)) { + secPrefsError = 1; + } + } + if (secPrefsValue & XSL_SECPREF_READ_NETWORK) { + if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid)) { + secPrefsError = 1; + } + } + if (secPrefsValue & XSL_SECPREF_WRITE_NETWORK) { + if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid)) { + secPrefsError = 1; + } + } + + if (0 != xsltSetCtxtSecurityPrefs(secPrefs, ctxt)) { + secPrefsError = 1; + } + } + + if (secPrefsError == 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't set libxslt security properties, not doing transformation for security reasons"); + } else { + newdocp = xsltApplyStylesheetUser(style, doc, (const char**) params, NULL, f, ctxt); + } if (f) { fclose(f); } + xsltFreeTransformContext(ctxt); + if (secPrefs) { + xsltFreeSecurityPrefs(secPrefs); + } if (intern->node_list != NULL) { zend_hash_destroy(intern->node_list); --- php-5.3.3/php.ini-development.cve0057 +++ php-5.3.3/php.ini-development @@ -1890,6 +1890,12 @@ ldap.max_links = -1 [dba] ;dba.default_handler= +[xsl] +; Write operations from within XSLT are disabled by default. +; XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_WRITE_FILE = 44 +; Set it to 0 to allow all operations +;xsl.security_prefs = 44 + ; Local Variables: ; tab-width: 4 ; End: --- php-5.3.3/php.ini-production.cve0057 +++ php-5.3.3/php.ini-production @@ -1897,6 +1897,12 @@ ldap.max_links = -1 [dba] ;dba.default_handler= +[xsl] +; Write operations from within XSLT are disabled by default. +; XSL_SECPREF_CREATE_DIRECTORY | XSL_SECPREF_WRITE_NETWORK | XSL_SECPREF_WRITE_FILE = 44 +; Set it to 0 to allow all operations +;xsl.security_prefs = 44 + ; Local Variables: ; tab-width: 4 ; End: --- php-5.3.3/UPGRADING.cve0057 +++ php-5.3.3/UPGRADING @@ -150,6 +150,15 @@ UPGRADE NOTES - PHP 5.3 - SplObjectStorage now has ArrayAccess support. It is also now possible to store associative information with objects in SplObjectStorage. + +===================== +4.1 New in PHP 5.3.9 +===================== + +- Write operations within XSLT (for example with the extension sax:output) are + disabled by default. You can define what is forbidden with the INI option + xsl.security_prefs. This option will be marked as deprecated in 5.4 again. + Use the method XsltProcess::setSecurityPrefs($options) there. ============= 5. Deprecated