From d4e9bb339360cb7d6ece5b1b60c08c8611bac19c Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Wed, 24 Feb 2016 23:33:34 +0100 Subject: executor improvements --- execute_ih.c | 495 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 495 insertions(+) create mode 100644 execute_ih.c (limited to 'execute_ih.c') diff --git a/execute_ih.c b/execute_ih.c new file mode 100644 index 0000000..fa511b9 --- /dev/null +++ b/execute_ih.c @@ -0,0 +1,495 @@ +#include "php.h" +#include "php_suhosin7.h" +#include "execute.h" + +// #ifdef SUHOSIN7_PREG_REPLACE_NULL +// preg_replace \0 protection may be redundant, because PHP already checks for \0 +S7_IH_FUNCTION(preg_replace) +{ + zval *regex, *replace, *subject, *zcount = NULL; + zend_long limit = -1; + // int replace_count; + +#ifndef FAST_ZPP + /* Get function parameters and do error-checking. */ + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|lz/", ®ex, &replace, &subject, &limit, &zcount) == FAILURE) { + return FAILURE; + } +#else + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_ZVAL(regex) + Z_PARAM_ZVAL(replace) + Z_PARAM_ZVAL(subject) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(limit) + Z_PARAM_ZVAL_EX(zcount, 0, 1) + ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); +#endif + + if (Z_TYPE_P(regex) != IS_ARRAY) { + convert_to_string_ex(regex); + // regex is string + + if (strlen(Z_STRVAL_P(regex)) != Z_STRLEN_P(regex)) { + suhosin_log(S_EXECUTOR, "string termination attack on first preg_replace parameter detected"); + if (!SUHOSIN7_G(simulation)) { + RETVAL_NULL(); + return FAILURE; + } + } + } else { + // regex is array + + /* For each entry in the regex array, get the entry */ + zval *regex_entry; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(regex), regex_entry) { + /* Make sure we're dealing with strings. */ + zend_string *regex_str = zval_get_string(regex_entry); + + if (strlen(ZSTR_VAL(regex_str)) != ZSTR_LEN(regex_str)) { + suhosin_log(S_EXECUTOR, "string termination attack on first preg_replace parameter detected"); + if (!SUHOSIN7_G(simulation)) { + RETVAL_NULL(); + zend_string_release(regex_str); + return FAILURE; + } + } + + zend_string_release(regex_str); + } ZEND_HASH_FOREACH_END(); + + } + + return SUCCESS; +} + +// #endif /* SUHOSIN7_PREG_REPLACE_NULL */ + + +// int ih_symlink(IH_HANDLER_PARAMS) +// { +// if (SUHOSIN7_G(executor_allow_symlink)) { +// return (0); +// } +// +// if (PG(open_basedir) && PG(open_basedir)[0]) { +// suhosin_log(S_EXECUTOR, "symlink called during open_basedir"); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// +// return (0); +// } + +// int ih_mail(IH_HANDLER_PARAMS) +// { +// char *to=NULL, *message=NULL, *headers=NULL; +// char *subject=NULL, *extra_cmd=NULL; +// char *tmp; +// int to_len, message_len, headers_len; +// int subject_len, extra_cmd_len; +// +// if (SUHOSIN7_G(mailprotect) == 0) { +// return (0); +// } +// +// if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|ss", +// &to, &to_len, +// &subject, &subject_len, +// &message, &message_len, +// &headers, &headers_len, +// &extra_cmd, &extra_cmd_len +// ) == FAILURE) { +// RETVAL_FALSE; +// return (1); +// } +// +// if (headers_len > 0 && headers && +// (strstr(headers, "\n\n") || strstr(headers, "\n\r\n") /* double newline */ +// || *headers == '\n' || (headers[0] == '\r' && headers[1] == '\n') /* starts with newline */ +// )) { +// suhosin_log(S_MAIL, "mail() - double newline in headers, possible injection, mail dropped"); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// +// /* check for spam attempts with buggy webforms */ +// if (to_len > 0 && to) { +// do { +// if ((tmp = strchr(to, '\n')) == NULL) +// tmp = strchr(to, '\r'); +// if (tmp == NULL) break; +// to = tmp + 1; +// if (!isspace(*to)) break; +// } while (1); +// if (tmp != NULL) { +// suhosin_log(S_MAIL, "mail() - newline in To header, possible injection, mail dropped"); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// } +// +// if (subject_len > 0 && subject) { +// do { +// if ((tmp = strchr(subject, '\n')) == NULL) +// tmp = strchr(subject, '\r'); +// if (tmp == NULL) break; +// subject = tmp + 1; +// if (!isspace(*subject)) break; +// } while (1); +// if (tmp != NULL) { +// suhosin_log(S_MAIL, "mail() - newline in Subject header, possible injection, mail dropped"); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// } +// +// if (SUHOSIN7_G(mailprotect) > 1) { +// /* search for to, cc or bcc headers */ +// if (headers_len > 0 && headers != NULL) { +// if (strncasecmp(headers, "to:", sizeof("to:") - 1) == 0 || suhosin_strcasestr(headers, "\nto:")) { +// suhosin_log(S_MAIL, "mail() - To: headers aren't allowed in the headers parameter."); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// +// if (strncasecmp(headers, "cc:", sizeof("cc:") - 1) == 0 || suhosin_strcasestr(headers, "\ncc:")) { +// suhosin_log(S_MAIL, "mail() - CC: headers aren't allowed in the headers parameter."); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// +// if (strncasecmp(headers, "bcc:", sizeof("bcc:") - 1) == 0 || suhosin_strcasestr(headers, "\nbcc:")) { +// suhosin_log(S_MAIL, "mail() - BCC: headers aren't allowed in the headers parameter."); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// } +// } +// +// return (0); +// } + +// #define SQLSTATE_SQL 0 +// #define SQLSTATE_IDENTIFIER 1 +// #define SQLSTATE_STRING 2 +// #define SQLSTATE_COMMENT 3 +// #define SQLSTATE_MLCOMMENT 4 +// +// int ih_querycheck(IH_HANDLER_PARAMS) +// { +// void **p = zend_vm_stack_top() - 1; +// unsigned long arg_count; +// zval **arg; +// char *query, *s, *e; +// zval *backup; +// int len; +// char quote; +// int state = SQLSTATE_SQL; +// int cnt_union = 0, cnt_select = 0, cnt_comment = 0, cnt_opencomment = 0; +// int mysql_extension = 0; +// +// +// SDEBUG("function: %s", ih->name); +// arg_count = (unsigned long) *p; +// +// if (ht < (long) ih->arg1) { +// return (0); +// } +// +// if ((long) ih->arg2) { +// mysql_extension = 1; +// } +// +// arg = (zval **) p - (arg_count - (long) ih->arg1 + 1); /* count from 0 */ +// +// backup = *arg; +// if (Z_TYPE_P(backup) != IS_STRING) { +// return (0); +// } +// len = Z_STRLEN_P(backup); +// query = Z_STRVAL_P(backup); +// SDEBUG("SQL |%s|", query); +// +// s = query; +// e = s+len; +// +// while (s < e) { +// switch (state) +// { +// case SQLSTATE_SQL: +// switch (s[0]) +// { +// case '`': +// state = SQLSTATE_IDENTIFIER; +// quote = '`'; +// break; +// case '\'': +// case '"': +// state = SQLSTATE_STRING; +// quote = *s; +// break; +// case '/': +// if (s[1]=='*') { +// if (mysql_extension == 1 && s[2] == '!') { +// s += 2; +// break; +// } +// s++; +// state = SQLSTATE_MLCOMMENT; +// cnt_comment++; +// } +// break; +// case '-': +// if (s[1]=='-') { +// s++; +// state = SQLSTATE_COMMENT; +// cnt_comment++; +// } +// break; +// case '#': +// state = SQLSTATE_COMMENT; +// cnt_comment++; +// break; +// case 'u': +// case 'U': +// if (strncasecmp("union", s, 5)==0) { +// s += 4; +// cnt_union++; +// } +// break; +// case 's': +// case 'S': +// if (strncasecmp("select", s, 6)==0) { +// s += 5; +// cnt_select++; +// } +// break; +// } +// break; +// case SQLSTATE_STRING: +// case SQLSTATE_IDENTIFIER: +// if (s[0] == quote) { +// if (s[1] == quote) { +// s++; +// } else { +// state = SQLSTATE_SQL; +// } +// } +// if (s[0] == '\\') { +// s++; +// } +// break; +// case SQLSTATE_COMMENT: +// while (s[0] && s[0] != '\n') { +// s++; +// } +// state = SQLSTATE_SQL; +// break; +// case SQLSTATE_MLCOMMENT: +// while (s[0] && (s[0] != '*' || s[1] != '/')) { +// s++; +// } +// if (s[0]) { +// state = SQLSTATE_SQL; +// } +// break; +// } +// s++; +// } +// if (state == SQLSTATE_MLCOMMENT) { +// cnt_opencomment = 1; +// } +// +// if (cnt_opencomment && SUHOSIN7_G(sql_opencomment)>0) { +// suhosin_log(S_SQL, "Open comment in SQL query: '%*s'", len, query); +// if (SUHOSIN7_G(sql_opencomment)>1) { +// suhosin_bailout(); +// } +// } +// +// if (cnt_comment && SUHOSIN7_G(sql_comment)>0) { +// suhosin_log(S_SQL, "Comment in SQL query: '%*s'", len, query); +// if (SUHOSIN7_G(sql_comment)>1) { +// suhosin_bailout(); +// } +// } +// +// if (cnt_union && SUHOSIN7_G(sql_union)>0) { +// suhosin_log(S_SQL, "UNION in SQL query: '%*s'", len, query); +// if (SUHOSIN7_G(sql_union)>1) { +// suhosin_bailout(); +// } +// } +// +// if (cnt_select>1 && SUHOSIN7_G(sql_mselect)>0) { +// suhosin_log(S_SQL, "Multiple SELECT in SQL query: '%*s'", len, query); +// if (SUHOSIN7_G(sql_mselect)>1) { +// suhosin_bailout(); +// } +// } +// +// return (0); +// } +// +// +// int ih_fixusername(IH_HANDLER_PARAMS) +// { +// void **p = zend_vm_stack_top() - 1; +// unsigned long arg_count; +// zval **arg; +// char *prefix, *postfix, *user, *user_match, *cp; +// zval *backup, *my_user; +// int prefix_len, postfix_len, len; +// +// SDEBUG("function (fixusername): %s", ih->name); +// +// prefix = SUHOSIN7_G(sql_user_prefix); +// postfix = SUHOSIN7_G(sql_user_postfix); +// user_match = SUHOSIN7_G(sql_user_match); +// +// arg_count = (unsigned long) *p; +// +// if (ht < (long) ih->arg1) { +// return (0); +// } +// +// arg = (zval **) p - (arg_count - (long) ih->arg1 + 1); /* count from 0 */ +// +// backup = *arg; +// if (Z_TYPE_P(backup) != IS_STRING) { +// user = ""; +// len = 0; +// } else { +// len = Z_STRLEN_P(backup); +// user = Z_STRVAL_P(backup); +// } +// +// cp = user; +// while (cp < user+len) { +// if (*cp < 32) { +// suhosin_log(S_SQL, "SQL username contains invalid characters"); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// break; +// } +// cp++; +// } +// +// if ((prefix != NULL && prefix[0]) || (postfix != NULL && postfix[0])) { +// if (prefix == NULL) { +// prefix = ""; +// } +// if (postfix == NULL) { +// postfix = ""; +// } +// prefix_len = strlen(prefix); +// postfix_len = strlen(postfix); +// +// MAKE_STD_ZVAL(my_user); +// my_user->type = IS_STRING; +// my_user->value.str.len = spprintf(&my_user->value.str.val, 0, "%s%s%s", prefix, user, postfix); +// +// /* XXX: memory_leak? */ +// *arg = my_user; +// +// len = Z_STRLEN_P(my_user); +// user = Z_STRVAL_P(my_user); +// } +// +// if (user_match && user_match[0]) { +// #ifdef HAVE_FNMATCH +// if (fnmatch(user_match, user, 0) != 0) { +// suhosin_log(S_SQL, "SQL username ('%s') does not match suhosin.sql.user_match ('%s')", user, user_match); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// } +// #else +// #warning no support for fnmatch() - setting suhosin.sql.user_match will always fail. +// suhosin_log(S_SQL, "suhosin.sql.user_match specified, but system does not support fnmatch()"); +// if (!SUHOSIN7_G(simulation)) { +// RETVAL_FALSE; +// return (1); +// } +// #endif +// } +// +// SDEBUG("function: %s - user: %s", ih->name, user); +// +// return (0); +// } +// +// +// static int ih_function_exists(IH_HANDLER_PARAMS) +// { +// zval **function_name; +// zend_function *func; +// char *lcname; +// zend_bool retval; +// int func_name_len; +// +// if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &function_name)==FAILURE) { +// ZEND_WRONG_PARAM_COUNT_WITH_RETVAL(1); +// } +// convert_to_string_ex(function_name); +// func_name_len = Z_STRLEN_PP(function_name); +// lcname = estrndup(Z_STRVAL_PP(function_name), func_name_len); +// zend_str_tolower(lcname, func_name_len); +// +// retval = (zend_hash_find(EG(function_table), lcname, func_name_len+1, (void **)&func) == SUCCESS); +// +// /* +// * A bit of a hack, but not a bad one: we see if the handler of the function +// * is actually one that displays "function is disabled" message. +// */ +// if (retval && func->type == ZEND_INTERNAL_FUNCTION && +// func->internal_function.handler == zif_display_disabled_function) { +// retval = 0; +// } +// +// /* Now check if function is forbidden by Suhosin */ +// if (SUHOSIN7_G(in_code_type) == SUHOSIN_EVAL) { +// if (SUHOSIN7_G(eval_whitelist) != NULL) { +// if (!zend_hash_exists(SUHOSIN7_G(eval_whitelist), lcname, func_name_len+1)) { +// retval = 0; +// } +// } else if (SUHOSIN7_G(eval_blacklist) != NULL) { +// if (zend_hash_exists(SUHOSIN7_G(eval_blacklist), lcname, func_name_len+1)) { +// retval = 0; +// } +// } +// } +// +// if (SUHOSIN7_G(func_whitelist) != NULL) { +// if (!zend_hash_exists(SUHOSIN7_G(func_whitelist), lcname, func_name_len+1)) { +// retval = 0; +// } +// } else if (SUHOSIN7_G(func_blacklist) != NULL) { +// if (zend_hash_exists(SUHOSIN7_G(func_blacklist), lcname, func_name_len+1)) { +// retval = 0; +// } +// } +// +// efree(lcname); +// +// RETVAL_BOOL(retval); +// return (1); +// } -- cgit v1.3