Did you fail school today

The disable_function in PHP is obtained by EG(ini_directives), and PHPInfo obtains the information according to EG(ini_directives) and prints it.The zend_disable_function() function is then used to disable it, simply by passing itfunc->handler = ZEND_FN(display_disabled_function);Modified handler.Phpinfo has always been a reliable way to view server PHP information, but after an attack on FPM that included a parameter change to Disable_function, phpInfo has shown the changes, but the test function is still disabled. In the configuration of the FPM attack EG(ini_DIRECTIVES) finds the INI_entry representing DISABle_functions and then modifies the value to what we pass in and the value shown in PHPInfo is derived from there.It also passes the disabled function string to the fpM_PHp_disable function and calls the zend_disable_function function to modify func->handler to disable the function.

Therefore, a malicious FastCgi attack on FPM containing PHP_VALUE == DISABle_function = can only modify the display phpInfo information

The EG(ini_DIRECTIVES), that is, surface modifications, are not effective for already disabled functions, but new functions can be disabled by FPM.

Disable_function is disabled by func->handler. For malicious FastCgi attacks on FPM containing PHP_VALUE == DISABLE_function =, only the EG(ini_DIRECTIVES) that show PHPInfo information can be modified, that is, surface modifications are not effective for already disabled functions, However, new functions can be disabled through FPM. Common and effective options for FPM attacks are extension_DIR +extension, open_basedir, allow_URl_include = On + auto_prepend_file = PHP ://input.

So I see the introduction of FPM to bypass disable_function. So how? What’s at the bottom?

FPM can bypass DF by configuring PHP_VALUE == extension_DIR +extension, and then we upload our so to load the execution. Loading so can bypass??

Because df is loaded at the last step of the module initialization phase and so is loaded before this probably rCE is caused by thisHere’s the clear one.So you can get around

LD_PRELOAD is used in conjunction with putenv, where the environment variable LD_PRELOAD specifies a path (which is also a SO file) and putenv sets environment variables before any other files.

We introduced a PHP function, which I think can fork a child process during execution. Then we hook the child process and rewrite it to complete rCE.

Such as:

Mail (', ' ' ' ' ', ' '); #include <stdlib.h> #include <stdio.h> #include <string.h> void payload() { system("ls / > /tmp/sky"); } int geteuid() { if (getenv("LD_PRELOAD") == NULL) { return 0; } unsetenv("LD_PRELOAD"); payload(); C -o hack.so there are imap_mail(), mb_send_mail(), error_log(), etc #include <stdlib.h> #include <unistd.h> #include <sys/types.h> __attribute__ ((__constructor__)) void angel (void){ unsetenv("LD_PRELOAD"); system("ls"); }Copy the code

__attribute__ ((constructor)) is described as follows

1.It’s run when a shared library is loaded, typically during program startup. 2.That’s how all GCC attributes are; presumably to distinguish them from function calls. 3.The destructor is run when the shared library is unloaded, typically at program exit.

1. It runs when the shared library is loaded, usually when the program is started. //putenv(“LD_PRELOAD=hack.so”); 2. This is true for all GCC attributes; Probably to distinguish them from function calls. 3. The destructor is run when the shared library is uninstalled, usually when the program exits. So we don’t need to find a function to trigger.