| Age | Commit message (Collapse) | Author |
|
PHP 8.5's opcache optimizer can inline trivial user functions (constant
return values), completely eliminating the DO_UCALL opcode. When this
happens, zend_execute_ex is never invoked and snuffleupagus's
return-value monitoring hooks never fire.
Fix this by setting ZEND_ACC_HAS_TYPE_HINTS on monitored functions'
op_arrays during compilation (via sp_op_array_handler). This flag is
checked by opcache's zend_try_inline_call() and prevents inlining.
For 0-arg functions — the only ones eligible for inlining — there are
no RECV opcodes, so the runtime impact is zero.
To enable sp_op_array_handler when return-value rules are configured,
the extension now registers itself as a zend extension and sets
ZEND_COMPILE_HANDLE_OP_ARRAY (previously only done for global_strict).
The disabled_function_echo_2 test is updated to use separate echo
statements and opcache.optimization_level=0, since opcache's echo
merging is a compile-time string concatenation that cannot be prevented
per-function.
This is a bit ugly, but it's the less awful solution to be able to hook return
values.
|
|
PHP is now optimizing `echo A,B,C` into `echo A B C`, so the test is pointless.
|
|
|
|
|
|
`protocol_name` can be NULL if `zend_parse_parameters_ex` fails (it uses
`ZEND_PARSE_PARAMS_QUIET`), but it was then unconditionally passed to
`strcasecmp`.
|
|
`getenv("REMOTE_ADDR")` can return NULL, and it is passed directly to
`spprintf`. While `spprintf` might handle `NULL` gracefully, it's not always
the case.
|
|
php_raw_url_encode returned a new zend_string, but the old arg_value_dup is
never released. Also arg_value_dup was reassigned, leaking the initial
zend_string_init allocation.
|
|
`sp_is_dangerous_char[(int)*p]` is indexed by `(int)*p`. If char is signed
(default on x86), values 0x80–0xFF produce negative indices into the array,
causing an out-of-bounds read. The `sp_server_encode` function has the same
issue.
|
|
|
|
Cookies can be arrays (session_id[]=x), and
we called `Z_STRLEN_P(pDest)` without checking if `Z_TYPE_P(pDest) == IS_STRING`,
leading to a type confusion, leaking at least `HashTable->arData`, and the rest
of the code is going to corrupt some stuff, leading to a crash.
While exploitation can't be ruled out, it looks stupidly harder. The array will
be decoded as base64 into another variable, decrypted, and have this value
written back to the array. To obtain a controlled read, an attacker would have
to bruteforce decryption to find an encrypted value that could be properly
decrypted, as we're using authenticated encryption. The next steps are
depending on the heap's layout, which should be pretty deterministic/simple as
cookie decryption happens at RINIT. But since the heap overflow is happening in
the cookies, odds are that they're stored somewhere with other data like
POST/GET/… and thus nothing super-duper juicy. While remote heap exploitation
in PHP have been done in the past, this primitive looks a tad too limited to
yield something powerful enough to pop a shell.
Reported-by: Vozec
|
|
|
|
objects contains null bytes (for example in private fields)
|
|
As it has been privately reported that the rule might not be working, so better
safe than sorry. Moreover, we didn't have tests for `__construct`
|
|
The members sid_min_length and sid_max_length are of type unsigned long,
thus use %lu instead of %zu and a cast.
|
|
|
|
|
|
|
|
Dead since almost 5 years with commit ae4ac9f ("properly free memory on
shutdown")
|
|
On uncommon architectures, like s390x, `-2` instead of `-1` might be printed.
|
|
Can causes issues on uncommon architectures, like s390x.
|
|
|
|
Co-authored-by: Julien "jvoisin" Voisin <julien.voisin@dustri.org>
|
|
|
|
Set the correct PHP versions for each rule and add the mb_send_mail function.
|
|
|
|
When `upload_validation` is enabled, and when VLD isn't installed, an attacker
sending a multipart POST is able to get arbitrary PHP content executed.
Reported-By: thomas-chauchefoin-tob
|
|
setcookie() is always URL encoded, urlencode is only turned off for setrawcookie().
Turning it off breaks cookies that have a value containing certain characters (namely spaces)
https://github.com/php/php-src/blob/685e99655ae97c667950f7f7d176985958718f56/ext/standard/head.c#L97
|
|
|
|
|
|
|
|
|
|
|
|
|
|
When the `php` logging facility is used, the error could have been caught by
using `set_error_handler` and whatnot. This commit ensures that if the
`.drop()` option is set, we're calling `zend_bailout()` that can't be caught.
An attacker could have used this issue to silently perform some recon of the
running environment. This isn't considered a vulnerability as an attacker
with arbitrary php code execution can simply use the use-after-free of the day
to gain arbitrary (native) code execution anyway, after detecting that
Snuffleupagus is in use, to take little risks of detection.
|
|
|
|
```
========DIFF========
001- OK
001+ Fatal error: Uncaught ValueError: setcookie(): "partitioned" option cannot be used without "secure" option in /builddir/build/BUILD/snuffleupagus-1c7598c432551d0c49c2c57f249ccd5ccabce638/src/tests/samesite_cookies.php:2
002+ Stack trace:
003+ #0 /builddir/build/BUILD/snuffleupagus-1c7598c432551d0c49c2c57f249ccd5ccabce638/src/tests/samesite_cookies.php(2): setcookie('super_cookie', 'super_value')
004+ #1 {main}
005+ thrown in /builddir/build/BUILD/snuffleupagus-1c7598c432551d0c49c2c57f249ccd5ccabce638/src/tests/samesite_cookies.php on line 2
========DONE========
FAIL Cookie samesite [tests/samesite_cookies.phpt]
```
Even though the warning might be spurious, let's fix this properly, by
initialising `partitioned` to false, and by setting it only if `secure` is set
as well.
|
|
|
|
|
|
As suggested by @santii-git in https://github.com/jvoisin/snuffleupagus/issues/522
|
|
|
|
|
|
```
Program terminated with signal SIGSEGV, Segmentation fault.
20 if (!(func->common.function_name)) {
(gdb) info locals
func = 0x0
function_name = 0xffb25f6d0190 "SearchByCallback"
complete_path_function = 0xffb26c8a0570 "\240\005\212l\262\377"
```
It seems that in some callback shenanigans, there is currently no non-NULL
`func` member in execute_data. PHP truly is marvelous.
This should close #515
|
|
|
|
|
|
|
|
|
|
sp_log_debug() does not take a feature as first argument:
src/sp_wrapper.c: In function 'sp_reregister_php_wrapper':
src/sp_utils.h:61:53: warning: too many arguments for format [-Wformat-extra-args]
61 | if (sp_debug_stderr > 0) dprintf(sp_debug_stderr, "[snuffleupagus][DEBUG] %s(): " fmt "\n", __FUNCTION__, ##__VA_ARGS__);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/sp_wrapper.c:144:3: note: in expansion of macro 'sp_log_debug'
144 | sp_log_debug(LOG_FEATURE, "Stream \"php\" successfully re-registered");
| ^~~~~~~~~~~~
|
|
Please GCC conversion warning:
src/sp_upload_validation.c: In function 'sp_rfc1867_callback':
src/sp_utils.h:61:53: warning: format '%lld' expects argument of type 'long long int', but argument 7 has type 'zend_long' {aka 'long int'} [-Wformat=]
61 | if (sp_debug_stderr > 0) dprintf(sp_debug_stderr, "[snuffleupagus][DEBUG] %s(): " fmt "\n", __FUNCTION__, ##__VA_ARGS__);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/sp_upload_validation.c:48:7: note: in expansion of macro 'sp_log_debug'
48 | sp_log_debug("Filename: %s\nTmpname: %s\nSize: %zd\nError: %lld\nScript: %s",
| ^~~~~~~~~~~~
|
|
Do not dereference the hash key for cookie encryption if it's NULL:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 zend_string_equal_content (s1=0x79bdb92170f0, s2=0x0) at /usr/include/php/20240924/Zend/zend_string.h:386
No locals.
#1 zend_string_equals (s1=0x79bdb92170f0, s2=0x0) at /usr/include/php/20240924/Zend/zend_string.h:391
No locals.
#2 sp_match_value (value=0x0, to_match=0x79bdb92170f0, rx=0x0) at ./src/sp_utils.c:273
No locals.
#3 0x00007989377b0709 in sp_lookup_cookie_config (key=0x0) at ./src/sp_cookie_encryption.c:8
config = 0x79bdb92158d0
it = 0x79ae80dabd00
it = <optimized out>
config = <optimized out>
#4 decrypt_cookie (pDest=0x79893b6787c0, num_args=<optimized out>, args=<optimized out>, hash_key=0x7ffe657c3880) at ./src/sp_cookie_encryption.c:19
cookie = <optimized out>
#5 0x000061875aac52df in zend_hash_apply_with_arguments ()
No symbol table info available.
#6 0x00007989377ae74b in zm_activate_snuffleupagus (type=<optimized out>, module_number=<optimized out>) at ./src/snuffleupagus.c:228
config_wrapper = 0x7989377c3490 <snuffleupagus_globals+144>
#7 0x000061875aa21710 in zend_activate_modules ()
No symbol table info available.
#8 0x000061875a9a7f18 in php_request_startup ()
No symbol table info available.
|
|
|