New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP payloads rely on eval (won't work when suhosin.executor.disable_eval=On) #8630

Closed
emanuelb opened this Issue Jun 28, 2017 · 7 comments

Comments

Projects
None yet
4 participants
@emanuelb
Contributor

emanuelb commented Jun 28, 2017

eval can be disabled in PHP that use suhosin extension by directive:

suhosin.executor.disable_eval=On

which will result in failed exploitation that use PHP payloads that rely on eval.

fix:
check if eval disabled via

ini_get('suhosin.executor.disable_eval')

if so offer alternatives, also take into account possible whitelist/blacklist settings for eval via:

ini_get('suhosin.executor.eval.whitelist')
ini_get('suhosin.executor.eval.blacklist')

possible alternatives include:

  1. using create_function (beware: DEPRECATED from php > 7.2.0)

$x=create_function('$param','phpinfo();//code-here...');
$x();

  1. using Anonymous functions
    See: https://secure.php.net/manual/en/functions.anonymous.php

TESTING:
The following can be used to setup vulnerable PHP script with suhosin enabled using Docker:

Run:

mkdir /tmp/evalblocked && nano /tmp/evalblocked/Dockerfile

Enter:

FROM debian:jessie
RUN apt-get update \
    && apt-get install -y php5-cli wget \
    && wget https://sektioneins.de/files/repository.asc -O /tmp/repository.asc \
    && apt-key add /tmp/repository.asc \
    && echo 'deb http://repo.suhosin.org/ debian-jessie main' >> /etc/apt/sources.list \
    && apt-get update \
    && apt-get install php5-suhosin-extension \
    && mkdir /www/ \
    && cp /etc/php5/mods-available/suhosin.ini /etc/php5/cli/conf.d/suhosin.ini
RUN echo "suhosin.executor.disable_eval = On" >> /etc/php5/cli/conf.d/suhosin.ini
RUN echo "<?php if(isset(\$_GET['code'])){file_put_contents('script.php', \$_GET['code']);include 'script.php';} ?>visit <a href='?code=%3c?=phpinfo();?%3e'>?code=&lt;?=phpinfo();?&gt;</a>" > /www/index.php
EXPOSE 8080
ENTRYPOINT ["php5", "-S", "0.0.0.0:8080", "-t", "/www/"]

Then run:

cd /tmp/evalblocked/ && docker build -t phpevalblocked . && docker run -d --name phpevalblocked -p 4000:8080 phpevalblocked

and Visit:

http://localhost:4000/?code=<?php phpinfo(); // METASPLOIT PAYLOAD HERE ?>

@egypt

This comment has been minimized.

Show comment
Hide comment
@egypt

egypt Jun 29, 2017

Contributor

That's a bummer. =(

Contributor

egypt commented Jun 29, 2017

That's a bummer. =(

@jvoisin

This comment has been minimized.

Show comment
Hide comment
@jvoisin

jvoisin Jul 8, 2017

Contributor

How could this be improved? I don't think it's viable to patch every single module. Does msf come with some kind of php helpers library?

Contributor

jvoisin commented Jul 8, 2017

How could this be improved? I don't think it's viable to patch every single module. Does msf come with some kind of php helpers library?

@emanuelb

This comment has been minimized.

Show comment
Hide comment
@emanuelb

emanuelb Jul 8, 2017

Contributor
  1. fix the eval call in: (if blocked by ini_get('suhosin.executor.disable_eval') use alternatives)
    https://github.com/rapid7/metasploit-payloads/blob/6d774f59c80b78451e3d0ea4f24ca23012aef7cb/php/meterpreter/meterpreter.php#L416
  2. develop another php encoder / add option to php/base64 encoder, which used when badchars appear in payload, so the resulting code will not use eval as:
    eval(base64_decode(...
    but other alternatives.

alternatives availability information:
create_function is available from PHP 4 & DEPRECATED from php > 7.2.0
Anonymous functions available from PHP > 5.3.0

Contributor

emanuelb commented Jul 8, 2017

  1. fix the eval call in: (if blocked by ini_get('suhosin.executor.disable_eval') use alternatives)
    https://github.com/rapid7/metasploit-payloads/blob/6d774f59c80b78451e3d0ea4f24ca23012aef7cb/php/meterpreter/meterpreter.php#L416
  2. develop another php encoder / add option to php/base64 encoder, which used when badchars appear in payload, so the resulting code will not use eval as:
    eval(base64_decode(...
    but other alternatives.

alternatives availability information:
create_function is available from PHP 4 & DEPRECATED from php > 7.2.0
Anonymous functions available from PHP > 5.3.0

@emanuelb

This comment has been minimized.

Show comment
Hide comment
@emanuelb

emanuelb Jul 8, 2017

Contributor

another possible solution is to use call_user_func or call_user_func_array functions https://secure.php.net/call_user_func
https://secure.php.net/manual/en/function.call-user-func-array.php
instead of eval when possible.

Contributor

emanuelb commented Jul 8, 2017

another possible solution is to use call_user_func or call_user_func_array functions https://secure.php.net/call_user_func
https://secure.php.net/manual/en/function.call-user-func-array.php
instead of eval when possible.

@jvoisin

This comment has been minimized.

Show comment
Hide comment
@jvoisin

jvoisin Jul 9, 2017

Contributor

I don't think that an encoder would be the right solution, since a search'n'replace for eval( with something else might completely screw the payload.

Contributor

jvoisin commented Jul 9, 2017

I don't think that an encoder would be the right solution, since a search'n'replace for eval( with something else might completely screw the payload.

@sempervictus

This comment has been minimized.

Show comment
Hide comment
@sempervictus

sempervictus Jul 15, 2017

Contributor

Is suhosin reading the php text calling eval, or intercepting the interpreters call site for it?

Contributor

sempervictus commented Jul 15, 2017

Is suhosin reading the php text calling eval, or intercepting the interpreters call site for it?

@jvoisin

This comment has been minimized.

Show comment
Hide comment
@jvoisin

jvoisin Jul 16, 2017

Contributor

It hooks the call to eval, but there are several other functions that are using the internal function called by eval.

Contributor

jvoisin commented Jul 16, 2017

It hooks the call to eval, but there are several other functions that are using the internal function called by eval.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment