Preliminary PHP taint support available

php.internals

(Wietse Venema)

18 years ago
A preliminary implementation of PHP taint support is available from ftp://ftp.porcupine.org/pub/php/ This code is released under version 2.00 of the Zend license. Below are fragments from the README file. For the full text please see ftp://ftp.porcupine.org/pub/php/php-5.2.3-taint-20071102.README.html This file also has information about using taint in real applications, about run-time performance, and about changes within the PHP core. Most of all, your feedback is welcome, so that I can make this code as easy to use and as performant as possible. Wietse Venema IBM Research [ Start of README fragments ] Introduction ============ This is a preliminary implementation of support for tainted variables in PHP. The goal is to help PHP application programmers find and eliminate opportunities for HTML script injection, SQL or shell code injection, or PHP control hijacking, before other people can exploit them. The implementation provides taint support for basic operators and for a selection of built- functions and extensions. A list of what is implemented sofar is at the end of this document. The good news is that performance is better than I hoped it would be. However, the implementation is incomplete, so please don't be surprised when something is still missing. For example, I have not yet implemented taint support for object-specific operations, and taint checks assume that output has a Content-Type: of text/html. It also does not yet fully adhere to coding and documentation conventions. All this needs to be taken care of in future releases. I need your feedback to make this code complete. I hope to do several quick 1-2 month release cycles in which I collect feedback, fill in missing things, and adjust course until things stabilize. Right now the code is based on PHP 5.2.3, but I expect to catch up with the current PHP release next time. A quick example =============== To give an idea of the functionality, consider this simple PHP program with an obvious HTML script injection bug: <?php $inputfield = $_GET['inputfield']; echo "You entered: $inputfield\n"; ?> With default .ini settings, this program does exactly what the programmer wrote: it echos the contents of the client's inputfield request attribute, including all the HTML script code that an attacker may have supplied along with it. When I add one setting to a php.ini file, or the equivalent ini_set() call to the script itself, the program still produces the same output, but it also produces a warning: Add to php.ini: taint_error_level = E_WARNING Add to script: ini_set("taint_error_level", E_WARNING); Warning: echo(): Argument contains data that is not converted with htmlspecialchars() or htmlentities() in /path/to/script on line 3 When I change the taint error level from E_WARNING into E_ERROR, script execution terminates before echo produces any output. Introducing multiple flavors of taint ===================================== Conversion functions such as htmlspecialchars() exist not only for boring security reasons! They are also required for robustness. Without the proper output conversion, shell or SQL commands fail when given a legitimate name such as O'Reilly. Bugs like this are easily overlooked, because they trigger only with unusual data. However, these bugs are trivial to find with taint support, because you get the "missing conversion" warning message even when you test the program with ordinary data. This point is worth repeating, so I will repeat it now: With taint support, you don't need malicious inputs to find out where a PHP script may have opportunities for HTML script injection, shell or SQL code injection, or PHP control hijacking. To encourage programmers to use the RIGHT conversion function, I have implemented multiple flavors of taint. Each time data enters a PHP application from the web, from database or from elsewhere, it may be "tainted" with zero or more taint flavors, so that the PHP engine can warn the programmer and suggest an appropriate conversion function. [ End of README fragments ] Please see the complete README file for the unabridged text, including information on the other topics: * Using taint support with real PHP applications * Performance * Low-level implementation * Taint propagation policy * PHP core changes * Loose ends * Distant future * Feature summary The complete README file and source code are available from ftp://ftp.porcupine.org/pub/php/

Nuno Lopes

18 years ago
Hi, It sounds cool, indeed. The obvious question now is: how it performs with real-world applications? Have you been able to identify security bugs (either new or already known)? I don't have time to perform these tests myself, but I would love to see some results. Regards, Nuno ----- Original Message ----- From: "Wietse Venema" <wietse@porcupine.org> To: <internals@lists.php.net> Sent: Friday, November 02, 2007 8:44 PM Subject: [PHP-DEV] Preliminary PHP taint support available

(Wietse Venema)

18 years ago
Nuno Lopes:
> Hi, > > It sounds cool, indeed. > The obvious question now is: how it performs with real-world applications?
This is the main reason I asked for feedback from the list :-)
> Have you been able to identify security bugs (either new or already known)? > I don't have time to perform these tests myself, but I would love to see > some results.
I have played with very few applications. Right now I am focused on making taint easy to use, and on minimizing the performance hit. If I can keep it down at the 1-2% level, that would be great. It takes time to go through all the possible web pages, especially with unfamiliar applications. I'll let the application authors know first, should I find a serious problem. Wietse

Tomas Kuliavas

18 years ago
> A preliminary implementation of PHP taint support is available from > ftp://ftp.porcupine.org/pub/php/ This code is released under version > 2.00 of the Zend license. > > Below are fragments from the README file. For the full text please see > ftp://ftp.porcupine.org/pub/php/php-5.2.3-taint-20071102.README.html > This file also has information about using taint in real applications, > about run-time performance, and about changes within the PHP core. > > Most of all, your feedback is welcome, so that I can make this code > as easy to use and as performant as possible.
php-5.2.3-taint-20071102 gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) compiling apache 2.2.4 dso module configure with --enable-mbstring --disable-mbregex ---- ext/mbstring/mb_gpc.c: In function 'mbstr_treat_data': ext/mbstring/mb_gpc.c:63: warning: passing argument 3 of 'php_default_treat_data' makes integer from pointer without a cast ext/mbstring/mb_gpc.c:63: error: too few arguments to function 'php_default_treat_data' ext/mbstring/mb_gpc.c: In function '_php_mb_encoding_handler_ex': ext/mbstring/mb_gpc.c:331: warning: passing argument 5 of 'sapi_module.input_filter' makes integer from pointer without a cast ext/mbstring/mb_gpc.c:331: error: too few arguments to function 'sapi_module.input_filter' make: *** [ext/mbstring/mb_gpc.lo] Error 1 ---- Without mbstring options same compilation stops at ---- sapi/apache2handler/sapi_apache2.c: In function 'php_apache_sapi_register_variables': sapi/apache2handler/sapi_apache2.c:246: warning: passing argument 5 of 'sapi_module.input_filter' makes integer from pointer without a cast sapi/apache2handler/sapi_apache2.c:246: error: too few arguments to function 'sapi_module.input_filter' sapi/apache2handler/sapi_apache2.c:251: warning: passing argument 5 of 'sapi_module.input_filter' makes integer from pointer without a cast sapi/apache2handler/sapi_apache2.c:251: error: too few arguments to function 'sapi_module.input_filter' make: *** [sapi/apache2handler/sapi_apache2.lo] Error 1 ---- Compiles fine without --enable-taint. Do you need more information about other configure options or compilation environment?
-- Tomas

(Wietse Venema)

18 years ago
Tomas Kuliavas:
> > A preliminary implementation of PHP taint support is available from > > ftp://ftp.porcupine.org/pub/php/ This code is released under version > > 2.00 of the Zend license. > > > > Below are fragments from the README file. For the full text please see > > ftp://ftp.porcupine.org/pub/php/php-5.2.3-taint-20071102.README.html > > This file also has information about using taint in real applications, > > about run-time performance, and about changes within the PHP core. > > > > Most of all, your feedback is welcome, so that I can make this code > > as easy to use and as performant as possible. > > php-5.2.3-taint-20071102 > gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) > compiling apache 2.2.4 dso module > > configure with --enable-mbstring --disable-mbregex
As documented, the SAPIs that currently work are cli, cgi, and apache module (--with-apxs); and the extensions that work are --with-mysql and --with-mysqli. Other SAPIs, and extensions that depend on SAPIs need to be converted because some function pointers require an extra argument when taint is compiled in (I could not hide this under another layer of macros in an #include file). Most other code should compile out of the box.
> Do you need more information about other configure options or compilation > environment?
I would need the full ./configure line. There's a ton of SAPIs and I could not update all of them in time for IBM's annual performance review deadline, and still release decent quality code/documentation. Wietse

Tomas Kuliavas

18 years ago
> Tomas Kuliavas: >> > A preliminary implementation of PHP taint support is available from >> > ftp://ftp.porcupine.org/pub/php/ This code is released under version >> > 2.00 of the Zend license. >> > >> > Below are fragments from the README file. For the full text please see >> > ftp://ftp.porcupine.org/pub/php/php-5.2.3-taint-20071102.README.html >> > This file also has information about using taint in real applications, >> > about run-time performance, and about changes within the PHP core. >> > >> > Most of all, your feedback is welcome, so that I can make this code >> > as easy to use and as performant as possible. >> >> php-5.2.3-taint-20071102 >> gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) >> compiling apache 2.2.4 dso module >> >> configure with --enable-mbstring --disable-mbregex > > As documented, the SAPIs that currently work are cli, cgi, and > apache module (--with-apxs); and the extensions that work are > --with-mysql and --with-mysqli. > > Other SAPIs, and extensions that depend on SAPIs need to be converted > because some function pointers require an extra argument when taint > is compiled in (I could not hide this under another layer of macros > in an #include file). Most other code should compile out of the box. > >> Do you need more information about other configure options or >> compilation environment? > > I would need the full ./configure line. There's a ton of SAPIs and > I could not update all of them in time for IBM's annual performance > review deadline, and still release decent quality code/documentation.
make distclean ./configure --prefix=/somepath/php \ --with-config-file-path=/somepath/config/ \ --with-apxs2=/somepath/apache/bin/apxs \ --enable-taint \ --enable-mbstring --disable-mbregex \ --with-gettext=/usr \ --with-mysqli \ --with-mysql=/usr \ --with-pspell \ --with-ldap \ --with-openssl=/usr \ --with-mhash=/usr \ --with-mcrypt=/usr \ --with-pear \ --enable-dba=shared \ --with-gdbm=/usr --with-db4=/usr --with-cdb \ --enable-memory-limit \ --with-gd=/usr \ --with-jpeg-dir=/usr --with-png-dir=/usr --with-xpm-dir=/usr \ --with-ttf=/usr --with-freetype-dir=/usr --with-t1lib=/usr \ --enable-gd-native-ttf --with-tiff-dir=/usr \ --enable-soap \ --with-zlib=/usr make make install Apache 1.3.33 DSO module compiles, if mbstring options are removed.
-- Tomas

(Wietse Venema)

18 years ago
Tomas Kuliavas:
> make distclean > ./configure --prefix=/somepath/php \ > --with-config-file-path=/somepath/config/ \ > --with-apxs2=/somepath/apache/bin/apxs \ > --enable-taint \ > --enable-mbstring --disable-mbregex \ > --with-gettext=/usr \
[17 more lines deleted] OK, I have updated the apache2 module SAPI, and the mbstring extension. I haven't had time to test the other two dozen modules. I've also added a few words of clarification about what to expect with SAPIs and extensions that haven't been updated for taint support, and what to expect when you run an application for the first time with taint support. Fragments of these are below my signature. The updated code is at ftp://ftp.porcupine.org/pub/php/ 6924 Nov 3 21:14 php-5.2.3-taint-20071102-20071103.diff.gz 45718 Nov 3 20:59 php-5.2.3-taint-20071103.README 43662 Nov 3 20:58 php-5.2.3-taint-20071103.README.html 182130 Nov 3 21:18 php-5.2.3-taint-20071103.diff.gz 9381474 Nov 3 21:15 php-5.2.3-taint-20071103.tar.gz (PGP signature files exist, too, but are not shown above). Wietse == README fragment 1 What about the other SAPIs and extensions? The SAPIs need work because some SAPI functions need an extra taint argument, and I could not hide this with macros in some central #include file. The other extensions will work just fine as long as they don't depend on the changed SAPI interface, and as long as you leave taint_error_level at its default setting. They may trigger false warnings when you raise the taint error level, because they don't know how to properly initialize certain bits that taint support relies on. This problem should not exist, but unfortunately there is a lot of PHP source code that does not use standard macros when initializing PHP data structures. Extensions that haven't been updated with taint support will ignore taint information in their inputs, and will therefore not propagate taint information from their inputs to their outputs. == README fragment 2 While testing code for the first time with PHP taint support you will find that you will sometimes need to explicitly mark data as "safe". Usually this happens imediately after successful input validation. if (some expression to make sure $data is safe) { untaint($data); do something with $data; } else { error ... } This is admittedly imperfect: it would be better to specify what context the data is safe for. A proper user interface for this will have to be developed in a future version of PHP taint support.

Cristian Rodriguez

18 years ago
2007/11/3, Wietse Venema <wietse@porcupine.org>:
> OK, I have updated the apache2 module SAPI, a
The CGI sapi. using this tarball ftp://ftp.porcupine.org/pub/php/php-5.2.3-taint-20071103.tar.gz does not compile /home/cristian/php5.2.3-tainted/php-5.2.3-taint-20071103/sapi/cgi/cgi_main.c: In function 'cgi_php_import_environment_variables': /home/cristian/php5.2.3-tainted/php-5.2.3-taint-20071103/sapi/cgi/cgi_main.c:514: warning: passing argument 5 of 'sapi_module.input_filter' makes integer from pointer without a cast /home/cristian/php5.2.3-tainted/php-5.2.3-taint-20071103/sapi/cgi/cgi_main.c:514: error: too few arguments to function 'sapi_module.input_filter' make: *** [sapi/cgi/cgi_main.lo] Error 1
-- http://www.kissofjudas.net/

(Wietse Venema)

18 years ago
Cristian Rodriguez:
> 2007/11/3, Wietse Venema <wietse@porcupine.org>: > > > OK, I have updated the apache2 module SAPI, a > > The CGI sapi. using this tarball > ftp://ftp.porcupine.org/pub/php/php-5.2.3-taint-20071103.tar.gz > > does not compile > > /home/cristian/php5.2.3-tainted/php-5.2.3-taint-20071103/sapi/cgi/cgi_main.c: > In function 'cgi_php_import_environment_variables': > /home/cristian/php5.2.3-tainted/php-5.2.3-taint-20071103/sapi/cgi/cgi_main.c:514: > warning: passing argument 5 of 'sapi_module.input_filter' makes > integer from pointer without a cast > /home/cristian/php5.2.3-tainted/php-5.2.3-taint-20071103/sapi/cgi/cgi_main.c:514: > error: too few arguments to function 'sapi_module.input_filter' > make: *** [sapi/cgi/cgi_main.lo] Error 1
PHP compiles error-free with: $ fetch ftp://ftp.porcupine.org/pub/php/php-5.2.3-taint-20071103.tar.gz $ gzcat php-5.2.3-taint-20071103.tar.gz | tar xf - $ cd php-5.2.3-taint-20071103 $ ./configure $ make $ ls -l sapi/cgi/cgi_main* -rw-r--r-- 1 wietse wheel 54118 Sep 28 20:30 sapi/cgi/cgi_main.c -rw-r--r-- 1 wietse wheel 310 Nov 8 07:01 sapi/cgi/cgi_main.lo -rw-r--r-- 1 wietse wheel 61604 Nov 8 07:01 sapi/cgi/cgi_main.o What commands were you were using? Wietse

(Wietse Venema)

18 years ago
Wietse Venema:
> PHP compiles error-free with: > > $ fetch ftp://ftp.porcupine.org/pub/php/php-5.2.3-taint-20071103.tar.gz > $ gzcat php-5.2.3-taint-20071103.tar.gz | tar xf - > $ cd php-5.2.3-taint-20071103 > $ ./configure
And also with: ./configure --enable-taint Wietse

Christian Schneider

18 years ago
First of all: I've been playing around with it and it looks great! Some comments: 1) I added taint support to func_get_args() and func_get_arg(), a patch is attached. 2) Maybe the functions should be renamed to taint_xxx (e.g. taint_set, taint_clear, taint_check or the like) to reside in their own 'namespace'. I hope your work will be integrated in the main PHP tree as it provides a useful tool to developers IMHO. For now I plan to use your patch on our development machines so I might have more feedback in the near future. Cheers, - Chris

(Wietse Venema)

18 years ago
Christian Schneider:
> First of all: I've been playing around with it and it looks great! > > Some comments: > 1) I added taint support to func_get_args() and func_get_arg(), a patch > is attached.
Thanks. I will add a .phpt test script so that from now on it will always work.
> 2) Maybe the functions should be renamed to taint_xxx (e.g. taint_set, > taint_clear, taint_check or the like) to reside in their own 'namespace'.
I hope to revise the user interface after I have caught up with PHP 5.2.5. The longer I wait the harder it will be.
> I hope your work will be integrated in the main PHP tree as it provides > a useful tool to developers IMHO. > > For now I plan to use your patch on our development machines so I might > have more feedback in the near future.
Wietse