php/hardening-patch-5.1.6-0.4.15.patch

8760 lines
288 KiB
Diff
Raw Normal View History

diff -Nura php-5.1.6/Changelog.hphp hardening-patch-5.1.6-0.4.15/Changelog.hphp
--- php-5.1.6/Changelog.hphp 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Changelog.hphp 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,61 @@
+Changelog of the Hardening-Patch
+--------------------------------
+
+0.4.15 - 07. September 2006
+
+ PHP4:
+ [+] Fix for potential DOS in handling of include blacklists
+
+ PHP4+5:
+ [+] Backported a fix for open_basedir problems with insanse PHP scripts
+ [+] Added a fix for ini_restore() PHP security vulnerability
+
+0.4.14 - 11. August 2006
+
+ PHP4:
+ [+] Remove unecessary call to AC_BROKEN_REALPATH
+
+ PHP5:
+ [+] Fix Remote URL Include Protection - Thanks to: Bart Vanbrabant
+
+ PHP4+5:
+ [+] Added a few PHP security fixes / see changelog.secfix for details
+ [+] Fixed the memory_limit protection for systems with different perdir memory_limits
+ [+] Fixed a possible memory corruption when foreach() is used with wrong arguments
+
+0.4.13 - 07. August 2006
+
+ PHP4+5:
+ [+] Added a fix for a compile problem on solaris due to missing strcasestr()
+
+0.4.12 - 19. July 2006
+
+ PHP4:
+ [+] Added fixes from sf4 security patch / see changelog.secfix for details
+
+ PHP5:
+ [+] Added fixes from sf5 security patch / see changelog.secfix for details
+
+ PHP4+5:
+ [+] Added anti mail spam feature
+ [+] Speedup of zend_hash canary (clear/destroy)
+ [+] Added a fix for a DOS in the handling of URL blacklists
+
+0.4.11 - 13. May 2006
+
+ PHP5:
+ [+] tsrm_virtual_cwd.c: close open_basedir, safe_mode hole introduced by realpath() cache
+ [+] install-pear-nozlib.phar: bundle in full package download of 5.1.4
+
+ PHP4+5:
+ [+] tsrm_virtual_cwd.c: realpath() hotfix to solve problems with non existing directories
+
+
+0.4.10 - 11. May 2006
+
+ PHP4:
+ [+] info.c: backport from 5.1.4 contained TSRMLS macro that had to be removed
+
+ PHP4+5:
+ [+] fopen_wrappers.c: fix for a trailing slash problem with open_basedir
+
diff -Nura php-5.1.6/Changelog.secfix hardening-patch-5.1.6-0.4.15/Changelog.secfix
--- php-5.1.6/Changelog.secfix 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Changelog.secfix 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,40 @@
+Changelog of PHP 5.1.4 Security Fixes
+
+Release 6 - 11. August 2006
+
+ [+] Added IMAP open_basedir/safe_mode check
+ [+] Added a fix for previous ext/session fixes
+ [+] Added upstream fix to ext/socket
+ [+] Added sscanf() security fix
+ [+] Added fixes for handling of corrupt .gif files to gdlib
+
+Release 5 - 13. July 2006
+
+ [+] Fixed compilation of Security-Patch Release 4 in ZTS mode
+
+Release 4 - 13. July 2006
+
+ [+] Added a recursive array printing fix to the phpinfo() XSS fix
+ [+] Added a fix for stat() on non existing files in safe_mode
+
+Release 3 - 07. July 2006
+
+ [+] Added a fix for an integer overflow in str_repeat()
+ [+] Added a *working* wordwrap() fix
+ [+] Added code to make memory_limit work on 64bit systems
+ [+] Added a fix for the error_log() safe_mode/open_basedir vulnerability
+ [+] Added a fix for overlong tempfilename
+ [+] Added multiple fixes for new safe_mode/open_basedir problems in ext/curl
+ [+] Added a high characters fix to ext/wddx
+
+Release 2 - 16. May 2006
+
+ [+] Remove install-pear-nozlib.phar from the patchfile, because the official PHP
+ tarball got updated
+
+Release 1 - 13. May 2006
+
+ [+] Bundle install-pear-nozlib.phar which was missing in the official PHP tarball
+ and is downloaded when make install is called (usually as root -> security risk)
+ [+] Fixed open_basedir/safe_mode bypass via the realpath() cache
+
diff -Nura php-5.1.6/configure hardening-patch-5.1.6-0.4.15/configure
--- php-5.1.6/configure 2006-08-23 14:55:02.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/configure 2006-09-07 19:41:16.000000000 +0200
@@ -942,6 +942,16 @@
ac_help="$ac_help
--with-libdir=NAME Look for libraries in .../NAME rather than .../lib"
ac_help="$ac_help
+ --disable-hardening-patch-mm-protect Disable the Memory Manager protection."
+ac_help="$ac_help
+ --disable-hardening-patch-ll-protect Disable the Linked List protection."
+ac_help="$ac_help
+ --disable-hardening-patch-inc-protect Disable include/require protection."
+ac_help="$ac_help
+ --disable-hardening-patch-fmt-protect Disable format string protection."
+ac_help="$ac_help
+ --disable-hardening-patch-hash-protect Disable Zend HashTable DTOR protection."
+ac_help="$ac_help
SAPI modules:
"
@@ -1410,6 +1420,8 @@
ac_help="$ac_help
--enable-wddx Enable WDDX support"
ac_help="$ac_help
+ --disable-varfilter Disable Hardening-Patch's variable filter"
+ac_help="$ac_help
--disable-xml Disable XML support"
ac_help="$ac_help
--with-libxml-dir=DIR XML: libxml2 install prefix"
@@ -3618,6 +3630,157 @@
+# Check whether --enable-hardening-patch-mm-protect or --disable-hardening-patch-mm-protect was given.
+if test "${enable_hardening_patch_mm_protect+set}" = set; then
+ enableval="$enable_hardening_patch_mm_protect"
+
+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
+
+else
+
+ DO_HARDENING_PATCH_MM_PROTECT=yes
+
+fi
+
+
+# Check whether --enable-hardening-patch-ll-protect or --disable-hardening-patch-ll-protect was given.
+if test "${enable_hardening_patch_ll_protect+set}" = set; then
+ enableval="$enable_hardening_patch_ll_protect"
+
+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
+
+else
+
+ DO_HARDENING_PATCH_LL_PROTECT=yes
+
+fi
+
+
+# Check whether --enable-hardening-patch-inc-protect or --disable-hardening-patch-inc-protect was given.
+if test "${enable_hardening_patch_inc_protect+set}" = set; then
+ enableval="$enable_hardening_patch_inc_protect"
+
+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
+
+else
+
+ DO_HARDENING_PATCH_INC_PROTECT=yes
+
+fi
+
+
+# Check whether --enable-hardening-patch-fmt-protect or --disable-hardening-patch-fmt-protect was given.
+if test "${enable_hardening_patch_fmt_protect+set}" = set; then
+ enableval="$enable_hardening_patch_fmt_protect"
+
+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
+
+else
+
+ DO_HARDENING_PATCH_FMT_PROTECT=yes
+
+fi
+
+
+# Check whether --enable-hardening-patch-hash-protect or --disable-hardening-patch-hash-protect was given.
+if test "${enable_hardening_patch_hash_protect+set}" = set; then
+ enableval="$enable_hardening_patch_hash_protect"
+
+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
+
+else
+
+ DO_HARDENING_PATCH_HASH_PROTECT=yes
+
+fi
+
+
+echo $ac_n "checking whether to protect the Zend Memory Manager""... $ac_c" 1>&6
+echo "configure:2725: checking whether to protect the Zend Memory Manager" >&5
+echo "$ac_t""$DO_HARDENING_PATCH_MM_PROTECT" 1>&6
+
+echo $ac_n "checking whether to protect the Zend Linked Lists""... $ac_c" 1>&6
+echo "configure:2729: checking whether to protect the Zend Linked Lists" >&5
+echo "$ac_t""$DO_HARDENING_PATCH_LL_PROTECT" 1>&6
+
+echo $ac_n "checking whether to protect include/require statements""... $ac_c" 1>&6
+echo "configure:2733: checking whether to protect include/require statements" >&5
+echo "$ac_t""$DO_HARDENING_PATCH_INC_PROTECT" 1>&6
+
+echo $ac_n "checking whether to protect PHP Format String functions""... $ac_c" 1>&6
+echo "configure:2737: checking whether to protect PHP Format String functions" >&5
+echo "$ac_t""$DO_HARDENING_PATCH_FMT_PROTECT" 1>&6
+
+echo $ac_n "checking whether to protect the Zend HashTable Destructors""... $ac_c" 1>&6
+echo "configure:2737: checking whether to protect the Zend HashTable Destructors" >&5
+echo "$ac_t""$DO_HARDENING_PATCH_HASH_PROTECT" 1>&6
+
+
+cat >> confdefs.h <<\EOF
+#define HARDENING_PATCH 1
+EOF
+
+
+
+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define HARDENING_PATCH_MM_PROTECT 1
+EOF
+
+else
+ cat >> confdefs.h <<\EOF
+#define HARDENING_PATCH_MM_PROTECT 0
+EOF
+
+fi
+
+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define HARDENING_PATCH_LL_PROTECT 1
+EOF
+
+else
+ cat >> confdefs.h <<\EOF
+#define HARDENING_PATCH_LL_PROTECT 0
+EOF
+
+fi
+
+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define HARDENING_PATCH_INC_PROTECT 1
+EOF
+
+else
+ cat >> confdefs.h <<\EOF
+#define HARDENING_PATCH_INC_PROTECT 0
+EOF
+
+fi
+
+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define HARDENING_PATCH_FMT_PROTECT 1
+EOF
+
+else
+ cat >> confdefs.h <<\EOF
+#define HARDENING_PATCH_FMT_PROTECT 0
+EOF
+
+fi
+
+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define HARDENING_PATCH_HASH_PROTECT 1
+EOF
+
+else
+ cat >> confdefs.h <<\EOF
+#define HARDENING_PATCH_HASH_PROTECT 0
+EOF
+
+fi
@@ -18607,6 +18770,62 @@
fi
+ echo $ac_n "checking whether realpath is broken""... $ac_c" 1>&6
+echo "configure:14928: checking whether realpath is broken" >&5
+if eval "test \"`echo '$''{'ac_cv_broken_realpath'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ if test "$cross_compiling" = yes; then
+
+ ac_cv_broken_realpath=no
+
+else
+ cat > conftest.$ac_ext <<EOF
+#line 14939 "configure"
+#include "confdefs.h"
+
+main() {
+ char buf[4096+1];
+ buf[0] = 0;
+ realpath("/etc/hosts/../passwd", buf);
+ exit(strcmp(buf, "/etc/passwd")==0);
+}
+
+EOF
+if { (eval echo configure:14958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+
+ ac_cv_broken_realpath=no
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+
+ ac_cv_broken_realpath=yes
+
+fi
+rm -fr conftest*
+fi
+
+
+fi
+
+echo "$ac_t""$ac_cv_broken_realpath" 1>&6
+ if test "$ac_cv_broken_realpath" = "yes"; then
+ cat >> confdefs.h <<\EOF
+#define PHP_BROKEN_REALPATH 1
+EOF
+
+ else
+ cat >> confdefs.h <<\EOF
+#define PHP_BROKEN_REALPATH 0
+EOF
+
+ fi
+
+
echo $ac_n "checking for declared timezone""... $ac_c" 1>&6
echo "configure:18612: checking for declared timezone" >&5
if eval "test \"`echo '$''{'ac_cv_declared_timezone'+set}'`\" = set"; then
@@ -89422,7 +89641,7 @@
if test "$ac_cv_crypt_blowfish" = "yes"; then
ac_result=1
else
- ac_result=0
+ ac_result=1
fi
cat >> confdefs.h <<EOF
#define PHP_BLOWFISH_CRYPT $ac_result
@@ -92022,7 +92241,7 @@
incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
var_unserializer.c ftok.c sha1.c user_filters.c uuencode.c \
- filters.c proc_open.c streamsfuncs.c http.c; do
+ filters.c proc_open.c streamsfuncs.c http.c sha256.c crypt_blowfish.c ; do
IFS=.
set $ac_src
@@ -92081,7 +92300,7 @@
incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
var_unserializer.c ftok.c sha1.c user_filters.c uuencode.c \
- filters.c proc_open.c streamsfuncs.c http.c; do
+ filters.c proc_open.c streamsfuncs.c http.c sha256.c crypt_blowfish.c ; do
IFS=.
set $ac_src
@@ -92211,7 +92430,7 @@
incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
var_unserializer.c ftok.c sha1.c user_filters.c uuencode.c \
- filters.c proc_open.c streamsfuncs.c http.c; do
+ filters.c proc_open.c streamsfuncs.c http.c sha256.c crypt_blowfish.c ; do
IFS=.
set $ac_src
@@ -92266,7 +92485,7 @@
incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
var_unserializer.c ftok.c sha1.c user_filters.c uuencode.c \
- filters.c proc_open.c streamsfuncs.c http.c; do
+ filters.c proc_open.c streamsfuncs.c http.c sha256.c crypt_blowfish.c ; do
IFS=.
set $ac_src
@@ -96101,6 +96320,265 @@
fi
+echo $ac_n "checking whether to enable Hardening-Patch's variable filter""... $ac_c" 1>&6
+echo "configure:82041: checking whether to enable Hardening-Patch's variable filter" >&5
+# Check whether --enable-varfilter or --disable-varfilter was given.
+if test "${enable_varfilter+set}" = set; then
+ enableval="$enable_varfilter"
+ PHP_VARFILTER=$enableval
+else
+
+ PHP_VARFILTER=yes
+
+ if test "$PHP_ENABLE_ALL" && test "yes" = "yes"; then
+ PHP_VARFILTER=$PHP_ENABLE_ALL
+ fi
+
+fi
+
+
+
+ext_output="yes, shared"
+ext_shared=yes
+case $PHP_VARFILTER in
+shared,*)
+ PHP_VARFILTER=`echo "$PHP_VARFILTER"|sed 's/^shared,//'`
+ ;;
+shared)
+ PHP_VARFILTER=yes
+ ;;
+no)
+ ext_output=no
+ ext_shared=no
+ ;;
+*)
+ ext_output=yes
+ ext_shared=no
+ ;;
+esac
+
+
+
+echo "$ac_t""$ext_output" 1>&6
+
+
+
+
+if test "$PHP_VARFILTER" != "no"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_VARFILTER 1
+EOF
+
+
+ ext_builddir=ext/varfilter
+ ext_srcdir=$abs_srcdir/ext/varfilter
+
+ ac_extra=
+
+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" != "cli"; then
+
+
+
+ case ext/varfilter in
+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
+ esac
+
+
+
+ b_c_pre=$php_c_pre
+ b_cxx_pre=$php_cxx_pre
+ b_c_meta=$php_c_meta
+ b_cxx_meta=$php_cxx_meta
+ b_c_post=$php_c_post
+ b_cxx_post=$php_cxx_post
+ b_lo=$php_lo
+
+
+ old_IFS=$IFS
+ for ac_src in varfilter.c; do
+
+ IFS=.
+ set $ac_src
+ ac_obj=$1
+ IFS=$old_IFS
+
+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
+
+ case $ac_src in
+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
+ esac
+
+ cat >>Makefile.objects<<EOF
+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
+ $ac_comp
+EOF
+ done
+
+
+ EXT_STATIC="$EXT_STATIC varfilter"
+ if test "$ext_shared" != "nocli"; then
+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
+ fi
+ else
+ if test "$ext_shared" = "shared" || test "$ext_shared" = "yes"; then
+
+ case ext/varfilter in
+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
+ esac
+
+
+
+ b_c_pre=$shared_c_pre
+ b_cxx_pre=$shared_cxx_pre
+ b_c_meta=$shared_c_meta
+ b_cxx_meta=$shared_cxx_meta
+ b_c_post=$shared_c_post
+ b_cxx_post=$shared_cxx_post
+ b_lo=$shared_lo
+
+
+ old_IFS=$IFS
+ for ac_src in varfilter.c; do
+
+ IFS=.
+ set $ac_src
+ ac_obj=$1
+ IFS=$old_IFS
+
+ shared_objects_varfilter="$shared_objects_varfilter $ac_bdir$ac_obj.lo"
+
+ case $ac_src in
+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
+ esac
+
+ cat >>Makefile.objects<<EOF
+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
+ $ac_comp
+EOF
+ done
+
+
+ install_modules="install-modules"
+ PHP_MODULES="$PHP_MODULES \$(phplibdir)/varfilter.la"
+
+ PHP_VAR_SUBST="$PHP_VAR_SUBST shared_objects_varfilter"
+
+ cat >>Makefile.objects<<EOF
+\$(phplibdir)/varfilter.la: $ext_builddir/varfilter.la
+ \$(LIBTOOL) --mode=install cp $ext_builddir/varfilter.la \$(phplibdir)
+
+$ext_builddir/varfilter.la: \$(shared_objects_varfilter) \$(VARFILTER_SHARED_DEPENDENCIES)
+ \$(LIBTOOL) --mode=link \$(CC) \$(COMMON_FLAGS) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(LDFLAGS) -o \$@ -export-dynamic -avoid-version -prefer-pic -module -rpath \$(phplibdir) \$(EXTRA_LDFLAGS) \$(shared_objects_varfilter) \$(VARFILTER_SHARED_LIBADD)
+
+EOF
+
+ cat >> confdefs.h <<EOF
+#define COMPILE_DL_VARFILTER 1
+EOF
+
+ fi
+ fi
+
+ if test "$ext_shared" != "shared" && test "$ext_shared" != "yes" && test "" = "cli"; then
+ if test "$PHP_SAPI" = "cgi"; then
+
+
+ case ext/varfilter in
+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
+ esac
+
+
+
+ b_c_pre=$php_c_pre
+ b_cxx_pre=$php_cxx_pre
+ b_c_meta=$php_c_meta
+ b_cxx_meta=$php_cxx_meta
+ b_c_post=$php_c_post
+ b_cxx_post=$php_cxx_post
+ b_lo=$php_lo
+
+
+ old_IFS=$IFS
+ for ac_src in varfilter.c; do
+
+ IFS=.
+ set $ac_src
+ ac_obj=$1
+ IFS=$old_IFS
+
+ PHP_GLOBAL_OBJS="$PHP_GLOBAL_OBJS $ac_bdir$ac_obj.lo"
+
+ case $ac_src in
+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
+ esac
+
+ cat >>Makefile.objects<<EOF
+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
+ $ac_comp
+EOF
+ done
+
+
+ EXT_STATIC="$EXT_STATIC varfilter"
+ else
+
+
+ case ext/varfilter in
+ "") ac_srcdir="$abs_srcdir/"; unset ac_bdir; ac_inc="-I. -I$abs_srcdir" ;;
+ /*) ac_srcdir=`echo "ext/varfilter"|cut -c 2-`"/"; ac_bdir=$ac_srcdir; ac_inc="-I$ac_bdir -I$abs_srcdir/$ac_bdir" ;;
+ *) ac_srcdir="$abs_srcdir/ext/varfilter/"; ac_bdir="ext/varfilter/"; ac_inc="-I$ac_bdir -I$ac_srcdir" ;;
+ esac
+
+
+
+ b_c_pre=$php_c_pre
+ b_cxx_pre=$php_cxx_pre
+ b_c_meta=$php_c_meta
+ b_cxx_meta=$php_cxx_meta
+ b_c_post=$php_c_post
+ b_cxx_post=$php_cxx_post
+ b_lo=$php_lo
+
+
+ old_IFS=$IFS
+ for ac_src in varfilter.c; do
+
+ IFS=.
+ set $ac_src
+ ac_obj=$1
+ IFS=$old_IFS
+
+ PHP_CLI_OBJS="$PHP_CLI_OBJS $ac_bdir$ac_obj.lo"
+
+ case $ac_src in
+ *.c) ac_comp="$b_c_pre $ac_extra $ac_inc $b_c_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;;
+ *.cpp) ac_comp="$b_cxx_pre $ac_extra $ac_inc $b_cxx_meta -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;;
+ esac
+
+ cat >>Makefile.objects<<EOF
+$ac_bdir$ac_obj.lo: $ac_srcdir$ac_src
+ $ac_comp
+EOF
+ done
+
+
+ fi
+ EXT_CLI_STATIC="$EXT_CLI_STATIC varfilter"
+ fi
+
+ BUILD_DIR="$BUILD_DIR $ext_builddir"
+
+
+fi
echo $ac_n "checking whether to enable WDDX support""... $ac_c" 1>&6
@@ -112351,7 +112829,7 @@
php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
network.c php_open_temporary_file.c php_logos.c \
- output.c ; do
+ output.c hardening_patch.c ; do
IFS=.
set $ac_src
@@ -112596,7 +113074,7 @@
zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
- zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c; do
+ zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_canary.c; do
IFS=.
set $ac_src
diff -Nura php-5.1.6/configure.in hardening-patch-5.1.6-0.4.15/configure.in
--- php-5.1.6/configure.in 2006-08-23 15:17:36.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/configure.in 2006-09-07 19:41:16.000000000 +0200
@@ -209,7 +209,7 @@
sinclude(Zend/Zend.m4)
sinclude(TSRM/tsrm.m4)
-
+sinclude(main/hardening_patch.m4)
divert(2)
@@ -1275,7 +1275,7 @@
php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
network.c php_open_temporary_file.c php_logos.c \
- output.c )
+ output.c hardening_patch.c )
PHP_ADD_SOURCES(main/streams, streams.c cast.c memory.c filter.c \
plain_wrapper.c userspace.c transports.c xp_socket.c mmap.c)
@@ -1302,7 +1302,7 @@
zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \
- zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c)
+ zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_canary.c )
if test -r "$abs_srcdir/Zend/zend_objects.c"; then
PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c \
diff -Nura php-5.1.6/ext/curl/interface.c hardening-patch-5.1.6-0.4.15/ext/curl/interface.c
--- php-5.1.6/ext/curl/interface.c 2006-08-10 19:16:35.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/curl/interface.c 2006-09-07 19:41:16.000000000 +0200
@@ -172,6 +172,11 @@
RETURN_FALSE; \
} \
\
+ if (php_memnstr(str, tmp_url->path, strlen(tmp_url->path), str + len)) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Url '%s' contains unencoded control characters.", str); \
+ RETURN_FALSE; \
+ } \
+ \
if (tmp_url->query || tmp_url->fragment || php_check_open_basedir(tmp_url->path TSRMLS_CC) || \
(PG(safe_mode) && !php_checkuid(tmp_url->path, "rb+", CHECKUID_CHECK_MODE_PARAM)) \
) { \
diff -Nura php-5.1.6/ext/fbsql/php_fbsql.c hardening-patch-5.1.6-0.4.15/ext/fbsql/php_fbsql.c
--- php-5.1.6/ext/fbsql/php_fbsql.c 2006-08-14 20:40:20.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/fbsql/php_fbsql.c 2006-09-07 19:41:16.000000000 +0200
@@ -1949,8 +1949,24 @@
}
else if (fbcmdErrorsFound(md))
{
+#if HARDENING_PATCH
+ char* query_copy;
+ int i;
+#endif
FBCErrorMetaData* emd = fbcdcErrorMetaData(c, md);
char* emg = fbcemdAllErrorMessages(emd);
+#if HARDENING_PATCH
+ query_copy=estrdup(query_copy);
+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
+ php_security_log(S_SQL, "fbsql error: %s - query: %s", emg, query_copy);
+ efree(query_copy);
+ if (HG(hphp_sql_bailout_on_error)) {
+ free(emg);
+ fbcemdRelease(emd);
+ result = 0;
+ zend_bailout();
+ }
+#endif
if (FB_SQL_G(generateWarnings))
{
if (emg)
diff -Nura php-5.1.6/ext/imap/php_imap.c hardening-patch-5.1.6-0.4.15/ext/imap/php_imap.c
--- php-5.1.6/ext/imap/php_imap.c 2006-08-11 17:07:13.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/imap/php_imap.c 2006-09-07 19:41:16.000000000 +0200
@@ -768,6 +768,13 @@
RETURN_FALSE;
}
+ /* local filename, need to perform open_basedir and safe_mode checks */
+ if (Z_STRVAL_PP(mailbox)[0] != '{' &&
+ (php_check_open_basedir(Z_STRVAL_PP(mailbox) TSRMLS_CC) ||
+ (PG(safe_mode) && !php_checkuid(Z_STRVAL_PP(mailbox), NULL, CHECKUID_CHECK_FILE_AND_DIR)))) {
+ RETURN_FALSE;
+ }
+
IMAPG(imap_user) = estrndup(Z_STRVAL_PP(user), Z_STRLEN_PP(user));
IMAPG(imap_password) = estrndup(Z_STRVAL_PP(passwd), Z_STRLEN_PP(passwd));
diff -Nura php-5.1.6/ext/mysql/php_mysql.c hardening-patch-5.1.6-0.4.15/ext/mysql/php_mysql.c
--- php-5.1.6/ext/mysql/php_mysql.c 2006-01-01 13:50:09.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/mysql/php_mysql.c 2006-09-07 19:41:16.000000000 +0200
@@ -1231,6 +1231,8 @@
{
php_mysql_conn *mysql;
MYSQL_RES *mysql_result;
+ char *copy_query;
+ int i;
ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, link_id, "MySQL-Link", le_link, le_plink);
@@ -1281,6 +1283,13 @@
php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
}
}
+ copy_query = estrdup(Z_STRVAL_PP(query));
+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
+ efree(copy_query);
+ if (HG(hphp_sql_bailout_on_error)) {
+ zend_bailout();
+ }
RETURN_FALSE;
}
#else
@@ -1291,6 +1300,13 @@
php_error_docref("http://www.mysql.com/doc" TSRMLS_CC, E_WARNING, "%s", mysql_error(&mysql->conn));
}
}
+ copy_query = estrdup(Z_STRVAL_PP(query));
+ for (i=0; copy_query[i]; i++) if (copy_query[i] < 32) copy_query[i]='.';
+ php_security_log(S_SQL, "MySQL error: %s - query: %s", mysql_error(&mysql->conn), copy_query);
+ efree(copy_query);
+ if (HG(hphp_sql_bailout_on_error)) {
+ zend_bailout();
+ }
RETURN_FALSE;
}
#endif
diff -Nura php-5.1.6/ext/mysqli/mysqli_nonapi.c hardening-patch-5.1.6-0.4.15/ext/mysqli/mysqli_nonapi.c
--- php-5.1.6/ext/mysqli/mysqli_nonapi.c 2006-03-24 10:32:24.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/mysqli/mysqli_nonapi.c 2006-09-07 19:41:16.000000000 +0200
@@ -184,6 +184,17 @@
if (mysql_real_query(mysql->mysql, query, query_len)) {
char s_error[MYSQL_ERRMSG_SIZE], s_sqlstate[SQLSTATE_LENGTH+1];
unsigned int s_errno;
+#if HARDENING_PATCH
+ char *query_copy = estrdup(query);
+ int i;
+
+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
+ php_security_log(S_SQL, "MySQLi error: %s - query: %s", mysql->mysql->net.last_error, query_copy);
+ efree(query_copy);
+ if (HG(hphp_sql_bailout_on_error)) {
+ zend_bailout();
+ }
+#endif
MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
/* we have to save error information, cause
@@ -234,6 +245,17 @@
MYSQLI_DISABLE_MQ;
if (mysql_real_query(mysql->mysql, query, query_len)) {
+#if HARDENING_PATCH
+ char *query_copy = estrdup(query);
+ int i;
+
+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
+ php_security_log(S_SQL, "MySQLi error: %s - query: %s", mysql->mysql->net.last_error, query_copy);
+ efree(query_copy);
+ if (HG(hphp_sql_bailout_on_error)) {
+ zend_bailout();
+ }
+#endif
MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
RETURN_FALSE;
}
diff -Nura php-5.1.6/ext/pgsql/pgsql.c hardening-patch-5.1.6-0.4.15/ext/pgsql/pgsql.c
--- php-5.1.6/ext/pgsql/pgsql.c 2006-04-10 21:51:55.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/pgsql/pgsql.c 2006-09-07 19:41:16.000000000 +0200
@@ -1152,10 +1152,28 @@
case PGRES_EMPTY_QUERY:
case PGRES_BAD_RESPONSE:
case PGRES_NONFATAL_ERROR:
- case PGRES_FATAL_ERROR:
- PHP_PQ_ERROR("Query failed: %s", pgsql);
- PQclear(pgsql_result);
- RETURN_FALSE;
+ case PGRES_FATAL_ERROR:
+ {
+#if HARDENING_PATCH
+ int i;
+ char *query_copy;
+#endif
+ char *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL);
+ PQclear(pgsql_result);
+#if HARDENING_PATCH
+ query_copy = estrdup(Z_STRVAL_PP(query));
+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
+ php_security_log(S_SQL, "PgSQL error: %s - query: %s", msgbuf, query_copy);
+ efree(query_copy);
+ if (HG(hphp_sql_bailout_on_error)) {
+ efree(msgbuf);
+ zend_bailout();
+ }
+#endif
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Query failed: %s", msgbuf);
+ efree(msgbuf);
+ RETURN_FALSE;
+ }
break;
case PGRES_COMMAND_OK: /* successful command that did not return rows */
default:
diff -Nura php-5.1.6/ext/session/mod_files.c hardening-patch-5.1.6-0.4.15/ext/session/mod_files.c
--- php-5.1.6/ext/session/mod_files.c 2006-04-18 02:31:45.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/session/mod_files.c 2006-09-07 19:41:16.000000000 +0200
@@ -152,6 +152,7 @@
if (!ps_files_valid_key(key)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,'");
+ PS(invalid_session_id) = 1;
return;
}
if (!ps_files_path_create(buf, sizeof(buf), data, key))
@@ -401,7 +402,12 @@
ps_files_close(data);
if (VCWD_UNLINK(buf) == -1) {
- return FAILURE;
+ /* This is a little safety check for instances when we are dealing with a regenerated session
+ * that was not yet written to disk
+ */
+ if (!VCWD_ACCESS(buf, F_OK)) {
+ return FAILURE;
+ }
}
}
@@ -422,6 +428,35 @@
return SUCCESS;
}
+PS_VALIDATE_SID_FUNC(files)
+{
+ char buf[MAXPATHLEN];
+ int fd;
+ PS_FILES_DATA;
+
+ if (!ps_files_valid_key(key)) {
+ return FAILURE;
+ }
+
+ if (!PS(use_strict_mode)) {
+ return SUCCESS;
+ }
+
+ if (!ps_files_path_create(buf, sizeof(buf), data, key)) {
+ return FAILURE;
+ }
+
+ fd = VCWD_OPEN_MODE(buf, O_RDWR | O_BINARY,
+ data->filemode);
+
+ if (fd != -1) {
+ close(fd);
+ return SUCCESS;
+ }
+
+ return FAILURE;
+}
+
/*
* Local variables:
* tab-width: 4
diff -Nura php-5.1.6/ext/session/mod_mm.c hardening-patch-5.1.6-0.4.15/ext/session/mod_mm.c
--- php-5.1.6/ext/session/mod_mm.c 2006-01-01 13:50:12.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/session/mod_mm.c 2006-09-07 19:41:16.000000000 +0200
@@ -425,6 +425,42 @@
return SUCCESS;
}
+PS_VALIDATE_SID_FUNC(mm)
+{
+ PS_MM_DATA;
+ ps_sd *sd;
+ const char *p;
+ char c;
+ int ret = SUCCESS;
+
+ for (p = key; (c = *p); p++) {
+ /* valid characters are a..z,A..Z,0..9 */
+ if (!((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || c == ','
+ || c == '-')) {
+ return FAILURE;
+ }
+ }
+
+ if (!PS(use_strict_mode)) {
+ return SUCCESS;
+ }
+
+ mm_lock(data->mm, MM_LOCK_RD);
+
+ sd = ps_sd_lookup(data, key, 0);
+ if (sd) {
+ mm_unlock(data->mm);
+ return SUCCESS;
+ }
+
+ mm_unlock(data->mm);
+
+ return FAILURE;
+}
+
#endif
/*
diff -Nura php-5.1.6/ext/session/mod_user.c hardening-patch-5.1.6-0.4.15/ext/session/mod_user.c
--- php-5.1.6/ext/session/mod_user.c 2006-01-01 13:50:12.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/session/mod_user.c 2006-09-07 19:41:16.000000000 +0200
@@ -23,7 +23,7 @@
#include "mod_user.h"
ps_module ps_mod_user = {
- PS_MOD(user)
+ PS_MOD_SID(user)
};
#define SESS_ZVAL_LONG(val, a) \
@@ -174,6 +174,83 @@
FINISH;
}
+PS_CREATE_SID_FUNC(user)
+{
+ int i;
+ char *val = NULL;
+ zval *retval;
+ ps_user *mdata = PS_GET_MOD_DATA();
+
+ if (!mdata)
+ return estrndup("", 0);
+
+ if (PSF(create) == NULL || ZVAL_IS_NULL(PSF(create))) {
+ return php_session_create_id(mod_data, newlen TSRMLS_CC);
+ }
+ retval = ps_call_handler(PSF(create), 0, NULL TSRMLS_CC);
+
+ if (retval) {
+ if (Z_TYPE_P(retval) == IS_STRING) {
+ val = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
+ } else {
+ val = estrndup("", 0);
+ }
+ zval_ptr_dtor(&retval);
+ } else {
+ val = estrndup("", 0);
+ }
+
+ return val;
+}
+
+static int ps_user_valid_key(const char *key TSRMLS_DC)
+{
+ size_t len;
+ const char *p;
+ char c;
+ int ret = SUCCESS;
+
+ for (p = key; (c = *p); p++) {
+ /* valid characters are a..z,A..Z,0..9 */
+ if (!((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || c == ','
+ || c == '-')) {
+ ret = FAILURE;
+ break;
+ }
+ }
+
+ len = p - key;
+
+ if (len == 0)
+ ret = FAILURE;
+
+ return ret;
+}
+
+PS_VALIDATE_SID_FUNC(user)
+{
+ zval *args[1];
+ STDVARS;
+
+ if (PSF(validate) == NULL || ZVAL_IS_NULL(PSF(validate))) {
+ return ps_user_valid_key(key TSRMLS_CC);
+ }
+ SESS_ZVAL_STRING(key, args[0]);
+
+ retval = ps_call_handler(PSF(validate), 1, args TSRMLS_CC);
+
+ if (retval) {
+ convert_to_long(retval);
+ ret = Z_LVAL_P(retval) ? SUCCESS : FAILURE;
+ zval_ptr_dtor(&retval);
+ }
+
+ return ret;
+}
+
/*
* Local variables:
* tab-width: 4
diff -Nura php-5.1.6/ext/session/mod_user.h hardening-patch-5.1.6-0.4.15/ext/session/mod_user.h
--- php-5.1.6/ext/session/mod_user.h 2006-01-01 13:50:12.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/session/mod_user.h 2006-09-07 19:41:16.000000000 +0200
@@ -22,7 +22,7 @@
#define MOD_USER_H
typedef union {
- zval *names[6];
+ zval *names[8];
struct {
zval *ps_open;
zval *ps_close;
@@ -30,6 +30,8 @@
zval *ps_write;
zval *ps_destroy;
zval *ps_gc;
+ zval *ps_create;
+ zval *ps_validate;
} name;
} ps_user;
diff -Nura php-5.1.6/ext/session/php_session.h hardening-patch-5.1.6-0.4.15/ext/session/php_session.h
--- php-5.1.6/ext/session/php_session.h 2006-01-28 07:14:49.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/session/php_session.h 2006-09-07 19:41:16.000000000 +0200
@@ -23,7 +23,7 @@
#include "ext/standard/php_var.h"
-#define PHP_SESSION_API 20020330
+#define PHP_SESSION_API 20051121
#define PS_OPEN_ARGS void **mod_data, const char *save_path, const char *session_name TSRMLS_DC
#define PS_CLOSE_ARGS void **mod_data TSRMLS_DC
@@ -32,6 +32,7 @@
#define PS_DESTROY_ARGS void **mod_data, const char *key TSRMLS_DC
#define PS_GC_ARGS void **mod_data, int maxlifetime, int *nrdels TSRMLS_DC
#define PS_CREATE_SID_ARGS void **mod_data, int *newlen TSRMLS_DC
+#define PS_VALIDATE_SID_ARGS void **mod_data, const char *key TSRMLS_DC
/* default create id function */
PHPAPI char *php_session_create_id(PS_CREATE_SID_ARGS);
@@ -45,6 +46,7 @@
int (*s_destroy)(PS_DESTROY_ARGS);
int (*s_gc)(PS_GC_ARGS);
char *(*s_create_sid)(PS_CREATE_SID_ARGS);
+ int (*s_validate_sid)(PS_VALIDATE_SID_ARGS);
} ps_module;
#define PS_GET_MOD_DATA() *mod_data
@@ -57,6 +59,7 @@
#define PS_DESTROY_FUNC(x) int ps_delete_##x(PS_DESTROY_ARGS)
#define PS_GC_FUNC(x) int ps_gc_##x(PS_GC_ARGS)
#define PS_CREATE_SID_FUNC(x) char *ps_create_sid_##x(PS_CREATE_SID_ARGS)
+#define PS_VALIDATE_SID_FUNC(x) int ps_validate_sid_##x(PS_VALIDATE_SID_ARGS)
#define PS_FUNCS(x) \
PS_OPEN_FUNC(x); \
@@ -65,11 +68,12 @@
PS_WRITE_FUNC(x); \
PS_DESTROY_FUNC(x); \
PS_GC_FUNC(x); \
- PS_CREATE_SID_FUNC(x)
+ PS_CREATE_SID_FUNC(x); \
+ PS_VALIDATE_SID_FUNC(x)
#define PS_MOD(x) \
#x, ps_open_##x, ps_close_##x, ps_read_##x, ps_write_##x, \
- ps_delete_##x, ps_gc_##x, php_session_create_id
+ ps_delete_##x, ps_gc_##x, php_session_create_id, ps_validate_sid_##x
/* SID enabled module handler definitions */
#define PS_FUNCS_SID(x) \
@@ -79,11 +83,12 @@
PS_WRITE_FUNC(x); \
PS_DESTROY_FUNC(x); \
PS_GC_FUNC(x); \
- PS_CREATE_SID_FUNC(x)
+ PS_CREATE_SID_FUNC(x); \
+ PS_VALIDATE_SID(x)
#define PS_MOD_SID(x) \
#x, ps_open_##x, ps_close_##x, ps_read_##x, ps_write_##x, \
- ps_delete_##x, ps_gc_##x, ps_create_sid_##x
+ ps_delete_##x, ps_gc_##x, ps_create_sid_##x, ps_validate_sid_##x
typedef enum {
php_session_disabled,
@@ -120,11 +125,13 @@
zend_bool use_only_cookies;
zend_bool use_trans_sid; /* contains the INI value of whether to use trans-sid */
zend_bool apply_trans_sid; /* whether or not to enable trans-sid for the current request */
+ zend_bool use_strict_mode; /* whether or not PHP accepts unknown session ids */
long hash_func;
long hash_bits_per_character;
int send_cookie;
int define_sid;
+ zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */
} php_ps_globals;
typedef php_ps_globals zend_ps_globals;
diff -Nura php-5.1.6/ext/session/session.c hardening-patch-5.1.6-0.4.15/ext/session/session.c
--- php-5.1.6/ext/session/session.c 2006-02-10 08:39:13.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/session/session.c 2006-09-07 19:41:16.000000000 +0200
@@ -166,6 +166,7 @@
STD_PHP_INI_BOOLEAN("session.cookie_secure", "", PHP_INI_ALL, OnUpdateBool, cookie_secure, php_ps_globals, ps_globals)
STD_PHP_INI_BOOLEAN("session.use_cookies", "1", PHP_INI_ALL, OnUpdateBool, use_cookies, php_ps_globals, ps_globals)
STD_PHP_INI_BOOLEAN("session.use_only_cookies", "0", PHP_INI_ALL, OnUpdateBool, use_only_cookies, php_ps_globals, ps_globals)
+ STD_PHP_INI_BOOLEAN("session.use_strict_mode", "1", PHP_INI_ALL, OnUpdateBool, use_strict_mode, php_ps_globals, ps_globals)
STD_PHP_INI_ENTRY("session.referer_check", "", PHP_INI_ALL, OnUpdateString, extern_referer_chk, php_ps_globals, ps_globals)
STD_PHP_INI_ENTRY("session.entropy_file", "", PHP_INI_ALL, OnUpdateString, entropy_file, php_ps_globals, ps_globals)
STD_PHP_INI_ENTRY("session.entropy_length", "0", PHP_INI_ALL, OnUpdateLong, entropy_length, php_ps_globals, ps_globals)
@@ -280,9 +281,13 @@
PHPAPI void php_add_session_var(char *name, size_t namelen TSRMLS_DC)
{
zval **sym_track = NULL;
-
- zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), name, namelen + 1,
- (void *) &sym_track);
+
+ IF_SESSION_VARS() {
+ zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), name, namelen + 1,
+ (void *) &sym_track);
+ } else {
+ return;
+ }
/*
* Set up a proper reference between $_SESSION["x"] and $x.
@@ -758,9 +763,23 @@
return;
}
+ /* If there is an ID, use session module to verify it */
+ if (PS(id)) {
+ if (PS(mod)->s_validate_sid(&PS(mod_data), PS(id) TSRMLS_CC) == FAILURE) {
+ efree(PS(id));
+ PS(id) = NULL;
+ PS(send_cookie) = 1;
+ }
+ }
+
/* If there is no ID, use session module to create one */
- if (!PS(id))
+ if (!PS(id)) {
+new_session:
PS(id) = PS(mod)->s_create_sid(&PS(mod_data), NULL TSRMLS_CC);
+ if (PS(use_cookies)) {
+ PS(send_cookie) = 1;
+ }
+ }
/* Read data */
/* Question: if you create a SID here, should you also try to read data?
@@ -769,9 +788,14 @@
* session information
*/
php_session_track_init(TSRMLS_C);
+ PS(invalid_session_id) = 0;
if (PS(mod)->s_read(&PS(mod_data), PS(id), &val, &vallen TSRMLS_CC) == SUCCESS) {
php_session_decode(val, vallen TSRMLS_CC);
efree(val);
+ } else if (PS(invalid_session_id)) { /* address instances where the session read fails due to an invalid id */
+ PS(invalid_session_id) = 0;
+ efree(PS(id));
+ goto new_session;
}
}
@@ -1377,22 +1401,29 @@
}
/* }}} */
-/* {{{ proto void session_set_save_handler(string open, string close, string read, string write, string destroy, string gc)
+/* {{{ proto void session_set_save_handler(string open, string close, string read, string write, string destroy, string gc[, string create, string validate])
Sets user-level functions */
PHP_FUNCTION(session_set_save_handler)
{
- zval **args[6];
- int i;
+ zval **args[8];
+ int i, numargs;
ps_user *mdata;
char *name;
- if (ZEND_NUM_ARGS() != 6 || zend_get_parameters_array_ex(6, args) == FAILURE)
+ numargs = ZEND_NUM_ARGS();
+ args[6] = NULL;
+ args[7] = NULL;
+
+ if (numargs < 6 || numargs > 8 || zend_get_parameters_array_ex(numargs, args) == FAILURE)
WRONG_PARAM_COUNT;
if (PS(session_status) != php_session_none)
RETURN_FALSE;
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < 8; i++) {
+ if (i >= 6 && (args[i] == NULL || ZVAL_IS_NULL(*args[i]))) {
+ continue;
+ }
if (!zend_is_callable(*args[i], 0, &name)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument %d is not a valid callback", i+1);
efree(name);
@@ -1405,7 +1436,11 @@
mdata = emalloc(sizeof(*mdata));
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < 8; i++) {
+ if (i >= 6 && (args[i] == NULL || ZVAL_IS_NULL(*args[i]))) {
+ mdata->names[i] = NULL;
+ continue;
+ }
ZVAL_ADDREF(*args[i]);
mdata->names[i] = *args[i];
}
@@ -1475,6 +1510,11 @@
WRONG_PARAM_COUNT;
}
+ if (SG(headers_sent)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot regenerate session id - headers already sent");
+ RETURN_FALSE;
+ }
+
if (PS(session_status) == php_session_active) {
if (PS(id)) {
if (del_ses && PS(mod)->s_destroy(&PS(mod_data), PS(id) TSRMLS_CC) == FAILURE) {
@@ -1531,8 +1571,8 @@
WRONG_PARAM_COUNT;
if (ac == 1) {
- convert_to_long_ex(p_cache_expire);
- PS(cache_expire) = Z_LVAL_PP(p_cache_expire);
+ convert_to_string_ex(p_cache_expire);
+ zend_alter_ini_entry("session.cache_expire", sizeof("session.cache_expire"), Z_STRVAL_PP(p_cache_expire), Z_STRLEN_PP(p_cache_expire), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
}
RETVAL_LONG(old);
diff -Nura php-5.1.6/ext/session/tests/014.phpt hardening-patch-5.1.6-0.4.15/ext/session/tests/014.phpt
--- php-5.1.6/ext/session/tests/014.phpt 2005-07-04 15:09:14.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/session/tests/014.phpt 2006-09-07 19:41:16.000000000 +0200
@@ -5,6 +5,7 @@
--INI--
session.use_trans_sid=1
session.use_cookies=0
+session.use_strict_mode=0
session.cache_limiter=
register_globals=1
session.bug_compat_42=1
diff -Nura php-5.1.6/ext/session/tests/015.phpt hardening-patch-5.1.6-0.4.15/ext/session/tests/015.phpt
--- php-5.1.6/ext/session/tests/015.phpt 2005-07-04 15:09:14.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/session/tests/015.phpt 2006-09-07 19:41:16.000000000 +0200
@@ -5,6 +5,7 @@
--INI--
session.use_trans_sid=1
session.use_cookies=0
+session.use_strict_mode=0
session.cache_limiter=
arg_separator.output=&
session.name=PHPSESSID
diff -Nura php-5.1.6/ext/session/tests/018.phpt hardening-patch-5.1.6-0.4.15/ext/session/tests/018.phpt
--- php-5.1.6/ext/session/tests/018.phpt 2005-07-04 15:09:14.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/session/tests/018.phpt 2006-09-07 19:41:16.000000000 +0200
@@ -4,6 +4,7 @@
<?php include('skipif.inc'); ?>
--INI--
session.use_cookies=0
+session.use_strict_mode=0
session.cache_limiter=
session.use_trans_sid=1
session.name=PHPSESSID
diff -Nura php-5.1.6/ext/session/tests/019.phpt hardening-patch-5.1.6-0.4.15/ext/session/tests/019.phpt
--- php-5.1.6/ext/session/tests/019.phpt 2005-07-04 15:09:14.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/session/tests/019.phpt 2006-09-07 19:41:16.000000000 +0200
@@ -4,6 +4,7 @@
<?php include('skipif.inc'); ?>
--INI--
session.use_cookies=0
+session.use_strict_mode=0
session.cache_limiter=
register_globals=1
session.serialize_handler=php
diff -Nura php-5.1.6/ext/session/tests/020.phpt hardening-patch-5.1.6-0.4.15/ext/session/tests/020.phpt
--- php-5.1.6/ext/session/tests/020.phpt 2005-07-04 15:09:14.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/session/tests/020.phpt 2006-09-07 19:41:16.000000000 +0200
@@ -4,6 +4,7 @@
<?php include('skipif.inc'); ?>
--INI--
session.use_cookies=0
+session.use_strict_mode=0
session.cache_limiter=
session.use_trans_sid=1
arg_separator.output=&amp;
diff -Nura php-5.1.6/ext/session/tests/021.phpt hardening-patch-5.1.6-0.4.15/ext/session/tests/021.phpt
--- php-5.1.6/ext/session/tests/021.phpt 2005-07-04 15:09:14.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/session/tests/021.phpt 2006-09-07 19:41:16.000000000 +0200
@@ -4,6 +4,7 @@
<?php include('skipif.inc'); ?>
--INI--
session.use_cookies=0
+session.use_strict_mode=0
session.cache_limiter=
session.use_trans_sid=1
url_rewriter.tags="a=href,area=href,frame=src,input=src,form=,fieldset="
diff -Nura php-5.1.6/ext/session/tests/bug38377.phpt hardening-patch-5.1.6-0.4.15/ext/session/tests/bug38377.phpt
--- php-5.1.6/ext/session/tests/bug38377.phpt 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/session/tests/bug38377.phpt 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,13 @@
+--TEST--
+bug #38377 (session_destroy() gives warning after session_regenerate_id())
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+session_start();
+session_regenerate_id();
+session_destroy();
+echo "Done\n";
+?>
+--EXPECT--
+Done
diff -Nura php-5.1.6/ext/sockets/sockets.c hardening-patch-5.1.6-0.4.15/ext/sockets/sockets.c
--- php-5.1.6/ext/sockets/sockets.c 2006-04-07 16:04:36.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/sockets/sockets.c 2006-09-07 19:41:16.000000000 +0200
@@ -533,6 +533,7 @@
{
zval **element;
php_socket *php_sock;
+ int num = 0;
if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0;
@@ -547,9 +548,10 @@
if (php_sock->bsd_socket > *max_fd) {
*max_fd = php_sock->bsd_socket;
}
+ num++;
}
- return 1;
+ return num ? 1 : 0;
}
static int php_sock_array_from_fd_set(zval *sock_array, fd_set *fds TSRMLS_DC)
@@ -558,6 +560,7 @@
zval **dest_element;
php_socket *php_sock;
HashTable *new_hash;
+ int num = 0;
if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0;
@@ -575,6 +578,7 @@
zend_hash_next_index_insert(new_hash, (void *)element, sizeof(zval *), (void **)&dest_element);
if (dest_element) zval_add_ref(dest_element);
}
+ num++;
}
/* Destroy old array, add new one */
@@ -584,7 +588,7 @@
zend_hash_internal_pointer_reset(new_hash);
Z_ARRVAL_P(sock_array) = new_hash;
- return 1;
+ return num ? 1 : 0;
}
/* {{{ proto int socket_select(array &read_fds, array &write_fds, &array except_fds, int tv_sec[, int tv_usec])
diff -Nura php-5.1.6/ext/sqlite/sess_sqlite.c hardening-patch-5.1.6-0.4.15/ext/sqlite/sess_sqlite.c
--- php-5.1.6/ext/sqlite/sess_sqlite.c 2006-01-01 13:50:14.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/sqlite/sess_sqlite.c 2006-09-07 19:41:16.000000000 +0200
@@ -185,6 +185,76 @@
return SQLITE_RETVAL(rv);
}
+PS_VALIDATE_SID_FUNC(sqlite)
+{
+ PS_SQLITE_DATA;
+ char *query;
+ const char *tail;
+ sqlite_vm *vm;
+ int colcount, result;
+ const char **rowdata, **colnames;
+ char *error;
+ size_t len;
+ const char *p;
+ char c;
+ int ret = FAILURE;
+
+ for (p = key; (c = *p); p++) {
+ /* valid characters are a..z,A..Z,0..9 */
+ if (!((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || c == ','
+ || c == '-')) {
+ return FAILURE;
+ break;
+ }
+ }
+
+ len = p - key;
+
+ if (len == 0)
+ return FAILURE;
+
+ if (!PS(use_strict_mode)) {
+ return SUCCESS;
+ }
+
+ query = sqlite_mprintf("SELECT value FROM session_data WHERE sess_id='%q' LIMIT 1", key);
+ if (query == NULL) {
+ /* no memory */
+ return FAILURE;
+ }
+
+ if (sqlite_compile(db, query, &tail, &vm, &error) != SQLITE_OK) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: Could not compile session validate sid query: %s", error);
+ sqlite_freemem(error);
+ sqlite_freemem(query);
+ return FAILURE;
+ }
+
+ switch ((result = sqlite_step(vm, &colcount, &rowdata, &colnames))) {
+ case SQLITE_ROW:
+ if (rowdata[0] != NULL) {
+ ret = SUCCESS;
+ }
+ break;
+ default:
+ sqlite_freemem(error);
+ error = NULL;
+ }
+
+ if (SQLITE_OK != sqlite_finalize(vm, &error)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLite: session validate sid: error %s", error);
+ sqlite_freemem(error);
+ error = NULL;
+ }
+
+ sqlite_freemem(query);
+
+ return ret;
+}
+
#endif /* HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION) */
/*
diff -Nura php-5.1.6/ext/sqlite/sqlite.c hardening-patch-5.1.6-0.4.15/ext/sqlite/sqlite.c
--- php-5.1.6/ext/sqlite/sqlite.c 2006-04-18 16:30:15.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/sqlite/sqlite.c 2006-09-07 19:41:16.000000000 +0200
@@ -1530,6 +1530,19 @@
db->last_err_code = ret;
if (ret != SQLITE_OK) {
+#if HARDENING_PATCH
+ char *query_copy;
+ int i;
+
+ query_copy = estrdup(sql);
+ for (i=0; query_copy[i]; i++) if (query_copy[i]<32) query_copy[i]='.';
+ php_security_log(S_SQL, "SQLite error: %s - query: %s", errtext, query_copy);
+ efree(query_copy);
+ if (HG(hphp_sql_bailout_on_error)) {
+ sqlite_freemem(errtext);
+ zend_bailout();
+ }
+#endif
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
if (errmsg) {
ZVAL_STRING(errmsg, errtext, 1);
diff -Nura php-5.1.6/ext/standard/array.c hardening-patch-5.1.6-0.4.15/ext/standard/array.c
--- php-5.1.6/ext/standard/array.c 2006-06-03 20:59:55.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/standard/array.c 2006-09-07 19:41:16.000000000 +0200
@@ -1297,6 +1297,32 @@
}
}
}
+
+ if (var_name[0] == 'H') {
+ if ((strcmp(var_name, "HTTP_GET_VARS")==0)||
+ (strcmp(var_name, "HTTP_POST_VARS")==0)||
+ (strcmp(var_name, "HTTP_POST_FILES")==0)||
+ (strcmp(var_name, "HTTP_ENV_VARS")==0)||
+ (strcmp(var_name, "HTTP_SERVER_VARS")==0)||
+ (strcmp(var_name, "HTTP_SESSION_VARS")==0)||
+ (strcmp(var_name, "HTTP_COOKIE_VARS")==0)||
+ (strcmp(var_name, "HTTP_RAW_POST_DATA")==0)) {
+ return 0;
+ }
+ } else if (var_name[0] == '_') {
+ if ((strcmp(var_name, "_COOKIE")==0)||
+ (strcmp(var_name, "_ENV")==0)||
+ (strcmp(var_name, "_FILES")==0)||
+ (strcmp(var_name, "_GET")==0)||
+ (strcmp(var_name, "_POST")==0)||
+ (strcmp(var_name, "_REQUEST")==0)||
+ (strcmp(var_name, "_SESSION")==0)||
+ (strcmp(var_name, "_SERVER")==0)) {
+ return 0;
+ }
+ } else if (strcmp(var_name, "GLOBALS")==0) {
+ return 0;
+ }
return 1;
}
diff -Nura php-5.1.6/ext/standard/basic_functions.c hardening-patch-5.1.6-0.4.15/ext/standard/basic_functions.c
--- php-5.1.6/ext/standard/basic_functions.c 2006-06-29 00:08:59.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/standard/basic_functions.c 2006-09-07 19:41:16.000000000 +0200
@@ -151,12 +151,14 @@
typedef struct _php_shutdown_function_entry {
zval **arguments;
int arg_count;
+ zend_bool created_by_eval;
} php_shutdown_function_entry;
typedef struct _user_tick_function_entry {
zval **arguments;
int arg_count;
int calling;
+ zend_bool created_by_eval;
} user_tick_function_entry;
/* some prototypes for local functions */
@@ -188,6 +190,8 @@
PHP_FE(get_html_translation_table, NULL)
PHP_FE(sha1, NULL)
PHP_FE(sha1_file, NULL)
+ PHP_FE(sha256, NULL)
+ PHP_FE(sha256_file, NULL)
PHP_NAMED_FE(md5,php_if_md5, NULL)
PHP_NAMED_FE(md5_file,php_if_md5_file, NULL)
PHP_NAMED_FE(crc32,php_if_crc32, NULL)
@@ -632,7 +636,7 @@
PHP_FALIAS(socket_get_status, stream_get_meta_data, NULL)
#if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
- PHP_FE(realpath, NULL)
+ PHP_STATIC_FE("realpath", zif_real_path, NULL)
#endif
#ifdef HAVE_FNMATCH
@@ -2279,6 +2283,13 @@
{
zval retval;
char *function_name = NULL;
+#if HARDENING_PATCH
+ zend_uint orig_code_type = EG(in_code_type);
+
+ if (shutdown_function_entry->created_by_eval) {
+ EG(in_code_type) = ZEND_EVAL_CODE;
+ }
+#endif
if (!zend_is_callable(shutdown_function_entry->arguments[0], 0, &function_name)) {
php_error(E_WARNING, "(Registered shutdown functions) Unable to call %s() - function does not exist", function_name);
@@ -2294,6 +2305,9 @@
if (function_name) {
efree(function_name);
}
+#if HARDENING_PATCH
+ EG(in_code_type) = orig_code_type;
+#endif
return 0;
}
@@ -2301,6 +2315,13 @@
{
zval retval;
zval *function = tick_fe->arguments[0];
+#if HARDENING_PATCH
+ zend_uint orig_code_type = EG(in_code_type);
+
+ if (tick_fe->created_by_eval) {
+ EG(in_code_type) = ZEND_EVAL_CODE;
+ }
+#endif
/* Prevent reentrant calls to the same user ticks function */
if (! tick_fe->calling) {
@@ -2332,6 +2353,9 @@
tick_fe->calling = 0;
}
+#if HARDENING_PATCH
+ EG(in_code_type) = orig_code_type;
+#endif
}
static void run_user_tick_functions(int tick_count)
@@ -2395,6 +2419,13 @@
}
shutdown_function_entry.arguments = (zval **) safe_emalloc(sizeof(zval *), shutdown_function_entry.arg_count, 0);
+#if HARDENING_PATCH
+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
+ shutdown_function_entry.created_by_eval = 1;
+ } else {
+ shutdown_function_entry.created_by_eval = 0;
+ }
+#endif
if (zend_get_parameters_array(ht, shutdown_function_entry.arg_count, shutdown_function_entry.arguments) == FAILURE) {
efree(shutdown_function_entry.arguments);
@@ -2722,6 +2753,15 @@
convert_to_string_ex(varname);
+ /* checks that ensure the user does not overwrite certain ini settings when safe_mode is enabled */
+ if (PG(safe_mode)) {
+ if (!strncmp("max_execution_time", Z_STRVAL_PP(varname), sizeof("max_execution_time")) ||
+ !strncmp("memory_limit", Z_STRVAL_PP(varname), sizeof("memory_limit")) ||
+ !strncmp("child_terminate", Z_STRVAL_PP(varname), sizeof("child_terminate"))) {
+ RETURN_FALSE;
+ }
+ }
+
zend_restore_ini_entry(Z_STRVAL_PP(varname), Z_STRLEN_PP(varname)+1, PHP_INI_STAGE_RUNTIME);
}
/* }}} */
@@ -2979,6 +3019,13 @@
}
tick_fe.arguments = (zval **) safe_emalloc(sizeof(zval *), tick_fe.arg_count, 0);
+#if HARDENING_PATCH
+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
+ tick_fe.created_by_eval = 1;
+ } else {
+ tick_fe.created_by_eval = 0;
+ }
+#endif
if (zend_get_parameters_array(ht, tick_fe.arg_count, tick_fe.arguments) == FAILURE) {
efree(tick_fe.arguments);
@@ -3282,6 +3329,35 @@
new_key_len = spprintf(&new_key, 0, "%s%ld", prefix, hash_key->h);
}
+ if (new_key[0] == 'H') {
+ if ((strcmp(new_key, "HTTP_GET_VARS")==0)||
+ (strcmp(new_key, "HTTP_POST_VARS")==0)||
+ (strcmp(new_key, "HTTP_POST_FILES")==0)||
+ (strcmp(new_key, "HTTP_ENV_VARS")==0)||
+ (strcmp(new_key, "HTTP_SERVER_VARS")==0)||
+ (strcmp(new_key, "HTTP_SESSION_VARS")==0)||
+ (strcmp(new_key, "HTTP_COOKIE_VARS")==0)||
+ (strcmp(new_key, "HTTP_RAW_POST_DATA")==0)) {
+ efree(new_key);
+ return 0;
+ }
+ } else if (new_key[0] == '_') {
+ if ((strcmp(new_key, "_COOKIE")==0)||
+ (strcmp(new_key, "_ENV")==0)||
+ (strcmp(new_key, "_FILES")==0)||
+ (strcmp(new_key, "_GET")==0)||
+ (strcmp(new_key, "_POST")==0)||
+ (strcmp(new_key, "_REQUEST")==0)||
+ (strcmp(new_key, "_SESSION")==0)||
+ (strcmp(new_key, "_SERVER")==0)) {
+ efree(new_key);
+ return 0;
+ }
+ } else if (strcmp(new_key, "GLOBALS")==0) {
+ efree(new_key);
+ return 0;
+ }
+
zend_delete_global_variable(new_key, new_key_len-1 TSRMLS_CC);
ZEND_SET_SYMBOL_WITH_LENGTH(&EG(symbol_table), new_key, new_key_len, *var, (*var)->refcount+1, 0);
diff -Nura php-5.1.6/ext/standard/config.m4 hardening-patch-5.1.6-0.4.15/ext/standard/config.m4
--- php-5.1.6/ext/standard/config.m4 2006-01-04 22:31:29.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/standard/config.m4 2006-09-07 19:41:16.000000000 +0200
@@ -203,7 +203,7 @@
if test "$ac_cv_crypt_blowfish" = "yes"; then
ac_result=1
else
- ac_result=0
+ ac_result=1
fi
AC_DEFINE_UNQUOTED(PHP_BLOWFISH_CRYPT, $ac_result, [Whether the system supports BlowFish salt])
])
@@ -489,7 +489,7 @@
incomplete_class.c url_scanner_ex.c ftp_fopen_wrapper.c \
http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
var_unserializer.c ftok.c sha1.c user_filters.c uuencode.c \
- filters.c proc_open.c streamsfuncs.c http.c)
+ filters.c proc_open.c streamsfuncs.c http.c sha256.c crypt_blowfish.c )
PHP_ADD_MAKEFILE_FRAGMENT
diff -Nura php-5.1.6/ext/standard/config.w32 hardening-patch-5.1.6-0.4.15/ext/standard/config.w32
--- php-5.1.6/ext/standard/config.w32 2006-01-04 22:31:29.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/standard/config.w32 2006-09-07 19:41:16.000000000 +0200
@@ -16,5 +16,5 @@
url_scanner_ex.c ftp_fopen_wrapper.c http_fopen_wrapper.c \
php_fopen_wrapper.c credits.c css.c var_unserializer.c ftok.c sha1.c \
user_filters.c uuencode.c filters.c proc_open.c \
- streamsfuncs.c http.c", false /* never shared */);
+ streamsfuncs.c http.c sha256.c crypt_blowfish.c", false /* never shared */);
diff -Nura php-5.1.6/ext/standard/crypt_blowfish.c hardening-patch-5.1.6-0.4.15/ext/standard/crypt_blowfish.c
--- php-5.1.6/ext/standard/crypt_blowfish.c 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/standard/crypt_blowfish.c 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,748 @@
+/*
+ * This code comes from John the Ripper password cracker, with reentrant
+ * and crypt(3) interfaces added, but optimizations specific to password
+ * cracking removed.
+ *
+ * Written by Solar Designer <solar at openwall.com> in 1998-2002 and
+ * placed in the public domain.
+ *
+ * There's absolutely no warranty.
+ *
+ * It is my intent that you should be able to use this on your system,
+ * as a part of a software package, or anywhere else to improve security,
+ * ensure compatibility, or for any other purpose. I would appreciate
+ * it if you give credit where it is due and keep your modifications in
+ * the public domain as well, but I don't require that in order to let
+ * you place this code and any modifications you make under a license
+ * of your choice.
+ *
+ * This implementation is compatible with OpenBSD bcrypt.c (version 2a)
+ * by Niels Provos <provos at citi.umich.edu>, and uses some of his
+ * ideas. The password hashing algorithm was designed by David Mazieres
+ * <dm at lcs.mit.edu>.
+ *
+ * There's a paper on the algorithm that explains its design decisions:
+ *
+ * http://www.usenix.org/events/usenix99/provos.html
+ *
+ * Some of the tricks in BF_ROUND might be inspired by Eric Young's
+ * Blowfish library (I can't be sure if I would think of something if I
+ * hadn't seen his code).
+ */
+
+#include <string.h>
+
+#include <errno.h>
+#ifndef __set_errno
+#define __set_errno(val) errno = (val)
+#endif
+
+#undef __CONST
+#ifdef __GNUC__
+#define __CONST __const
+#else
+#define __CONST
+#endif
+
+#ifdef __i386__
+#define BF_ASM 0
+#define BF_SCALE 1
+#elif defined(__alpha__) || defined(__hppa__)
+#define BF_ASM 0
+#define BF_SCALE 1
+#else
+#define BF_ASM 0
+#define BF_SCALE 0
+#endif
+
+typedef unsigned int BF_word;
+
+/* Number of Blowfish rounds, this is also hardcoded into a few places */
+#define BF_N 16
+
+typedef BF_word BF_key[BF_N + 2];
+
+typedef struct {
+ BF_word S[4][0x100];
+ BF_key P;
+} BF_ctx;
+
+/*
+ * Magic IV for 64 Blowfish encryptions that we do at the end.
+ * The string is "OrpheanBeholderScryDoubt" on big-endian.
+ */
+static BF_word BF_magic_w[6] = {
+ 0x4F727068, 0x65616E42, 0x65686F6C,
+ 0x64657253, 0x63727944, 0x6F756274
+};
+
+/*
+ * P-box and S-box tables initialized with digits of Pi.
+ */
+static BF_ctx BF_init_state = {
+ {
+ {
+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+ 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+ 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+ 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+ 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+ 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+ 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+ 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+ 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+ 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+ 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+ 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+ 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+ 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+ 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+ 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+ 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+ 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+ 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+ 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+ 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+ 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+ 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+ 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+ 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+ 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+ 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+ 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+ 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+ 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+ 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+ 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
+ }, {
+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+ 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+ 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+ 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+ 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+ 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+ 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+ 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+ 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+ 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+ 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+ 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+ 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+ 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+ 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+ 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+ 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+ 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+ 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+ 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+ 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+ 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+ 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+ 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+ 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+ 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+ 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+ 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+ 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+ 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+ 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+ 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+ 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+ 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+ 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+ 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+ 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+ 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+ 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+ 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+ 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
+ }, {
+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+ 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+ 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+ 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+ 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+ 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+ 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+ 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+ 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+ 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+ 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+ 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+ 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+ 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+ 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+ 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+ 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+ 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+ 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+ 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+ 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+ 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+ 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+ 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+ 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+ 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+ 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+ 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+ 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+ 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+ 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+ 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+ 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+ 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+ 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+ 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+ 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+ 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+ 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+ 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+ 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+ 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+ 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+ 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+ 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+ 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+ 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
+ }, {
+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+ 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+ 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+ 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+ 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+ 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+ 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+ 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+ 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+ 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+ 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+ 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+ 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+ 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+ 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+ 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+ 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+ 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+ 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+ 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+ 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+ 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+ 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+ 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+ 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+ 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+ 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+ 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+ 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+ 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+ 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+ 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+ 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+ 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+ 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+ 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+ 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+ 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+ 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+ 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+ 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+ 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+ 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
+ }
+ }, {
+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+ 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+ 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+ 0x9216d5d9, 0x8979fb1b
+ }
+};
+
+static unsigned char BF_itoa64[64 + 1] =
+ "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+static unsigned char BF_atoi64[0x60] = {
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
+ 64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64,
+ 64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
+};
+
+/*
+ * This may be optimized out if built with function inlining and no BF_ASM.
+ */
+static void clean(void *data, int size)
+{
+#if BF_ASM
+ extern void _BF_clean(void *data);
+#endif
+ memset(data, 0, size);
+#if BF_ASM
+ _BF_clean(data);
+#endif
+}
+
+#define BF_safe_atoi64(dst, src) \
+{ \
+ tmp = (unsigned char)(src); \
+ if (tmp == '$') break; \
+ if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
+ tmp = BF_atoi64[tmp]; \
+ if (tmp > 63) return -1; \
+ (dst) = tmp; \
+}
+
+static int BF_decode(BF_word *dst, __CONST char *src, int size)
+{
+ unsigned char *dptr = (unsigned char *)dst;
+ unsigned char *end = dptr + size;
+ unsigned char *sptr = (unsigned char *)src;
+ unsigned int tmp, c1, c2, c3, c4;
+
+ do {
+ BF_safe_atoi64(c1, *sptr++);
+ BF_safe_atoi64(c2, *sptr++);
+ *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
+ if (dptr >= end) break;
+
+ BF_safe_atoi64(c3, *sptr++);
+ *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
+ if (dptr >= end) break;
+
+ BF_safe_atoi64(c4, *sptr++);
+ *dptr++ = ((c3 & 0x03) << 6) | c4;
+ } while (dptr < end);
+
+ while (dptr < end)
+ *dptr++ = 0;
+
+ return 0;
+}
+
+static void BF_encode(char *dst, __CONST BF_word *src, int size)
+{
+ unsigned char *sptr = (unsigned char *)src;
+ unsigned char *end = sptr + size;
+ unsigned char *dptr = (unsigned char *)dst;
+ unsigned int c1, c2;
+
+ do {
+ c1 = *sptr++;
+ *dptr++ = BF_itoa64[c1 >> 2];
+ c1 = (c1 & 0x03) << 4;
+ if (sptr >= end) {
+ *dptr++ = BF_itoa64[c1];
+ break;
+ }
+
+ c2 = *sptr++;
+ c1 |= c2 >> 4;
+ *dptr++ = BF_itoa64[c1];
+ c1 = (c2 & 0x0f) << 2;
+ if (sptr >= end) {
+ *dptr++ = BF_itoa64[c1];
+ break;
+ }
+
+ c2 = *sptr++;
+ c1 |= c2 >> 6;
+ *dptr++ = BF_itoa64[c1];
+ *dptr++ = BF_itoa64[c2 & 0x3f];
+ } while (sptr < end);
+}
+
+static void BF_swap(BF_word *x, int count)
+{
+ static int endianness_check = 1;
+ char *is_little_endian = (char *)&endianness_check;
+ BF_word tmp;
+
+ if (*is_little_endian)
+ do {
+ tmp = *x;
+ tmp = (tmp << 16) | (tmp >> 16);
+ *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
+ } while (--count);
+}
+
+#if BF_SCALE
+/* Architectures which can shift addresses left by 2 bits with no extra cost */
+#define BF_ROUND(L, R, N) \
+ tmp1 = L & 0xFF; \
+ tmp2 = L >> 8; \
+ tmp2 &= 0xFF; \
+ tmp3 = L >> 16; \
+ tmp3 &= 0xFF; \
+ tmp4 = L >> 24; \
+ tmp1 = data.ctx.S[3][tmp1]; \
+ tmp2 = data.ctx.S[2][tmp2]; \
+ tmp3 = data.ctx.S[1][tmp3]; \
+ tmp3 += data.ctx.S[0][tmp4]; \
+ tmp3 ^= tmp2; \
+ R ^= data.ctx.P[N + 1]; \
+ tmp3 += tmp1; \
+ R ^= tmp3;
+#else
+/* Architectures with no complicated addressing modes supported */
+#define BF_INDEX(S, i) \
+ (*((BF_word *)(((unsigned char *)S) + (i))))
+#define BF_ROUND(L, R, N) \
+ tmp1 = L & 0xFF; \
+ tmp1 <<= 2; \
+ tmp2 = L >> 6; \
+ tmp2 &= 0x3FC; \
+ tmp3 = L >> 14; \
+ tmp3 &= 0x3FC; \
+ tmp4 = L >> 22; \
+ tmp4 &= 0x3FC; \
+ tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
+ tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
+ tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
+ tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
+ tmp3 ^= tmp2; \
+ R ^= data.ctx.P[N + 1]; \
+ tmp3 += tmp1; \
+ R ^= tmp3;
+#endif
+
+/*
+ * Encrypt one block, BF_N is hardcoded here.
+ */
+#define BF_ENCRYPT \
+ L ^= data.ctx.P[0]; \
+ BF_ROUND(L, R, 0); \
+ BF_ROUND(R, L, 1); \
+ BF_ROUND(L, R, 2); \
+ BF_ROUND(R, L, 3); \
+ BF_ROUND(L, R, 4); \
+ BF_ROUND(R, L, 5); \
+ BF_ROUND(L, R, 6); \
+ BF_ROUND(R, L, 7); \
+ BF_ROUND(L, R, 8); \
+ BF_ROUND(R, L, 9); \
+ BF_ROUND(L, R, 10); \
+ BF_ROUND(R, L, 11); \
+ BF_ROUND(L, R, 12); \
+ BF_ROUND(R, L, 13); \
+ BF_ROUND(L, R, 14); \
+ BF_ROUND(R, L, 15); \
+ tmp4 = R; \
+ R = L; \
+ L = tmp4 ^ data.ctx.P[BF_N + 1];
+
+#if BF_ASM
+#define BF_body() \
+ _BF_body_r(&data.ctx);
+#else
+#define BF_body() \
+ L = R = 0; \
+ ptr = data.ctx.P; \
+ do { \
+ ptr += 2; \
+ BF_ENCRYPT; \
+ *(ptr - 2) = L; \
+ *(ptr - 1) = R; \
+ } while (ptr < &data.ctx.P[BF_N + 2]); \
+\
+ ptr = data.ctx.S[0]; \
+ do { \
+ ptr += 2; \
+ BF_ENCRYPT; \
+ *(ptr - 2) = L; \
+ *(ptr - 1) = R; \
+ } while (ptr < &data.ctx.S[3][0xFF]);
+#endif
+
+static void BF_set_key(__CONST char *key, BF_key expanded, BF_key initial)
+{
+ __CONST char *ptr = key;
+ int i, j;
+ BF_word tmp;
+
+ for (i = 0; i < BF_N + 2; i++) {
+ tmp = 0;
+ for (j = 0; j < 4; j++) {
+ tmp <<= 8;
+ tmp |= *ptr;
+
+ if (!*ptr) ptr = key; else ptr++;
+ }
+
+ expanded[i] = tmp;
+ initial[i] = BF_init_state.P[i] ^ tmp;
+ }
+}
+
+char *_crypt_blowfish_rn(__CONST char *key, __CONST char *setting,
+ char *output, int size)
+{
+#if BF_ASM
+ extern void _BF_body_r(BF_ctx *ctx);
+#endif
+ struct {
+ BF_ctx ctx;
+ BF_key expanded_key;
+ union {
+ BF_word salt[4];
+ BF_word output[6];
+ } binary;
+ } data;
+ BF_word L, R;
+ BF_word tmp1, tmp2, tmp3, tmp4;
+ BF_word *ptr;
+ BF_word count;
+ int i;
+
+ if (size < 7 + 22 + 31 + 1) {
+ __set_errno(ERANGE);
+ return NULL;
+ }
+
+ if (setting[0] != '$' ||
+ setting[1] != '2' ||
+ setting[2] != 'a' ||
+ setting[3] != '$' ||
+ setting[4] < '0' || setting[4] > '3' ||
+ setting[5] < '0' || setting[5] > '9' ||
+ setting[6] != '$') {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+
+ count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
+ if (count < 16 || BF_decode(data.binary.salt, &setting[7], 16)) {
+ clean(data.binary.salt, sizeof(data.binary.salt));
+ __set_errno(EINVAL);
+ return NULL;
+ }
+
+ BF_swap(data.binary.salt, 4);
+
+ BF_set_key(key, data.expanded_key, data.ctx.P);
+
+ memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
+
+ L = R = 0;
+ for (i = 0; i < BF_N + 2; i += 2) {
+ L ^= data.binary.salt[i & 2];
+ R ^= data.binary.salt[(i & 2) + 1];
+ BF_ENCRYPT;
+ data.ctx.P[i] = L;
+ data.ctx.P[i + 1] = R;
+ }
+
+ ptr = data.ctx.S[0];
+ do {
+ ptr += 4;
+ L ^= data.binary.salt[(BF_N + 2) & 3];
+ R ^= data.binary.salt[(BF_N + 3) & 3];
+ BF_ENCRYPT;
+ *(ptr - 4) = L;
+ *(ptr - 3) = R;
+
+ L ^= data.binary.salt[(BF_N + 4) & 3];
+ R ^= data.binary.salt[(BF_N + 5) & 3];
+ BF_ENCRYPT;
+ *(ptr - 2) = L;
+ *(ptr - 1) = R;
+ } while (ptr < &data.ctx.S[3][0xFF]);
+
+ do {
+ data.ctx.P[0] ^= data.expanded_key[0];
+ data.ctx.P[1] ^= data.expanded_key[1];
+ data.ctx.P[2] ^= data.expanded_key[2];
+ data.ctx.P[3] ^= data.expanded_key[3];
+ data.ctx.P[4] ^= data.expanded_key[4];
+ data.ctx.P[5] ^= data.expanded_key[5];
+ data.ctx.P[6] ^= data.expanded_key[6];
+ data.ctx.P[7] ^= data.expanded_key[7];
+ data.ctx.P[8] ^= data.expanded_key[8];
+ data.ctx.P[9] ^= data.expanded_key[9];
+ data.ctx.P[10] ^= data.expanded_key[10];
+ data.ctx.P[11] ^= data.expanded_key[11];
+ data.ctx.P[12] ^= data.expanded_key[12];
+ data.ctx.P[13] ^= data.expanded_key[13];
+ data.ctx.P[14] ^= data.expanded_key[14];
+ data.ctx.P[15] ^= data.expanded_key[15];
+ data.ctx.P[16] ^= data.expanded_key[16];
+ data.ctx.P[17] ^= data.expanded_key[17];
+
+ BF_body();
+
+ tmp1 = data.binary.salt[0];
+ tmp2 = data.binary.salt[1];
+ tmp3 = data.binary.salt[2];
+ tmp4 = data.binary.salt[3];
+ data.ctx.P[0] ^= tmp1;
+ data.ctx.P[1] ^= tmp2;
+ data.ctx.P[2] ^= tmp3;
+ data.ctx.P[3] ^= tmp4;
+ data.ctx.P[4] ^= tmp1;
+ data.ctx.P[5] ^= tmp2;
+ data.ctx.P[6] ^= tmp3;
+ data.ctx.P[7] ^= tmp4;
+ data.ctx.P[8] ^= tmp1;
+ data.ctx.P[9] ^= tmp2;
+ data.ctx.P[10] ^= tmp3;
+ data.ctx.P[11] ^= tmp4;
+ data.ctx.P[12] ^= tmp1;
+ data.ctx.P[13] ^= tmp2;
+ data.ctx.P[14] ^= tmp3;
+ data.ctx.P[15] ^= tmp4;
+ data.ctx.P[16] ^= tmp1;
+ data.ctx.P[17] ^= tmp2;
+
+ BF_body();
+ } while (--count);
+
+ for (i = 0; i < 6; i += 2) {
+ L = BF_magic_w[i];
+ R = BF_magic_w[i + 1];
+
+ count = 64;
+ do {
+ BF_ENCRYPT;
+ } while (--count);
+
+ data.binary.output[i] = L;
+ data.binary.output[i + 1] = R;
+ }
+
+ memcpy(output, setting, 7 + 22 - 1);
+ output[7 + 22 - 1] = BF_itoa64[(int)
+ BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30];
+
+/* This has to be bug-compatible with the original implementation, so
+ * only encode 23 of the 24 bytes. :-) */
+ BF_swap(data.binary.output, 6);
+ BF_encode(&output[7 + 22], data.binary.output, 23);
+ output[7 + 22 + 31] = '\0';
+
+/* Overwrite the most obvious sensitive data we have on the stack. Note
+ * that this does not guarantee there's no sensitive data left on the
+ * stack and/or in registers; I'm not aware of portable code that does. */
+ clean(&data, sizeof(data));
+
+ return output;
+}
+
+char *_crypt_gensalt_blowfish_rn(unsigned long count,
+ __CONST char *input, int size, char *output, int output_size)
+{
+ if (size < 16 || output_size < 7 + 22 + 1 ||
+ (count && (count < 4 || count > 31))) {
+ if (output_size > 0) output[0] = '\0';
+ __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
+ return NULL;
+ }
+
+ if (!count) count = 5;
+
+ output[0] = '$';
+ output[1] = '2';
+ output[2] = 'a';
+ output[3] = '$';
+ output[4] = '0' + count / 10;
+ output[5] = '0' + count % 10;
+ output[6] = '$';
+
+ BF_encode(&output[7], (BF_word *)input, 16);
+ output[7 + 22] = '\0';
+
+ return output;
+}
diff -Nura php-5.1.6/ext/standard/crypt.c hardening-patch-5.1.6-0.4.15/ext/standard/crypt.c
--- php-5.1.6/ext/standard/crypt.c 2006-01-01 13:50:14.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/standard/crypt.c 2006-09-07 19:41:16.000000000 +0200
@@ -100,6 +100,8 @@
return SUCCESS;
}
+char *_crypt_blowfish_rn(char *key, char *setting, char *output, int size);
+char *_crypt_gensalt_blowfish_rn(unsigned long count, char *input, int size, char *output, int output_size);
static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
@@ -135,7 +137,14 @@
/* The automatic salt generation only covers standard DES and md5-crypt */
if(!*salt) {
-#if PHP_MD5_CRYPT
+#if PHP_BLOWFISH_CRYPT
+ char randat[16];
+ int i;
+
+ for (i=0; i<16; i++) randat[i] = PHP_CRYPT_RAND;
+
+ _crypt_gensalt_blowfish_rn(5, randat, sizeof(randat), salt, sizeof(salt));
+#elif PHP_MD5_CRYPT
strcpy(salt, "$1$");
php_to64(&salt[3], PHP_CRYPT_RAND, 4);
php_to64(&salt[7], PHP_CRYPT_RAND, 4);
@@ -145,8 +154,24 @@
salt[2] = '\0';
#endif
}
-
- RETVAL_STRING(crypt(str, salt), 1);
+
+ if (salt[0] == '$' &&
+ salt[1] == '2' &&
+ salt[2] == 'a' &&
+ salt[3] == '$' &&
+ salt[4] >= '0' && salt[4] <= '3' &&
+ salt[5] >= '0' && salt[5] <= '9' &&
+ salt[6] == '$') {
+
+ char output[PHP_MAX_SALT_LEN+1];
+
+ output[0] = 0;
+ _crypt_blowfish_rn(str, salt, output, sizeof(output));
+ RETVAL_STRING(output, 1);
+
+ } else {
+ RETVAL_STRING(crypt(str, salt), 1);
+ }
}
/* }}} */
#endif
diff -Nura php-5.1.6/ext/standard/dl.c hardening-patch-5.1.6-0.4.15/ext/standard/dl.c
--- php-5.1.6/ext/standard/dl.c 2006-01-01 13:50:14.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/standard/dl.c 2006-09-07 19:41:16.000000000 +0200
@@ -164,8 +164,35 @@
RETURN_FALSE;
}
module_entry = get_module();
+
+ /* check if Hardening-Patch is installed */
+ if (module_entry->zend_api < 1000000000) {
+ php_error_docref(NULL TSRMLS_CC, error_type,
+ "%s: Unable to initialize module\n"
+ "Module compiled without Hardening-Patch, module API=%d, debug=%d, thread-safety=%d\n"
+ "PHP compiled with Hardening-Patch=%d, module API=%d, debug=%d, thread-safety=%d\n"
+ "These options need to match\n",
+ module_entry->name, module_entry->zend_api, module_entry->zend_debug, module_entry->zts,
+ HARDENING_PATCH_ZEND_MODULE_API_NO, ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS);
+ DL_UNLOAD(handle);
+ RETURN_FALSE;
+ }
+
+ /* check if correct Hardening-Patch is installed */
+ if (module_entry->zend_api != HARDENING_PATCH_ZEND_MODULE_API_NO) {
+ php_error_docref(NULL TSRMLS_CC, error_type,
+ "%s: Unable to initialize module\n"
+ "Module compiled with Hardening-Patch=%d, module API=%d, debug=%d, thread-safety=%d\n"
+ "PHP compiled with Hardening-Patch=%d, module API=%d, debug=%d, thread-safety=%d\n"
+ "These options need to match\n",
+ module_entry->name, module_entry->zend_api, module_entry->real_zend_api, module_entry->zend_debug, module_entry->zts,
+ HARDENING_PATCH_ZEND_MODULE_API_NO, ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS);
+ DL_UNLOAD(handle);
+ RETURN_FALSE;
+ }
+
if ((module_entry->zend_debug != ZEND_DEBUG) || (module_entry->zts != USING_ZTS)
- || (module_entry->zend_api != ZEND_MODULE_API_NO)) {
+ || (module_entry->real_zend_api != ZEND_MODULE_API_NO)) {
/* Check for pre-4.1.0 module which has a slightly different module_entry structure :( */
struct pre_4_1_0_module_entry {
char *name;
@@ -199,7 +226,7 @@
zts = ((struct pre_4_1_0_module_entry *)module_entry)->zts;
} else {
name = module_entry->name;
- zend_api = module_entry->zend_api;
+ zend_api = module_entry->real_zend_api;
zend_debug = module_entry->zend_debug;
zts = module_entry->zts;
}
diff -Nura php-5.1.6/ext/standard/file.c hardening-patch-5.1.6-0.4.15/ext/standard/file.c
--- php-5.1.6/ext/standard/file.c 2006-04-06 04:39:55.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/standard/file.c 2006-09-07 19:41:16.000000000 +0200
@@ -2302,7 +2302,7 @@
#if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
/* {{{ proto string realpath(string path)
Return the resolved path */
-PHP_FUNCTION(realpath)
+PHP_FUNCTION(real_path)
{
zval **path;
char resolved_path_buff[MAXPATHLEN];
diff -Nura php-5.1.6/ext/standard/file.h hardening-patch-5.1.6-0.4.15/ext/standard/file.h
--- php-5.1.6/ext/standard/file.h 2006-01-13 05:05:59.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/standard/file.h 2006-09-07 19:41:16.000000000 +0200
@@ -61,7 +61,7 @@
PHP_FUNCTION(fd_set);
PHP_FUNCTION(fd_isset);
#if (!defined(__BEOS__) && HAVE_REALPATH) || defined(ZTS)
-PHP_FUNCTION(realpath);
+PHP_FUNCTION(real_path);
PHP_FUNCTION(fnmatch);
#endif
PHP_NAMED_FUNCTION(php_if_ftruncate);
diff -Nura php-5.1.6/ext/standard/head.c hardening-patch-5.1.6-0.4.15/ext/standard/head.c
--- php-5.1.6/ext/standard/head.c 2006-01-01 13:50:14.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/standard/head.c 2006-09-07 19:41:16.000000000 +0200
@@ -45,7 +45,7 @@
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bl", &ctr.line,
&ctr.line_len, &rep, &ctr.response_code) == FAILURE)
return;
-
+
sapi_header_op(rep ? SAPI_HEADER_REPLACE:SAPI_HEADER_ADD, &ctr TSRMLS_CC);
}
/* }}} */
diff -Nura php-5.1.6/ext/standard/info.c hardening-patch-5.1.6-0.4.15/ext/standard/info.c
--- php-5.1.6/ext/standard/info.c 2006-03-31 13:11:12.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/standard/info.c 2006-09-07 19:41:16.000000000 +0200
@@ -154,7 +154,7 @@
if (Z_TYPE_PP(tmp) == IS_ARRAY) {
if (!sapi_module.phpinfo_as_text) {
PUTS("<pre>");
- zend_print_zval_ex((zend_write_func_t) php_info_write_wrapper, *tmp, 0);
+ zend_print_zval_r_ex((zend_write_func_t) php_info_write_wrapper, *tmp, 0 TSRMLS_CC);
PUTS("</pre>");
} else {
zend_print_zval_r(*tmp, 0 TSRMLS_CC);
@@ -411,7 +411,7 @@
if (flag & PHP_INFO_GENERAL) {
char *zend_version = get_zend_version();
- char temp_api[10];
+ char temp_api[11];
char *logo_guid;
php_uname = php_get_uname('a');
@@ -434,11 +434,22 @@
PUTS("\" alt=\"PHP Logo\" /></a>");
}
+#if HARDENING_PATCH
+ if (!sapi_module.phpinfo_as_text) {
+ php_printf("<h1 class=\"p\">PHP Version %s with <a href=\"http://www.hardened-php.net\">Hardening-Patch</a> %s</h1>\n", PHP_VERSION, HARDENING_PATCH_VERSION);
+ } else {
+ char temp_ver[40];
+
+ snprintf(temp_ver, sizeof(temp_ver), "%s/%s", PHP_VERSION, HARDENING_PATCH_VERSION);
+ php_info_print_table_row(2, "PHP/Hardening-Patch Version", temp_ver);
+ }
+#else
if (!sapi_module.phpinfo_as_text) {
php_printf("<h1 class=\"p\">PHP Version %s</h1>\n", PHP_VERSION);
} else {
php_info_print_table_row(2, "PHP Version", PHP_VERSION);
- }
+ }
+#endif
php_info_print_box_end();
php_info_print_table_start();
php_info_print_table_row(2, "System", php_uname );
diff -Nura php-5.1.6/ext/standard/mail.c hardening-patch-5.1.6-0.4.15/ext/standard/mail.c
--- php-5.1.6/ext/standard/mail.c 2006-01-01 13:50:15.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/standard/mail.c 2006-09-07 19:41:16.000000000 +0200
@@ -78,6 +78,25 @@
}
/* }}} */
+/* {{{ hphp_strcasestr */
+char *hphp_strcasestr(char *haystack, char *needle)
+{
+ unsigned char *t, *h, *n;
+
+ h = (unsigned char *) haystack;
+conts:
+ while (*h) {
+ n = (unsigned char *) needle;
+ for (t=h++; *n && *h; t++, n++) {
+ if (toupper(*t) != toupper(*n)) goto conts;
+ }
+ return ((char*)h-1);
+ }
+
+ return (NULL);
+}
+/* }}} */
+
/* {{{ proto int mail(string to, string subject, string message [, string additional_headers [, string additional_parameters]])
Send an email message */
PHP_FUNCTION(mail)
@@ -104,6 +123,44 @@
return;
}
+ if (HG(hphp_mailprotect) > 0) {
+ if (headers_len > 0 && headers && (strstr(headers,"\n\n") || strstr(headers,"\r\n\r\n")) ) {
+ php_security_log(S_MAIL, "mail() - double newline in headers, possible injection, mail dropped");
+ RETURN_FALSE;
+ }
+
+ /* check for spam attempts with buggy webforms */
+ if (to_len > 0 && to && (strchr(to, '\n') != NULL || strchr(to, '\r') != NULL)) {
+ php_security_log(S_MAIL, "mail() - newline in to header, possible injection, mail dropped");
+ RETURN_FALSE;
+ }
+
+ if (subject_len > 0 && subject && (strchr(subject, '\n') != NULL || strchr(subject, '\r') != NULL)) {
+ php_security_log(S_MAIL, "mail() - newline subject header, possible injection, mail dropped");
+ RETURN_FALSE;
+ }
+
+ if (HG(hphp_mailprotect) > 1) {
+ /* search for to, cc or bcc headers */
+ if (headers_len > 0 && headers != NULL) {
+ if (strncasecmp(headers, "to:", sizeof("to:") - 1) == 0 || hphp_strcasestr(headers, "\nto:")) {
+ php_security_log(S_MAIL, "mail() - To: headers aren't allowed in the headers parameter.");
+ RETURN_FALSE;
+ }
+
+ if (strncasecmp(headers, "cc:", sizeof("cc:") - 1) == 0 || hphp_strcasestr(headers, "\ncc:")) {
+ php_security_log(S_MAIL, "mail() - CC: headers aren't allowed in the headers parameter.");
+ RETURN_FALSE;
+ }
+
+ if (strncasecmp(headers, "bcc:", sizeof("bcc:") - 1) == 0 || hphp_strcasestr(headers, "\nbcc:")) {
+ php_security_log(S_MAIL, "mail() - BCC: headers aren't allowed in the headers parameter.");
+ RETURN_FALSE;
+ }
+ }
+ }
+ }
+
if (to_len > 0) {
to_r = estrndup(to, to_len);
for (; to_len; to_len--) {
diff -Nura php-5.1.6/ext/standard/php_standard.h hardening-patch-5.1.6-0.4.15/ext/standard/php_standard.h
--- php-5.1.6/ext/standard/php_standard.h 2006-01-04 22:31:29.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/standard/php_standard.h 2006-09-07 19:41:16.000000000 +0200
@@ -28,6 +28,7 @@
#include "php_mail.h"
#include "md5.h"
#include "sha1.h"
+#include "sha256.h"
#include "html.h"
#include "exec.h"
#include "file.h"
diff -Nura php-5.1.6/ext/standard/sha256.c hardening-patch-5.1.6-0.4.15/ext/standard/sha256.c
--- php-5.1.6/ext/standard/sha256.c 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/standard/sha256.c 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,388 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Stefan Esser <sesser@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: sha256.c,v 1.9 2004/01/08 08:17:34 andi Exp $ */
+
+#include "php.h"
+
+/* This code is heavily based on the PHP md5/sha1 implementations */
+
+#include "sha256.h"
+
+PHPAPI void make_sha256_digest(char *sha256str, unsigned char *digest)
+{
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ sprintf(sha256str, "%02x", digest[i]);
+ sha256str += 2;
+ }
+
+ *sha256str = '\0';
+}
+
+/* {{{ proto string sha256(string str [, bool raw_output])
+ Calculate the sha256 hash of a string */
+PHP_FUNCTION(sha256)
+{
+ char *arg;
+ int arg_len;
+ zend_bool raw_output = 0;
+ char sha256str[65];
+ PHP_SHA256_CTX context;
+ unsigned char digest[32];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
+ return;
+ }
+
+ sha256str[0] = '\0';
+ PHP_SHA256Init(&context);
+ PHP_SHA256Update(&context, arg, arg_len);
+ PHP_SHA256Final(digest, &context);
+ if (raw_output) {
+ RETURN_STRINGL(digest, 32, 1);
+ } else {
+ make_sha256_digest(sha256str, digest);
+ RETVAL_STRING(sha256str, 1);
+ }
+
+}
+
+/* }}} */
+
+/* {{{ proto string sha256_file(string filename [, bool raw_output])
+ Calculate the sha256 hash of given filename */
+PHP_FUNCTION(sha256_file)
+{
+ char *arg;
+ int arg_len;
+ zend_bool raw_output = 0;
+ char sha256str[65];
+ unsigned char buf[1024];
+ unsigned char digest[32];
+ PHP_SHA256_CTX context;
+ int n;
+ php_stream *stream;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
+ return;
+ }
+
+ stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
+ if (!stream) {
+ RETURN_FALSE;
+ }
+
+ PHP_SHA256Init(&context);
+
+ while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
+ PHP_SHA256Update(&context, buf, n);
+ }
+
+ PHP_SHA256Final(digest, &context);
+
+ php_stream_close(stream);
+
+ if (n<0) {
+ RETURN_FALSE;
+ }
+
+ if (raw_output) {
+ RETURN_STRINGL(digest, 32, 1);
+ } else {
+ make_sha256_digest(sha256str, digest);
+ RETVAL_STRING(sha256str, 1);
+ }
+}
+/* }}} */
+
+
+static void SHA256Transform(php_uint32[8], const unsigned char[64]);
+static void SHA256Encode(unsigned char *, php_uint32 *, unsigned int);
+static void SHA256Decode(php_uint32 *, const unsigned char *, unsigned int);
+
+static unsigned char PADDING[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic SHA256 functions.
+ */
+#define F(x) (ROTATE_RIGHT(x,2) ^ ROTATE_RIGHT(x,13) ^ ROTATE_RIGHT(x,22))
+#define G(x, y, z) (((x) & (y)) | ((z) & ((y) | (x))))
+#define H(x) (ROTATE_RIGHT(x,6) ^ ROTATE_RIGHT(x,11) ^ ROTATE_RIGHT(x,25))
+#define I(x, y, z) (((x) & (y)) | ((~x) & z))
+
+/* ROTATE_RIGHT rotates x right n bits.
+ */
+#define ROTATE_RIGHT(x, n) (((x) >> (n)) | ((x) << (32-(n))))
+
+/* W[i]
+ */
+#define W(i) ( tmp1=ROTATE_RIGHT(x[(i-15)&15],7)^ROTATE_RIGHT(x[(i-15)&15],18)^(x[(i-15)&15] >> 3), \
+ tmp2=ROTATE_RIGHT(x[(i-2)&15],17)^ROTATE_RIGHT(x[(i-2)&15],19)^(x[(i-2)&15] >> 10), \
+ (x[i&15]=x[i&15] + tmp1 + x[(i-7)&15] + tmp2) )
+
+/* ROUND function of sha256
+ */
+
+#define ROUND(a,b,c,d,e,f,g,h,w,k) { \
+ t1 = (h) + H((e)) + I((e), (f), (g)) + (k) + (php_uint32)(w); \
+ (h) = F((a)) + G((a), (b), (c)) + t1; \
+ (d) += t1; \
+ }
+
+
+/* {{{ PHP_SHA256Init
+ * SHA256 initialization. Begins an SHA256 operation, writing a new context.
+ */
+static void PHP_SHA256Init(PHP_SHA256_CTX * context)
+{
+ context->count[0] = context->count[1] = 0;
+ /* Load magic initialization constants.
+ */
+ context->state[0] = 0x6a09e667;
+ context->state[1] = 0xbb67ae85;
+ context->state[2] = 0x3c6ef372;
+ context->state[3] = 0xa54ff53a;
+ context->state[4] = 0x510e527f;
+ context->state[5] = 0x9b05688c;
+ context->state[6] = 0x1f83d9ab;
+ context->state[7] = 0x5be0cd19;
+}
+/* }}} */
+
+/* {{{ PHP_SHA256Update
+ SHA256 block update operation. Continues an SHA256 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+static void PHP_SHA256Update(PHP_SHA256_CTX * context, const unsigned char *input,
+ unsigned int inputLen)
+{
+ unsigned int i, index, partLen;
+
+ /* Compute number of bytes mod 64 */
+ index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((php_uint32) inputLen << 3))
+ < ((php_uint32) inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((php_uint32) inputLen >> 29);
+
+ partLen = 64 - index;
+
+ /* Transform as many times as possible.
+ */
+ if (inputLen >= partLen) {
+ memcpy
+ ((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
+ SHA256Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ SHA256Transform(context->state, &input[i]);
+
+ index = 0;
+ } else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy
+ ((unsigned char*) & context->buffer[index], (unsigned char*) & input[i],
+ inputLen - i);
+}
+/* }}} */
+
+/* {{{ PHP_SHA256Final
+ SHA256 finalization. Ends an SHA256 message-digest operation, writing the
+ the message digest and zeroizing the context.
+ */
+static void PHP_SHA256Final(unsigned char digest[32], PHP_SHA256_CTX * context)
+{
+ unsigned char bits[8];
+ unsigned int index, padLen;
+
+ /* Save number of bits */
+ bits[7] = context->count[0] & 0xFF;
+ bits[6] = (context->count[0] >> 8) & 0xFF;
+ bits[5] = (context->count[0] >> 16) & 0xFF;
+ bits[4] = (context->count[0] >> 24) & 0xFF;
+ bits[3] = context->count[1] & 0xFF;
+ bits[2] = (context->count[1] >> 8) & 0xFF;
+ bits[1] = (context->count[1] >> 16) & 0xFF;
+ bits[0] = (context->count[1] >> 24) & 0xFF;
+
+ /* Pad out to 56 mod 64.
+ */
+ index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ PHP_SHA256Update(context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ PHP_SHA256Update(context, bits, 8);
+
+ /* Store state in digest */
+ SHA256Encode(digest, context->state, 32);
+
+ /* Zeroize sensitive information.
+ */
+ memset((unsigned char*) context, 0, sizeof(*context));
+}
+/* }}} */
+
+/* {{{ SHA256Transform
+ * SHA256 basic transformation. Transforms state based on block.
+ */
+static void SHA256Transform(state, block)
+php_uint32 state[8];
+const unsigned char block[64];
+{
+ php_uint32 a = state[0], b = state[1], c = state[2];
+ php_uint32 d = state[3], e = state[4], f = state[5];
+ php_uint32 g = state[6], h = state[7], x[16], tmp1, tmp2, t1;
+
+ SHA256Decode(x, block, 64);
+
+ ROUND(a, b, c, d, e, f, g, h, x[0], 0x428a2f98)
+ ROUND(h, a, b, c, d, e, f, g, x[1], 0x71374491)
+ ROUND(g, h, a, b, c, d, e, f, x[2], 0xb5c0fbcf)
+ ROUND(f, g, h, a, b, c, d, e, x[3], 0xe9b5dba5)
+ ROUND(e, f, g, h, a, b, c, d, x[4], 0x3956c25b)
+ ROUND(d, e, f, g, h, a, b, c, x[5], 0x59f111f1)
+ ROUND(c, d, e, f, g, h, a, b, x[6], 0x923f82a4)
+ ROUND(b, c, d, e, f, g, h, a, x[7], 0xab1c5ed5)
+ ROUND(a, b, c, d, e, f, g, h, x[8], 0xd807aa98)
+ ROUND(h, a, b, c, d, e, f, g, x[9], 0x12835b01)
+ ROUND(g, h, a, b, c, d, e, f, x[10], 0x243185be)
+ ROUND(f, g, h, a, b, c, d, e, x[11], 0x550c7dc3)
+ ROUND(e, f, g, h, a, b, c, d, x[12], 0x72be5d74)
+ ROUND(d, e, f, g, h, a, b, c, x[13], 0x80deb1fe)
+ ROUND(c, d, e, f, g, h, a, b, x[14], 0x9bdc06a7)
+ ROUND(b, c, d, e, f, g, h, a, x[15], 0xc19bf174)
+ ROUND(a, b, c, d, e, f, g, h, W(16), 0xe49b69c1)
+ ROUND(h, a, b, c, d, e, f, g, W(17), 0xefbe4786)
+ ROUND(g, h, a, b, c, d, e, f, W(18), 0x0fc19dc6)
+ ROUND(f, g, h, a, b, c, d, e, W(19), 0x240ca1cc)
+ ROUND(e, f, g, h, a, b, c, d, W(20), 0x2de92c6f)
+ ROUND(d, e, f, g, h, a, b, c, W(21), 0x4a7484aa)
+ ROUND(c, d, e, f, g, h, a, b, W(22), 0x5cb0a9dc)
+ ROUND(b, c, d, e, f, g, h, a, W(23), 0x76f988da)
+ ROUND(a, b, c, d, e, f, g, h, W(24), 0x983e5152)
+ ROUND(h, a, b, c, d, e, f, g, W(25), 0xa831c66d)
+ ROUND(g, h, a, b, c, d, e, f, W(26), 0xb00327c8)
+ ROUND(f, g, h, a, b, c, d, e, W(27), 0xbf597fc7)
+ ROUND(e, f, g, h, a, b, c, d, W(28), 0xc6e00bf3)
+ ROUND(d, e, f, g, h, a, b, c, W(29), 0xd5a79147)
+ ROUND(c, d, e, f, g, h, a, b, W(30), 0x06ca6351)
+ ROUND(b, c, d, e, f, g, h, a, W(31), 0x14292967)
+ ROUND(a, b, c, d, e, f, g, h, W(32), 0x27b70a85)
+ ROUND(h, a, b, c, d, e, f, g, W(33), 0x2e1b2138)
+ ROUND(g, h, a, b, c, d, e, f, W(34), 0x4d2c6dfc)
+ ROUND(f, g, h, a, b, c, d, e, W(35), 0x53380d13)
+ ROUND(e, f, g, h, a, b, c, d, W(36), 0x650a7354)
+ ROUND(d, e, f, g, h, a, b, c, W(37), 0x766a0abb)
+ ROUND(c, d, e, f, g, h, a, b, W(38), 0x81c2c92e)
+ ROUND(b, c, d, e, f, g, h, a, W(39), 0x92722c85)
+ ROUND(a, b, c, d, e, f, g, h, W(40), 0xa2bfe8a1)
+ ROUND(h, a, b, c, d, e, f, g, W(41), 0xa81a664b)
+ ROUND(g, h, a, b, c, d, e, f, W(42), 0xc24b8b70)
+ ROUND(f, g, h, a, b, c, d, e, W(43), 0xc76c51a3)
+ ROUND(e, f, g, h, a, b, c, d, W(44), 0xd192e819)
+ ROUND(d, e, f, g, h, a, b, c, W(45), 0xd6990624)
+ ROUND(c, d, e, f, g, h, a, b, W(46), 0xf40e3585)
+ ROUND(b, c, d, e, f, g, h, a, W(47), 0x106aa070)
+ ROUND(a, b, c, d, e, f, g, h, W(48), 0x19a4c116)
+ ROUND(h, a, b, c, d, e, f, g, W(49), 0x1e376c08)
+ ROUND(g, h, a, b, c, d, e, f, W(50), 0x2748774c)
+ ROUND(f, g, h, a, b, c, d, e, W(51), 0x34b0bcb5)
+ ROUND(e, f, g, h, a, b, c, d, W(52), 0x391c0cb3)
+ ROUND(d, e, f, g, h, a, b, c, W(53), 0x4ed8aa4a)
+ ROUND(c, d, e, f, g, h, a, b, W(54), 0x5b9cca4f)
+ ROUND(b, c, d, e, f, g, h, a, W(55), 0x682e6ff3)
+ ROUND(a, b, c, d, e, f, g, h, W(56), 0x748f82ee)
+ ROUND(h, a, b, c, d, e, f, g, W(57), 0x78a5636f)
+ ROUND(g, h, a, b, c, d, e, f, W(58), 0x84c87814)
+ ROUND(f, g, h, a, b, c, d, e, W(59), 0x8cc70208)
+ ROUND(e, f, g, h, a, b, c, d, W(60), 0x90befffa)
+ ROUND(d, e, f, g, h, a, b, c, W(61), 0xa4506ceb)
+ ROUND(c, d, e, f, g, h, a, b, W(62), 0xbef9a3f7)
+ ROUND(b, c, d, e, f, g, h, a, W(63), 0xc67178f2)
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ state[5] += f;
+ state[6] += g;
+ state[7] += h;
+
+ /* Zeroize sensitive information. */
+ memset((unsigned char*) x, 0, sizeof(x));
+}
+/* }}} */
+
+/* {{{ SHA256Encode
+ Encodes input (php_uint32) into output (unsigned char). Assumes len is
+ a multiple of 4.
+ */
+static void SHA256Encode(output, input, len)
+unsigned char *output;
+php_uint32 *input;
+unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char) ((input[i] >> 24) & 0xff);
+ output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff);
+ output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff);
+ output[j + 3] = (unsigned char) (input[i] & 0xff);
+ }
+}
+/* }}} */
+
+/* {{{ SHA256Decode
+ Decodes input (unsigned char) into output (php_uint32). Assumes len is
+ a multiple of 4.
+ */
+static void SHA256Decode(output, input, len)
+php_uint32 *output;
+const unsigned char *input;
+unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((php_uint32) input[j + 3]) | (((php_uint32) input[j + 2]) << 8) |
+ (((php_uint32) input[j + 1]) << 16) | (((php_uint32) input[j]) << 24);
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff -Nura php-5.1.6/ext/standard/sha256.h hardening-patch-5.1.6-0.4.15/ext/standard/sha256.h
--- php-5.1.6/ext/standard/sha256.h 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/standard/sha256.h 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,40 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2004 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Stefan Esser <sesser@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: sha256.h,v 1.4 2004/01/08 17:32:52 sniper Exp $ */
+
+#ifndef SHA256_H
+#define SHA256_H
+
+#include "ext/standard/basic_functions.h"
+
+/* SHA1 context. */
+typedef struct {
+ php_uint32 state[8]; /* state (ABCD) */
+ php_uint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} PHP_SHA256_CTX;
+
+static void PHP_SHA256Init(PHP_SHA256_CTX *);
+static void PHP_SHA256Update(PHP_SHA256_CTX *, const unsigned char *, unsigned int);
+static void PHP_SHA256Final(unsigned char[32], PHP_SHA256_CTX *);
+
+PHP_FUNCTION(sha256);
+PHP_FUNCTION(sha256_file);
+
+#endif
diff -Nura php-5.1.6/ext/standard/syslog.c hardening-patch-5.1.6-0.4.15/ext/standard/syslog.c
--- php-5.1.6/ext/standard/syslog.c 2006-03-21 01:59:08.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/standard/syslog.c 2006-09-07 19:41:16.000000000 +0200
@@ -42,6 +42,7 @@
*/
PHP_MINIT_FUNCTION(syslog)
{
+#if !HARDENING_PATCH
/* error levels */
REGISTER_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
REGISTER_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
@@ -97,6 +98,7 @@
/* AIX doesn't have LOG_PERROR */
REGISTER_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
#endif
+#endif
BG(syslog_device)=NULL;
return SUCCESS;
diff -Nura php-5.1.6/ext/varfilter/config.m4 hardening-patch-5.1.6-0.4.15/ext/varfilter/config.m4
--- php-5.1.6/ext/varfilter/config.m4 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/varfilter/config.m4 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,11 @@
+dnl
+dnl $Id: config.m4,v 1.1 2004/11/14 13:27:16 ionic Exp $
+dnl
+
+PHP_ARG_ENABLE(varfilter, whether to enable Hardening-Patch's variable filter,
+[ --disable-varfilter Disable Hardening-Patch's variable filter], yes)
+
+if test "$PHP_VARFILTER" != "no"; then
+ AC_DEFINE(HAVE_VARFILTER, 1, [ ])
+ PHP_NEW_EXTENSION(varfilter, varfilter.c, $ext_shared)
+fi
diff -Nura php-5.1.6/ext/varfilter/CREDITS hardening-patch-5.1.6-0.4.15/ext/varfilter/CREDITS
--- php-5.1.6/ext/varfilter/CREDITS 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/varfilter/CREDITS 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,2 @@
+varfilter
+Stefan Esser
\ Kein Zeilenumbruch am Dateiende.
diff -Nura php-5.1.6/ext/varfilter/php_varfilter.h hardening-patch-5.1.6-0.4.15/ext/varfilter/php_varfilter.h
--- php-5.1.6/ext/varfilter/php_varfilter.h 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/varfilter/php_varfilter.h 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,144 @@
+/*
+ +----------------------------------------------------------------------+
+ | Hardened-PHP Project's varfilter extension |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2004-2005 Stefan Esser |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Stefan Esser <sesser@hardened-php.net> |
+ +----------------------------------------------------------------------+
+
+ $Id: php_varfilter.h,v 1.1 2004/11/14 13:27:16 ionic Exp $
+*/
+
+#ifndef PHP_VARFILTER_H
+#define PHP_VARFILTER_H
+
+extern zend_module_entry varfilter_module_entry;
+#define phpext_varfilter_ptr &varfilter_module_entry
+
+#ifdef PHP_WIN32
+#define PHP_VARFILTER_API __declspec(dllexport)
+#else
+#define PHP_VARFILTER_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+#include "SAPI.h"
+
+#include "php_variables.h"
+
+#ifdef ZEND_ENGINE_2
+#define HASH_HTTP_GET_VARS 0x2095733f
+#define HASH_HTTP_POST_VARS 0xbfee1265
+#define HASH_HTTP_COOKIE_VARS 0xaaca9d99
+#define HASH_HTTP_ENV_VARS 0x1fe186a8
+#define HASH_HTTP_SERVER_VARS 0xc987afd6
+#define HASH_HTTP_SESSION_VARS 0x7aba0d43
+#define HASH_HTTP_POST_FILES 0x98eb1ddc
+#define HASH_HTTP_RAW_POST_DATA 0xdd633fec
+#else
+#define HASH_HTTP_GET_VARS 0x8d8645bd
+#define HASH_HTTP_POST_VARS 0x7c699bf3
+#define HASH_HTTP_COOKIE_VARS 0x93ad0d6f
+#define HASH_HTTP_ENV_VARS 0x84da3016
+#define HASH_HTTP_SERVER_VARS 0x6dbf964e
+#define HASH_HTTP_SESSION_VARS 0x322906f5
+#define HASH_HTTP_POST_FILES 0xe4e4ce70
+#define HASH_HTTP_RAW_POST_DATA 0xe6137a0e
+#endif
+
+PHP_MINIT_FUNCTION(varfilter);
+PHP_MSHUTDOWN_FUNCTION(varfilter);
+PHP_RINIT_FUNCTION(varfilter);
+PHP_RSHUTDOWN_FUNCTION(varfilter);
+PHP_MINFO_FUNCTION(varfilter);
+
+
+ZEND_BEGIN_MODULE_GLOBALS(varfilter)
+/* request variables */
+ long max_request_variables;
+ long cur_request_variables;
+ long max_varname_length;
+ long max_totalname_length;
+ long max_value_length;
+ long max_array_depth;
+ long max_array_index_length;
+ zend_bool disallow_nul;
+/* cookie variables */
+ long max_cookie_vars;
+ long cur_cookie_vars;
+ long max_cookie_name_length;
+ long max_cookie_totalname_length;
+ long max_cookie_value_length;
+ long max_cookie_array_depth;
+ long max_cookie_array_index_length;
+ zend_bool disallow_cookie_nul;
+/* get variables */
+ long max_get_vars;
+ long cur_get_vars;
+ long max_get_name_length;
+ long max_get_totalname_length;
+ long max_get_value_length;
+ long max_get_array_depth;
+ long max_get_array_index_length;
+ zend_bool disallow_get_nul;
+/* post variables */
+ long max_post_vars;
+ long cur_post_vars;
+ long max_post_name_length;
+ long max_post_totalname_length;
+ long max_post_value_length;
+ long max_post_array_depth;
+ long max_post_array_index_length;
+ zend_bool disallow_post_nul;
+/* fileupload */
+ long max_uploads;
+ long cur_uploads;
+ zend_bool disallow_elf_files;
+ char *verification_script;
+
+ zend_bool no_more_variables;
+ zend_bool no_more_get_variables;
+ zend_bool no_more_post_variables;
+ zend_bool no_more_cookie_variables;
+ zend_bool no_more_uploads;
+
+ZEND_END_MODULE_GLOBALS(varfilter)
+
+
+#ifdef ZTS
+#define VARFILTER_G(v) TSRMG(varfilter_globals_id, zend_varfilter_globals *, v)
+#else
+#define VARFILTER_G(v) (varfilter_globals.v)
+#endif
+
+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter);
+SAPI_UPLOAD_VARNAME_FILTER_FUNC(varfilter_upload_varname_filter);
+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter);
+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter);
+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter);
+SAPI_TREAT_DATA_FUNC(varfilter_treat_data);
+
+
+
+#endif /* PHP_VARFILTER_H */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff -Nura php-5.1.6/ext/varfilter/varfilter.c hardening-patch-5.1.6-0.4.15/ext/varfilter/varfilter.c
--- php-5.1.6/ext/varfilter/varfilter.c 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/ext/varfilter/varfilter.c 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,915 @@
+/*
+ +----------------------------------------------------------------------+
+ | Hardened-PHP Project's varfilter extension |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2004-2005 Stefan Esser |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Stefan Esser <sesser@hardened-php.net> |
+ +----------------------------------------------------------------------+
+
+ $Id: varfilter.c,v 1.1 2004/11/14 13:27:16 ionic Exp $
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "php_varfilter.h"
+#include "hardening_patch.h"
+
+ZEND_DECLARE_MODULE_GLOBALS(varfilter)
+
+/* True global resources - no need for thread safety here */
+static int le_varfilter;
+
+static void (*orig_register_server_variables)(zval *track_vars_array TSRMLS_DC) = NULL;
+static int (*orig_header_handler)(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) = NULL;
+static zend_bool hooked = 0;
+
+/* {{{ varfilter_module_entry
+ */
+zend_module_entry varfilter_module_entry = {
+#if ZEND_MODULE_API_NO >= 20010901
+ STANDARD_MODULE_HEADER,
+#endif
+ "varfilter",
+ NULL,
+ PHP_MINIT(varfilter),
+ PHP_MSHUTDOWN(varfilter),
+ PHP_RINIT(varfilter), /* Replace with NULL if there's nothing to do at request start */
+ PHP_RSHUTDOWN(varfilter), /* Replace with NULL if there's nothing to do at request end */
+ PHP_MINFO(varfilter),
+#if ZEND_MODULE_API_NO >= 20010901
+ "0.4.15", /* Replace with version number for your extension */
+#endif
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+#ifdef COMPILE_DL_VARFILTER
+ZEND_GET_MODULE(varfilter)
+#endif
+
+/* {{{ PHP_INI
+ */
+PHP_INI_BEGIN()
+ /* for backward compatibility */
+ STD_PHP_INI_ENTRY("varfilter.max_request_variables", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("varfilter.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("varfilter.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("varfilter.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("varfilter.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("varfilter.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
+
+ STD_PHP_INI_ENTRY("hphp.request.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_request_variables, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.request.max_varname_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_varname_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.request.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_value_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.request.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_array_depth, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.request.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_totalname_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.request.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_array_index_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.request.disallow_nul", "1", PHP_INI_PERDIR, OnUpdateBool, disallow_nul, zend_varfilter_globals, varfilter_globals)
+
+ STD_PHP_INI_ENTRY("hphp.cookie.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_vars, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.cookie.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_name_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.cookie.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_cookie_totalname_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.cookie.max_value_length", "10000", PHP_INI_PERDIR, OnUpdateLong, max_cookie_value_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_depth, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.cookie.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_cookie_array_index_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.cookie.disallow_nul", "1", PHP_INI_PERDIR, OnUpdateBool, disallow_cookie_nul, zend_varfilter_globals, varfilter_globals)
+
+ STD_PHP_INI_ENTRY("hphp.get.max_vars", "100", PHP_INI_PERDIR, OnUpdateLong, max_get_vars, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.get.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_name_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.get.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_get_totalname_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.get.max_value_length", "512", PHP_INI_PERDIR, OnUpdateLong, max_get_value_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.get.max_array_depth", "50", PHP_INI_PERDIR, OnUpdateLong, max_get_array_depth, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.get.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_get_array_index_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.get.disallow_nul", "1", PHP_INI_PERDIR, OnUpdateBool, disallow_get_nul, zend_varfilter_globals, varfilter_globals)
+
+ STD_PHP_INI_ENTRY("hphp.post.max_vars", "200", PHP_INI_PERDIR, OnUpdateLong, max_post_vars, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.post.max_name_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_name_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.post.max_totalname_length", "256", PHP_INI_PERDIR, OnUpdateLong, max_post_totalname_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.post.max_value_length", "65000", PHP_INI_PERDIR, OnUpdateLong, max_post_value_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.post.max_array_depth", "100", PHP_INI_PERDIR, OnUpdateLong, max_post_array_depth, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.post.max_array_index_length", "64", PHP_INI_PERDIR, OnUpdateLong, max_post_array_index_length, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.post.disallow_nul", "1", PHP_INI_PERDIR, OnUpdateBool, disallow_post_nul, zend_varfilter_globals, varfilter_globals)
+
+ STD_PHP_INI_ENTRY("hphp.upload.max_uploads", "25", PHP_INI_PERDIR, OnUpdateLong, max_uploads, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.upload.disallow_elf_files", "1", PHP_INI_SYSTEM, OnUpdateBool, disallow_elf_files, zend_varfilter_globals, varfilter_globals)
+ STD_PHP_INI_ENTRY("hphp.upload.verification_script", NULL, PHP_INI_SYSTEM, OnUpdateString, verification_script, zend_varfilter_globals, varfilter_globals)
+
+
+PHP_INI_END()
+/* }}} */
+
+/* {{{ php_varfilter_init_globals
+ */
+static void php_varfilter_init_globals(zend_varfilter_globals *varfilter_globals)
+{
+ varfilter_globals->max_request_variables = 200;
+ varfilter_globals->max_varname_length = 64;
+ varfilter_globals->max_value_length = 10000;
+ varfilter_globals->max_array_depth = 100;
+ varfilter_globals->max_totalname_length = 256;
+ varfilter_globals->max_array_index_length = 64;
+ varfilter_globals->disallow_nul = 1;
+
+ varfilter_globals->max_cookie_vars = 100;
+ varfilter_globals->max_cookie_name_length = 64;
+ varfilter_globals->max_cookie_totalname_length = 256;
+ varfilter_globals->max_cookie_value_length = 10000;
+ varfilter_globals->max_cookie_array_depth = 100;
+ varfilter_globals->max_cookie_array_index_length = 64;
+ varfilter_globals->disallow_cookie_nul = 1;
+
+ varfilter_globals->max_get_vars = 100;
+ varfilter_globals->max_get_name_length = 64;
+ varfilter_globals->max_get_totalname_length = 256;
+ varfilter_globals->max_get_value_length = 512;
+ varfilter_globals->max_get_array_depth = 50;
+ varfilter_globals->max_get_array_index_length = 64;
+ varfilter_globals->disallow_get_nul = 1;
+
+ varfilter_globals->max_post_vars = 200;
+ varfilter_globals->max_post_name_length = 64;
+ varfilter_globals->max_post_totalname_length = 256;
+ varfilter_globals->max_post_value_length = 65000;
+ varfilter_globals->max_post_array_depth = 100;
+ varfilter_globals->max_post_array_index_length = 64;
+ varfilter_globals->disallow_post_nul = 1;
+
+ varfilter_globals->max_uploads = 25;
+ varfilter_globals->disallow_elf_files = 1;
+ varfilter_globals->verification_script = NULL;
+
+ varfilter_globals->no_more_variables = 0;
+ varfilter_globals->no_more_get_variables = 0;
+ varfilter_globals->no_more_post_variables = 0;
+ varfilter_globals->no_more_cookie_variables = 0;
+ varfilter_globals->no_more_uploads = 0;
+
+ varfilter_globals->cur_request_variables = 0;
+ varfilter_globals->cur_get_vars = 0;
+ varfilter_globals->cur_post_vars = 0;
+ varfilter_globals->cur_cookie_vars = 0;
+
+ varfilter_globals->cur_uploads = 0;
+
+}
+/* }}} */
+
+
+void varfilter_register_server_variables(zval *track_vars_array TSRMLS_DC)
+{
+ HashTable *svars;
+ int retval, failure=0;
+
+ orig_register_server_variables(track_vars_array TSRMLS_CC);
+
+ svars = Z_ARRVAL_P(track_vars_array);
+
+ retval = zend_hash_del_key_or_index(svars, "HTTP_GET_VARS", sizeof("HTTP_GET_VARS"), HASH_HTTP_GET_VARS, HASH_DEL_INDEX);
+ if (retval == SUCCESS) failure = 1;
+ retval = zend_hash_del_key_or_index(svars, "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"), HASH_HTTP_POST_VARS, HASH_DEL_INDEX);
+ if (retval == SUCCESS) failure = 1;
+ retval = zend_hash_del_key_or_index(svars, "HTTP_COOKIE_VARS", sizeof("HTTP_COOKIE_VARS"), HASH_HTTP_COOKIE_VARS, HASH_DEL_INDEX);
+ if (retval == SUCCESS) failure = 1;
+ retval = zend_hash_del_key_or_index(svars, "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS"), HASH_HTTP_ENV_VARS, HASH_DEL_INDEX);
+ if (retval == SUCCESS) failure = 1;
+ retval = zend_hash_del_key_or_index(svars, "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"), HASH_HTTP_SERVER_VARS, HASH_DEL_INDEX);
+ if (retval == SUCCESS) failure = 1;
+ retval = zend_hash_del_key_or_index(svars, "HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"), HASH_HTTP_SESSION_VARS, HASH_DEL_INDEX);
+ if (retval == SUCCESS) failure = 1;
+ retval = zend_hash_del_key_or_index(svars, "HTTP_POST_FILES", sizeof("HTTP_POST_FILES"), HASH_HTTP_POST_FILES, HASH_DEL_INDEX);
+ if (retval == SUCCESS) failure = 1;
+ retval = zend_hash_del_key_or_index(svars, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"), HASH_HTTP_RAW_POST_DATA, HASH_DEL_INDEX);
+ if (retval == SUCCESS) failure = 1;
+
+ if (failure) {
+ php_security_log(S_VARS, "Attacker tried to overwrite a superglobal through a HTTP header");
+ }
+}
+
+int varfilter_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC)
+{
+ int retval = SAPI_HEADER_ADD, i;
+ char *tmp;
+
+ if (!HG(hphp_multiheader) && sapi_header && sapi_header->header) {
+
+ tmp = sapi_header->header;
+ for (i=0; i<sapi_header->header_len; i++, tmp++) {
+ if (tmp[0] == 0) {
+ char *fname = get_active_function_name(TSRMLS_C);
+
+ if (!fname) {
+ fname = "unknown";
+ }
+
+ php_security_log(S_MISC, "%s() - wanted to send a HTTP header with an ASCII NUL in it", fname);
+ sapi_header->header_len = i;
+ } else if (tmp[0] == '\n' && (i == sapi_header->header_len-1 || (tmp[1] != ' ' && tmp[1] != '\t'))) {
+ char *fname = get_active_function_name(TSRMLS_C);
+
+ if (!fname) {
+ fname = "unknown";
+ }
+
+ php_security_log(S_MISC, "%s() - wanted to send multiple HTTP headers at once", fname);
+ sapi_header->header_len = i;
+ tmp[0] = 0;
+ }
+ }
+ }
+
+ if (orig_header_handler) {
+ retval = orig_header_handler(sapi_header, sapi_headers TSRMLS_CC);
+ }
+
+ return retval;
+}
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(varfilter)
+{
+ ZEND_INIT_MODULE_GLOBALS(varfilter, php_varfilter_init_globals, NULL);
+ REGISTER_INI_ENTRIES();
+
+ if (!hooked) {
+ void *temp;
+ hooked = 1;
+
+ temp = (void *)sapi_module.register_server_variables;
+ if (temp != varfilter_register_server_variables) {
+ orig_register_server_variables = temp;
+ }
+ temp = (void *)sapi_module.header_handler;
+ if (temp != varfilter_header_handler) {
+ orig_header_handler = temp;
+ }
+ }
+
+ sapi_register_input_filter(varfilter_input_filter);
+ sapi_register_upload_varname_filter(varfilter_upload_varname_filter);
+ sapi_register_pre_upload_filter(varfilter_pre_upload_filter);
+ sapi_register_upload_content_filter(varfilter_upload_content_filter);
+ sapi_register_post_upload_filter(varfilter_post_upload_filter);
+
+ sapi_module.header_handler = varfilter_header_handler;
+ sapi_module.register_server_variables = varfilter_register_server_variables;
+
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(varfilter)
+{
+ UNREGISTER_INI_ENTRIES();
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* Remove if there's nothing to do at request start */
+/* {{{ PHP_RINIT_FUNCTION
+ */
+PHP_RINIT_FUNCTION(varfilter)
+{
+ VARFILTER_G(cur_request_variables) = 0;
+ VARFILTER_G(cur_get_vars) = 0;
+ VARFILTER_G(cur_post_vars) = 0;
+ VARFILTER_G(cur_cookie_vars) = 0;
+
+ VARFILTER_G(cur_uploads) = 0;
+
+ VARFILTER_G(no_more_variables) = 0;
+ VARFILTER_G(no_more_get_variables) = 0;
+ VARFILTER_G(no_more_post_variables) = 0;
+ VARFILTER_G(no_more_cookie_variables) = 0;
+ VARFILTER_G(no_more_uploads) = 0;
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* Remove if there's nothing to do at request end */
+/* {{{ PHP_RSHUTDOWN_FUNCTION
+ */
+PHP_RSHUTDOWN_FUNCTION(varfilter)
+{
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(varfilter)
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "Hardening-Patch's variable filter support", "enabled");
+ php_info_print_table_end();
+
+ DISPLAY_INI_ENTRIES();
+}
+/* }}} */
+
+/* {{{ normalize_varname
+ */
+static void normalize_varname(char *varname)
+{
+ char *s=varname, *index=NULL, *indexend=NULL, *p;
+
+ /* overjump leading space */
+ while (*s == ' ') {
+ s++;
+ }
+
+ /* and remove it */
+ if (s != varname) {
+ memmove(varname, s, strlen(s)+1);
+ }
+
+ for (p=varname; *p && *p != '['; p++) {
+ switch(*p) {
+ case ' ':
+ case '.':
+ *p='_';
+ break;
+ }
+ }
+
+ /* find index */
+ index = strchr(varname, '[');
+ if (index) {
+ index++;
+ s=index;
+ } else {
+ return;
+ }
+
+ /* done? */
+ while (index) {
+
+ while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') {
+ index++;
+ }
+ indexend = strchr(index, ']');
+ indexend = indexend ? indexend + 1 : index + strlen(index);
+
+ if (s != index) {
+ memmove(s, index, strlen(index)+1);
+ s += indexend-index;
+ } else {
+ s = indexend;
+ }
+
+ if (*s == '[') {
+ s++;
+ index = s;
+ } else {
+ index = NULL;
+ }
+ }
+ *s++='\0';
+}
+/* }}} */
+
+/* {{{ SAPI_UPLOAD_VARNAME_FILTER_FUNC
+ */
+SAPI_UPLOAD_VARNAME_FILTER_FUNC(varfilter_upload_varname_filter)
+{
+ char *index, *prev_index = NULL, *var;
+ unsigned int var_len, total_len, depth = 0;
+
+ var = estrdup(varname);
+
+ /* Normalize the variable name */
+ normalize_varname(var);
+
+ /* Find length of variable name */
+ index = strchr(var, '[');
+ total_len = strlen(var);
+ var_len = index ? index-var : total_len;
+
+ /* Drop this variable if it exceeds the varname/total length limit */
+ if (VARFILTER_G(max_varname_length) && VARFILTER_G(max_varname_length) < var_len) {
+ php_security_log(S_FILES, "configured request variable name length limit exceeded - dropped %s", var);
+ goto return_failure;
+ }
+ if (VARFILTER_G(max_totalname_length) && VARFILTER_G(max_totalname_length) < total_len) {
+ php_security_log(S_FILES, "configured request variable total name length limit exceeded - dropped %s", var);
+ goto return_failure;
+ }
+ if (VARFILTER_G(max_post_name_length) && VARFILTER_G(max_post_name_length) < var_len) {
+ php_security_log(S_FILES, "configured POST variable name length limit exceeded - dropped %s", var);
+
+ goto return_failure;
+ }
+ if (VARFILTER_G(max_post_totalname_length) && VARFILTER_G(max_post_totalname_length) < var_len) {
+ php_security_log(S_FILES, "configured POST variable total name length limit exceeded - dropped %s", var);
+ goto return_failure;
+ }
+
+ /* Find out array depth */
+ while (index) {
+ unsigned int index_length;
+
+ depth++;
+ index = strchr(index+1, '[');
+
+ if (prev_index) {
+ index_length = index ? index - 1 - prev_index - 1: strlen(prev_index);
+
+ if (VARFILTER_G(max_array_index_length) && VARFILTER_G(max_array_index_length) < index_length) {
+ php_security_log(S_FILES, "configured request variable array index length limit exceeded - dropped %s", var);
+ goto return_failure;
+ }
+ if (VARFILTER_G(max_post_array_index_length) && VARFILTER_G(max_post_array_index_length) < index_length) {
+ php_security_log(S_FILES, "configured POST variable array index length limit exceeded - dropped %s", var);
+ goto return_failure;
+ }
+ prev_index = index;
+ }
+
+ }
+
+ /* Drop this variable if it exceeds the array depth limit */
+ if (VARFILTER_G(max_array_depth) && VARFILTER_G(max_array_depth) < depth) {
+ php_security_log(S_FILES, "configured request variable array depth limit exceeded - dropped %s", var);
+ goto return_failure;
+ }
+ if (VARFILTER_G(max_post_array_depth) && VARFILTER_G(max_post_array_depth) < depth) {
+ php_security_log(S_FILES, "configured POST variable array depth limit exceeded - dropped %s", var);
+ goto return_failure;
+ }
+
+
+ /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
+ /* This is to protect several silly scripts that do globalizing themself */
+
+ switch (var_len) {
+ case 18:
+ if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname2;
+ break;
+ case 17:
+ if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname2;
+ break;
+ case 16:
+ if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname2;
+ if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname2;
+ break;
+ case 15:
+ if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname2;
+ break;
+ case 14:
+ if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname2;
+ break;
+ case 13:
+ if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname2;
+ if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname2;
+ break;
+ case 8:
+ if (memcmp(var, "_SESSION", 8)==0) goto protected_varname2;
+ if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname2;
+ break;
+ case 7:
+ if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname2;
+ if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname2;
+ if (memcmp(var, "_SERVER", 7)==0) goto protected_varname2;
+ break;
+ case 6:
+ if (memcmp(var, "_FILES", 6)==0) goto protected_varname2;
+ break;
+ case 5:
+ if (memcmp(var, "_POST", 5)==0) goto protected_varname2;
+ break;
+ case 4:
+ if (memcmp(var, "_ENV", 4)==0) goto protected_varname2;
+ if (memcmp(var, "_GET", 4)==0) goto protected_varname2;
+ break;
+ }
+
+ efree(var);
+ return SUCCESS;
+protected_varname2:
+ php_security_log(S_FILES, "tried to register forbidden variable '%s' through FILE variables", var);
+return_failure:
+ efree(var);
+ return FAILURE;
+}
+/* }}} */
+
+/* {{{ SAPI_PRE_UPLOAD_FILTER_FUNC
+ */
+SAPI_PRE_UPLOAD_FILTER_FUNC(varfilter_pre_upload_filter)
+{
+ /* Drop if no more variables flag is set */
+ if (VARFILTER_G(no_more_uploads)) {
+ return FAILURE;
+ }
+ /* Drop this fileupload if the limit is reached */
+ if (VARFILTER_G(max_uploads) && VARFILTER_G(max_uploads) <= VARFILTER_G(cur_uploads)) {
+ php_security_log(S_FILES, "configured fileupload limit exceeded - file dropped");
+ VARFILTER_G(no_more_uploads) = 1;
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ SAPI_UPLOAD_CONTENT_FILTER_FUNC
+ */
+SAPI_UPLOAD_CONTENT_FILTER_FUNC(varfilter_upload_content_filter)
+{
+
+ if (VARFILTER_G(disallow_elf_files)) {
+
+ if (offset == 0 && buffer_len > 10) {
+
+ if (buffer[0] == 0x7F && buffer[1] == 'E' && buffer[2] == 'L' && buffer[3] == 'F') {
+ php_security_log(S_FILES, "uploaded file is an ELF executable - file dropped");
+ return FAILURE;
+ }
+ }
+
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ SAPI_POST_UPLOAD_FILTER_FUNC
+ */
+SAPI_POST_UPLOAD_FILTER_FUNC(varfilter_post_upload_filter)
+{
+ int retval = SUCCESS;
+
+ if (VARFILTER_G(verification_script)) {
+ char cmd[8192];
+ FILE *in;
+ int first=1;
+
+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s", VARFILTER_G(verification_script), tmpfilename);
+
+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
+ php_security_log(S_FILES, "unable to execute fileupload verification script %s - file dropped", VARFILTER_G(verification_script));
+ return FAILURE;
+ }
+
+ retval = FAILURE;
+
+ /* read and forget the result */
+ while (1) {
+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
+ if (readbytes<=0) {
+ break;
+ }
+ if (first) {
+ retval = atoi(cmd) == 1 ? SUCCESS : FAILURE;
+ first = 0;
+ }
+ }
+ pclose(in);
+ }
+
+ if (retval != SUCCESS) {
+ php_security_log(S_FILES, "fileupload verification script disallows file - file dropped");
+ return FAILURE;
+ }
+
+ VARFILTER_G(cur_uploads)++;
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ SAPI_INPUT_FILTER_FUNC
+ */
+SAPI_INPUT_FILTER_FUNC(varfilter_input_filter)
+{
+ char *index, *prev_index = NULL;
+ unsigned int var_len, total_len, depth = 0;
+
+ /* Drop this variable if the limit was reached */
+ switch (arg) {
+ case PARSE_GET:
+ if (VARFILTER_G(no_more_get_variables)) {
+ return 0;
+ }
+ break;
+ case PARSE_POST:
+ if (VARFILTER_G(no_more_post_variables)) {
+ return 0;
+ }
+ break;
+ case PARSE_COOKIE:
+ if (VARFILTER_G(no_more_cookie_variables)) {
+ return 0;
+ }
+ break;
+ default: /* we do not want to protect parse_str() and friends */
+ if (new_val_len) {
+ *new_val_len = val_len;
+ }
+ return 1;
+ }
+ if (VARFILTER_G(no_more_variables)) {
+ return 0;
+ }
+
+ /* Drop this variable if the limit is now reached */
+ if (VARFILTER_G(max_request_variables) && VARFILTER_G(max_request_variables) <= VARFILTER_G(cur_request_variables)) {
+ php_security_log(S_VARS, "configured request variable limit exceeded - dropped %s", var);
+ VARFILTER_G(no_more_variables) = 1;
+ return 0;
+ }
+ switch (arg) {
+ case PARSE_GET:
+ if (VARFILTER_G(max_get_vars) && VARFILTER_G(max_get_vars) <= VARFILTER_G(cur_get_vars)) {
+ php_security_log(S_VARS, "configured GET variable limit exceeded - dropped %s", var);
+ VARFILTER_G(no_more_get_variables) = 1;
+ return 0;
+ }
+ break;
+ case PARSE_COOKIE:
+ if (VARFILTER_G(max_cookie_vars) && VARFILTER_G(max_cookie_vars) <= VARFILTER_G(cur_cookie_vars)) {
+ php_security_log(S_VARS, "configured COOKIE variable limit exceeded - dropped %s", var);
+ VARFILTER_G(no_more_cookie_variables) = 1;
+ return 0;
+ }
+ break;
+ case PARSE_POST:
+ if (VARFILTER_G(max_post_vars) && VARFILTER_G(max_post_vars) <= VARFILTER_G(cur_post_vars)) {
+ php_security_log(S_VARS, "configured POST variable limit exceeded - dropped %s", var);
+ VARFILTER_G(no_more_post_variables) = 1;
+ return 0;
+ }
+ break;
+ }
+
+
+ /* Drop this variable if it exceeds the value length limit */
+ if (VARFILTER_G(max_value_length) && VARFILTER_G(max_value_length) < val_len) {
+ php_security_log(S_VARS, "configured request variable value length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ switch (arg) {
+ case PARSE_GET:
+ if (VARFILTER_G(max_get_value_length) && VARFILTER_G(max_get_value_length) < val_len) {
+ php_security_log(S_VARS, "configured GET variable value length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ break;
+ case PARSE_COOKIE:
+ if (VARFILTER_G(max_cookie_value_length) && VARFILTER_G(max_cookie_value_length) < val_len) {
+ php_security_log(S_VARS, "configured COOKIE variable value length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ break;
+ case PARSE_POST:
+ if (VARFILTER_G(max_post_value_length) && VARFILTER_G(max_post_value_length) < val_len) {
+ php_security_log(S_VARS, "configured POST variable value length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ break;
+ }
+
+ /* Normalize the variable name */
+ normalize_varname(var);
+
+ /* Find length of variable name */
+ index = strchr(var, '[');
+ total_len = strlen(var);
+ var_len = index ? index-var : total_len;
+
+ /* Drop this variable if it exceeds the varname/total length limit */
+ if (VARFILTER_G(max_varname_length) && VARFILTER_G(max_varname_length) < var_len) {
+ php_security_log(S_VARS, "configured request variable name length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ if (VARFILTER_G(max_totalname_length) && VARFILTER_G(max_totalname_length) < total_len) {
+ php_security_log(S_VARS, "configured request variable total name length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ switch (arg) {
+ case PARSE_GET:
+ if (VARFILTER_G(max_get_name_length) && VARFILTER_G(max_get_name_length) < var_len) {
+ php_security_log(S_VARS, "configured GET variable name length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ if (VARFILTER_G(max_get_totalname_length) && VARFILTER_G(max_get_totalname_length) < var_len) {
+ php_security_log(S_VARS, "configured GET variable total name length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ break;
+ case PARSE_COOKIE:
+ if (VARFILTER_G(max_cookie_name_length) && VARFILTER_G(max_cookie_name_length) < var_len) {
+ php_security_log(S_VARS, "configured COOKIE variable name length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ if (VARFILTER_G(max_cookie_totalname_length) && VARFILTER_G(max_cookie_totalname_length) < var_len) {
+ php_security_log(S_VARS, "configured COOKIE variable total name length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ break;
+ case PARSE_POST:
+ if (VARFILTER_G(max_post_name_length) && VARFILTER_G(max_post_name_length) < var_len) {
+ php_security_log(S_VARS, "configured POST variable name length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ if (VARFILTER_G(max_post_totalname_length) && VARFILTER_G(max_post_totalname_length) < var_len) {
+ php_security_log(S_VARS, "configured POST variable total name length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ break;
+ }
+
+ /* Find out array depth */
+ while (index) {
+ unsigned int index_length;
+
+ depth++;
+ index = strchr(index+1, '[');
+
+ if (prev_index) {
+ index_length = index ? index - 1 - prev_index - 1: strlen(prev_index);
+
+ if (VARFILTER_G(max_array_index_length) && VARFILTER_G(max_array_index_length) < index_length) {
+ php_security_log(S_VARS, "configured request variable array index length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ switch (arg) {
+ case PARSE_GET:
+ if (VARFILTER_G(max_get_array_index_length) && VARFILTER_G(max_get_array_index_length) < index_length) {
+ php_security_log(S_VARS, "configured GET variable array index length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ break;
+ case PARSE_COOKIE:
+ if (VARFILTER_G(max_cookie_array_index_length) && VARFILTER_G(max_cookie_array_index_length) < index_length) {
+ php_security_log(S_VARS, "configured COOKIE variable array index length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ break;
+ case PARSE_POST:
+ if (VARFILTER_G(max_post_array_index_length) && VARFILTER_G(max_post_array_index_length) < index_length) {
+ php_security_log(S_VARS, "configured POST variable array index length limit exceeded - dropped %s", var);
+ return 0;
+ }
+ break;
+ }
+ prev_index = index;
+ }
+
+ }
+
+ /* Drop this variable if it exceeds the array depth limit */
+ if (VARFILTER_G(max_array_depth) && VARFILTER_G(max_array_depth) < depth) {
+ php_security_log(S_VARS, "configured request variable array depth limit exceeded - dropped %s", var);
+ return 0;
+ }
+ switch (arg) {
+ case PARSE_GET:
+ if (VARFILTER_G(max_get_array_depth) && VARFILTER_G(max_get_array_depth) < depth) {
+ php_security_log(S_VARS, "configured GET variable array depth limit exceeded - dropped %s", var);
+ return 0;
+ }
+ break;
+ case PARSE_COOKIE:
+ if (VARFILTER_G(max_cookie_array_depth) && VARFILTER_G(max_cookie_array_depth) < depth) {
+ php_security_log(S_VARS, "configured COOKIE variable array depth limit exceeded - dropped %s", var);
+ return 0;
+ }
+ break;
+ case PARSE_POST:
+ if (VARFILTER_G(max_post_array_depth) && VARFILTER_G(max_post_array_depth) < depth) {
+ php_security_log(S_VARS, "configured POST variable array depth limit exceeded - dropped %s", var);
+ return 0;
+ }
+ break;
+ }
+
+ /* Check if variable value is truncated by a \0 */
+
+ if (val && *val && val_len != strlen(*val)) {
+
+ if (VARFILTER_G(disallow_nul)) {
+ php_security_log(S_VARS, "ASCII-NUL chars not allowed within request variables - dropped %s", var);
+ return 0;
+ }
+ switch (arg) {
+ case PARSE_GET:
+ if (VARFILTER_G(disallow_get_nul)) {
+ php_security_log(S_VARS, "ASCII-NUL chars not allowed within GET variables - dropped %s", var);
+ return 0;
+ }
+ break;
+ case PARSE_COOKIE:
+ if (VARFILTER_G(disallow_cookie_nul)) {
+ php_security_log(S_VARS, "ASCII-NUL chars not allowed within COOKIE variables - dropped %s", var);
+ return 0;
+ }
+ break;
+ case PARSE_POST:
+ if (VARFILTER_G(disallow_post_nul)) {
+ php_security_log(S_VARS, "ASCII-NUL chars not allowed within POST variables - dropped %s", var);
+ return 0;
+ }
+ break;
+ }
+ }
+
+ /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
+ /* This is to protect several silly scripts that do globalizing themself */
+
+ switch (var_len) {
+ case 18:
+ if (memcmp(var, "HTTP_RAW_POST_DATA", 18)==0) goto protected_varname;
+ break;
+ case 17:
+ if (memcmp(var, "HTTP_SESSION_VARS", 17)==0) goto protected_varname;
+ break;
+ case 16:
+ if (memcmp(var, "HTTP_SERVER_VARS", 16)==0) goto protected_varname;
+ if (memcmp(var, "HTTP_COOKIE_VARS", 16)==0) goto protected_varname;
+ break;
+ case 15:
+ if (memcmp(var, "HTTP_POST_FILES", 15)==0) goto protected_varname;
+ break;
+ case 14:
+ if (memcmp(var, "HTTP_POST_VARS", 14)==0) goto protected_varname;
+ break;
+ case 13:
+ if (memcmp(var, "HTTP_GET_VARS", 13)==0) goto protected_varname;
+ if (memcmp(var, "HTTP_ENV_VARS", 13)==0) goto protected_varname;
+ break;
+ case 8:
+ if (memcmp(var, "_SESSION", 8)==0) goto protected_varname;
+ if (memcmp(var, "_REQUEST", 8)==0) goto protected_varname;
+ break;
+ case 7:
+ if (memcmp(var, "GLOBALS", 7)==0) goto protected_varname;
+ if (memcmp(var, "_COOKIE", 7)==0) goto protected_varname;
+ if (memcmp(var, "_SERVER", 7)==0) goto protected_varname;
+ break;
+ case 6:
+ if (memcmp(var, "_FILES", 6)==0) goto protected_varname;
+ break;
+ case 5:
+ if (memcmp(var, "_POST", 5)==0) goto protected_varname;
+ break;
+ case 4:
+ if (memcmp(var, "_ENV", 4)==0) goto protected_varname;
+ if (memcmp(var, "_GET", 4)==0) goto protected_varname;
+ break;
+ }
+
+ /* Okay let PHP register this variable */
+ VARFILTER_G(cur_request_variables)++;
+ switch (arg) {
+ case PARSE_GET:
+ VARFILTER_G(cur_get_vars)++;
+ break;
+ case PARSE_COOKIE:
+ VARFILTER_G(cur_cookie_vars)++;
+ break;
+ case PARSE_POST:
+ VARFILTER_G(cur_post_vars)++;
+ break;
+ }
+
+ if (new_val_len) {
+ *new_val_len = val_len;
+ }
+
+ return 1;
+protected_varname:
+ php_security_log(S_VARS, "tried to register forbidden variable '%s' through %s variables", var, arg == PARSE_GET ? "GET" : arg == PARSE_POST ? "POST" : "COOKIE");
+ return 0;
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
+
+
diff -Nura php-5.1.6/ext/wddx/wddx.c hardening-patch-5.1.6-0.4.15/ext/wddx/wddx.c
--- php-5.1.6/ext/wddx/wddx.c 2006-05-25 12:01:30.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/ext/wddx/wddx.c 2006-09-07 19:41:16.000000000 +0200
@@ -399,9 +399,9 @@
break;
default:
- if (iscntrl((int)*(unsigned char *)p)) {
+ if (iscntrl((int)*(unsigned char *)p)||(int)*(unsigned char *)p >= 127) {
FLUSH_BUF();
- sprintf(control_buf, WDDX_CHAR, *p);
+ sprintf(control_buf, WDDX_CHAR, (int)*(unsigned char *)p);
php_wddx_add_chunk(packet, control_buf);
} else
buf[l++] = *p;
diff -Nura php-5.1.6/main/fopen_wrappers.c hardening-patch-5.1.6-0.4.15/main/fopen_wrappers.c
--- php-5.1.6/main/fopen_wrappers.c 2006-03-17 11:42:31.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/main/fopen_wrappers.c 2006-09-07 19:41:16.000000000 +0200
@@ -104,7 +104,10 @@
}
/* Resolve the real path into resolved_name */
- if ((expand_filepath(path, resolved_name TSRMLS_CC) != NULL) && (expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) != NULL)) {
+ if (expand_filepath(path, resolved_name TSRMLS_CC) == NULL) {
+ return -2;
+ }
+ if (expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) != NULL) {
/* Handler for basedirs that end with a / */
resolved_basedir_len = strlen(resolved_basedir);
if (basedir[strlen(basedir) - 1] == PHP_DIR_SEPARATOR) {
@@ -114,14 +117,20 @@
}
}
+ resolved_name_len = strlen(resolved_name);
if (path[strlen(path)-1] == PHP_DIR_SEPARATOR) {
- resolved_name_len = strlen(resolved_name);
if (resolved_name[resolved_name_len - 1] != PHP_DIR_SEPARATOR) {
resolved_name[resolved_name_len] = PHP_DIR_SEPARATOR;
resolved_name[++resolved_name_len] = '\0';
}
}
+ if (resolved_name_len == resolved_basedir_len - 1) {
+ if (resolved_basedir[resolved_basedir_len - 1] == PHP_DIR_SEPARATOR) {
+ resolved_basedir_len--;
+ }
+ }
+
/* Check the path */
#if defined(PHP_WIN32) || defined(NETWARE)
if (strncasecmp(resolved_basedir, resolved_name, resolved_basedir_len) == 0) {
@@ -135,7 +144,7 @@
}
} else {
/* Unable to resolve the real path, return -1 */
- return -1;
+ return -3;
}
}
/* }}} */
@@ -154,22 +163,44 @@
char *pathbuf;
char *ptr;
char *end;
+ char path_copy[MAXPATHLEN];
+ int path_len;
+
+ /* Special case path ends with a trailing slash */
+ path_len = strlen(path);
+ if (path_len >= MAXPATHLEN) {
+ errno = EPERM; /* we deny permission to open it */
+ return -1;
+ }
+ if (path_len > 0 && path[path_len-1] == PHP_DIR_SEPARATOR) {
+ memcpy(path_copy, path, path_len+1);
+ while (path_len > 0 && path_copy[path_len-1] == PHP_DIR_SEPARATOR) path_len--;
+ path_copy[path_len] = '\0';
+ path = (const char *)&path_copy;
+ }
pathbuf = estrdup(PG(open_basedir));
ptr = pathbuf;
while (ptr && *ptr) {
+ int res;
end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
if (end != NULL) {
*end = '\0';
end++;
}
- if (php_check_specific_open_basedir(ptr, path TSRMLS_CC) == 0) {
+ res = php_check_specific_open_basedir(ptr, path TSRMLS_CC);
+ if (res == 0) {
efree(pathbuf);
return 0;
}
+ if (res == -2) {
+ efree(pathbuf);
+ errno = EPERM;
+ return -1;
+ }
ptr = end;
}
diff -Nura php-5.1.6/main/hardened_globals.h hardening-patch-5.1.6-0.4.15/main/hardened_globals.h
--- php-5.1.6/main/hardened_globals.h 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/main/hardened_globals.h 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,64 @@
+/*
+ +----------------------------------------------------------------------+
+ | Hardening-Patch for PHP |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2004-2005 Stefan Esser |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Stefan Esser <sesser@hardened-php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef HARDENED_GLOBALS_H
+#define HARDENED_GLOBALS_H
+
+typedef struct _hardened_globals hardened_globals_struct;
+
+#ifdef ZTS
+# define HG(v) TSRMG(hardened_globals_id, hardened_globals_struct *, v)
+extern int hardened_globals_id;
+#else
+# define HG(v) (hardened_globals.v)
+extern struct _hardened_globals hardened_globals;
+#endif
+
+
+struct _hardened_globals {
+#if HARDENING_PATCH_MM_PROTECT
+ unsigned int canary_1;
+ unsigned int canary_2;
+#endif
+#if HARDENING_PATCH_LL_PROTECT
+ unsigned int canary_3;
+ unsigned int canary_4;
+ unsigned int ll_canary_inited;
+#endif
+ zend_bool hphp_sql_bailout_on_error;
+ zend_bool hphp_multiheader;
+ unsigned long hphp_mailprotect;
+ long hard_memory_limit;
+ HashTable *eval_whitelist;
+ HashTable *eval_blacklist;
+ HashTable *func_whitelist;
+ HashTable *func_blacklist;
+ HashTable *include_whitelist;
+ HashTable *include_blacklist;
+ unsigned int dummy;
+};
+
+
+#endif /* HARDENED_GLOBALS_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff -Nura php-5.1.6/main/hardening_patch.c hardening-patch-5.1.6-0.4.15/main/hardening_patch.c
--- php-5.1.6/main/hardening_patch.c 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/main/hardening_patch.c 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,430 @@
+/*
+ +----------------------------------------------------------------------+
+ | Hardening Patch for PHP |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2004-2005 Stefan Esser |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Stefan Esser <sesser@hardened-php.net> |
+ +----------------------------------------------------------------------+
+ */
+/* $Id: hardening_patch.c,v 1.2 2004/11/21 09:38:52 ionic Exp $ */
+
+#include "php.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "SAPI.h"
+#include "php_globals.h"
+
+#if HARDENING_PATCH
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
+#undef AF_UNIX
+#endif
+
+#if defined(AF_UNIX)
+#include <sys/un.h>
+#endif
+
+#define SYSLOG_PATH "/dev/log"
+
+#include "snprintf.h"
+
+#include "hardening_patch.h"
+
+#ifdef ZTS
+#include "hardened_globals.h"
+int hardened_globals_id;
+#else
+struct _hardened_globals hardened_globals;
+#endif
+
+static void hardened_globals_ctor(hardened_globals_struct *hardened_globals TSRMLS_DC)
+{
+ memset(hardened_globals, 0, sizeof(*hardened_globals));
+}
+
+
+PHPAPI void hardened_startup()
+{
+#ifdef ZTS
+ ts_allocate_id(&hardened_globals_id, sizeof(hardened_globals_struct), (ts_allocate_ctor) hardened_globals_ctor, NULL);
+#else
+ hardened_globals_ctor(&hardened_globals TSRMLS_CC);
+#endif
+}
+
+PHPAPI void hardened_clear_mm_canaries(TSRMLS_D)
+{
+ HG(canary_1) = php_canary();
+ HG(canary_2) = php_canary();
+}
+
+char *loglevel2string(int loglevel)
+{
+ switch (loglevel) {
+ case S_FILES:
+ return "FILES";
+ case S_INCLUDE:
+ return "INCLUDE";
+ case S_MEMORY:
+ return "MEMORY";
+ case S_MISC:
+ return "MISC";
+ case S_SQL:
+ return "SQL";
+ case S_EXECUTOR:
+ return "EXECUTOR";
+ case S_VARS:
+ return "VARS";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+PHPAPI void php_security_log(int loglevel, char *fmt, ...)
+{
+#if defined(AF_UNIX)
+ int s, r, i=0;
+ struct sockaddr_un saun;
+ char buf[4096+64];
+ char error[4096+100];
+ char *ip_address;
+ char *fname;
+ int lineno;
+ va_list ap;
+ TSRMLS_FETCH();
+
+ if (EG(hphp_log_use_x_forwarded_for)) {
+ ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC);
+ if (ip_address == NULL) {
+ ip_address = "X-FORWARDED-FOR not set";
+ }
+ } else {
+ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC);
+ if (ip_address == NULL) {
+ ip_address = "REMOTE_ADDR not set";
+ }
+ }
+
+
+ va_start(ap, fmt);
+ ap_php_vsnprintf(error, sizeof(error), fmt, ap);
+ va_end(ap);
+ while (error[i]) {
+ if (error[i] < 32) error[i] = '.';
+ i++;
+ }
+
+ if (zend_is_executing(TSRMLS_C)) {
+ lineno = zend_get_executed_lineno(TSRMLS_C);
+ fname = zend_get_executed_filename(TSRMLS_C);
+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s', line %u)", error, ip_address, fname, lineno);
+ } else {
+ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC);
+ if (fname==NULL) {
+ fname = "unknown";
+ }
+ ap_php_snprintf(buf, sizeof(buf), "ALERT - %s (attacker '%s', file '%s')", error, ip_address, fname);
+ }
+
+ /* Syslog-Logging disabled? */
+ if ((EG(hphp_log_syslog) & loglevel)==0) {
+ goto log_sapi;
+ }
+
+ ap_php_snprintf(error, sizeof(error), "<%u>hphp[%u]: %s\n", EG(hphp_log_syslog_facility)|EG(hphp_log_syslog_priority),getpid(),buf);
+
+ s = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (s == -1) {
+ goto log_sapi;
+ }
+
+ memset(&saun, 0, sizeof(saun));
+ saun.sun_family = AF_UNIX;
+ strcpy(saun.sun_path, SYSLOG_PATH);
+ /*saun.sun_len = sizeof(saun);*/
+
+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
+ if (r) {
+ close(s);
+ s = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (s == -1) {
+ goto log_sapi;
+ }
+
+ memset(&saun, 0, sizeof(saun));
+ saun.sun_family = AF_UNIX;
+ strcpy(saun.sun_path, SYSLOG_PATH);
+ /*saun.sun_len = sizeof(saun);*/
+
+ r = connect(s, (struct sockaddr *)&saun, sizeof(saun));
+ if (r) {
+ close(s);
+ goto log_sapi;
+ }
+ }
+ send(s, error, strlen(error), 0);
+
+ close(s);
+
+log_sapi:
+ /* SAPI Logging activated? */
+ if ((EG(hphp_log_sapi) & loglevel)!=0) {
+ sapi_module.log_message(buf);
+ }
+
+log_script:
+ /* script logging activaed? */
+ if (((EG(hphp_log_script) & loglevel)!=0) && EG(hphp_log_scriptname)!=NULL) {
+ char cmd[8192], *cmdpos, *bufpos;
+ FILE *in;
+ int space;
+
+ ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", EG(hphp_log_scriptname), loglevel2string(loglevel));
+ space = sizeof(cmd) - strlen(cmd);
+ cmdpos = cmd + strlen(cmd);
+ bufpos = buf;
+ if (space <= 1) return;
+ while (space > 2 && *bufpos) {
+ if (*bufpos == '\'') {
+ if (space<=5) break;
+ *cmdpos++ = '\'';
+ *cmdpos++ = '\\';
+ *cmdpos++ = '\'';
+ *cmdpos++ = '\'';
+ bufpos++;
+ space-=4;
+ } else {
+ *cmdpos++ = *bufpos++;
+ space--;
+ }
+ }
+ *cmdpos++ = '\'';
+ *cmdpos = 0;
+
+ if ((in=VCWD_POPEN(cmd, "r"))==NULL) {
+ php_security_log(S_INTERNAL, "Unable to execute logging shell script: %s", EG(hphp_log_scriptname));
+ return;
+ }
+ /* read and forget the result */
+ while (1) {
+ int readbytes = fread(cmd, 1, sizeof(cmd), in);
+ if (readbytes<=0) {
+ break;
+ }
+ }
+ pclose(in);
+ }
+
+#endif
+}
+#endif
+
+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
+
+/* will be replaced later with more compatible method */
+PHPAPI unsigned int php_canary()
+{
+ time_t t;
+ unsigned int canary;
+ int fd;
+
+ fd = open("/dev/urandom", 0);
+ if (fd != -1) {
+ int r = read(fd, &canary, sizeof(canary));
+ close(fd);
+ if (r == sizeof(canary)) {
+ return (canary);
+ }
+ }
+ /* not good but we never want to do this */
+ time(&t);
+ canary = *(unsigned int *)&t + getpid() << 16;
+ return (canary);
+}
+#endif
+
+#if HARDENING_PATCH_INC_PROTECT
+
+PHPAPI int php_is_valid_include(zval *z)
+{
+ char *filename;
+ int len, i;
+ TSRMLS_FETCH();
+
+ /* must be of type string */
+ if (z->type != IS_STRING || z->value.str.val == NULL) {
+ return (0);
+ }
+
+ /* short cut */
+ filename = z->value.str.val;
+ len = z->value.str.len;
+
+ /* 1. must be shorter than MAXPATHLEN */
+ if (len > MAXPATHLEN) {
+ char *fname = estrndup(filename, len);
+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
+ php_security_log(S_INCLUDE, "Include filename ('%s') longer than MAXPATHLEN chars", fname);
+ efree(fname);
+ return (0);
+ }
+
+ /* 2. must not be cutted */
+ if (len != strlen(filename)) {
+ char *fname = estrndup(filename, len);
+ for (i=0; fname[i]; i++) if (fname[i] < 32) fname[i]='.';
+ php_security_log(S_INCLUDE, "Include filename truncated by a \\0 after '%s'", fname);
+ efree(fname);
+ return (0);
+ }
+
+ /* 3. when it is an URL first check black/whitelist if both are empty disallow all URLs */
+ if (strstr(filename, "://")) {
+ char *fname = estrndup(filename, len);
+ for (i=0; i < len; i++) if (fname[i] < 32) fname[i]='.';
+
+ /* no black or whitelist then disallow all */
+ if (HG(include_whitelist)==NULL && HG(include_blacklist)==NULL) {
+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL", fname);
+ efree(fname);
+ return (0);
+ }
+
+ /* whitelist is stronger than blacklist */
+ if (HG(include_whitelist)) {
+ char *s, *t, *h, *index;
+ uint indexlen;
+ ulong numindex;
+
+ s = filename;
+
+ do {
+ zend_bool isOk = 0;
+ int tlen;
+
+ t = h = strstr(s, "://");
+ if (h == NULL) break;
+
+
+ while (t > s && (isalnum(t[-1]) || t[-1]=='_')) {
+ t--;
+ }
+
+ tlen = strlen(t);
+
+ zend_hash_internal_pointer_reset(HG(include_whitelist));
+ do {
+ int r = zend_hash_get_current_key_ex(HG(include_whitelist), &index, &indexlen, &numindex, 0, NULL);
+
+ if (r==HASH_KEY_NON_EXISTANT) {
+ break;
+ }
+ if (r==HASH_KEY_IS_STRING) {
+ if (h-t <= indexlen-1 && tlen>=indexlen-1) {
+ if (strncmp(t, index, indexlen-1)==0) {
+ isOk = 1;
+ break;
+ }
+ }
+ }
+
+ zend_hash_move_forward(HG(include_whitelist));
+ } while (1);
+
+ /* not found in whitelist */
+ if (!isOk) {
+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL that is not allowed in whitelist", fname);
+ efree(fname);
+ return 0;
+ }
+
+ s = h + 3;
+ } while (1);
+ } else {
+ /* okay then handle the blacklist */
+ char *s, *t, *h, *index;
+ uint indexlen;
+ ulong numindex;
+
+ s = filename;
+
+ do {
+ int tlen;
+
+ t = h = strstr(s, "://");
+ if (h == NULL) break;
+
+
+ while (t > s && (isalnum(t[-1]) || t[-1]=='_')) {
+ t--;
+ }
+
+ tlen = strlen(t);
+
+ zend_hash_internal_pointer_reset(HG(include_blacklist));
+ do {
+ int r = zend_hash_get_current_key_ex(HG(include_blacklist), &index, &indexlen, &numindex, 0, NULL);
+
+ if (r==HASH_KEY_NON_EXISTANT) {
+ break;
+ }
+ if (r==HASH_KEY_IS_STRING) {
+ if (h-t <= indexlen-1 && tlen>=indexlen-1) {
+ if (strncmp(t, index, indexlen-1)==0) {
+ php_security_log(S_INCLUDE, "Include filename ('%s') is an URL that is forbidden by the blacklist", fname);
+ efree(fname);
+ return 0;
+ }
+ }
+ }
+
+ zend_hash_move_forward(HG(include_blacklist));
+ } while (1);
+
+ s = h + 3;
+ } while (1);
+ }
+
+ efree(fname);
+ }
+
+ /* 4. must not be an uploaded file */
+ if (SG(rfc1867_uploaded_files)) {
+ if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, len+1)) {
+ php_security_log(S_INCLUDE, "Include filename is an uploaded file");
+ return (0);
+ }
+ }
+
+ /* passed all tests */
+ return (1);
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff -Nura php-5.1.6/main/hardening_patch.h hardening-patch-5.1.6-0.4.15/main/hardening_patch.h
--- php-5.1.6/main/hardening_patch.h 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/main/hardening_patch.h 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,46 @@
+/*
+ +----------------------------------------------------------------------+
+ | Hardening Patch for PHP |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2004-2005 Stefan Esser |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Stefan Esser <sesser@hardened-php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef HARDENING_PATCH_H
+#define HARDENING_PATCH_H
+
+#include "zend.h"
+
+#if HARDENING_PATCH
+PHPAPI void php_security_log(int loglevel, char *fmt, ...);
+PHPAPI void hardened_startup();
+#define HARDENING_PATCH_VERSION "0.4.15"
+
+#endif
+
+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
+PHPAPI unsigned int php_canary();
+#endif
+
+#if HARDENING_PATCH_INC_PROTECT
+PHPAPI int php_is_valid_include(zval *z);
+#endif
+
+#endif /* HARDENING_PATCH_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff -Nura php-5.1.6/main/hardening_patch.m4 hardening-patch-5.1.6-0.4.15/main/hardening_patch.m4
--- php-5.1.6/main/hardening_patch.m4 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/main/hardening_patch.m4 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,95 @@
+dnl
+dnl $Id: hardening_patch.m4,v 1.1 2004/11/14 13:24:24 ionic Exp $
+dnl
+dnl This file contains Hardening Patch for PHP specific autoconf functions.
+dnl
+
+AC_ARG_ENABLE(hardening-patch-mm-protect,
+[ --disable-hardening-patch-mm-protect Disable the Memory Manager protection.],[
+ DO_HARDENING_PATCH_MM_PROTECT=$enableval
+],[
+ DO_HARDENING_PATCH_MM_PROTECT=yes
+])
+
+AC_ARG_ENABLE(hardening-patch-ll-protect,
+[ --disable-hardening-patch-ll-protect Disable the Linked List protection.],[
+ DO_HARDENING_PATCH_LL_PROTECT=$enableval
+],[
+ DO_HARDENING_PATCH_LL_PROTECT=yes
+])
+
+AC_ARG_ENABLE(hardening-patch-inc-protect,
+[ --disable-hardening-patch-inc-protect Disable include/require protection.],[
+ DO_HARDENING_PATCH_INC_PROTECT=$enableval
+],[
+ DO_HARDENING_PATCH_INC_PROTECT=yes
+])
+
+AC_ARG_ENABLE(hardening-patch-fmt-protect,
+[ --disable-hardening-patch-fmt-protect Disable format string protection.],[
+ DO_HARDENING_PATCH_FMT_PROTECT=$enableval
+],[
+ DO_HARDENING_PATCH_FMT_PROTECT=yes
+])
+
+AC_ARG_ENABLE(hardening-patch-hash-protect,
+[ --disable-hardening-patch-hash-protect Disable HashTable destructor protection.],[
+ DO_HARDENING_PATCH_HASH_PROTECT=$enableval
+],[
+ DO_HARDENING_PATCH_HASH_PROTECT=yes
+])
+
+AC_MSG_CHECKING(whether to protect the Zend Memory Manager)
+AC_MSG_RESULT($DO_HARDENING_PATCH_MM_PROTECT)
+
+AC_MSG_CHECKING(whether to protect the Zend Linked Lists)
+AC_MSG_RESULT($DO_HARDENING_PATCH_LL_PROTECT)
+
+AC_MSG_CHECKING(whether to protect include/require statements)
+AC_MSG_RESULT($DO_HARDENING_PATCH_INC_PROTECT)
+
+AC_MSG_CHECKING(whether to protect PHP Format String functions)
+AC_MSG_RESULT($DO_HARDENING_PATCH_FMT_PROTECT)
+
+AC_MSG_CHECKING(whether to protect the destructor of Zend HashTables)
+AC_MSG_RESULT($DO_HARDENING_PATCH_HASH_PROTECT)
+
+
+AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
+
+
+if test "$DO_HARDENING_PATCH_MM_PROTECT" = "yes"; then
+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 1, [Memory Manager Protection])
+else
+ AC_DEFINE(HARDENING_PATCH_MM_PROTECT, 0, [Memory Manager Protection])
+fi
+
+if test "$DO_HARDENING_PATCH_LL_PROTECT" = "yes"; then
+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 1, [Linked List Protection])
+else
+ AC_DEFINE(HARDENING_PATCH_LL_PROTECT, 0, [Linked List Protection])
+fi
+
+if test "$DO_HARDENING_PATCH_INC_PROTECT" = "yes"; then
+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 1, [Include/Require Protection])
+else
+ AC_DEFINE(HARDENING_PATCH_INC_PROTECT, 0, [Include/Require Protection])
+fi
+
+if test "$DO_HARDENING_PATCH_FMT_PROTECT" = "yes"; then
+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 1, [Fmt String Protection])
+else
+ AC_DEFINE(HARDENING_PATCH_FMT_PROTECT, 0, [Fmt String Protection])
+fi
+
+if test "$DO_HARDENING_PATCH_HASH_PROTECT" = "yes"; then
+dnl AC_DEFINE(HARDENING_PATCH, 1, [Hardening Patch])
+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 1, [HashTable DTOR Protection])
+else
+ AC_DEFINE(HARDENING_PATCH_HASH_PROTECT, 0, [HashTable DTOR Protection])
+fi
+
diff -Nura php-5.1.6/main/main.c hardening-patch-5.1.6-0.4.15/main/main.c
--- php-5.1.6/main/main.c 2006-08-10 23:49:56.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/main/main.c 2006-09-07 19:41:16.000000000 +0200
@@ -85,6 +85,10 @@
#include "SAPI.h"
#include "rfc1867.h"
+#if HARDENING_PATCH
+#include "hardened_globals.h"
+#endif
+
/* }}} */
#ifndef ZTS
@@ -109,17 +113,39 @@
*/
static PHP_INI_MH(OnChangeMemoryLimit)
{
+#if HARDENING_PATCH
+ long hard_memory_limit = 1<<30;
+
+ if (stage == ZEND_INI_STAGE_RUNTIME) {
+ if (HG(hard_memory_limit) == 0) {
+ HG(hard_memory_limit) = PG(memory_limit);
+ }
+ hard_memory_limit = HG(hard_memory_limit);
+ } else {
+ HG(hard_memory_limit) = 0;
+ }
+#endif
if (new_value) {
PG(memory_limit) = zend_atoi(new_value, new_value_length);
+#if HARDENING_PATCH
+ if (PG(memory_limit) > hard_memory_limit) {
+ PG(memory_limit) = hard_memory_limit;
+ php_security_log(S_MISC, "script tried to increase memory_limit above allowed value");
+ return FAILURE;
+ }
+#endif
} else {
+#if HARDENING_PATCH
+ PG(memory_limit) = hard_memory_limit;
+#else
PG(memory_limit) = 1<<30; /* effectively, no limit */
+#endif
}
return zend_set_memory_limit(PG(memory_limit));
}
/* }}} */
#endif
-
/* {{{ php_disable_functions
*/
static void php_disable_functions(TSRMLS_D)
@@ -1100,6 +1126,13 @@
sapi_add_header(SAPI_PHP_VERSION_HEADER, sizeof(SAPI_PHP_VERSION_HEADER)-1, 1);
}
+ /* Disable realpath cache if safe_mode or open_basedir are set */
+ if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
+ CWDG(realpath_cache_disable) = 1;
+ } else {
+ CWDG(realpath_cache_disable) = 0;
+ }
+
if (PG(output_handler) && PG(output_handler)[0]) {
php_start_ob_buffer_named(PG(output_handler), 0, 1 TSRMLS_CC);
} else if (PG(output_buffering)) {
@@ -1227,6 +1260,9 @@
zend_try {
shutdown_memory_manager(CG(unclean_shutdown), 0 TSRMLS_CC);
+#if HARDENING_PATCH
+ hardened_clear_mm_canaries(TSRMLS_C);
+#endif
} zend_end_try();
zend_try {
@@ -1398,6 +1434,10 @@
tsrm_ls = ts_resource(0);
#endif
+#if HARDENING_PATCH
+ hardened_startup();
+#endif
+
module_shutdown = 0;
module_startup = 1;
sapi_initialize_empty_request(TSRMLS_C);
@@ -1411,6 +1451,12 @@
php_output_startup();
+#if HARDENING_PATCH_INC_PROTECT
+ zuf.is_valid_include = php_is_valid_include;
+#endif
+#if HARDENING_PATCH
+ zuf.security_log_function = php_security_log;
+#endif
zuf.error_function = php_error_cb;
zuf.printf_function = php_printf;
zuf.write_function = php_body_write_wrapper;
@@ -1481,7 +1527,9 @@
/* Disable realpath cache if safe_mode or open_basedir are set */
if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
- CWDG(realpath_cache_size_limit) = 0;
+ CWDG(realpath_cache_disable) = 1;
+ } else {
+ CWDG(realpath_cache_disable) = 0;
}
/* initialize stream wrappers registry
@@ -1522,6 +1570,10 @@
REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_PATH", PHP_CONFIG_FILE_PATH, strlen(PHP_CONFIG_FILE_PATH), CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS);
+#if HARDENING_PATCH
+ REGISTER_MAIN_LONG_CONSTANT("HARDENING_PATCH", 1, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_STRINGL_CONSTANT("HARDENING_PATCH_VERSION", HARDENING_PATCH_VERSION, sizeof(HARDENING_PATCH_VERSION)-1, CONST_PERSISTENT | CONST_CS);
+#endif
REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS);
diff -Nura php-5.1.6/main/php_config.h.in hardening-patch-5.1.6-0.4.15/main/php_config.h.in
--- php-5.1.6/main/php_config.h.in 2006-08-23 14:55:05.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/main/php_config.h.in 2006-09-07 19:41:16.000000000 +0200
@@ -788,6 +788,39 @@
/* Enabling BIND8 compatibility for Panther */
#undef BIND_8_COMPAT
+/* Hardening-Patch for PHP */
+#undef HARDENING_PATCH
+
+/* Memory Manager Protection */
+#undef HARDENING_PATCH_MM_PROTECT
+
+/* Memory Manager Protection */
+#undef HARDENING_PATCH_MM_PROTECT
+
+/* Linked List Protection */
+#undef HARDENING_PATCH_LL_PROTECT
+
+/* Linked List Protection */
+#undef HARDENING_PATCH_LL_PROTECT
+
+/* Include/Require Protection */
+#undef HARDENING_PATCH_INC_PROTECT
+
+/* Include/Require Protection */
+#undef HARDENING_PATCH_INC_PROTECT
+
+/* Fmt String Protection */
+#undef HARDENING_PATCH_FMT_PROTECT
+
+/* Fmt String Protection */
+#undef HARDENING_PATCH_FMT_PROTECT
+
+/* HashTable DTOR Protection */
+#undef HARDENING_PATCH_HASH_PROTECT
+
+/* HashTable DTOR Protection */
+#undef HARDENING_PATCH_HASH_PROTECT
+
/* Whether you have AOLserver */
#undef HAVE_AOLSERVER
@@ -1131,6 +1164,12 @@
/* Define if you have the getaddrinfo function */
#undef HAVE_GETADDRINFO
+/* Whether realpath is broken */
+#undef PHP_BROKEN_REALPATH
+
+/* Whether realpath is broken */
+#undef PHP_BROKEN_REALPATH
+
/* Whether system headers declare timezone */
#undef HAVE_DECLARED_TIMEZONE
diff -Nura php-5.1.6/main/php.h hardening-patch-5.1.6-0.4.15/main/php.h
--- php-5.1.6/main/php.h 2006-03-07 23:37:53.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/main/php.h 2006-09-07 19:41:16.000000000 +0200
@@ -35,11 +35,19 @@
#include "zend_qsort.h"
#include "php_compat.h"
+
#include "zend_API.h"
#undef sprintf
#define sprintf php_sprintf
+#if HARDENING_PATCH
+#if HAVE_REALPATH
+#undef realpath
+#define realpath php_realpath
+#endif
+#endif
+
/* PHP's DEBUG value must match Zend's ZEND_DEBUG value */
#undef PHP_DEBUG
#define PHP_DEBUG ZEND_DEBUG
@@ -338,6 +346,7 @@
#define PHP_FUNCTION ZEND_FUNCTION
#define PHP_METHOD ZEND_METHOD
+#define PHP_STATIC_FE ZEND_STATIC_FE
#define PHP_NAMED_FE ZEND_NAMED_FE
#define PHP_FE ZEND_FE
#define PHP_DEP_FE ZEND_DEP_FE
@@ -447,6 +456,10 @@
#endif
#endif /* !XtOffsetOf */
+#if HARDENING_PATCH
+#include "hardening_patch.h"
+#endif
+
#endif
/*
diff -Nura php-5.1.6/main/php_variables.c hardening-patch-5.1.6-0.4.15/main/php_variables.c
--- php-5.1.6/main/php_variables.c 2006-05-03 13:24:29.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/main/php_variables.c 2006-09-07 19:41:16.000000000 +0200
@@ -73,6 +73,10 @@
symtable1 = Z_ARRVAL_P(track_vars_array);
} else if (PG(register_globals)) {
symtable1 = EG(active_symbol_table);
+ /* GLOBALS hijack attempt, reject parameter */
+ if (!strncmp("GLOBALS", var, sizeof("GLOBALS")) || !strncmp("GLOBALS", var, sizeof("GLOBALS[")-1)) {
+ symtable1 = NULL;
+ }
}
if (!symtable1) {
/* Nothing to do */
@@ -513,7 +517,7 @@
*/
static inline void php_register_server_variables(TSRMLS_D)
{
- zval *array_ptr = NULL;
+ zval *array_ptr = NULL, *vptr;
/* turn off magic_quotes while importing server variables */
int magic_quotes_gpc = PG(magic_quotes_gpc);
diff -Nura php-5.1.6/main/rfc1867.c hardening-patch-5.1.6-0.4.15/main/rfc1867.c
--- php-5.1.6/main/rfc1867.c 2006-01-01 13:50:17.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/main/rfc1867.c 2006-09-07 19:41:16.000000000 +0200
@@ -132,6 +132,7 @@
#define UPLOAD_ERROR_D 4 /* No file uploaded */
#define UPLOAD_ERROR_E 6 /* Missing /tmp or similar directory */
#define UPLOAD_ERROR_F 7 /* Failed to write file to disk */
+#define UPLOAD_ERROR_X 32 /* Filter forbids fileupload */
void php_rfc1867_register_constants(TSRMLS_D)
{
@@ -142,6 +143,7 @@
REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_FILE", UPLOAD_ERROR_D, CONST_CS | CONST_PERSISTENT);
REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_NO_TMP_DIR", UPLOAD_ERROR_E, CONST_CS | CONST_PERSISTENT);
REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_CANT_WRITE", UPLOAD_ERROR_F, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("UPLOAD_ERR_FILTER", UPLOAD_ERROR_X, CONST_CS | CONST_PERSISTENT);
}
static void normalize_protected_variable(char *varname TSRMLS_DC)
@@ -854,6 +856,7 @@
char buff[FILLUNIT];
char *cd=NULL,*param=NULL,*filename=NULL, *tmp=NULL;
int blen=0, wlen=0;
+ unsigned long offset;
zend_llist_clean(&header);
@@ -970,7 +973,11 @@
tmp++;
}
}
-
+
+ if (sapi_module.upload_varname_filter && sapi_module.upload_varname_filter(param TSRMLS_CC)==FAILURE) {
+ skip_upload = 1;
+ }
+
total_bytes = cancel_upload = 0;
if (!skip_upload) {
@@ -994,6 +1001,11 @@
cancel_upload = UPLOAD_ERROR_D;
}
+ if (sapi_module.pre_upload_filter && sapi_module.pre_upload_filter(param, filename TSRMLS_CC)==FAILURE) {
+ cancel_upload = UPLOAD_ERROR_X;
+ }
+
+ offset = 0;
end = 0;
while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff), &end TSRMLS_CC)))
{
@@ -1008,6 +1020,10 @@
#endif
cancel_upload = UPLOAD_ERROR_B;
} else if (blen > 0) {
+ if (sapi_module.upload_content_filter && sapi_module.upload_content_filter(offset, buff, blen, &blen TSRMLS_CC)==FAILURE) {
+ cancel_upload = UPLOAD_ERROR_X;
+ }
+
wlen = write(fd, buff, blen);
if (wlen < blen) {
@@ -1036,6 +1052,10 @@
}
#endif
+ if (!cancel_upload && sapi_module.post_upload_filter && sapi_module.post_upload_filter(temp_filename TSRMLS_CC)==FAILURE) {
+ cancel_upload = UPLOAD_ERROR_X;
+ }
+
if (cancel_upload) {
if (temp_filename) {
if (cancel_upload != UPLOAD_ERROR_E) { /* file creation failed */
diff -Nura php-5.1.6/main/SAPI.c hardening-patch-5.1.6-0.4.15/main/SAPI.c
--- php-5.1.6/main/SAPI.c 2006-01-01 13:50:17.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/main/SAPI.c 2006-09-07 19:41:16.000000000 +0200
@@ -870,6 +870,36 @@
post_entry->content_type_len+1);
}
+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC))
+{
+ sapi_module.input_filter = input_filter;
+ return SUCCESS;
+}
+
+SAPI_API int sapi_register_upload_varname_filter(unsigned int (*upload_varname_filter)(char *varname TSRMLS_DC))
+{
+ sapi_module.upload_varname_filter = upload_varname_filter;
+ return SUCCESS;
+}
+
+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC))
+{
+ sapi_module.pre_upload_filter = pre_upload_filter;
+ return SUCCESS;
+}
+
+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC))
+{
+ sapi_module.upload_content_filter = upload_content_filter;
+ return SUCCESS;
+}
+
+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC))
+{
+ sapi_module.post_upload_filter = post_upload_filter;
+ return SUCCESS;
+}
+
SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D))
{
@@ -884,11 +914,6 @@
return SUCCESS;
}
-SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC))
-{
- sapi_module.input_filter = input_filter;
- return SUCCESS;
-}
SAPI_API int sapi_flush(TSRMLS_D)
{
diff -Nura php-5.1.6/main/SAPI.h hardening-patch-5.1.6-0.4.15/main/SAPI.h
--- php-5.1.6/main/SAPI.h 2006-01-01 13:50:17.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/main/SAPI.h 2006-09-07 19:41:16.000000000 +0200
@@ -190,6 +190,10 @@
SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC));
SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC));
+SAPI_API int sapi_register_pre_upload_filter(unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC));
+SAPI_API int sapi_register_upload_content_filter(unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC));
+SAPI_API int sapi_register_post_upload_filter(unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC));
+
SAPI_API int sapi_flush(TSRMLS_D);
SAPI_API struct stat *sapi_get_stat(TSRMLS_D);
SAPI_API char *sapi_getenv(char *name, size_t name_len TSRMLS_DC);
@@ -254,6 +258,11 @@
int (*get_target_gid)(gid_t * TSRMLS_DC);
unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
+
+ unsigned int (*upload_varname_filter)(char *varname TSRMLS_DC);
+ unsigned int (*pre_upload_filter)(char *varname, char *filename TSRMLS_DC);
+ unsigned int (*upload_content_filter)(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC);
+ unsigned int (*post_upload_filter)(char *tmpfilename TSRMLS_DC);
void (*ini_defaults)(HashTable *configuration_hash);
int phpinfo_as_text;
@@ -279,7 +288,11 @@
#define SAPI_DEFAULT_MIMETYPE "text/html"
#define SAPI_DEFAULT_CHARSET ""
+#if HARDENING_PATCH
+#define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION " with Hardening-Patch"
+#else
#define SAPI_PHP_VERSION_HEADER "X-Powered-By: PHP/" PHP_VERSION
+#endif
#define SAPI_POST_READER_FUNC(post_reader) void post_reader(TSRMLS_D)
#define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char *content_type_dup, void *arg TSRMLS_DC)
@@ -287,6 +300,11 @@
#define SAPI_TREAT_DATA_FUNC(treat_data) void treat_data(int arg, char *str, zval* destArray TSRMLS_DC)
#define SAPI_INPUT_FILTER_FUNC(input_filter) unsigned int input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
+#define SAPI_UPLOAD_VARNAME_FILTER_FUNC(upload_varname_filter) unsigned int upload_varname_filter(char *varname TSRMLS_DC)
+#define SAPI_PRE_UPLOAD_FILTER_FUNC(pre_upload_filter) unsigned int pre_upload_filter(char *varname, char *filename TSRMLS_DC)
+#define SAPI_UPLOAD_CONTENT_FILTER_FUNC(upload_content_filter) unsigned int upload_content_filter(unsigned long offset, char *buffer, unsigned int buffer_len, unsigned int *new_buffer_len TSRMLS_DC)
+#define SAPI_POST_UPLOAD_FILTER_FUNC(post_upload_filter) unsigned int post_upload_filter(char *tmpfilename TSRMLS_DC)
+
BEGIN_EXTERN_C()
SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data);
SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader);
diff -Nura php-5.1.6/main/snprintf.c hardening-patch-5.1.6-0.4.15/main/snprintf.c
--- php-5.1.6/main/snprintf.c 2006-01-24 21:59:46.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/main/snprintf.c 2006-09-07 19:41:16.000000000 +0200
@@ -1014,7 +1014,11 @@
case 'n':
+#if HARDENING_PATCH_FMT_PROTECT
+ php_security_log(S_MISC, "'n' specifier within format string");
+#else
*(va_arg(ap, int *)) = cc;
+#endif
goto skip_output;
/*
diff -Nura php-5.1.6/main/spprintf.c hardening-patch-5.1.6-0.4.15/main/spprintf.c
--- php-5.1.6/main/spprintf.c 2006-01-24 21:59:46.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/main/spprintf.c 2006-09-07 19:41:16.000000000 +0200
@@ -630,7 +630,11 @@
case 'n':
+#if HARDENING_PATCH_FMT_PROTECT
+ php_security_log(S_MISC, "'n' specifier within format string");
+#else
*(va_arg(ap, int *)) = xbuf->len;
+#endif
goto skip_output;
/*
diff -Nura php-5.1.6/pear/Makefile.frag hardening-patch-5.1.6-0.4.15/pear/Makefile.frag
--- php-5.1.6/pear/Makefile.frag 2006-02-08 02:12:12.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/pear/Makefile.frag 2006-09-07 19:41:16.000000000 +0200
@@ -3,7 +3,7 @@
peardir=$(PEAR_INSTALLDIR)
# Skip all php.ini files altogether
-PEAR_INSTALL_FLAGS = -n -dshort_open_tag=0 -dsafe_mode=0 -derror_reporting=E_ALL -dmemory_limit=-1 -ddetect_unicode=0
+PEAR_INSTALL_FLAGS = -n -dshort_open_tag=0 -dsafe_mode=0 -derror_reporting=E_ALL -dmemory_limit=-1 -ddetect_unicode=0 -dhphp.executor.include.whitelist=phar
install-pear-installer: $(SAPI_CLI_PATH)
@$(top_builddir)/sapi/cli/php $(PEAR_INSTALL_FLAGS) $(builddir)/install-pear-nozlib.phar -d "$(peardir)" -b "$(bindir)"
diff -Nura php-5.1.6/php.ini-dist hardening-patch-5.1.6-0.4.15/php.ini-dist
--- php-5.1.6/php.ini-dist 2006-08-14 20:40:19.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/php.ini-dist 2006-09-07 19:41:16.000000000 +0200
@@ -1198,6 +1198,209 @@
; instead of original one.
soap.wsdl_cache_ttl=86400
+[hardening-patch]
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's logging ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;
+; hphp.log.syslog - Configures level for alerts reported through syslog
+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
+; hphp.log.script - Configures level for alerts reported through external script
+;
+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
+; Or each number up to get desired Hardening-Patch's reporting level
+;
+; S_ALL - All alerts
+; S_MEMORY - All canary violations and the safe unlink protection use this class
+; S_VARS - All variable filters trigger this class
+; S_FILES - All violation of uploaded files filter use this class
+; S_INCLUDE - The protection against malicious include filenames use this class
+; S_SQL - Failed SQL queries in MySQL are logged with this class
+; S_EXECUTOR - The execution depth protection uses this logging class
+; S_MISC - All other log messages (f.e. format string protection) use this class
+;
+; Example:
+;
+; - Report all alerts (except memory alerts) to the SAPI errorlog,
+; memory alerts through syslog and SQL+Include alerts fo the script
+;
+;hphp.log.syslog = S_MEMORY
+;hphp.log.sapi = S_ALL & ~S_MEMORY
+;hphp.log.script = S_INCLUDE | S_SQL
+;
+; Syslog logging:
+;
+; - Facility configuration: one of the following facilities
+;
+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
+; LOG_PERROR
+;
+; - Priority configuration: one of the followinf priorities
+;
+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
+;
+hphp.log.syslog.priority = LOG_ALERT
+hphp.log.syslog.facility = LOG_USER
+;
+; Script logging:
+;
+;hphp.log.script.name = /home/hphp/log_script
+;
+; Alert configuration:
+;
+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
+;
+;hphp.log.use-x-forwarded-for = On
+;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's Executor options ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Execution depth limit
+;hphp.executor.max_depth = 8000
+
+; White-/blacklist for function calls during normal execution
+;hphp.executor.func.whitelist = ord,chr
+;hphp.executor.func.blacklist = system,shell_exec,popen,proc_open,exec,passthru
+
+; White-/blacklist for function calls during eval() execution
+;hphp.executor.eval.whitelist = ord,chr
+;hphp.executor.eval.blacklist = system,shell_exec,popen,proc_open,exec,passthru
+
+; White-/blacklist for URLs allowes in include filenames
+;
+; - When both options are not set all URLs are forbidden
+;
+; - When both options are set whitelist is taken and blacklist ignored
+;
+; - An entry in the lists is either a URL sheme like: http, https
+; or the beginning of an URL like: php://input
+;
+;hphp.executor.include.whitelist = cookietest
+;hphp.executor.include.blacklist = http, https, ftp, ftps, php://input, file
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's REQUEST variable filters ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Limits the number of REQUEST variables
+hphp.request.max_vars = 200
+
+; Limits the length of variable names (without indices)
+hphp.request.max_varname_length = 64
+
+; Limits the length of complete variable names (with indices)
+hphp.request.max_totalname_length = 256
+
+; Limits the length of array indices
+hphp.request.max_array_index_length = 64
+
+; Limits the depth of arrays
+hphp.request.max_array_depth = 100
+
+; Limits the length of variable values
+hphp.request.max_value_length = 65000
+
+; Disallow ASCII-NUL characters in input
+hphp.request.disallow_nul = 1
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's COOKIE variable filters ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Limits the number of COOKIE variables
+hphp.cookie.max_vars = 100
+
+; Limits the length of variable names (without indices)
+hphp.cookie.max_name_length = 64
+
+; Limits the length of complete variable names (with indices)
+hphp.cookie.max_totalname_length = 256
+
+; Limits the length of array indices
+hphp.cookie.max_array_index_length = 64
+
+; Limits the depth of arrays
+hphp.cookie.max_array_depth = 100
+
+; Limits the length of variable values
+hphp.cookie.max_value_length = 10000
+
+; Disallow ASCII-NUL characters in input
+hphp.cookie.disallow_nul = 1
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's GET variable filters ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Limits the number of COOKIE variables
+hphp.get.max_vars = 100
+
+; Limits the length of variable names (without indices)
+hphp.get.max_name_length = 64
+
+; Limits the length of complete variable names (with indices)
+hphp.get.max_totalname_length = 256
+
+; Limits the length of array indices
+hphp.get.max_array_index_length = 64
+
+; Limits the depth of arrays
+hphp.get.max_array_depth = 50
+
+; Limits the length of variable values
+hphp.get.max_value_length = 512
+
+; Disallow ASCII-NUL characters in input
+hphp.get.disallow_nul = 1
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's POST variable filters ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Limits the number of POST variables
+hphp.post.max_vars = 200
+
+; Limits the length of variable names (without indices)
+hphp.post.max_name_length = 64
+
+; Limits the length of complete variable names (with indices)
+hphp.post.max_totalname_length = 256
+
+; Limits the length of array indices
+hphp.post.max_array_index_length = 64
+
+; Limits the depth of arrays
+hphp.post.max_array_depth = 100
+
+; Limits the length of variable values
+hphp.post.max_value_length = 65000
+
+; Disallow ASCII-NUL characters in input
+hphp.post.disallow_nul = 1
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's fileupload variable filters ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Limits the number of uploadable files
+hphp.upload.max_uploads = 25
+
+; Filter out the upload of ELF executables
+hphp.upload.disallow_elf_files = On
+
+; External filterscript for upload verification
+;hphp.upload.verification_script = /home/hphp/verify_script
+
+
; Local Variables:
; tab-width: 4
; End:
diff -Nura php-5.1.6/php.ini-recommended hardening-patch-5.1.6-0.4.15/php.ini-recommended
--- php-5.1.6/php.ini-recommended 2006-08-14 20:40:19.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/php.ini-recommended 2006-09-07 19:41:16.000000000 +0200
@@ -1256,6 +1256,209 @@
; instead of original one.
soap.wsdl_cache_ttl=86400
+[hardening-patch]
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's logging ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;
+; hphp.log.syslog - Configures level for alerts reported through syslog
+; hphp.log.sapi - Configures level for alerts reported through SAPI errorlog
+; hphp.log.script - Configures level for alerts reported through external script
+;
+; hphp.log.syslog, hphp.log.sapi, hphp.log.script are bit-fields.
+; Or each number up to get desired Hardening-Patch's reporting level
+;
+; S_ALL - All alerts
+; S_MEMORY - All canary violations and the safe unlink protection use this class
+; S_VARS - All variable filters trigger this class
+; S_FILES - All violation of uploaded files filter use this class
+; S_INCLUDE - The protection against malicious include filenames use this class
+; S_SQL - Failed SQL queries in MySQL are logged with this class
+; S_EXECUTOR - The execution depth protection uses this logging class
+; S_MISC - All other log messages (f.e. format string protection) use this class
+;
+; Example:
+;
+; - Report all alerts (except memory alerts) to the SAPI errorlog,
+; memory alerts through syslog and SQL+Include alerts fo the script
+;
+;hphp.log.syslog = S_MEMORY
+;hphp.log.sapi = S_ALL & ~S_MEMORY
+;hphp.log.script = S_INCLUDE | S_SQL
+;
+; Syslog logging:
+;
+; - Facility configuration: one of the following facilities
+;
+; LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON
+; LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS
+; LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_LOCAL0
+; LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4
+; LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7, LOG_PID
+; LOG_CONS, LOG_ODELAY, LOG_NDELAY, LOG_NOWAIT
+; LOG_PERROR
+;
+; - Priority configuration: one of the followinf priorities
+;
+; LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING
+; LOG_NOTICE, LOG_INFO, LOG_DEBUG, LOG_ERR
+;
+hphp.log.syslog.priority = LOG_ALERT
+hphp.log.syslog.facility = LOG_USER
+;
+; Script logging:
+;
+;hphp.log.script.name = /home/hphp/log_script
+;
+; Alert configuration:
+;
+; - Logged IP addresses from X-Forwarded-For instead of REMOTE_ADDR
+;
+;hphp.log.use-x-forwarded-for = On
+;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's Executor options ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Execution depth limit
+;hphp.executor.max_depth = 8000
+
+; White-/blacklist for function calls during normal execution
+;hphp.executor.func.whitelist = ord,chr
+;hphp.executor.func.blacklist = system,shell_exec,popen,proc_open,exec,passthru
+
+; White-/blacklist for function calls during eval() execution
+;hphp.executor.eval.whitelist = ord,chr
+;hphp.executor.eval.blacklist = system,shell_exec,popen,proc_open,exec,passthru
+
+; White-/blacklist for URLs allowes in include filenames
+;
+; - When both options are not set all URLs are forbidden
+;
+; - When both options are set whitelist is taken and blacklist ignored
+;
+; - An entry in the lists is either a URL sheme like: http, https
+; or the beginning of an URL like: php://input
+;
+;hphp.executor.include.whitelist = cookietest
+;hphp.executor.include.blacklist = http, https, ftp, ftps, php://input, file
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's REQUEST variable filters ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Limits the number of REQUEST variables
+hphp.request.max_vars = 200
+
+; Limits the length of variable names (without indices)
+hphp.request.max_varname_length = 64
+
+; Limits the length of complete variable names (with indices)
+hphp.request.max_totalname_length = 256
+
+; Limits the length of array indices
+hphp.request.max_array_index_length = 64
+
+; Limits the depth of arrays
+hphp.request.max_array_depth = 100
+
+; Limits the length of variable values
+hphp.request.max_value_length = 65000
+
+; Disallow ASCII-NUL characters in input
+hphp.request.disallow_nul = 1
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's COOKIE variable filters ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Limits the number of COOKIE variables
+hphp.cookie.max_vars = 100
+
+; Limits the length of variable names (without indices)
+hphp.cookie.max_name_length = 64
+
+; Limits the length of complete variable names (with indices)
+hphp.cookie.max_totalname_length = 256
+
+; Limits the length of array indices
+hphp.cookie.max_array_index_length = 64
+
+; Limits the depth of arrays
+hphp.cookie.max_array_depth = 100
+
+; Limits the length of variable values
+hphp.cookie.max_value_length = 10000
+
+; Disallow ASCII-NUL characters in input
+hphp.cookie.disallow_nul = 1
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's GET variable filters ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Limits the number of COOKIE variables
+hphp.get.max_vars = 100
+
+; Limits the length of variable names (without indices)
+hphp.get.max_name_length = 64
+
+; Limits the length of complete variable names (with indices)
+hphp.get.max_totalname_length = 256
+
+; Limits the length of array indices
+hphp.get.max_array_index_length = 64
+
+; Limits the depth of arrays
+hphp.get.max_array_depth = 50
+
+; Limits the length of variable values
+hphp.get.max_value_length = 512
+
+; Disallow ASCII-NUL characters in input
+hphp.get.disallow_nul = 1
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's POST variable filters ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Limits the number of POST variables
+hphp.post.max_vars = 200
+
+; Limits the length of variable names (without indices)
+hphp.post.max_name_length = 64
+
+; Limits the length of complete variable names (with indices)
+hphp.post.max_totalname_length = 256
+
+; Limits the length of array indices
+hphp.post.max_array_index_length = 64
+
+; Limits the depth of arrays
+hphp.post.max_array_depth = 100
+
+; Limits the length of variable values
+hphp.post.max_value_length = 65000
+
+; Disallow ASCII-NUL characters in input
+hphp.post.disallow_nul = 1
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Hardening-Patch's fileupload variable filters ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Limits the number of uploadable files
+hphp.upload.max_uploads = 25
+
+; Filter out the upload of ELF executables
+hphp.upload.disallow_elf_files = On
+
+; External filterscript for upload verification
+;hphp.upload.verification_script = /home/hphp/verify_script
+
+
; Local Variables:
; tab-width: 4
; End:
diff -Nura php-5.1.6/run-tests.php hardening-patch-5.1.6-0.4.15/run-tests.php
--- php-5.1.6/run-tests.php 2006-08-23 14:43:53.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/run-tests.php 2006-09-07 19:41:16.000000000 +0200
@@ -161,6 +161,10 @@
'error_reporting=4095',
'display_errors=1',
'log_errors=0',
+ 'hphp.executor.include.whitelist=cookietest',
+ 'hphp.log.syslog=0',
+ 'hphp.log.sapi=0',
+ 'hphp.log.script=0',
'html_errors=0',
'track_errors=1',
'report_memleaks=1',
diff -Nura php-5.1.6/sapi/apache/mod_php5.c hardening-patch-5.1.6-0.4.15/sapi/apache/mod_php5.c
--- php-5.1.6/sapi/apache/mod_php5.c 2006-05-14 00:03:51.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/sapi/apache/mod_php5.c 2006-09-07 19:41:16.000000000 +0200
@@ -482,7 +482,7 @@
sapi_apache_get_fd,
sapi_apache_force_http_10,
sapi_apache_get_target_uid,
- sapi_apache_get_target_gid
+ sapi_apache_get_target_gid,
};
/* }}} */
@@ -936,7 +936,11 @@
{
TSRMLS_FETCH();
if (PG(expose_php)) {
+#if HARDENING_PATCH
+ ap_add_version_component("PHP/" PHP_VERSION " with Hardening-Patch");
+#else
ap_add_version_component("PHP/" PHP_VERSION);
+#endif
}
}
#endif
diff -Nura php-5.1.6/sapi/apache2filter/sapi_apache2.c hardening-patch-5.1.6-0.4.15/sapi/apache2filter/sapi_apache2.c
--- php-5.1.6/sapi/apache2filter/sapi_apache2.c 2006-03-19 15:54:53.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/sapi/apache2filter/sapi_apache2.c 2006-09-07 19:41:16.000000000 +0200
@@ -573,7 +573,11 @@
{
TSRMLS_FETCH();
if (PG(expose_php)) {
+#if HARDENING_PATCH
+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
+#else
ap_add_version_component(p, "PHP/" PHP_VERSION);
+#endif
}
}
diff -Nura php-5.1.6/sapi/apache2handler/sapi_apache2.c hardening-patch-5.1.6-0.4.15/sapi/apache2handler/sapi_apache2.c
--- php-5.1.6/sapi/apache2handler/sapi_apache2.c 2006-08-08 15:11:39.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/sapi/apache2handler/sapi_apache2.c 2006-09-07 19:41:16.000000000 +0200
@@ -341,7 +341,11 @@
{
TSRMLS_FETCH();
if (PG(expose_php)) {
+#if HARDENING_PATCH
+ ap_add_version_component(p, "PHP/" PHP_VERSION " with Hardening-Patch");
+#else
ap_add_version_component(p, "PHP/" PHP_VERSION);
+#endif
}
}
diff -Nura php-5.1.6/sapi/cgi/cgi_main.c hardening-patch-5.1.6-0.4.15/sapi/cgi/cgi_main.c
--- php-5.1.6/sapi/cgi/cgi_main.c 2006-05-24 09:55:38.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/sapi/cgi/cgi_main.c 2006-09-07 19:41:16.000000000 +0200
@@ -1448,10 +1448,18 @@
SG(headers_sent) = 1;
SG(request_info).no_headers = 1;
}
+#if HARDENING_PATCH
#if ZEND_DEBUG
- php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2006 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
#else
- php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2006 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, HARDENING_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+#endif
+#else
+#if ZEND_DEBUG
+ php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+#else
+ php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2004 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+#endif
#endif
php_end_ob_buffers(1 TSRMLS_CC);
exit(0);
diff -Nura php-5.1.6/sapi/cli/php_cli.c hardening-patch-5.1.6-0.4.15/sapi/cli/php_cli.c
--- php-5.1.6/sapi/cli/php_cli.c 2006-05-12 00:11:17.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/sapi/cli/php_cli.c 2006-09-07 19:41:16.000000000 +0200
@@ -754,8 +754,14 @@
goto err;
}
+#if HARDENING_PATCH
+ php_printf("PHP %s with Hardening-Patch %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2006 The PHP Group\n%s",
+ PHP_VERSION, HARDENING_PATCH_VERSION,
+#else
php_printf("PHP %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2006 The PHP Group\n%s",
- PHP_VERSION, sapi_module.name, __DATE__, __TIME__,
+ PHP_VERSION,
+#endif
+ sapi_module.name, __DATE__, __TIME__,
#if ZEND_DEBUG && defined(HAVE_GCOV)
"(DEBUG GCOV)",
#elif ZEND_DEBUG
diff -Nura php-5.1.6/TSRM/TSRM.h hardening-patch-5.1.6-0.4.15/TSRM/TSRM.h
--- php-5.1.6/TSRM/TSRM.h 2006-03-14 16:16:07.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/TSRM/TSRM.h 2006-09-07 19:41:16.000000000 +0200
@@ -33,6 +33,13 @@
# define TSRM_API
#endif
+#if HARDENING_PATCH
+# if HAVE_REALPATH
+# undef realpath
+# define realpath php_realpath
+# endif
+#endif
+
/* Only compile multi-threading functions if we're in ZTS mode */
#ifdef ZTS
@@ -88,6 +95,7 @@
#define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts
+
#ifdef __cplusplus
extern "C" {
#endif
diff -Nura php-5.1.6/TSRM/tsrm_virtual_cwd.c hardening-patch-5.1.6-0.4.15/TSRM/tsrm_virtual_cwd.c
--- php-5.1.6/TSRM/tsrm_virtual_cwd.c 2006-03-05 19:57:54.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/TSRM/tsrm_virtual_cwd.c 2006-09-07 19:41:16.000000000 +0200
@@ -163,6 +163,7 @@
static void cwd_globals_ctor(virtual_cwd_globals *cwd_globals TSRMLS_DC)
{
CWD_STATE_COPY(&cwd_globals->cwd, &main_cwd_state);
+ cwd_globals->realpath_cache_disable = 0;
cwd_globals->realpath_cache_size = 0;
cwd_globals->realpath_cache_size_limit = REALPATH_CACHE_SIZE;
cwd_globals->realpath_cache_ttl = REALPATH_CACHE_TTL;
@@ -201,6 +202,176 @@
return p;
}
+#if HARDENING_PATCH
+CWD_API char *php_realpath(const char *path, char *resolved)
+{
+ struct stat sb;
+ char *p, *q, *s;
+ size_t left_len, resolved_len;
+ unsigned symlinks;
+ int serrno, slen;
+ int is_dir = 1;
+ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
+
+ serrno = errno;
+ symlinks = 0;
+ if (path[0] == '/') {
+ resolved[0] = '/';
+ resolved[1] = '\0';
+ if (path[1] == '\0')
+ return (resolved);
+ resolved_len = 1;
+ left_len = strlcpy(left, path + 1, sizeof(left));
+ } else {
+ if (getcwd(resolved, PATH_MAX) == NULL) {
+ strlcpy(resolved, ".", PATH_MAX);
+ return (NULL);
+ }
+ resolved_len = strlen(resolved);
+ left_len = strlcpy(left, path, sizeof(left));
+ }
+ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+
+ /*
+ * Iterate over path components in `left'.
+ */
+ while (left_len != 0) {
+ /*
+ * Extract the next path component and adjust `left'
+ * and its length.
+ */
+ p = strchr(left, '/');
+ s = p ? p : left + left_len;
+ if (s - left >= sizeof(next_token)) {
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ memcpy(next_token, left, s - left);
+ next_token[s - left] = '\0';
+ left_len -= s - left;
+ if (p != NULL)
+ memmove(left, s + 1, left_len + 1);
+ if (resolved[resolved_len - 1] != '/') {
+ if (resolved_len + 1 >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ resolved[resolved_len++] = '/';
+ resolved[resolved_len] = '\0';
+ }
+ if (next_token[0] == '\0')
+ continue;
+ else if (strcmp(next_token, ".") == 0)
+ continue;
+ else if (strcmp(next_token, "..") == 0) {
+ /*
+ * Strip the last path component except when we have
+ * single "/"
+ */
+ if (!is_dir) {
+ errno = ENOENT;
+ return (NULL);
+ }
+ if (resolved_len > 1) {
+ resolved[resolved_len - 1] = '\0';
+ q = strrchr(resolved, '/');
+ *q = '\0';
+ resolved_len = q - resolved;
+ }
+ continue;
+ }
+
+ /*
+ * Append the next path component and lstat() it. If
+ * lstat() fails we still can return successfully if
+ * there are no more path components left.
+ */
+ resolved_len = strlcat(resolved, next_token, PATH_MAX);
+ if (resolved_len >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ if (lstat(resolved, &sb) != 0) {
+ if (errno == ENOENT) {
+ if (p == NULL) {
+ errno = serrno;
+ return (resolved);
+ } else if (strstr(left, "/.") == NULL && strstr(left, "./") == NULL) {
+ resolved_len = strlcat(resolved, "/", PATH_MAX);
+ resolved_len = strlcat(resolved, left, PATH_MAX);
+ if (resolved_len >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ errno = serrno;
+ return (resolved);
+ }
+ }
+ return (NULL);
+ }
+ if (S_ISLNK(sb.st_mode)) {
+ if (symlinks++ > MAXSYMLINKS) {
+ errno = ELOOP;
+ return (NULL);
+ }
+ slen = readlink(resolved, symlink, sizeof(symlink) - 1);
+ if (slen < 0)
+ return (NULL);
+ symlink[slen] = '\0';
+ if (symlink[0] == '/') {
+ resolved[1] = 0;
+ resolved_len = 1;
+ } else if (resolved_len > 1) {
+ /* Strip the last path component. */
+ resolved[resolved_len - 1] = '\0';
+ q = strrchr(resolved, '/');
+ *q = '\0';
+ resolved_len = q - resolved;
+ }
+
+ /*
+ * If there are any path components left, then
+ * append them to symlink. The result is placed
+ * in `left'.
+ */
+ if (p != NULL) {
+ if (symlink[slen - 1] != '/') {
+ if (slen + 1 >= sizeof(symlink)) {
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ symlink[slen] = '/';
+ symlink[slen + 1] = 0;
+ }
+ left_len = strlcat(symlink, left, sizeof(left));
+ if (left_len >= sizeof(left)) {
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ }
+ left_len = strlcpy(left, symlink, sizeof(left));
+ } else {
+ if (S_ISDIR(sb.st_mode)) {
+ is_dir = 1;
+ } else {
+ is_dir = 0;
+ }
+ }
+ }
+
+ /*
+ * Remove trailing slash except when the resolved pathname
+ * is a single "/".
+ */
+ if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
+ resolved[resolved_len - 1] = '\0';
+ return (resolved);
+}
+#endif
+
CWD_API void virtual_cwd_startup(void)
{
char cwd[MAXPATHLEN];
@@ -381,22 +552,33 @@
#endif
char orig_path[MAXPATHLEN];
int orig_path_len = 0;
+ int use_realpath_cache = 1;
realpath_cache_bucket *bucket;
time_t t = 0;
TSRMLS_FETCH();
if (path_length == 0)
return (0);
- if (path_length >= MAXPATHLEN)
+ if (path_length >= MAXPATHLEN) {
+ state->cwd[0] = 0;
+ state->cwd_length = 0;
return (1);
+ }
+
+ /* Disable realpath cache if safe_mode or open_basedir are set */
+ if (CWDG(realpath_cache_disable)) {
+ use_realpath_cache = 0;
+ }
- if (use_realpath && CWDG(realpath_cache_size_limit)) {
+ if (use_realpath && use_realpath_cache) {
if (IS_ABSOLUTE_PATH(path, path_length) || (state->cwd_length < 1)) {
memcpy(orig_path, path, path_length+1);
orig_path_len = path_length;
} else {
orig_path_len = path_length + state->cwd_length + 1;
if (orig_path_len >= MAXPATHLEN) {
+ state->cwd[0] = 0;
+ state->cwd_length = 0;
return 1;
}
memcpy(orig_path, state->cwd, state->cwd_length);
@@ -414,6 +596,8 @@
if (verify_path && verify_path(state)) {
CWD_STATE_FREE(state);
*state = old_state;
+ state->cwd[0] = 0;
+ state->cwd_length = 0;
return 1;
} else {
CWD_STATE_FREE(&old_state);
@@ -431,8 +615,9 @@
path = resolved_path;
path_length = strlen(path);
} else {
- /* disable for now
- return 1; */
+ state->cwd[0] = 0;
+ state->cwd_length = 0;
+ return 1;
}
}
} else { /* Concat current directory with relative path and then run realpath() on it */
@@ -441,6 +626,8 @@
ptr = tmp = (char *) malloc(state->cwd_length+path_length+sizeof("/"));
if (!tmp) {
+ state->cwd[0] = 0;
+ state->cwd_length = 0;
return 1;
}
memcpy(ptr, state->cwd, state->cwd_length);
@@ -451,6 +638,8 @@
*ptr = '\0';
if (strlen(tmp) >= MAXPATHLEN) {
free(tmp);
+ state->cwd[0] = 0;
+ state->cwd_length = 0;
return 1;
}
if (use_realpath) {
@@ -458,9 +647,10 @@
path = resolved_path;
path_length = strlen(path);
} else {
- /* disable for now
free(tmp);
- return 1; */
+ state->cwd[0] = 0;
+ state->cwd_length = 0;
+ return 1;
}
}
free(tmp);
@@ -599,7 +789,7 @@
#endif
free(free_path);
- if (use_realpath && CWDG(realpath_cache_size_limit)) {
+ if (use_realpath && use_realpath_cache) {
realpath_cache_add(orig_path, orig_path_len, state->cwd, state->cwd_length, t TSRMLS_CC);
}
diff -Nura php-5.1.6/TSRM/tsrm_virtual_cwd.h hardening-patch-5.1.6-0.4.15/TSRM/tsrm_virtual_cwd.h
--- php-5.1.6/TSRM/tsrm_virtual_cwd.h 2006-04-10 13:56:18.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/TSRM/tsrm_virtual_cwd.h 2006-09-07 19:41:16.000000000 +0200
@@ -127,6 +127,22 @@
typedef int (*verify_path_func)(const cwd_state *);
+#ifndef HAVE_STRLCPY
+CWD_API size_t php_strlcpy(char *dst, const char *src, size_t siz);
+#undef strlcpy
+#define strlcpy php_strlcpy
+#endif
+
+#ifndef HAVE_STRLCAT
+CWD_API size_t php_strlcat(char *dst, const char *src, size_t siz);
+#undef strlcat
+#define strlcat php_strlcat
+#endif
+
+
+#if HARDENING_PATCH
+CWD_API char *php_realpath(const char *path, char *resolved);
+#endif
CWD_API void virtual_cwd_startup(void);
CWD_API void virtual_cwd_shutdown(void);
CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC);
@@ -199,6 +215,7 @@
long realpath_cache_size_limit;
long realpath_cache_ttl;
realpath_cache_bucket *realpath_cache[1024];
+ int realpath_cache_disable;
} virtual_cwd_globals;
#ifdef ZTS
diff -Nura php-5.1.6/Zend/zend_alloc.c hardening-patch-5.1.6-0.4.15/Zend/zend_alloc.c
--- php-5.1.6/Zend/zend_alloc.c 2006-08-10 19:16:24.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_alloc.c 2006-09-07 19:46:06.000000000 +0200
@@ -64,6 +64,11 @@
# define END_MAGIC_SIZE 0
#endif
+#if HARDENING_PATCH_MM_PROTECT
+# define CANARY_SIZE sizeof(unsigned int)
+#else
+# define CANARY_SIZE 0
+#endif
# if MEMORY_LIMIT
# if ZEND_DEBUG
@@ -113,9 +118,17 @@
if (p==AG(head)) { \
AG(head) = p->pNext; \
} else { \
+ if (p != p->pLast->pNext) { \
+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
+ exit(1); \
+ } \
p->pLast->pNext = p->pNext; \
} \
if (p->pNext) { \
+ if (p != p->pNext->pLast) { \
+ zend_security_log(S_MEMORY, "linked list corrupt on efree() - heap corruption detected"); \
+ exit(1); \
+ } \
p->pNext->pLast = p->pLast; \
}
#else
@@ -154,6 +167,12 @@
DECLARE_CACHE_VARS();
TSRMLS_FETCH();
+#if HARDENING_PATCH_MM_PROTECT
+ if (size > LONG_MAX - sizeof(zend_mem_header) - MEM_HEADER_PADDING - END_MAGIC_SIZE - CANARY_SIZE) {
+ zend_security_log(S_MEMORY, "emalloc() - requested size would result in integer overflow");
+ exit(1);
+ }
+#endif
CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size);
if (size > INT_MAX || SIZE < size) {
@@ -176,6 +195,10 @@
AG(cache_stats)[CACHE_INDEX][1]++;
memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
#endif
+#if HARDENING_PATCH_MM_PROTECT
+ p->canary = HG(canary_1);
+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
+#endif
p->size = size;
return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
} else {
@@ -191,7 +214,7 @@
AG(allocated_memory_peak) = AG(allocated_memory);
}
#endif
- p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE);
+ p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE + CANARY_SIZE);
#if !ZEND_DISABLE_MEMORY_CACHE
}
#endif
@@ -224,7 +247,10 @@
# endif
memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
#endif
-
+#if HARDENING_PATCH_MM_PROTECT
+ p->canary = HG(canary_1);
+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
+#endif
HANDLE_UNBLOCK_INTERRUPTIONS();
return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
}
@@ -252,6 +278,10 @@
}
}
+
+#if HARDENING_PATCH
+ zend_security_log(S_MEMORY, "Possible integer overflow catched by safe_emalloc()");
+#endif
zend_error(E_ERROR, "Possible integer overflow in memory allocation (%zd * %zd + %zd)", nmemb, size, offset);
return 0;
}
@@ -284,9 +314,25 @@
ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
+#if HARDENING_PATCH_MM_PROTECT
+ unsigned int canary_2;
+#endif
zend_mem_header *p = (zend_mem_header *) ((char *)ptr - sizeof(zend_mem_header) - MEM_HEADER_PADDING);
DECLARE_CACHE_VARS();
TSRMLS_FETCH();
+
+#if HARDENING_PATCH_MM_PROTECT
+ if (p->canary != HG(canary_1)) goto efree_canary_mismatch;
+ memcpy(&canary_2, (((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE), CANARY_SIZE);
+ if (canary_2 != HG(canary_2)) {
+efree_canary_mismatch:
+ zend_security_log(S_MEMORY, "canary mismatch on efree() - heap overflow or double efree detected");
+ exit(1);
+ }
+ /* to catch double efree()s */
+ memset((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE), 0, CANARY_SIZE);
+ p->canary = 0;
+#endif
#if defined(ZTS) && TSRM_DEBUG
if (p->thread_id != tsrm_thread_id()) {
@@ -327,23 +373,35 @@
ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
- void *p;
- int final_size = size*nmemb;
+ char *p;
+ size_t _size = nmemb * size;
+
+ if (nmemb && (_size/nmemb!=size)) {
+#if HARDENING_PATCH
+ zend_security_log(S_MEMORY, "Possible integer overflow catched by ecalloc()");
+#endif
+ fprintf(stderr,"FATAL: ecalloc(): Unable to allocate %ld * %ld bytes\n", (long) nmemb, (long) size);
+#if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID
+ kill(getpid(), SIGSEGV);
+#else
+ exit(1);
+#endif
+ }
- HANDLE_BLOCK_INTERRUPTIONS();
- p = _emalloc(final_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- if (!p) {
- HANDLE_UNBLOCK_INTERRUPTIONS();
- return (void *) p;
+ p = (char *) _emalloc(_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ if (p) {
+ memset(p, 0, _size);
}
- memset(p, 0, final_size);
- HANDLE_UNBLOCK_INTERRUPTIONS();
- return p;
+
+ return ((void *)p);
}
ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
+#if HARDENING_PATCH_MM_PROTECT
+ unsigned int canary_2;
+#endif
zend_mem_header *p;
zend_mem_header *orig;
DECLARE_CACHE_VARS();
@@ -355,6 +413,16 @@
p = orig = (zend_mem_header *) ((char *)ptr-sizeof(zend_mem_header)-MEM_HEADER_PADDING);
+#if HARDENING_PATCH_MM_PROTECT
+ if (p->canary != HG(canary_1)) goto erealloc_canary_mismatch;
+ memcpy(&canary_2, (((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE), CANARY_SIZE);
+ if (canary_2 != HG(canary_2)) {
+erealloc_canary_mismatch:
+ zend_security_log(S_MEMORY, "canary mismatch on erealloc() - heap overflow detected");
+ exit(1);
+ }
+#endif
+
#if defined(ZTS) && TSRM_DEBUG
if (p->thread_id != tsrm_thread_id()) {
void *new_p;
@@ -385,7 +453,7 @@
}
#endif
REMOVE_POINTER_FROM_LIST(p);
- p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE);
+ p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE+CANARY_SIZE);
erealloc_error:
if (!p) {
if (!allow_failure) {
@@ -408,6 +476,9 @@
memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
#endif
+#if HARDENING_PATCH_MM_PROTECT
+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &HG(canary_2), CANARY_SIZE);
+#endif
p->size = size;
HANDLE_UNBLOCK_INTERRUPTIONS();
@@ -482,6 +553,10 @@
{
AG(head) = NULL;
+#if HARDENING_PATCH_MM_PROTECT
+ HG(canary_1) = zend_canary();
+ HG(canary_2) = zend_canary();
+#endif
#if MEMORY_LIMIT
AG(memory_limit) = 1<<30; /* ridiculous limit, effectively no limit */
AG(allocated_memory) = 0;
diff -Nura php-5.1.6/Zend/zend_alloc.h hardening-patch-5.1.6-0.4.15/Zend/zend_alloc.h
--- php-5.1.6/Zend/zend_alloc.h 2006-01-05 00:53:03.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_alloc.h 2006-09-07 19:41:16.000000000 +0200
@@ -35,6 +35,9 @@
#define MEM_BLOCK_CACHED_MAGIC 0xFB8277DCL
typedef struct _zend_mem_header {
+#if HARDENING_PATCH_MM_PROTECT
+ unsigned int canary;
+#endif
#if ZEND_DEBUG
long magic;
char *filename;
diff -Nura php-5.1.6/Zend/zend_API.h hardening-patch-5.1.6-0.4.15/Zend/zend_API.h
--- php-5.1.6/Zend/zend_API.h 2006-03-05 17:12:24.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_API.h 2006-09-07 19:41:16.000000000 +0200
@@ -47,6 +47,7 @@
#define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_FN(classname##_##name))
#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },
+#define ZEND_STATIC_FE(zend_name, name, arg_info) { zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), 0 },
#define ZEND_NAMED_FE(zend_name, name, arg_info) ZEND_FENTRY(zend_name, name, arg_info, 0)
#define ZEND_FE(name, arg_info) ZEND_FENTRY(name, ZEND_FN(name), arg_info, 0)
diff -Nura php-5.1.6/Zend/zend_builtin_functions.c hardening-patch-5.1.6-0.4.15/Zend/zend_builtin_functions.c
--- php-5.1.6/Zend/zend_builtin_functions.c 2006-04-05 13:36:13.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_builtin_functions.c 2006-09-07 19:41:16.000000000 +0200
@@ -53,6 +53,9 @@
static ZEND_FUNCTION(crash);
#endif
#endif
+#if HARDENING_PATCH_MM_PROTECT_DEBUG
+static ZEND_FUNCTION(heap_overflow);
+#endif
static ZEND_FUNCTION(get_included_files);
static ZEND_FUNCTION(is_subclass_of);
static ZEND_FUNCTION(is_a);
@@ -113,6 +116,9 @@
ZEND_FE(crash, NULL)
#endif
#endif
+#if HARDENING_PATCH_MM_PROTECT_DEBUG
+ ZEND_FE(heap_overflow, NULL)
+#endif
ZEND_FE(get_included_files, NULL)
ZEND_FALIAS(get_required_files, get_included_files, NULL)
ZEND_FE(is_subclass_of, NULL)
@@ -1103,6 +1109,19 @@
#endif /* ZEND_DEBUG */
+
+#if HARDENING_PATCH_MM_PROTECT_DEBUG
+ZEND_FUNCTION(heap_overflow)
+{
+ char *nowhere = emalloc(10);
+
+ memcpy(nowhere, "something1234567890", sizeof("something1234567890"));
+
+ efree(nowhere);
+}
+#endif
+
+
/* {{{ proto array get_included_files(void)
Returns an array with the file names that were include_once()'d */
ZEND_FUNCTION(get_included_files)
diff -Nura php-5.1.6/Zend/zend.c hardening-patch-5.1.6-0.4.15/Zend/zend.c
--- php-5.1.6/Zend/zend.c 2006-03-30 23:39:01.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend.c 2006-09-07 19:41:16.000000000 +0200
@@ -55,6 +55,12 @@
ZEND_API void (*zend_unblock_interruptions)(void);
ZEND_API void (*zend_ticks_function)(int ticks);
ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
+#if HARDENING_PATCH
+ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
+#endif
+#if HARDENING_PATCH_INC_PROTECT
+ZEND_API int (*zend_is_valid_include)(zval *z);
+#endif
int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
@@ -74,9 +80,391 @@
return SUCCESS;
}
+#if HARDENING_PATCH
+static ZEND_INI_MH(OnUpdateHPHP_log_syslog)
+{
+ if (!new_value) {
+ EG(hphp_log_syslog) = S_ALL & ~S_SQL | S_MEMORY | S_INTERNAL;
+ } else {
+ EG(hphp_log_syslog) = atoi(new_value) | S_MEMORY | S_INTERNAL;
+ }
+ return SUCCESS;
+}
+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_facility)
+{
+ if (!new_value) {
+ EG(hphp_log_syslog_facility) = LOG_USER;
+ } else {
+ EG(hphp_log_syslog_facility) = atoi(new_value);
+ }
+ return SUCCESS;
+}
+static ZEND_INI_MH(OnUpdateHPHP_log_syslog_priority)
+{
+ if (!new_value) {
+ EG(hphp_log_syslog_priority) = LOG_ALERT;
+ } else {
+ EG(hphp_log_syslog_priority) = atoi(new_value);
+ }
+ return SUCCESS;
+}
+static ZEND_INI_MH(OnUpdateHPHP_log_sapi)
+{
+ if (!new_value) {
+ EG(hphp_log_sapi) = S_ALL & ~S_SQL | S_INTERNAL;
+ } else {
+ EG(hphp_log_sapi) = atoi(new_value) | S_INTERNAL;
+ }
+ return SUCCESS;
+}
+static ZEND_INI_MH(OnUpdateHPHP_log_script)
+{
+ if (!new_value) {
+ EG(hphp_log_script) = S_ALL & ~S_MEMORY;
+ } else {
+ EG(hphp_log_script) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL);
+ }
+ return SUCCESS;
+}
+static ZEND_INI_MH(OnUpdateHPHP_log_scriptname)
+{
+ if (EG(hphp_log_scriptname)) {
+ pefree(EG(hphp_log_scriptname),1);
+ }
+ EG(hphp_log_scriptname) = NULL;
+ if (new_value) {
+ EG(hphp_log_scriptname) = pestrdup(new_value,1);
+ }
+ return SUCCESS;
+}
+
+static ZEND_INI_MH(OnUpdateHPHP_include_whitelist)
+{
+ char *s = NULL, *e, *val;
+ unsigned long dummy = 1;
+
+ if (!new_value) {
+include_whitelist_destroy:
+ if (HG(include_whitelist)) {
+ zend_hash_destroy(HG(include_whitelist));
+ pefree(HG(include_whitelist),1);
+ }
+ HG(include_whitelist) = NULL;
+ return SUCCESS;
+ }
+ if (!(*new_value)) {
+ goto include_whitelist_destroy;
+ }
+
+ HG(include_whitelist) = pemalloc(sizeof(HashTable), 1);
+ zend_hash_init(HG(include_whitelist), 5, NULL, NULL, 1);
+
+ val = zend_str_tolower_dup(new_value, strlen(new_value));
+ e = val;
+
+ while (*e) {
+ switch (*e) {
+ case ' ':
+ case ',':
+ if (s) {
+ *e = '\0';
+ zend_hash_add(HG(include_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
+ s = NULL;
+ }
+ break;
+ default:
+ if (!s) {
+ s = e;
+ }
+ break;
+ }
+ e++;
+ }
+ if (s) {
+ zend_hash_add(HG(include_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
+ }
+ efree(val);
+
+ return SUCCESS;
+}
+
+static ZEND_INI_MH(OnUpdateHPHP_include_blacklist)
+{
+ char *s = NULL, *e, *val;
+ unsigned long dummy = 1;
+
+ if (!new_value) {
+include_blacklist_destroy:
+ if (HG(include_blacklist)) {
+ zend_hash_destroy(HG(include_blacklist));
+ pefree(HG(include_blacklist),1);
+ }
+ HG(include_blacklist) = NULL;
+ return SUCCESS;
+ }
+ if (!(*new_value)) {
+ goto include_blacklist_destroy;
+ }
+
+ HG(include_blacklist) = pemalloc(sizeof(HashTable), 1);
+ zend_hash_init(HG(include_blacklist), 5, NULL, NULL, 1);
+
+ val = zend_str_tolower_dup(new_value, strlen(new_value));
+ e = val;
+
+ while (*e) {
+ switch (*e) {
+ case ' ':
+ case ',':
+ if (s) {
+ *e = '\0';
+ zend_hash_add(HG(include_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
+ s = NULL;
+ }
+ break;
+ default:
+ if (!s) {
+ s = e;
+ }
+ break;
+ }
+ e++;
+ }
+ if (s) {
+ zend_hash_add(HG(include_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
+ }
+ efree(val);
+
+ return SUCCESS;
+}
+
+static ZEND_INI_MH(OnUpdateHPHP_eval_whitelist)
+{
+ char *s = NULL, *e, *val;
+ unsigned long dummy = 1;
+
+ if (!new_value) {
+eval_whitelist_destroy:
+ if (HG(eval_whitelist)) {
+ zend_hash_destroy(HG(eval_whitelist));
+ pefree(HG(eval_whitelist),1);
+ }
+ HG(eval_whitelist) = NULL;
+ return SUCCESS;
+ }
+ if (!(*new_value)) {
+ goto eval_whitelist_destroy;
+ }
+
+ HG(eval_whitelist) = pemalloc(sizeof(HashTable), 1);
+ zend_hash_init(HG(eval_whitelist), 5, NULL, NULL, 1);
+
+ val = zend_str_tolower_dup(new_value, strlen(new_value));
+ e = val;
+
+ while (*e) {
+ switch (*e) {
+ case ' ':
+ case ',':
+ if (s) {
+ *e = '\0';
+ zend_hash_add(HG(eval_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
+ s = NULL;
+ }
+ break;
+ default:
+ if (!s) {
+ s = e;
+ }
+ break;
+ }
+ e++;
+ }
+ if (s) {
+ zend_hash_add(HG(eval_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
+ }
+ efree(val);
+
+ return SUCCESS;
+}
+
+static ZEND_INI_MH(OnUpdateHPHP_eval_blacklist)
+{
+ char *s = NULL, *e, *val;
+ unsigned long dummy = 1;
+
+ if (!new_value) {
+eval_blacklist_destroy:
+ if (HG(eval_blacklist)) {
+ zend_hash_destroy(HG(eval_blacklist));
+ pefree(HG(eval_blacklist), 1);
+ }
+ HG(eval_blacklist) = NULL;
+ return SUCCESS;
+ }
+ if (!(*new_value)) {
+ goto eval_blacklist_destroy;
+ }
+
+ HG(eval_blacklist) = pemalloc(sizeof(HashTable), 1);
+ zend_hash_init(HG(eval_blacklist), 5, NULL, NULL, 1);
+
+ val = zend_str_tolower_dup(new_value, strlen(new_value));
+ e = val;
+
+ while (*e) {
+ switch (*e) {
+ case ' ':
+ case ',':
+ if (s) {
+ *e = '\0';
+ zend_hash_add(HG(eval_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
+ s = NULL;
+ }
+ break;
+ default:
+ if (!s) {
+ s = e;
+ }
+ break;
+ }
+ e++;
+ }
+ if (s) {
+ zend_hash_add(HG(eval_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
+ }
+ efree(val);
+
+
+ return SUCCESS;
+}
+
+static ZEND_INI_MH(OnUpdateHPHP_func_whitelist)
+{
+ char *s = NULL, *e, *val;
+ unsigned long dummy = 1;
+
+ if (!new_value) {
+func_whitelist_destroy:
+ if (HG(func_whitelist)) {
+ zend_hash_destroy(HG(func_whitelist));
+ pefree(HG(func_whitelist),1);
+ }
+ HG(func_whitelist) = NULL;
+ return SUCCESS;
+ }
+ if (!(*new_value)) {
+ goto func_whitelist_destroy;
+ }
+
+ HG(func_whitelist) = pemalloc(sizeof(HashTable), 1);
+ zend_hash_init(HG(func_whitelist), 5, NULL, NULL, 1);
+
+ val = zend_str_tolower_dup(new_value, strlen(new_value));
+ e = val;
+
+ while (*e) {
+ switch (*e) {
+ case ' ':
+ case ',':
+ if (s) {
+ *e = '\0';
+ zend_hash_add(HG(func_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
+ s = NULL;
+ }
+ break;
+ default:
+ if (!s) {
+ s = e;
+ }
+ break;
+ }
+ e++;
+ }
+ if (s) {
+ zend_hash_add(HG(func_whitelist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
+ }
+ efree(val);
+
+ return SUCCESS;
+}
+
+static ZEND_INI_MH(OnUpdateHPHP_func_blacklist)
+{
+ char *s = NULL, *e, *val;
+ unsigned long dummy = 1;
+
+ if (!new_value) {
+func_blacklist_destroy:
+ if (HG(func_blacklist)) {
+ zend_hash_destroy(HG(func_blacklist));
+ pefree(HG(func_blacklist),1);
+ }
+ HG(func_blacklist) = NULL;
+ return SUCCESS;
+ }
+ if (!(*new_value)) {
+ goto func_blacklist_destroy;
+ }
+
+ HG(func_blacklist) = pemalloc(sizeof(HashTable), 1);
+ zend_hash_init(HG(func_blacklist), 5, NULL, NULL, 1);
+
+ val = zend_str_tolower_dup(new_value, strlen(new_value));
+ e = val;
+
+ while (*e) {
+ switch (*e) {
+ case ' ':
+ case ',':
+ if (s) {
+ *e = '\0';
+ zend_hash_add(HG(func_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
+ s = NULL;
+ }
+ break;
+ default:
+ if (!s) {
+ s = e;
+ }
+ break;
+ }
+ e++;
+ }
+ if (s) {
+ zend_hash_add(HG(func_blacklist), s, e-s+1, &dummy, sizeof(unsigned long), NULL);
+ }
+ efree(val);
+
+
+ return SUCCESS;
+}
+
+#endif
ZEND_INI_BEGIN()
ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
+#if HARDENING_PATCH
+ ZEND_INI_ENTRY("hphp.log.syslog", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog)
+ ZEND_INI_ENTRY("hphp.log.syslog.facility", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_facility)
+ ZEND_INI_ENTRY("hphp.log.syslog.priority", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_syslog_priority)
+ ZEND_INI_ENTRY("hphp.log.sapi", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_sapi)
+ ZEND_INI_ENTRY("hphp.log.script", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_script)
+ ZEND_INI_ENTRY("hphp.log.script.name", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_log_scriptname)
+ STD_ZEND_INI_BOOLEAN("hphp.log.use-x-forwarded-for", "0", ZEND_INI_SYSTEM, OnUpdateBool, hphp_log_use_x_forwarded_for, zend_executor_globals, executor_globals)
+
+ ZEND_INI_ENTRY("hphp.executor.include.whitelist", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_include_whitelist)
+ ZEND_INI_ENTRY("hphp.executor.include.blacklist", NULL, ZEND_INI_SYSTEM, OnUpdateHPHP_include_blacklist)
+ ZEND_INI_ENTRY("hphp.executor.eval.whitelist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateHPHP_eval_whitelist)
+ ZEND_INI_ENTRY("hphp.executor.eval.blacklist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateHPHP_eval_blacklist)
+ ZEND_INI_ENTRY("hphp.executor.func.whitelist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateHPHP_func_whitelist)
+ ZEND_INI_ENTRY("hphp.executor.func.blacklist", NULL, ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateHPHP_func_blacklist)
+
+ STD_ZEND_INI_ENTRY("hphp.executor.max_depth", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateLong, hphp_executor_max_depth, zend_executor_globals, executor_globals)
+ STD_ZEND_INI_BOOLEAN("hphp.sql.bailout_on_error", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, hphp_sql_bailout_on_error, hardened_globals_struct, hardened_globals)
+ STD_ZEND_INI_BOOLEAN("hphp.multiheader", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateBool, hphp_multiheader, hardened_globals_struct, hardened_globals)
+ STD_ZEND_INI_ENTRY("hphp.mail.protect", "0", ZEND_INI_PERDIR|ZEND_INI_SYSTEM, OnUpdateLong, hphp_mailprotect, hardened_globals_struct, hardened_globals)
+#endif
STD_ZEND_INI_BOOLEAN("zend.ze1_compatibility_mode", "0", ZEND_INI_ALL, OnUpdateBool, ze1_compatibility_mode, zend_executor_globals, executor_globals)
#ifdef ZEND_MULTIBYTE
STD_ZEND_INI_BOOLEAN("detect_unicode", "1", ZEND_INI_ALL, OnUpdateBool, detect_unicode, zend_compiler_globals, compiler_globals)
@@ -501,9 +889,13 @@
EG(user_error_handler) = NULL;
EG(user_exception_handler) = NULL;
EG(in_execution) = 0;
+ EG(in_code_type) = 0;
EG(in_autoload) = NULL;
EG(current_execute_data) = NULL;
EG(current_module) = NULL;
+#if HARDENING_PATCH
+ EG(hphp_log_scriptname) = NULL;
+#endif
}
@@ -574,6 +966,14 @@
extern zend_scanner_globals language_scanner_globals;
#endif
+ /* Set up Hardening-Patch utility functions first */
+#if HARDENING_PATCH
+ zend_security_log = utility_functions->security_log_function;
+#endif
+#if HARDENING_PATCH_INC_PROTECT
+ zend_is_valid_include = utility_functions->is_valid_include;
+#endif
+
#ifdef ZTS
ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
#else
@@ -777,6 +1177,7 @@
}
CG(unclean_shutdown) = 1;
CG(in_compilation) = EG(in_execution) = 0;
+ EG(in_code_type) = 0;
EG(current_execute_data) = NULL;
longjmp(EG(bailout), FAILURE);
}
diff -Nura php-5.1.6/Zend/zend_canary.c hardening-patch-5.1.6-0.4.15/Zend/zend_canary.c
--- php-5.1.6/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_canary.c 2006-09-07 19:41:16.000000000 +0200
@@ -0,0 +1,58 @@
+/*
+ +----------------------------------------------------------------------+
+ | Hardening-Patch for PHP |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2004-2005 Stefan Esser |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Stefan Esser <sesser@hardened-php.net> |
+ +----------------------------------------------------------------------+
+ */
+/* $Id: zend_canary.c,v 1.1 2004/11/26 12:45:41 ionic Exp $ */
+
+#include "zend.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
+
+/* will be replaced later with more compatible method */
+ZEND_API unsigned int zend_canary()
+{
+ time_t t;
+ unsigned int canary;
+ int fd;
+
+ fd = open("/dev/urandom", 0);
+ if (fd != -1) {
+ int r = read(fd, &canary, sizeof(canary));
+ close(fd);
+ if (r == sizeof(canary)) {
+ return (canary);
+ }
+ }
+ /* not good but we never want to do this */
+ time(&t);
+ canary = *(unsigned int *)&t + getpid() << 16;
+ return (canary);
+}
+#endif
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff -Nura php-5.1.6/Zend/zend_compile.c hardening-patch-5.1.6-0.4.15/Zend/zend_compile.c
--- php-5.1.6/Zend/zend_compile.c 2006-05-02 17:49:26.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_compile.c 2006-09-07 19:41:16.000000000 +0200
@@ -1093,6 +1093,13 @@
op_array.prototype = NULL;
op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
+#if HARDENING_PATCH
+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
+ op_array.created_by_eval = 1;
+ } else {
+ op_array.created_by_eval = 0;
+ }
+#endif
if (is_method) {
char *short_class_name = CG(active_class_entry)->name;
diff -Nura php-5.1.6/Zend/zend_compile.h hardening-patch-5.1.6-0.4.15/Zend/zend_compile.h
--- php-5.1.6/Zend/zend_compile.h 2006-03-13 12:13:42.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_compile.h 2006-09-07 19:41:16.000000000 +0200
@@ -217,6 +217,9 @@
zend_uint doc_comment_len;
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
+#if HARDENING_PATCH
+ zend_bool created_by_eval;
+#endif
};
@@ -295,6 +298,8 @@
zval ***CVs;
zend_bool original_in_execution;
HashTable *symbol_table;
+ zend_uint original_in_code_type;
+ zend_uint execute_depth;
struct _zend_execute_data *prev_execute_data;
zval *old_error_reporting;
};
@@ -617,6 +622,7 @@
#define ZEND_OVERLOADED_FUNCTION 3
#define ZEND_EVAL_CODE 4
#define ZEND_OVERLOADED_FUNCTION_TEMPORARY 5
+#define ZEND_SANDBOX_CODE 6
#define ZEND_INTERNAL_CLASS 1
#define ZEND_USER_CLASS 2
diff -Nura php-5.1.6/Zend/zend_constants.c hardening-patch-5.1.6-0.4.15/Zend/zend_constants.c
--- php-5.1.6/Zend/zend_constants.c 2006-03-15 15:12:26.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_constants.c 2006-09-07 19:41:16.000000000 +0200
@@ -109,6 +109,74 @@
REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
+#if HARDENING_PATCH
+ REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_FILES, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("S_MAIL", S_MAIL, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("S_INTERNAL", S_INTERNAL, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS);
+
+ /* error levels */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRIT", LOG_CRIT, CONST_CS | CONST_PERSISTENT); /* critical conditions */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_ERR", LOG_ERR, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_WARNING", LOG_WARNING, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOTICE", LOG_NOTICE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_INFO", LOG_INFO, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_DEBUG", LOG_DEBUG, CONST_CS | CONST_PERSISTENT);
+ /* facility: type of program logging the message */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_KERN", LOG_KERN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_USER", LOG_USER, CONST_CS | CONST_PERSISTENT); /* generic user level */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_MAIL", LOG_MAIL, CONST_CS | CONST_PERSISTENT); /* log to email */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_DAEMON", LOG_DAEMON, CONST_CS | CONST_PERSISTENT); /* other system daemons */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTH", LOG_AUTH, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_SYSLOG", LOG_SYSLOG, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_LPR", LOG_LPR, CONST_CS | CONST_PERSISTENT);
+#ifdef LOG_NEWS
+ /* No LOG_NEWS on HP-UX */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_NEWS", LOG_NEWS, CONST_CS | CONST_PERSISTENT); /* usenet new */
+#endif
+#ifdef LOG_UUCP
+ /* No LOG_UUCP on HP-UX */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_UUCP", LOG_UUCP, CONST_CS | CONST_PERSISTENT);
+#endif
+#ifdef LOG_CRON
+ /* apparently some systems don't have this one */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_CRON", LOG_CRON, CONST_CS | CONST_PERSISTENT);
+#endif
+#ifdef LOG_AUTHPRIV
+ /* AIX doesn't have LOG_AUTHPRIV */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT);
+#endif
+#if !defined(PHP_WIN32) && !defined(NETWARE)
+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL3", LOG_LOCAL3, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL4", LOG_LOCAL4, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL5", LOG_LOCAL5, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL6", LOG_LOCAL6, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL7", LOG_LOCAL7, CONST_CS | CONST_PERSISTENT);
+#endif
+ /* options */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_PID", LOG_PID, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_CONS", LOG_CONS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_ODELAY", LOG_ODELAY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_MAIN_LONG_CONSTANT("LOG_NDELAY", LOG_NDELAY, CONST_CS | CONST_PERSISTENT);
+#ifdef LOG_NOWAIT
+ REGISTER_MAIN_LONG_CONSTANT("LOG_NOWAIT", LOG_NOWAIT, CONST_CS | CONST_PERSISTENT);
+#endif
+#ifdef LOG_PERROR
+ /* AIX doesn't have LOG_PERROR */
+ REGISTER_MAIN_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/
+#endif
+#endif
/* true/false constants */
{
diff -Nura php-5.1.6/Zend/zend_errors.h hardening-patch-5.1.6-0.4.15/Zend/zend_errors.h
--- php-5.1.6/Zend/zend_errors.h 2006-01-05 00:53:04.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_errors.h 2006-09-07 19:41:16.000000000 +0200
@@ -38,6 +38,19 @@
#define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE)
#define E_CORE (E_CORE_ERROR | E_CORE_WARNING)
+#if HARDENING_PATCH
+#define S_MEMORY (1<<0L)
+#define S_VARS (1<<1L)
+#define S_FILES (1<<2L)
+#define S_INCLUDE (1<<3L)
+#define S_SQL (1<<4L)
+#define S_EXECUTOR (1<<5L)
+#define S_MAIL (1<<6L)
+#define S_MISC (1<<30L)
+#define S_INTERNAL (1<<29L)
+#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MAIL | S_MISC | S_SQL | S_EXECUTOR)
+#endif
+
#endif /* ZEND_ERRORS_H */
/*
diff -Nura php-5.1.6/Zend/zend_execute_API.c hardening-patch-5.1.6-0.4.15/Zend/zend_execute_API.c
--- php-5.1.6/Zend/zend_execute_API.c 2006-04-21 00:49:20.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_execute_API.c 2006-09-07 19:41:16.000000000 +0200
@@ -142,6 +142,7 @@
EG(class_table) = CG(class_table);
EG(in_execution) = 0;
+ EG(in_code_type) = 0;
EG(in_autoload) = NULL;
EG(autoload_func) = NULL;
@@ -784,6 +785,39 @@
if (zend_hash_find(fci->function_table, function_name_lc, fname_len+1, (void **) &EX(function_state).function)==FAILURE) {
EX(function_state).function = NULL;
}
+#if HARDENING_PATCH
+ else {
+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
+ if (HG(eval_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(eval_whitelist), function_name_lc, fci->function_name->value.str.len+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", function_name_lc);
+ efree(function_name_lc);
+ zend_bailout();
+ }
+ } else if (HG(eval_blacklist) != NULL) {
+ if (zend_hash_exists(HG(eval_blacklist), function_name_lc, fci->function_name->value.str.len+1)) {
+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", function_name_lc);
+ efree(function_name_lc);
+ zend_bailout();
+ }
+ }
+ }
+
+ if (HG(func_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(func_whitelist), function_name_lc, fci->function_name->value.str.len+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", function_name_lc);
+ efree(function_name_lc);
+ zend_bailout();
+ }
+ } else if (HG(func_blacklist) != NULL) {
+ if (zend_hash_exists(HG(func_blacklist), function_name_lc, fci->function_name->value.str.len+1)) {
+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", function_name_lc);
+ efree(function_name_lc);
+ zend_bailout();
+ }
+ }
+ }
+#endif
efree(function_name_lc);
}
@@ -1076,7 +1110,7 @@
return zend_lookup_class_ex(name, name_length, 1, ce TSRMLS_CC);
}
-ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
+ZEND_API int zend_eval_string_ex_ex(char *str, zval *retval_ptr, char *string_name, int type TSRMLS_DC)
{
zval pv;
zend_op_array *new_op_array;
@@ -1109,6 +1143,7 @@
zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr);
zend_op **original_opline_ptr = EG(opline_ptr);
+ new_op_array->type = type;
EG(return_value_ptr_ptr) = &local_retval_ptr;
EG(active_op_array) = new_op_array;
EG(no_extensions)=1;
@@ -1143,6 +1178,12 @@
}
+ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
+{
+ return (zend_eval_string_ex_ex(str, retval_ptr, string_name, ZEND_EVAL_CODE TSRMLS_CC));
+}
+
+
ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC)
{
int result;
diff -Nura php-5.1.6/Zend/zend_execute.c hardening-patch-5.1.6-0.4.15/Zend/zend_execute.c
--- php-5.1.6/Zend/zend_execute.c 2006-02-26 11:53:38.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_execute.c 2006-09-07 19:41:16.000000000 +0200
@@ -1351,6 +1351,37 @@
/* OBJ-TBI - doesn't support new object model! */
zend_hash_apply(Z_OBJPROP_PP(pz), (apply_func_t) zend_check_symbol TSRMLS_CC);
}
+#if HARDENING_PATCH
+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
+ if (HG(eval_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(eval_whitelist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ } else if (HG(eval_blacklist) != NULL) {
+ if (zend_hash_exists(HG(eval_blacklist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ }
+ }
+
+ if (HG(func_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(func_whitelist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ } else if (HG(func_blacklist) != NULL) {
+ if (zend_hash_exists(HG(func_blacklist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ }
+#endif
return 0;
}
@@ -1396,6 +1427,7 @@
efree(EX(Ts)); \
} \
EG(in_execution) = EX(original_in_execution); \
+ EG(in_code_type) = EX(original_in_code_type); \
EG(current_execute_data) = EX(prev_execute_data); \
ZEND_VM_RETURN()
diff -Nura php-5.1.6/Zend/zend_extensions.c hardening-patch-5.1.6-0.4.15/Zend/zend_extensions.c
--- php-5.1.6/Zend/zend_extensions.c 2006-01-05 00:53:04.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_extensions.c 2006-09-07 19:41:16.000000000 +0200
@@ -55,23 +55,44 @@
return FAILURE;
}
+ /* check if module is compiled against Hardening-Patch */
+ if (extension_version_info->zend_extension_api_no < 1000000000) {
+ fprintf(stderr, "%s is not compiled with Hardening-Patch.\n"
+ "The Hardening-Patch version %d is installed.\n\n",
+ new_extension->name,
+ HARDENING_PATCH_ZEND_EXTENSION_API_NO);
+ DL_UNLOAD(handle);
+ return FAILURE;
+ }
+
+
+ /* check if module is compiled against correct Hardening-Patch version */
+ if (extension_version_info->zend_extension_api_no != HARDENING_PATCH_ZEND_EXTENSION_API_NO) {
+ fprintf(stderr, "%s requires Hardening-Patch version %d.\n"
+ "The Hardening-Patch version %d is installed.\n\n",
+ new_extension->name,
+ extension_version_info->zend_extension_api_no,
+ HARDENING_PATCH_ZEND_EXTENSION_API_NO);
+ DL_UNLOAD(handle);
+ return FAILURE;
+ }
/* allow extension to proclaim compatibility with any Zend version */
- if (extension_version_info->zend_extension_api_no != ZEND_EXTENSION_API_NO &&(!new_extension->api_no_check || new_extension->api_no_check(ZEND_EXTENSION_API_NO) != SUCCESS)) {
- if (extension_version_info->zend_extension_api_no > ZEND_EXTENSION_API_NO) {
+ if (extension_version_info->real_zend_extension_api_no != ZEND_EXTENSION_API_NO &&(!new_extension->api_no_check || new_extension->api_no_check(ZEND_EXTENSION_API_NO) != SUCCESS)) {
+ if (extension_version_info->real_zend_extension_api_no > ZEND_EXTENSION_API_NO) {
fprintf(stderr, "%s requires Zend Engine API version %d.\n"
"The Zend Engine API version %d which is installed, is outdated.\n\n",
new_extension->name,
- extension_version_info->zend_extension_api_no,
+ extension_version_info->real_zend_extension_api_no,
ZEND_EXTENSION_API_NO);
DL_UNLOAD(handle);
return FAILURE;
- } else if (extension_version_info->zend_extension_api_no < ZEND_EXTENSION_API_NO) {
+ } else if (extension_version_info->real_zend_extension_api_no < ZEND_EXTENSION_API_NO) {
fprintf(stderr, "%s requires Zend Engine API version %d.\n"
"The Zend Engine API version %d which is installed, is newer.\n"
"Contact %s at %s for a later version of %s.\n\n",
new_extension->name,
- extension_version_info->zend_extension_api_no,
+ extension_version_info->real_zend_extension_api_no,
ZEND_EXTENSION_API_NO,
new_extension->author,
new_extension->URL,
diff -Nura php-5.1.6/Zend/zend_extensions.h hardening-patch-5.1.6-0.4.15/Zend/zend_extensions.h
--- php-5.1.6/Zend/zend_extensions.h 2006-01-05 00:53:04.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_extensions.h 2006-09-07 19:41:16.000000000 +0200
@@ -24,9 +24,11 @@
#include "zend_compile.h"
-/* The first number is the engine version and the rest is the date.
+/* The first API number is a flag saying that Hardening-Patch is used.
+ * The second number is the engine version and the date.
* This way engine 2 API no. is always greater than engine 1 API no..
*/
+#define HARDENING_PATCH_ZEND_EXTENSION_API_NO 1022051106
#define ZEND_EXTENSION_API_NO 220051025
typedef struct _zend_extension_version_info {
@@ -34,6 +36,7 @@
char *required_zend_version;
unsigned char thread_safe;
unsigned char debug;
+ int real_zend_extension_api_no;
} zend_extension_version_info;
@@ -101,7 +104,7 @@
#define ZEND_EXTENSION() \
- ZEND_EXT_API zend_extension_version_info extension_version_info = { ZEND_EXTENSION_API_NO, ZEND_VERSION, ZTS_V, ZEND_DEBUG }
+ ZEND_EXT_API zend_extension_version_info extension_version_info = { HARDENING_PATCH_ZEND_EXTENSION_API_NO, ZEND_VERSION, ZTS_V, ZEND_DEBUG, ZEND_EXTENSION_API_NO }
#define STANDARD_ZEND_EXTENSION_PROPERTIES NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1
#define COMPAT_ZEND_EXTENSION_PROPERTIES NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1
diff -Nura php-5.1.6/Zend/zend_globals.h hardening-patch-5.1.6-0.4.15/Zend/zend_globals.h
--- php-5.1.6/Zend/zend_globals.h 2006-01-05 00:53:04.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_globals.h 2006-09-07 19:41:16.000000000 +0200
@@ -180,6 +180,16 @@
int error_reporting;
int orig_error_reporting;
+#if HARDENING_PATCH
+ int hphp_log_syslog;
+ int hphp_log_syslog_facility;
+ int hphp_log_syslog_priority;
+ int hphp_log_sapi;
+ int hphp_log_script;
+ char *hphp_log_scriptname;
+ zend_bool hphp_log_use_x_forwarded_for;
+ long hphp_executor_max_depth;
+#endif
int exit_status;
zend_op_array *active_op_array;
@@ -197,6 +207,7 @@
int ticks_count;
zend_bool in_execution;
+ zend_uint in_code_type;
HashTable *in_autoload;
zend_function *autoload_func;
zend_bool bailout_set;
diff -Nura php-5.1.6/Zend/zend.h hardening-patch-5.1.6-0.4.15/Zend/zend.h
--- php-5.1.6/Zend/zend.h 2006-03-30 23:39:01.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend.h 2006-09-07 19:41:16.000000000 +0200
@@ -297,6 +297,7 @@
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount;
+ zend_ushort flags;
zend_uchar type; /* active type */
zend_uchar is_ref;
};
@@ -382,6 +383,12 @@
int (*stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
int (*vspprintf_function)(char **pbuf, size_t max_len, const char *format, va_list ap);
char *(*getenv_function)(char *name, size_t name_len TSRMLS_DC);
+#if HARDENING_PATCH
+ void (*security_log_function)(int loglevel, char *fmt, ...);
+#endif
+#if HARDENING_PATCH_INC_PROTECT
+ int (*is_valid_include)(zval *z);
+#endif
} zend_utility_functions;
@@ -519,7 +526,16 @@
extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
+#if HARDENING_PATCH
+extern ZEND_API void (*zend_security_log)(int loglevel, char *fmt, ...);
+#endif
+#if HARDENING_PATCH_INC_PROTECT
+extern ZEND_API int (*zend_is_valid_include)(zval *z);
+#endif
+#if HARDENING_PATCH_MM_PROTECT || HARDENING_PATCH_LL_PROTECT || HARDENING_PATCH_HASH_PROTECT
+ZEND_API unsigned int zend_canary(void);
+#endif
ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
@@ -644,6 +660,11 @@
#include "zend_variables.h"
+#if HARDENING_PATCH
+#include "hardened_globals.h"
+#include "php_syslog.h"
+#endif
+
#endif /* ZEND_H */
/*
diff -Nura php-5.1.6/Zend/zend_hash.c hardening-patch-5.1.6-0.4.15/Zend/zend_hash.c
--- php-5.1.6/Zend/zend_hash.c 2006-04-07 12:06:21.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_hash.c 2006-09-07 19:41:16.000000000 +0200
@@ -21,6 +21,18 @@
#include "zend.h"
+#if HARDENING_PATCH_HASH_PROTECT
+ unsigned int zend_hash_canary = 0x1234567;
+ zend_bool zend_hash_canary_inited = 0;
+#endif
+
+#define CHECK_HASH_CANARY(hash) \
+ if (zend_hash_canary != (hash)->canary) { \
+ zend_security_log(S_MEMORY, "Zend HashTable canary was overwritten"); \
+ exit(1); \
+ }
+
+
#define CONNECT_TO_BUCKET_DLLIST(element, list_head) \
(element)->pNext = (list_head); \
(element)->pLast = NULL; \
@@ -138,6 +150,9 @@
{
uint i = 3;
Bucket **tmp;
+#if HARDENING_PATCH_HASH_PROTECT
+ TSRMLS_FETCH();
+#endif
SET_INCONSISTENT(HT_OK);
@@ -147,6 +162,13 @@
ht->nTableSize = 1 << i;
ht->nTableMask = ht->nTableSize - 1;
+#if HARDENING_PATCH_HASH_PROTECT
+ if (zend_hash_canary_inited==0) {
+ zend_hash_canary = zend_canary();
+ zend_hash_canary_inited = 1;
+ }
+ ht->canary = zend_hash_canary;
+#endif
ht->pDestructor = pDestructor;
ht->arBuckets = NULL;
ht->pListHead = NULL;
@@ -226,6 +248,9 @@
}
#endif
if (ht->pDestructor) {
+#if HARDENING_PATCH_HASH_PROTECT
+ CHECK_HASH_CANARY(ht);
+#endif
ht->pDestructor(p->pData);
}
UPDATE_DATA(ht, p, pData, nDataSize);
@@ -291,6 +316,9 @@
}
#endif
if (ht->pDestructor) {
+#if HARDENING_PATCH_HASH_PROTECT
+ CHECK_HASH_CANARY(ht);
+#endif
ht->pDestructor(p->pData);
}
UPDATE_DATA(ht, p, pData, nDataSize);
@@ -366,6 +394,9 @@
}
#endif
if (ht->pDestructor) {
+#if HARDENING_PATCH_HASH_PROTECT
+ CHECK_HASH_CANARY(ht);
+#endif
ht->pDestructor(p->pData);
}
UPDATE_DATA(ht, p, pData, nDataSize);
@@ -414,7 +445,7 @@
IS_CONSISTENT(ht);
if ((ht->nTableSize << 1) > 0) { /* Let's double the table size */
- t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
+ t = (Bucket **) perealloc(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
if (t) {
HANDLE_BLOCK_INTERRUPTIONS();
ht->arBuckets = t;
@@ -424,6 +455,7 @@
HANDLE_UNBLOCK_INTERRUPTIONS();
return SUCCESS;
}
+ zend_error(E_ERROR, "zend_hash_do_resize - out of memory");
return FAILURE;
}
return SUCCESS;
@@ -489,6 +521,9 @@
ht->pInternalPointer = p->pListNext;
}
if (ht->pDestructor) {
+#if HARDENING_PATCH_HASH_PROTECT
+ CHECK_HASH_CANARY(ht);
+#endif
ht->pDestructor(p->pData);
}
if (p->pData != &p->pDataPtr) {
@@ -513,6 +548,11 @@
SET_INCONSISTENT(HT_IS_DESTROYING);
+#if HARDENING_PATCH_HASH_PROTECT
+ if (ht->pDestructor) {
+ CHECK_HASH_CANARY(ht);
+ }
+#endif
p = ht->pListHead;
while (p != NULL) {
q = p;
@@ -539,6 +579,11 @@
SET_INCONSISTENT(HT_CLEANING);
+#if HARDENING_PATCH_HASH_PROTECT
+ if (ht->pDestructor) {
+ CHECK_HASH_CANARY(ht);
+ }
+#endif
p = ht->pListHead;
while (p != NULL) {
q = p;
@@ -573,6 +618,9 @@
HANDLE_BLOCK_INTERRUPTIONS();
if (ht->pDestructor) {
+#if HARDENING_PATCH_HASH_PROTECT
+ CHECK_HASH_CANARY(ht);
+#endif
ht->pDestructor(p->pData);
}
if (p->pData != &p->pDataPtr) {
diff -Nura php-5.1.6/Zend/zend_hash.h hardening-patch-5.1.6-0.4.15/Zend/zend_hash.h
--- php-5.1.6/Zend/zend_hash.h 2006-01-05 00:53:04.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_hash.h 2006-09-07 19:41:16.000000000 +0200
@@ -58,6 +58,9 @@
} Bucket;
typedef struct _hashtable {
+#if HARDENING_PATCH_HASH_PROTECT
+ unsigned int canary;
+#endif
uint nTableSize;
uint nTableMask;
uint nNumOfElements;
diff -Nura php-5.1.6/Zend/zend_ini.c hardening-patch-5.1.6-0.4.15/Zend/zend_ini.c
--- php-5.1.6/Zend/zend_ini.c 2006-01-05 00:53:04.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_ini.c 2006-09-07 19:41:16.000000000 +0200
@@ -256,7 +256,8 @@
zend_ini_entry *ini_entry;
TSRMLS_FETCH();
- if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==FAILURE) {
+ if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==FAILURE ||
+ (stage == ZEND_INI_STAGE_RUNTIME && (ini_entry->modifiable & ZEND_INI_USER) == 0)) {
return FAILURE;
}
diff -Nura php-5.1.6/Zend/zend_language_scanner.l hardening-patch-5.1.6-0.4.15/Zend/zend_language_scanner.l
--- php-5.1.6/Zend/zend_language_scanner.l 2006-04-13 15:48:28.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_language_scanner.l 2006-09-07 19:41:16.000000000 +0200
@@ -389,6 +389,13 @@
compilation_successful=0;
} else {
init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
+#if HARDENING_PATCH
+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
+ op_array->created_by_eval = 1;
+ } else {
+ op_array->created_by_eval = 0;
+ }
+#endif
CG(in_compilation) = 1;
CG(active_op_array) = op_array;
compiler_result = zendparse(TSRMLS_C);
diff -Nura php-5.1.6/Zend/zend_language_scanner.c hardening-patch-5.1.6-0.4.15/Zend/zend_language_scanner.c
--- php-5.1.6/Zend/zend_language_scanner.c 2006-08-23 14:55:05.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_language_scanner.c 2006-09-07 19:41:16.000000000 +0200
@@ -3075,6 +3075,13 @@
compilation_successful=0;
} else {
init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
+#if HARDENING_PATCH
+ if (EG(in_code_type)==ZEND_EVAL_CODE) {
+ op_array->created_by_eval = 1;
+ } else {
+ op_array->created_by_eval = 0;
+ }
+#endif
CG(in_compilation) = 1;
CG(active_op_array) = op_array;
compiler_result = zendparse(TSRMLS_C);
diff -Nura php-5.1.6/Zend/zend_llist.c hardening-patch-5.1.6-0.4.15/Zend/zend_llist.c
--- php-5.1.6/Zend/zend_llist.c 2006-01-05 00:53:04.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_llist.c 2006-09-07 19:41:16.000000000 +0200
@@ -22,9 +22,49 @@
#include "zend.h"
#include "zend_llist.h"
#include "zend_qsort.h"
+#include "zend_globals.h"
+
+#if HARDENING_PATCH_LL_PROTECT
+ unsigned int zend_llist_canary_1 = 0x1234567;
+ unsigned int zend_llist_canary_2 = 0x1553425;
+ zend_bool zend_llist_canary_inited = 0;
+#endif
+
+#define CHECK_LIST_CANARY(list) \
+ if (((list)->persistent && (zend_llist_canary_1 != (list)->canary_h || zend_llist_canary_2 != (list)->canary_t)) \
+ ||(!(list)->persistent && (HG(canary_3) != (list)->canary_h || HG(canary_4) != (list)->canary_t))) { \
+ zend_security_log(S_MEMORY, "linked list canary was overwritten"); \
+ exit(1); \
+ }
+
+#define CHECK_LISTELEMENT_CANARY(elem, list) \
+ if (((list)->persistent && zend_llist_canary_1 != (elem)->canary)||(!(list)->persistent && HG(canary_3) != (elem)->canary)) { \
+ zend_security_log(S_MEMORY, "linked list element canary was overwritten"); \
+ exit(1); \
+ }
+
ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
{
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+
+ if (persistent) {
+ if (!zend_llist_canary_inited) {
+ /* do not change order to ensure thread safety */
+ zend_llist_canary_1 = zend_canary();
+ zend_llist_canary_2 = zend_canary();
+ zend_llist_canary_inited = 1;
+ }
+ } else
+ if (!HG(ll_canary_inited)) {
+ HG(canary_3) = zend_canary();
+ HG(canary_4) = zend_canary();
+ HG(ll_canary_inited) = 1;
+ }
+ l->canary_h = persistent ? zend_llist_canary_1 : HG(canary_3);
+ l->canary_t = persistent ? zend_llist_canary_2 : HG(canary_4);
+#endif
l->head = NULL;
l->tail = NULL;
l->count = 0;
@@ -38,6 +78,11 @@
{
zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+ CHECK_LIST_CANARY(l)
+ tmp->canary = l->persistent ? zend_llist_canary_1 : HG(canary_3);
+#endif
tmp->prev = l->tail;
tmp->next = NULL;
if (l->tail) {
@@ -56,6 +101,11 @@
{
zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+ CHECK_LIST_CANARY(l)
+ tmp->canary = l->persistent ? zend_llist_canary_1 : HG(canary_3);
+#endif
tmp->next = l->head;
tmp->prev = NULL;
if (l->head) {
@@ -93,10 +143,20 @@
zend_llist_element *current=l->head;
zend_llist_element *next;
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+ CHECK_LIST_CANARY(l)
+#endif
while (current) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(current, l)
+#endif
next = current->next;
if (compare(current->data, element)) {
DEL_LLIST_ELEMENT(current, l);
+#if HARDENING_PATCH_LL_PROTECT
+ current->canary = 0;
+#endif
break;
}
current = next;
@@ -108,7 +168,14 @@
{
zend_llist_element *current=l->head, *next;
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+ CHECK_LIST_CANARY(l)
+#endif
while (current) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(current, l)
+#endif
next = current->next;
if (l->dtor) {
l->dtor(current->data);
@@ -133,7 +200,14 @@
zend_llist_element *old_tail;
void *data;
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+ CHECK_LIST_CANARY(l)
+#endif
if ((old_tail = l->tail)) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(old_tail, l)
+#endif
if (l->tail->prev) {
l->tail->prev->next = NULL;
}
@@ -159,9 +233,16 @@
{
zend_llist_element *ptr;
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+ CHECK_LIST_CANARY(src)
+#endif
zend_llist_init(dst, src->size, src->dtor, src->persistent);
ptr = src->head;
while (ptr) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(ptr, src)
+#endif
zend_llist_add_element(dst, ptr->data);
ptr = ptr->next;
}
@@ -172,11 +253,21 @@
{
zend_llist_element *element, *next;
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+ CHECK_LIST_CANARY(l)
+#endif
element=l->head;
while (element) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(element, l)
+#endif
next = element->next;
if (func(element->data)) {
DEL_LLIST_ELEMENT(element, l);
+#if HARDENING_PATCH_LL_PROTECT
+ element->canary = 0;
+#endif
}
element = next;
}
@@ -187,7 +278,13 @@
{
zend_llist_element *element;
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LIST_CANARY(l)
+#endif
for (element=l->head; element; element=element->next) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(element, l)
+#endif
func(element->data TSRMLS_CC);
}
}
@@ -199,6 +296,9 @@
zend_llist_element **elements;
zend_llist_element *element, **ptr;
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LIST_CANARY(l)
+#endif
if (l->count <= 0) {
return;
}
@@ -208,6 +308,9 @@
ptr = &elements[0];
for (element=l->head; element; element=element->next) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(element, l)
+#endif
*ptr++ = element;
}
@@ -230,7 +333,13 @@
{
zend_llist_element *element;
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LIST_CANARY(l)
+#endif
for (element=l->head; element; element=element->next) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(element, l)
+#endif
func(element->data, arg TSRMLS_CC);
}
}
@@ -241,8 +350,14 @@
zend_llist_element *element;
va_list args;
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LIST_CANARY(l)
+#endif
va_start(args, num_args);
for (element=l->head; element; element=element->next) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(element, l)
+#endif
func(element->data, num_args, args TSRMLS_CC);
}
va_end(args);
@@ -251,6 +366,10 @@
ZEND_API int zend_llist_count(zend_llist *l)
{
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+ CHECK_LIST_CANARY(l)
+#endif
return l->count;
}
@@ -259,8 +378,15 @@
{
zend_llist_position *current = pos ? pos : &l->traverse_ptr;
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+ CHECK_LIST_CANARY(l)
+#endif
*current = l->head;
if (*current) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(*current, l)
+#endif
return (*current)->data;
} else {
return NULL;
@@ -272,8 +398,15 @@
{
zend_llist_position *current = pos ? pos : &l->traverse_ptr;
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+ CHECK_LIST_CANARY(l)
+#endif
*current = l->tail;
if (*current) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(*current, l)
+#endif
return (*current)->data;
} else {
return NULL;
@@ -285,9 +418,19 @@
{
zend_llist_position *current = pos ? pos : &l->traverse_ptr;
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+ CHECK_LIST_CANARY(l)
+#endif
if (*current) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(*current, l)
+#endif
*current = (*current)->next;
if (*current) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(*current, l)
+#endif
return (*current)->data;
}
}
@@ -299,9 +442,19 @@
{
zend_llist_position *current = pos ? pos : &l->traverse_ptr;
+#if HARDENING_PATCH_LL_PROTECT
+ TSRMLS_FETCH();
+ CHECK_LIST_CANARY(l)
+#endif
if (*current) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(*current, l)
+#endif
*current = (*current)->prev;
if (*current) {
+#if HARDENING_PATCH_LL_PROTECT
+ CHECK_LISTELEMENT_CANARY(*current, l)
+#endif
return (*current)->data;
}
}
diff -Nura php-5.1.6/Zend/zend_llist.h hardening-patch-5.1.6-0.4.15/Zend/zend_llist.h
--- php-5.1.6/Zend/zend_llist.h 2006-01-05 00:53:04.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_llist.h 2006-09-07 19:41:16.000000000 +0200
@@ -23,6 +23,9 @@
#define ZEND_LLIST_H
typedef struct _zend_llist_element {
+#if HARDENING_PATCH_LL_PROTECT
+ unsigned int canary, padding;
+#endif
struct _zend_llist_element *next;
struct _zend_llist_element *prev;
char data[1]; /* Needs to always be last in the struct */
@@ -35,6 +38,9 @@
typedef void (*llist_apply_func_t)(void * TSRMLS_DC);
typedef struct _zend_llist {
+#if HARDENING_PATCH_LL_PROTECT
+ unsigned int canary_h; /* head */
+#endif
zend_llist_element *head;
zend_llist_element *tail;
size_t count;
@@ -42,6 +48,9 @@
llist_dtor_func_t dtor;
unsigned char persistent;
zend_llist_element *traverse_ptr;
+#if HARDENING_PATCH_LL_PROTECT
+ unsigned int canary_t; /* tail */
+#endif
} zend_llist;
typedef zend_llist_element* zend_llist_position;
diff -Nura php-5.1.6/Zend/zend_modules.h hardening-patch-5.1.6-0.4.15/Zend/zend_modules.h
--- php-5.1.6/Zend/zend_modules.h 2006-04-06 23:10:45.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_modules.h 2006-09-07 19:41:16.000000000 +0200
@@ -39,6 +39,7 @@
extern struct _zend_arg_info fifth_arg_force_ref[6];
extern struct _zend_arg_info all_args_by_ref[1];
+#define HARDENING_PATCH_ZEND_MODULE_API_NO 1002051106
#define ZEND_MODULE_API_NO 20050922
#ifdef ZTS
#define USING_ZTS 1
@@ -46,13 +47,13 @@
#define USING_ZTS 0
#endif
-#define STANDARD_MODULE_HEADER_EX sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS
+#define STANDARD_MODULE_HEADER_EX sizeof(zend_module_entry), HARDENING_PATCH_ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS
#define STANDARD_MODULE_HEADER \
STANDARD_MODULE_HEADER_EX, NULL, NULL
#define ZE2_STANDARD_MODULE_HEADER \
STANDARD_MODULE_HEADER_EX, ini_entries, NULL
-#define STANDARD_MODULE_PROPERTIES_EX 0, 0, 0, NULL, 0
+#define STANDARD_MODULE_PROPERTIES_EX 0, 0, 0, NULL, 0, ZEND_MODULE_API_NO
#define STANDARD_MODULE_PROPERTIES \
NULL, STANDARD_MODULE_PROPERTIES_EX
@@ -87,6 +88,7 @@
unsigned char type;
void *handle;
int module_number;
+ unsigned int real_zend_api;
};
#define MODULE_DEP_REQUIRED 1
diff -Nura php-5.1.6/Zend/zend_opcode.c hardening-patch-5.1.6-0.4.15/Zend/zend_opcode.c
--- php-5.1.6/Zend/zend_opcode.c 2006-04-10 14:26:53.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_opcode.c 2006-09-07 19:41:16.000000000 +0200
@@ -98,6 +98,9 @@
op_array->uses_this = 0;
op_array->start_op = NULL;
+#if HARDENING_PATCH
+ op_array->created_by_eval = 0;
+#endif
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC);
}
diff -Nura php-5.1.6/Zend/zend_vm_def.h hardening-patch-5.1.6-0.4.15/Zend/zend_vm_def.h
--- php-5.1.6/Zend/zend_vm_def.h 2006-07-06 17:39:23.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_vm_def.h 2006-09-07 19:41:16.000000000 +0200
@@ -1771,6 +1771,37 @@
efree(lcname);
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
}
+#if HARDENING_PATCH
+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
+ if (HG(eval_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(eval_whitelist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ } else if (HG(eval_blacklist) != NULL) {
+ if (zend_hash_exists(HG(eval_blacklist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ }
+ }
+
+ if (HG(func_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(func_whitelist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ } else if (HG(func_blacklist) != NULL) {
+ if (zend_hash_exists(HG(func_blacklist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ }
+#endif
efree(lcname);
if (OP2_TYPE != IS_CONST) {
@@ -1996,6 +2027,34 @@
if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
zend_error_noreturn(E_ERROR, "Unknown function: %s()", fname->value.str.val);
}
+#if HARDENING_PATCH
+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
+ if (HG(eval_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(eval_whitelist), fname->value.str.val, fname->value.str.len+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", fname->value.str.val);
+ zend_bailout();
+ }
+ } else if (HG(eval_blacklist) != NULL) {
+ if (zend_hash_exists(HG(eval_blacklist), fname->value.str.val, fname->value.str.len+1)) {
+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", fname->value.str.val);
+ zend_bailout();
+ }
+ }
+ }
+
+ if (HG(func_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(func_whitelist), fname->value.str.val, fname->value.str.len+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", fname->value.str.val);
+ zend_bailout();
+ }
+ } else if (HG(func_blacklist) != NULL) {
+ if (zend_hash_exists(HG(func_blacklist), fname->value.str.val, fname->value.str.len+1)) {
+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", fname->value.str.val);
+ zend_bailout();
+ }
+ }
+#endif
+
EX(object) = NULL;
FREE_OP1();
@@ -2711,7 +2770,12 @@
int dummy = 1;
zend_file_handle file_handle;
- if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
+#if HARDENING_PATCH_INC_PROTECT
+ if (zend_is_valid_include(inc_filename)
+ && (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC))) {
+#else
+ if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
+#endif
if (!file_handle.opened_path) {
file_handle.opened_path = estrndup(inc_filename->value.str.val, inc_filename->value.str.len);
@@ -2736,6 +2800,11 @@
break;
case ZEND_INCLUDE:
case ZEND_REQUIRE:
+#if HARDENING_PATCH_INC_PROTECT
+ if (!zend_is_valid_include(inc_filename)) {
+ break;
+ }
+#endif
new_op_array = compile_filename(opline->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
break;
case ZEND_EVAL: {
diff -Nura php-5.1.6/Zend/zend_vm_execute.h hardening-patch-5.1.6-0.4.15/Zend/zend_vm_execute.h
--- php-5.1.6/Zend/zend_vm_execute.h 2006-07-06 17:39:23.000000000 +0200
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_vm_execute.h 2006-09-07 19:42:45.000000000 +0200
@@ -56,6 +56,16 @@
EX(symbol_table) = EG(active_symbol_table);
EX(prev_execute_data) = EG(current_execute_data);
EG(current_execute_data) = &execute_data;
+#if HARDENING_PATCH
+ EX(execute_depth) = 0;
+
+ if ((op_array->type == ZEND_EVAL_CODE || op_array->created_by_eval)&& EG(in_code_type) != ZEND_SANDBOX_CODE) {
+ EG(in_code_type) = ZEND_EVAL_CODE;
+ } else if (op_array->type == ZEND_SANDBOX_CODE) {
+ EG(in_code_type) = ZEND_SANDBOX_CODE;
+ op_array->type = ZEND_EVAL_CODE;
+ }
+#endif
EG(in_execution) = 1;
if (op_array->start_op) {
@@ -81,6 +91,18 @@
*/
EX(function_state).function_symbol_table = NULL;
#endif
+#if HARDENING_PATCH
+ if (EX(prev_execute_data) == NULL) {
+ EX(execute_depth) = 0;
+ } else {
+ EX(execute_depth) = EX(prev_execute_data)->execute_depth + 1;
+ }
+
+ if (EG(hphp_executor_max_depth) > 0 && EX(execute_depth) > EG(hphp_executor_max_depth)) {
+ zend_security_log(S_EXECUTOR, "Maximum execution depth of %u violated", EG(hphp_executor_max_depth));
+ zend_bailout();
+ }
+#endif
while (1) {
#ifdef ZEND_WIN32
@@ -724,6 +746,37 @@
efree(lcname);
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
}
+#if HARDENING_PATCH
+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
+ if (HG(eval_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(eval_whitelist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ } else if (HG(eval_blacklist) != NULL) {
+ if (zend_hash_exists(HG(eval_blacklist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ }
+ }
+
+ if (HG(func_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(func_whitelist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ } else if (HG(func_blacklist) != NULL) {
+ if (zend_hash_exists(HG(func_blacklist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ }
+#endif
efree(lcname);
if (IS_CONST != IS_CONST) {
@@ -925,6 +978,37 @@
efree(lcname);
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
}
+#if HARDENING_PATCH
+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
+ if (HG(eval_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(eval_whitelist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ } else if (HG(eval_blacklist) != NULL) {
+ if (zend_hash_exists(HG(eval_blacklist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ }
+ }
+
+ if (HG(func_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(func_whitelist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ } else if (HG(func_blacklist) != NULL) {
+ if (zend_hash_exists(HG(func_blacklist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ }
+#endif
efree(lcname);
if (IS_TMP_VAR != IS_CONST) {
@@ -1083,6 +1167,37 @@
efree(lcname);
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
}
+#if HARDENING_PATCH
+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
+ if (HG(eval_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(eval_whitelist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ } else if (HG(eval_blacklist) != NULL) {
+ if (zend_hash_exists(HG(eval_blacklist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ }
+ }
+
+ if (HG(func_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(func_whitelist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ } else if (HG(func_blacklist) != NULL) {
+ if (zend_hash_exists(HG(func_blacklist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ }
+#endif
efree(lcname);
if (IS_VAR != IS_CONST) {
@@ -1330,6 +1445,37 @@
efree(lcname);
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
}
+#if HARDENING_PATCH
+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
+ if (HG(eval_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(eval_whitelist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ } else if (HG(eval_blacklist) != NULL) {
+ if (zend_hash_exists(HG(eval_blacklist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ }
+ }
+
+ if (HG(func_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(func_whitelist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ } else if (HG(func_blacklist) != NULL) {
+ if (zend_hash_exists(HG(func_blacklist), lcname, function_name_strlen+1)) {
+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", lcname);
+ efree(lcname);
+ zend_bailout();
+ }
+ }
+#endif
efree(lcname);
if (IS_CV != IS_CONST) {
@@ -1635,6 +1781,34 @@
if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
zend_error_noreturn(E_ERROR, "Unknown function: %s()", fname->value.str.val);
}
+#if HARDENING_PATCH
+ if (EG(in_code_type) == ZEND_EVAL_CODE) {
+ if (HG(eval_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(eval_whitelist), fname->value.str.val, fname->value.str.len+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", fname->value.str.val);
+ zend_bailout();
+ }
+ } else if (HG(eval_blacklist) != NULL) {
+ if (zend_hash_exists(HG(eval_blacklist), fname->value.str.val, fname->value.str.len+1)) {
+ zend_security_log(S_EXECUTOR, "function within eval blacklist called: %s()", fname->value.str.val);
+ zend_bailout();
+ }
+ }
+ }
+
+ if (HG(func_whitelist) != NULL) {
+ if (!zend_hash_exists(HG(func_whitelist), fname->value.str.val, fname->value.str.len+1)) {
+ zend_security_log(S_EXECUTOR, "function outside of whitelist called: %s()", fname->value.str.val);
+ zend_bailout();
+ }
+ } else if (HG(func_blacklist) != NULL) {
+ if (zend_hash_exists(HG(func_blacklist), fname->value.str.val, fname->value.str.len+1)) {
+ zend_security_log(S_EXECUTOR, "function within blacklist called: %s()", fname->value.str.val);
+ zend_bailout();
+ }
+ }
+#endif
+
EX(object) = NULL;
return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -1914,7 +2088,12 @@
int dummy = 1;
zend_file_handle file_handle;
- if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
+#if HARDENING_PATCH_INC_PROTECT
+ if (zend_is_valid_include(inc_filename)
+ && (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC))) {
+#else
+ if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
+#endif
if (!file_handle.opened_path) {
file_handle.opened_path = estrndup(inc_filename->value.str.val, inc_filename->value.str.len);
@@ -1939,6 +2118,11 @@
break;
case ZEND_INCLUDE:
case ZEND_REQUIRE:
+#if HARDENING_PATCH_INC_PROTECT
+ if (!zend_is_valid_include(inc_filename)) {
+ break;
+ }
+#endif
new_op_array = compile_filename(opline->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
break;
case ZEND_EVAL: {
@@ -4345,7 +4529,12 @@
int dummy = 1;
zend_file_handle file_handle;
- if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
+#if HARDENING_PATCH_INC_PROTECT
+ if (zend_is_valid_include(inc_filename)
+ && (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC))) {
+#else
+ if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
+#endif
if (!file_handle.opened_path) {
file_handle.opened_path = estrndup(inc_filename->value.str.val, inc_filename->value.str.len);
@@ -4370,6 +4559,11 @@
break;
case ZEND_INCLUDE:
case ZEND_REQUIRE:
+#if HARDENING_PATCH_INC_PROTECT
+ if (!zend_is_valid_include(inc_filename)) {
+ break;
+ }
+#endif
new_op_array = compile_filename(opline->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
break;
case ZEND_EVAL: {
@@ -7358,7 +7552,12 @@
int dummy = 1;
zend_file_handle file_handle;
- if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
+#if HARDENING_PATCH_INC_PROTECT
+ if (zend_is_valid_include(inc_filename)
+ && (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC))) {
+#else
+ if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
+#endif
if (!file_handle.opened_path) {
file_handle.opened_path = estrndup(inc_filename->value.str.val, inc_filename->value.str.len);
@@ -7383,6 +7582,11 @@
break;
case ZEND_INCLUDE:
case ZEND_REQUIRE:
+#if HARDENING_PATCH_INC_PROTECT
+ if (!zend_is_valid_include(inc_filename)) {
+ break;
+ }
+#endif
new_op_array = compile_filename(opline->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
break;
case ZEND_EVAL: {
@@ -19486,7 +19690,12 @@
int dummy = 1;
zend_file_handle file_handle;
- if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
+#if HARDENING_PATCH_INC_PROTECT
+ if (zend_is_valid_include(inc_filename)
+ && (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC))) {
+#else
+ if (SUCCESS == zend_stream_open(inc_filename->value.str.val, &file_handle TSRMLS_CC)) {
+#endif
if (!file_handle.opened_path) {
file_handle.opened_path = estrndup(inc_filename->value.str.val, inc_filename->value.str.len);
@@ -19511,6 +19720,11 @@
break;
case ZEND_INCLUDE:
case ZEND_REQUIRE:
+#if HARDENING_PATCH_INC_PROTECT
+ if (!zend_is_valid_include(inc_filename)) {
+ break;
+ }
+#endif
new_op_array = compile_filename(opline->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
break;
case ZEND_EVAL: {
diff -Nura php-5.1.6/Zend/zend_vm_execute.skl hardening-patch-5.1.6-0.4.15/Zend/zend_vm_execute.skl
--- php-5.1.6/Zend/zend_vm_execute.skl 2005-12-01 13:50:58.000000000 +0100
+++ hardening-patch-5.1.6-0.4.15/Zend/zend_vm_execute.skl 2006-09-07 19:41:16.000000000 +0200
@@ -27,6 +27,16 @@
EX(symbol_table) = EG(active_symbol_table);
EX(prev_execute_data) = EG(current_execute_data);
EG(current_execute_data) = &execute_data;
+#if HARDENING_PATCH
+ EX(execute_depth) = 0;
+
+ if ((op_array->type == ZEND_EVAL_CODE || op_array->created_by_eval)&& EG(in_code_type) != ZEND_SANDBOX_CODE) {
+ EG(in_code_type) = ZEND_EVAL_CODE;
+ } else if (op_array->type == ZEND_SANDBOX_CODE) {
+ EG(in_code_type) = ZEND_SANDBOX_CODE;
+ op_array->type = ZEND_EVAL_CODE;
+ }
+#endif
EG(in_execution) = 1;
if (op_array->start_op) {
@@ -52,6 +62,18 @@
*/
EX(function_state).function_symbol_table = NULL;
#endif
+#if HARDENING_PATCH
+ if (EX(prev_execute_data) == NULL) {
+ EX(execute_depth) = 0;
+ } else {
+ EX(execute_depth) = EX(prev_execute_data)->execute_depth + 1;
+ }
+
+ if (EG(hphp_executor_max_depth) > 0 && EX(execute_depth) > EG(hphp_executor_max_depth)) {
+ zend_security_log(S_EXECUTOR, "Maximum execution depth of %u violated", EG(hphp_executor_max_depth));
+ zend_bailout();
+ }
+#endif
while (1) {
{%ZEND_VM_CONTINUE_LABEL%}