Created
October 3, 2011 16:28
-
-
Save chregu/1259520 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: ext/xsl/tests/bug54446.phpt | |
=================================================================== | |
--- ext/xsl/tests/bug54446.phpt (revision 0) | |
+++ ext/xsl/tests/bug54446.phpt (revision 0) | |
@@ -0,0 +1,95 @@ | |
+--TEST-- | |
+Bug #54446 (Arbitrary file creation via libxslt 'output' extension) | |
+--SKIPIF-- | |
+<?php | |
+if (!extension_loaded('xsl')) die("skip Extension XSL is required\n"); | |
+?> | |
+--FILE-- | |
+<?php | |
+include("prepare.inc"); | |
+ | |
+$outputfile = dirname(__FILE__)."/bug54446test.txt"; | |
+if (file_exists($outputfile)) { | |
+ unlink($outputfile); | |
+} | |
+ | |
+$sXsl = <<<EOT | |
+<xsl:stylesheet version="1.0" | |
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | |
+ xmlns:sax="http://icl.com/saxon" | |
+ extension-element-prefixes="sax"> | |
+ | |
+ <xsl:template match="/"> | |
+ <sax:output href="$outputfile" method="text"> | |
+ <xsl:value-of select="'0wn3d via PHP and libxslt ...'"/> | |
+ </sax:output> | |
+ </xsl:template> | |
+ | |
+</xsl:stylesheet> | |
+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 | |
+ | |
Index: ext/xsl/php_xsl.h | |
=================================================================== | |
--- ext/xsl/php_xsl.h (revision 317654) | |
+++ ext/xsl/php_xsl.h (working copy) | |
@@ -32,6 +32,7 @@ | |
#include <libxslt/xsltInternals.h> | |
#include <libxslt/xsltutils.h> | |
#include <libxslt/transform.h> | |
+#include <libxslt/security.h> | |
#if HAVE_XSL_EXSLT | |
#include <libexslt/exslt.h> | |
#include <libexslt/exsltconfig.h> | |
@@ -43,6 +44,13 @@ | |
#include <libxslt/extensions.h> | |
#include <libxml/xpathInternals.h> | |
+#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 | |
+ | |
typedef struct _xsl_object { | |
zend_object std; | |
void *ptr; | |
Index: ext/xsl/xsltprocessor.c | |
=================================================================== | |
--- ext/xsl/xsltprocessor.c (revision 317654) | |
+++ ext/xsl/xsltprocessor.c (working copy) | |
@@ -475,6 +475,9 @@ | |
zval *doXInclude, *member; | |
zend_object_handlers *std_hnd; | |
FILE *f; | |
+ int secPrefsError; | |
+ int secPrefsIni; | |
+ xsltSecurityPrefsPtr secPrefs = NULL; | |
node = php_libxml_import_node(docp TSRMLS_CC); | |
@@ -531,11 +534,56 @@ | |
} | |
efree(member); | |
- newdocp = xsltApplyStylesheetUser(style, doc, (const char**) params, NULL, f, ctxt); | |
+ | |
+ secPrefsIni = INI_INT("xsl.security_prefs"); | |
+ | |
+ //if securityPrefs is set to NONE, we don't have to do any checks, but otherwise... | |
+ if (secPrefsIni != XSL_SECPREF_NONE) { | |
+ secPrefs = xsltNewSecurityPrefs(); | |
+ if (secPrefsIni & XSL_SECPREF_READ_FILE ) { | |
+ if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid)) { | |
+ secPrefsError = 1; | |
+ } | |
+ } | |
+ if (secPrefsIni & XSL_SECPREF_WRITE_FILE ) { | |
+ if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid)) { | |
+ secPrefsError = 1; | |
+ } | |
+ } | |
+ if (secPrefsIni & XSL_SECPREF_CREATE_DIRECTORY ) { | |
+ if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid)) { | |
+ secPrefsError = 1; | |
+ } | |
+ } | |
+ if (secPrefsIni & XSL_SECPREF_READ_NETWORK) { | |
+ if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid)) { | |
+ secPrefsError = 1; | |
+ } | |
+ } | |
+ if (secPrefsIni & 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); | |
Index: ext/xsl/php_xsl.c | |
=================================================================== | |
--- ext/xsl/php_xsl.c (revision 317654) | |
+++ ext/xsl/php_xsl.c (working copy) | |
@@ -141,6 +141,11 @@ | |
} | |
/* }}} */ | |
+PHP_INI_BEGIN() | |
+//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 +172,13 @@ | |
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("LIBXSLT_VERSION", LIBXSLT_VERSION, CONST_CS | CONST_PERSISTENT); | |
REGISTER_STRING_CONSTANT("LIBXSLT_DOTTED_VERSION", LIBXSLT_DOTTED_VERSION, CONST_CS | CONST_PERSISTENT); | |
@@ -175,6 +187,8 @@ | |
REGISTER_STRING_CONSTANT("LIBEXSLT_DOTTED_VERSION", LIBEXSLT_DOTTED_VERSION, CONST_CS | CONST_PERSISTENT); | |
#endif | |
+ REGISTER_INI_ENTRIES(); | |
+ | |
return SUCCESS; | |
} | |
/* }}} */ | |
@@ -258,6 +272,8 @@ | |
xsltCleanupGlobals(); | |
+ UNREGISTER_INI_ENTRIES(); | |
+ | |
return SUCCESS; | |
} | |
/* }}} */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment