Suhosin is breaking a lot of webshells, including meterpreter (this is now fixed ;) ), but it's possible to walk around it in certain configurations. I haven't found a self-contained way to bypass suhosin's functions blacklist, even by messing pretty hard with classes/namespaces, but most of the time, you can just abuse Apache's CGI handling anyway.
Priority-base bypass
Suhosin is using the filename of the executed file to get the codetype of
the current execution (see
execute.c):
static int suhosin_detect_codetype(zend_op_array *op_array TSRMLS_DC)
{
char *s;
int r;
s = (char *)op_array->filename;
/* eval, assert, create_function, preg_replace */
if (op_array->type == ZEND_EVAL_CODE) {
if (s == NULL) {
return SUHOSIN_CODE_TYPE_UNKNOWN;
}
if (strstr(s, "eval()'d code") != NULL) {
return SUHOSIN_CODE_TYPE_EVAL;
}
if (strstr(s, "regexp code") != NULL) {
return SUHOSIN_CODE_TYPE_REGEXP;
}
if (strstr(s, "mbregex replace") != NULL) {
return SUHOSIN_CODE_TYPE_MBREGEXP;
}
if (strstr(s, "assert code") != NULL) {
return SUHOSIN_CODE_TYPE_ASSERT;
}
if (strstr(s, "runtime-created function") != NULL) {
return SUHOSIN_CODE_TYPE_CFUNC;
}
if (strstr(s, "Command line code") != NULL) {
return SUHOSIN_CODE_TYPE_COMMANDLINE;
}
if (strstr(s, "Command line begin code") != NULL) {
return SUHOSIN_CODE_TYPE_COMMANDLINE;
}
if (strstr(s, "Command line run code") != NULL) {
return SUHOSIN_CODE_TYPE_COMMANDLINE;
}
if (strstr(s, "Command line end code") != NULL) {
return SUHOSIN_CODE_TYPE_COMMANDLINE;
}
if (strstr(s, "suhosin internal code") != NULL) {
return SUHOSIN_CODE_TYPE_SUHOSIN;
}
} else {
r = suhosin_check_filename(s, strlen(s) TSRMLS_CC);
return r;
}
return SUHOSIN_CODE_TYPE_UNKNOWN;
}
This means that if the feature that you're trying to bypass has its codetype placed bellow a non-blacklisted one, you can simply rename your file to bypass it.
For example, if the e flag for preg_replace is disabled,
you can still use it by putting the string eval()'d code in your file name.
$ cat eval\(\)\'d\ code.php
<?php var_dump(preg_replace('/[a-z]/e', "strtoupper('\\0')", "capslock"));
$ php eval\(\)\'d\ code.php
string(5) "CAPSLOCK"
$
Alternatives to eval
Suhosin can block
eval, but there are many ways to emulate it
- assert, as said in the
documentation, if its parameter is a string, it'll be evaluated as PHP code.
A minor caveat is that not everything can be executed this way, for example
echowill fail. - create_function,
with something like
create_function('', '}phpinfo();//');(yes, it's working, thanks to kpcyrd for the reminder ♥). - mb_ereg_replace is
explicitly
ignored
by suhosin, while providing the same primitives than
preg_replace.