-
Notifications
You must be signed in to change notification settings - Fork 1
News
Every system has its limits. The goal of the following exercise was to check for ways to execute code even though Snuffleupagus would have been configured to prevent code execution. This was done systematically by checking for the correct matching of usual suspects, e.g. eval()
, system()
, ... If a suitable unit test was missing, it was added to the test suite. After that a look into features added to PHP recently, as well as release notes for PHP 8.0 and PHP 8.1 lead to some interesting ideas.
Some test cases were already in place, specifically for system()
, call_user_func()
and a few other examples.
The following test cases were added with commit c3fddfecfab29504097932184389a94251991bc7:
- direct execution of
exec()
,passthru()
,popen()
,proc_open()
- indirect execution of
shell_exec()
via backtick syntax in a few different ways:
echo `ls`;
echo ${`ls`};
echo "{${`ls`}}";
- Closure syntax
$x = Closure::fromCallable('shell_exec');
echo $x('ls');
// --- and ---
$x = shell_exec(...);
echo $x('ls');
- Calling via variable function name
$x = 'shell_exec';
echo $x('ls');
- Callbacks
echo filter_input(INPUT_GET, 'cmd', FILTER_CALLBACK, array('options' => 'shell_exec'));
register_shutdown_function('shell_exec', 'ls');
header_register_callback('phpinfo');
- Opcache preload feature and data:// URLs
allow_url_include=1
opcache.enable=1
opcache.enable_cli=1
opcache.preload=data://text/plain,%3C%3Fphp+shell_exec%28%22ls%22%29%3B
- Include and special URLs
include('data://text/plain,'.urlencode('<?php shell_exec("ls");'));
include('php://filter//resource=data://text/plain,'.urlencode('<?php shell_exec("ls");'));
- Signal hander via pnctl
declare(ticks=1);
ini_set("pcntl.async_signals", "1");
pcntl_signal(SIGALRM, function($signo) { shell_exec("ls"); });
// pcntl_alarm(1); // too slow
system("kill -14 " . getmypid());
sleep(5);
Another test case failed starting with PHP 8.1, which turned out to be a missing check for oversight by not checking for the opcode ZEND_TICKS
, after calling register_tick_function()
. This was fixed with commit 6095651e2caa729ff56ae5a53c908b09e5f7dc29 along with minor issues regarding PHP 8.1 compatibility.
Matching of class names in eval()
'd code with whitelisting was added/fixed with 4a45ba42b609d48c8297456d67cc8d955073b567, so we can match common method calls, e.g.
class Foo {
static function bar($a) { echo $a . PHP_EOL; return 11; }
};
eval('Foo::bar("test");');
using a config line such as
sp.disable_function.function("Foo::bar").ret("11").drop();
And finally, function checks are applied to internal functions (not user-defined functions) as well, so that class methods, which are not hooked automatically, can be matched and filtered, too. See a5dcbb8cb802ba18e618ca38ea8e6acbf8b133ff.
During the testing phase I came across the FFI extension, which dynamically generates an interface to call C functions, e.g. on MacOS we might load system()
from libSystem.dylib
:
$ffi = FFI::cdef("
int system(const char *);
", "libSystem.dylib");
$ffi->system("ls");
Incidentally the function name set by FFI to call $ffi->system()
is system
rather than FFI::system
, which makes matching rather problematic. As a general rule, I would recommend to disable FFI entirely in production environments.
Snuffleupagus has done a great job protecting PHP with many features, some of which were inspired by the original Suhosin extension. But there are still a few things missing that had been available with Suhosin before. Some of these missing features were selected and have been ported back to Snuffleupagus:
- Recursion depth limit: The default PHP behaviour when calling a function that calls a function that calls a function ..., is to proceed until the maximum allowed memory is exhausted. This feature adds a limit to the stack depth - see commit https://github.com/sektioneins/snuffleupagus/commit/31d6a3cddd18cef447698ba2beaa7b5d9ab9dd94
- Encode troubling characters in
_SERVER
variablesREQUEST_URI
andQUERY_STRING
: A lot of injection vulnerabilities such as XSS, SQL Injection or CRLF (newline) Injection into HTTP headers or other line based protocols. Troubling in this regard would be newline, single and double quotes, open/close tag symbols and backtick. - Replace troubling characters in
PHP_SELF
,PATH_INFO
,PATH_TRANSLATED
andHTTP_USER_AGENT
. See commit https://github.com/sektioneins/snuffleupagus/commit/6e07cdb870513270a3c08abc7ecdca64ad2af400 for both features. - Limit session ID length (minimum/maximum): PHP has one of the few non-strict session systems by default. Every session ID is trusted to be valid even if it was not generated by PHP, unless the php.ini directive
session.use_strict_mode
was set. An attacker may try to inject a very short and predictable session ID or a rather long session ID in order to try a DoS attack. This patch limits the session ID length to user defined values. See commit https://github.com/sektioneins/snuffleupagus/commit/a99c0b3ba7ebbd27fd62f2bde3963354c2bf55e3
I don't know what it is about configuration files, but people tend to leave them as they are, once their application runs smoothly. But with a PHP security extension such as Snuffleupagus, leaving features disabled or not configured properly is like forgetting to fasten your seatbelt. So, what could possibly be done to make this task - well, as much fun as a CLI tool can be.
I decided to do a Q&A style tool for two reasons: (1) The entire questionnaire must be completed. That means all features will be known at least from reading and understanding the questions. Also, it is unlikely that someone forgets to complete the configuration process over a lunch break as it might be with editing configuration files. And (2), providing easy questions for complex configuration options enables more people to actually do an informed decision.
Example:
$ ./snggen --qa
Hi.
This is a short questionnaire, just to get to know your system better.
|==========[ display_errors ]==========>
Is this a configuration for a production system, or for a development setup?
For production systems it is usually best to disable error output and similar information
disclosure.
[p]: production system
[d]: development system
Answer [default=p]:
Ok. Storing answer `[p]: production system`
You can check out the first tool at the new SNG Tools Repository. Please, let me know what you think about it either via Twitter (@suhosin) or via the repo's issue tracker.
A lot of security can come from a little secure configuration. In order to enforce certain restrictions on INI settings, Snuffleupagus was extended to provide an easy and straightforward way to set up the rules for such restrictions. This was done with commit id 2392c46.
Let's start by activating the feature:
sp.ini_protection.enable();
INI settings can be set to read-only globally or individually. Example:
## global read-only policy
sp.ini_protection.policy_readonly();
## then make one setting read-write:
sp.ini.key("display_errors").rw();
or
## global read-write policy
sp.ini_protection.policy_readwrite();
## then set one setting to read-only mode
sp.ini.key("display_errors").ro();
Numeric settings can be checked for minimum/maximum value. Of course shorthand notation (K/M/G) is allowed.
sp.ini.key("memory_limit").min("4M").max("256M").rw();
A regular expression check can be applied.
sp.ini.key("highlight.comment").regexp("^#[0-9a-fA-F]{6}$");
Rule violations can fail silently or with a log message, as well as stop the request entirely
## fail silently
#sp.ini_protection.policy_silent_fail();
## or always stop the request
#sp.ini_protection.policy_drop();
## or just stop for this one rule
sp.ini.key("display_errors").ro().drop();
And of course, initial values can be enforced, which overrides php.ini or .htaccess settings:
sp.ini.key("display_errors").set("0").ro();
A more elaborate example can be found here.
During the last couple of months a manual code review of Snuffleupagus, the basis for most Suhosin-NG efforts, was performed in order to find both security issues and ways to improve the code for further development. Uncovered issues were then fixed and pushed to our fork of Snuffleupagus with the idea to eventually merge most of the changes back upstream. As the PHP extension is written in C, a particular focus was set to memory management, e.g.
- double free()
- use after free
- memory leaks
- memory corruption
- format string issues
- stack/heap overflows
Other checks are listed below: (The list may be incomplete)
- Off-by-One mistakes
- data/string encoding
- incorrect byte order
- arithmetic boundaries
- type conversion, e.g. signed/unsigned, truncation, comparison
- pointer arithmetic
- typos in code or output
- algorithmic boundaries, e.g. non-deterministic behaviour, infinite loops
- algorithmic flaws
- string handling
- file handling and permissions
- race conditions
- logical flaws
The following issues were found and fixed with the corresponding git commit:
-
log forging - https://github.com/sektioneins/snuffleupagus/commit/01528718850c8528ef6d2ed5296e244d4aa7b675
-
parameter matching logic - https://github.com/sektioneins/snuffleupagus/commit/fb9b3787246dff3e9b76e75f698ff7131ea5403d (still work-in-progress)
-
strict configuration consistency checks - https://github.com/sektioneins/snuffleupagus/commit/d8bf25aa20e93d366133b4550ac8304d06186ad3
-
memory management on module shutdown - https://github.com/sektioneins/snuffleupagus/commit/ae4ac9f69de3120004557824e0d766fe8140b27d
-
added configuration duplication check - originally later occurrences silently overrode previous ones leaving a memory leak - https://github.com/sektioneins/snuffleupagus/commit/55e431217df5e45b8ea1b48dab1f4b3736aa5ee0
-
various memory leaks
- https://github.com/sektioneins/snuffleupagus/commit/62f6d31d88e4536269b60471d7a4f7431442276a
- https://github.com/sektioneins/snuffleupagus/commit/238c363b48a9189ad3f1df80cc330e01aed09cb4 (incorrect use of free())
- https://github.com/sektioneins/snuffleupagus/commit/ef7072a631ad96def3299c92e5569658ac306b2c
- https://github.com/sektioneins/snuffleupagus/commit/7cce9171be0c8bb19818e9f668626af41efe3aae
- https://github.com/sektioneins/snuffleupagus/commit/d4993c7deaefadbc5675f39404a46e64006174b9
-
NULL pointer dereference in sp_session.c / sp_hook_session_RINIT() - https://github.com/sektioneins/snuffleupagus/commit/9a26fff9a4ca132dd61184cc244d52695e347770
-
logic flaw where neither enable nor disable leads to incorrect configuration parsing - https://github.com/sektioneins/snuffleupagus/commit/dce966ffec7dfdae2b701d581d71df6a5a542db9
-
incorrect error handling in CIDR parsing - https://github.com/sektioneins/snuffleupagus/commit/a997aac81cdda77028f74211cad2d07489854994
That's it for now. Stay tuned for another update about the new INI protection feature.
Hello everyone. It's been some time since the last suhosing-ng annoucement and a lot has happened. First of all, there was and still is the COVID-19 pandemic, which affected most people on this planet in some way or another. But hopefully, everybody will be inoculated soon, so that's that. Then, on a more technical note, PHP 8 was released with marvelous new features and internal workings. And of course, the original Snuffleupagus, which is the basis for the Suhosin-NG efforts, was developed quite a bit in the right direction.
So, where do we stand now? During the past couple of months there was a lot of brainstorming and prototype development being done behind the curtains. The results of this development will be incorporated into our fork of Snuffleupagus as well as the Suhosin-NG repository for additional tooling over the next few weeks.
Overwhelmingly marvellous news: Suhosin-NG was accepted for the 2019-04 open call from NLnet.
When it comes to important ideas that can help improve our society, there really are no boundaries. The challenge is to turn those opportunities into reality. Great ideas just come, but they are gone in a breeze as well. Lets make good use of them.
Suhosin (pronounced 'su-ho-shin') is an advanced protection system for PHP installations. It is designed to protect servers and users from known and unknown flaws in PHP applications and the PHP core. Suhosin comes in two independent parts, that can be used separately or in combination. The first part is a small patch against the PHP core, that implements a few low-level protections against buffer overflows or format string vulnerabilities and the second part is a powerful PHP extension that implements numerous other protections.
Since the release of PHP 7.0 in December 2015 the internet community has been desperately hoping to get the protection of the Suhosin PHP extension for their freshly baked PHP 7 installation. There was a first attempt to port Suhosin to PHP 7 conveniently named "Suhosin7". Unfortunately the Suhosin7 development stagnated increasingly and eventually came to an end during the alpha stage.
A few years later in 2017 another project called Snuffleupagus (or "SP" for short, because nobody really knows how to pronounce "Snuffleupagus" in Central Europe) took the opportunity and implemented a powerful PHP protection system. And they did excellent work. Why this project has not gotten the attention that Suhosin did back with PHP 5 is unclear to me, but this is about to change drastically.
The Suhosin-NG project will improve upon SP by integrating a number of old and new ideas over the next couple of months. If all goes according to plan, most ideas will be sent as Github pull-requests to the upstream SP project and hopefully get integrated.
The original Suhosin project was developed and maintained for years at SektionEins. For more than a decade we have been well known in the internet and web community for our expertise in web application security audits -- source code audits, penetration testing, infrastructure analysis, training and consulting. More than a few projects were released as open source software over the years including Suhosin (the PHP hardening extension), PCC (PHP secure configuration checker), scd-pkcs-11 (PKCS#11 provider with smart card support via GnuPG) and other mind-blowing projects.
Here is a sneak preview of upcoming milestones:
- Setup and get started: In order to be as transparent as possible and provide the most value for the internet, Suhosin-NG needs some infrastructure setup. Also the internet should be made aware of NLnet/SektionEins collaboration and some details about the project itself.
- Research and Brainstorming (and collecting ideas): We have collected a few ideas about how to harden web applications during our work on web application audits. In order to get even more up to date, a selective code review of PHP 7 will spark the creativity and provide the necessary insight into new Suhosin-NG features.
- SP code review: Do a code review with security flaws in mind. We are writing security software, so the more eyes the better. If we happen to uncover ways to improve SP, there will be patches.
- SP limitation testing: According to the SP documentation it is currently not possible to "hook every language construct“. A few more unit tests will uncover just how effective SP can protect against weird or uncommon language constructs.
- SP Configuration Defaults: With disable_function rules SP provides a very powerful and versatile tool to restrict PHP’s function calls. This milestone should provide a reasonable default configuration for SP by mimicking suhosin’s feature set.
- Simplify SP configuration: Configuring protections against security threats is an expert task. It should be possible for the average sysadmin to configure SP in a secure way with as little effort as possible.
- Automate SP configuration checks: There is no easy way to check SP rules for semantic errors. This milestone provides a way to perform „unit tests“ on SP configuration rules.
- Integrate php.ini protection: A lot of security flaws can be prevented by restricting the php.ini configuration. The PHP secure configuration checker (PCC) already provides reasonable checks for php.ini. SP should be able to provide runtime restrictions to php.ini configuration based on PCC rules.
- Suhosin feature backports to SP: SP provides matching features for most but not all of Suhosin’s features. The goal should be to provide SP with some of the missing features.
- Implementation of Ideas and new Features: Implement hardening ideas from the milestone „Research and Brainstorming“, as well as community ideas provided via Github issue tracker.
- Porting and packaging: All new tools should be packaged for numerous operating systems.
- WCAG (Accessibility), Security Scan and Wrap Up: The software should be checked for accessibility and security. Also, there may be other open issues from the community, which have to be addressed.
Nothing is absolutely set in stone. If you happen to have a great idea on how to improve PHP security, please feel free to leave a comment in the Issue tracker.
This news page will be updated on a regular basis every few weeks. Also, check out our social media presence: @suhosin on Twitter.