Hi,
it recently came to my attention that the function whitelist and blacklist feature inside Suhosin is easily bypassable since PHP 5.0.
The reason for this is that PHP is no longer calling the zend_execute_internal() hook if a function is called from another function (via zend_call_function)
In the days of PHP 4 the code looked like this:
if (!zend_execute_internal) {
((zend_internal_function *) EX(function_state).function)->handler(EX(opline)->extended_value, EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(object).ptr, 1 TSRMLS_CC);
} else {
zend_execute_internal(&execute_data, 1 TSRMLS_CC);
}
Nowadays (since PHP 5.0) the code was moved from call_user_function_ex to zend_call_function and just looks like this:
((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
While this has no immediate impact for average PHP users, it basically kills the possibility for an extension like Suhosin to catch all function starts.
This should also be a problem for your DTRACE support. And IIRC Xdebug was hooking this point (at least in the past), too.
My suggestion is to change the code to call the hook again.
Regards,
Stefan
While this has no immediate impact for average PHP users, it basically
kills the possibility for an extension like Suhosin to catch all
function starts. This should also be a problem for your DTRACE
support. And IIRC Xdebug was hooking this point (at least in the
past), too.
Indeed. And it finally explains why functions called from array_map()
didn't show up in function traces anymore!
My suggestion is to change the code to call the hook again.
Yes, I'd like that too.
cheers,
Derick
Sent from my iPhone
在 2012-5-21,18:42,Stefan Esser stefan.esser@sektioneins.de 写道:
Hi,
it recently came to my attention that the function whitelist and blacklist feature inside Suhosin is easily bypassable since PHP 5.0.
The reason for this is that PHP is no longer calling the zend_execute_internal() hook if a function is called from another function (via zend_call_function)
In the days of PHP 4 the code looked like this:
if (!zend_execute_internal) { ((zend_internal_function *) EX(function_state).function)->handler(EX(opline)->extended_value, EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(object).ptr, 1 TSRMLS_CC); } else { zend_execute_internal(&execute_data, 1 TSRMLS_CC); }
Nowadays (since PHP 5.0) the code was moved from call_user_function_ex to zend_call_function and just looks like this:
((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
While this has no immediate impact for average PHP users, it basically kills the possibility for an extension like Suhosin to catch all function starts.
Actually, there is one, use user opcode handler hook the fcall series
opcodes, that is how I did in taint extension.
http://svn.php.net/viewvc/pecl/taint/trunk/taint.c?view=markup&pathrev=325586
line 995
Thanks
This should also be a problem for your DTRACE support. And IIRC Xdebug was hooking this point (at least in the past), too.
My suggestion is to change the code to call the hook again.
Regards,
Stefan
Hi,
While this has no immediate impact for average PHP users, it basically kills the possibility for an extension like Suhosin to catch all function starts.
Actually, there is one, use user opcode handler hook the fcall series
opcodes, that is how I did in taint extension.
From what I can see your taint extension also does not catch functions called by call_user_func()
or array_map()
or or or…
Regards,
Stefan
发自我的 iPad
在 2012-5-21,21:05,Stefan Esser stefan.esser@sektioneins.de 写道:
Hi,
While this has no immediate impact for average PHP users, it basically kills the possibility for an extension like Suhosin to catch all function starts.
Actually, there is one, use user opcode handler hook the fcall series
opcodes, that is how I did in taint extension.From what I can see your taint extension also does not catch functions called by
call_user_func()
orarray_map()
or or or…
I just want to say there is a way in theory , If you want a 100%
intercept that you can also use override call_user_function
additionally, which is also what I did to mark some function's return
value in taint extension. Of course it's a little ugly, but it works
:)
Thanks
Regards,
Stefan
Hi!
Nowadays (since PHP 5.0) the code was moved from
call_user_function_ex to zend_call_function and just looks like
this:((zend_internal_function *)
EX(function_state).function)->handler(fci->param_count,
*fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1
TSRMLS_CC);
So in zend_vm_def.h we have:
if (!zend_execute_internal) {
/* saves one function call if
zend_execute_internal is not used */
fbc->internal_function.handler(opline->extended_value, ret->var.ptr,
(fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr :
NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_execute_internal(EXECUTE_DATA,
RETURN_VALUE_USED(opline) TSRMLS_CC);
}
But in zend_call_function it goes just:
((zend_internal_function *)
EX(function_state).function)->handler(fci->param_count,
*fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
So looks like the code is not consistent. You can still catch user
functions with zend_execute override but not the internal ones. No idea
why the difference exists, I'll look through commits and if I find no
reason I guess the should be synchronized.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
it recently came to my attention that the function whitelist and
blacklist feature inside Suhosin is easily bypassable since PHP 5.0.
Did you have a bug report for this? If not, could you please submit one
so we could track it properly? If yes, please send me its number.
Thanks,
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
Nowadays (since PHP 5.0) the code was moved from
call_user_function_ex to zend_call_function and just looks like
this:((zend_internal_function *)
EX(function_state).function)->handler(fci->param_count,
*fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1
TSRMLS_CC);While this has no immediate impact for average PHP users, it
basically kills the possibility for an extension like Suhosin to
catch all function starts. This should also be a problem for your
DTRACE support. And IIRC Xdebug was hooking this point (at least in
the past), too.My suggestion is to change the code to call the hook again.
There's a bit of a problem there. The problem is that execute_internal
looks like this:
zval **return_value_ptr = &(*(temp_variable *)((char *)
execute_data_ptr->Ts + execute_data_ptr->opline->result.var)).var.ptr;
((zend_internal_function *)
execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value,
*return_value_ptr,
(execute_data_ptr->function_state.function->common.fn_flags &
ZEND_ACC_RETURN_REFERENCE)?return_value_ptr:NULL,
execute_data_ptr->object, return_value_used TSRMLS_CC);
You note it takes return values from opline. Which is fine when running
PHP code, but when running internal function from internal function,
there's no opline. So zend_call_function calls this:
((zend_internal_function *)
EX(function_state).function)->handler(fci->param_count,
*fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC);
I.e. it uses data from fci. But if we use zend_execute_internal we have
only execute_data_ptr to work with, which has wrong return values. So we
need to either make fake opline somehow or find a way to pass correct
return vars to the handler via execute_internal. I'll see how it can be
done but that'd be probably in 5.5 since it may require some engine
changes, which is not an option for stable versions.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
While this has no immediate impact for average PHP users, it
basically kills the possibility for an extension like Suhosin to
catch all function starts. This should also be a problem for your
DTRACE support. And IIRC Xdebug was hooking this point (at least in
the past), too.My suggestion is to change the code to call the hook again.
Please take a look at https://github.com/php/php-src/pull/178. Would it
be a satisfactory solution for this problem?
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
While this has no immediate impact for average PHP users, it
basically kills the possibility for an extension like Suhosin to
catch all function starts. This should also be a problem for your
DTRACE support. And IIRC Xdebug was hooking this point (at least in
the past), too.My suggestion is to change the code to call the hook again.
Please take a look at https://github.com/php/php-src/pull/178. Would
it be a satisfactory solution for this problem?
Works for me! I think - I will give it a test with Xdebug.
cheers,
Derick
--
http://derickrethans.nl | http://xdebug.org
Like Xdebug? Consider a donation: http://xdebug.org/donate.php
twitter: @derickr and @xdebug
Posted with an email client that doesn't mangle email: alpine