Title: A few (lame) post-compromission Suhosin workarounds
Date: 2017-07-15 01:00

[Suhosin]( https://suhosin.org ) is breaking a lot of webshells,
including
[meterpreter](https://www.offensive-security.com/metasploit-unleashed/about-meterpreter/) (this is now
[fixed](https://github.com/rapid7/metasploit-payloads/pull/217) ;) ),
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](https://suhosin.org/stories/configuration.html#suhosin-executor-func-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](https://github.com/sektioneins/suhosin/blob/master/execute.c#L318)):

```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](https://suhosin.org/stories/configuration.html#suhosin-executor-disable-emodifier),
you can still use it by putting the string `eval()'d code` in your file name.

```php
$ 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`](https://suhosin.org/stories/configuration.html#suhosin-executor-disable-eval), but there are many ways to emulate it

- [assert](http://php.net/manual/en/function.assert.php), 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
  `echo` will fail.
- [create_function](http://php.net/manual/en/function.create-function.php),
  with something like `create_function('', '}phpinfo();//');` (yes, it's
  working, thanks to _kpcyrd_ for the reminder ♥).
- [mb_ereg_replace](http://php.net/manual/en/function.mb-ereg-replace.php) is
  [explicitly
  ignored](https://github.com/sektioneins/suhosin/blob/master/execute.c#L541)
  by suhosin, while providing the same primitives than `preg_replace`.
