diff options
| author | Ben Fuhrmannek | 2016-02-26 19:07:18 +0100 |
|---|---|---|
| committer | Ben Fuhrmannek | 2016-02-26 19:07:18 +0100 |
| commit | adbeda7daaa6ff3a1fbc25d35cc62a1979214f7f (patch) | |
| tree | ebbc74b74106fe4d4d5dcb6e760dc6cdbaa322c8 /execute.c | |
| parent | 09d9dfaaa94c69125ceb388c69bc18237837eec9 (diff) | |
executor / include protection
Diffstat (limited to 'execute.c')
| -rw-r--r-- | execute.c | 446 |
1 files changed, 190 insertions, 256 deletions
| @@ -39,16 +39,16 @@ | |||
| 39 | 39 | ||
| 40 | // #include "sha256.h" | 40 | // #include "sha256.h" |
| 41 | 41 | ||
| 42 | #ifdef PHP_WIN32 | 42 | // #ifdef PHP_WIN32 |
| 43 | // # include "win32/fnmatch.h" | 43 | // # include "win32/fnmatch.h" |
| 44 | # include "win32/winutil.h" | 44 | // # include "win32/winutil.h" |
| 45 | # include "win32/time.h" | 45 | // # include "win32/time.h" |
| 46 | #else | 46 | // #else |
| 47 | // # ifdef HAVE_FNMATCH | 47 | // # ifdef HAVE_FNMATCH |
| 48 | // # include <fnmatch.h> | 48 | // # include <fnmatch.h> |
| 49 | // # endif | 49 | // # endif |
| 50 | # include <sys/time.h> | 50 | // # include <sys/time.h> |
| 51 | #endif | 51 | // #endif |
| 52 | 52 | ||
| 53 | ZEND_API static void (*old_execute_ex)(zend_execute_data *execute_data); | 53 | ZEND_API static void (*old_execute_ex)(zend_execute_data *execute_data); |
| 54 | ZEND_API static void suhosin_execute_ex(zend_execute_data *execute_data); | 54 | ZEND_API static void suhosin_execute_ex(zend_execute_data *execute_data); |
| @@ -63,8 +63,9 @@ ZEND_API static void suhosin_execute(zend_op_array *op_array, zval *return_value | |||
| 63 | 63 | ||
| 64 | // extern zend_extension suhosin_zend_extension_entry; | 64 | // extern zend_extension suhosin_zend_extension_entry; |
| 65 | 65 | ||
| 66 | #ifdef SUHOSIN_STRCASESTR | ||
| 66 | /* {{{ suhosin_strcasestr */ | 67 | /* {{{ suhosin_strcasestr */ |
| 67 | static char *suhosin_strcasestr(char *haystack, char *needle) | 68 | char *suhosin_strcasestr(char *haystack, char *needle) |
| 68 | { | 69 | { |
| 69 | unsigned char *t, *h, *n; | 70 | unsigned char *t, *h, *n; |
| 70 | h = (unsigned char *) haystack; | 71 | h = (unsigned char *) haystack; |
| @@ -82,7 +83,33 @@ conts: | |||
| 82 | return (NULL); | 83 | return (NULL); |
| 83 | } | 84 | } |
| 84 | /* }}} */ | 85 | /* }}} */ |
| 86 | #endif | ||
| 85 | 87 | ||
| 88 | static int match_include_list(HashTable *ht, char *s, size_t slen) | ||
| 89 | { | ||
| 90 | char *h = strstr(s, "://"); | ||
| 91 | char *h2 = suhosin_strcasestr(s, "data:"); | ||
| 92 | h2 = h2 == NULL ? NULL : h2 + 4; | ||
| 93 | char *t = h = (h == NULL) ? h2 : ( (h2 == NULL) ? h : ( (h <= h2) ? h : h2 ) ); | ||
| 94 | if (h == NULL) return -1; // no URL | ||
| 95 | |||
| 96 | while (t > s && (isalnum(t[-1]) || t[-1]=='_' || t[-1]=='.')) { | ||
| 97 | t--; | ||
| 98 | } | ||
| 99 | |||
| 100 | size_t tlen = slen - (t - s); | ||
| 101 | |||
| 102 | zend_ulong num_key; | ||
| 103 | zend_string *key; | ||
| 104 | ZEND_HASH_FOREACH_KEY(ht, num_key, key) { | ||
| 105 | if (tlen < ZSTR_LEN(key)) { continue; } | ||
| 106 | if (ZSTR_LEN(key) == 0) { continue; } // ignore empty list entries | ||
| 107 | if (strncasecmp(t, ZSTR_VAL(key), ZSTR_LEN(key)) == 0) { | ||
| 108 | return 1; | ||
| 109 | } | ||
| 110 | } ZEND_HASH_FOREACH_END(); | ||
| 111 | return 0; | ||
| 112 | } | ||
| 86 | 113 | ||
| 87 | #define SUHOSIN_CODE_TYPE_UNKNOWN 0 | 114 | #define SUHOSIN_CODE_TYPE_UNKNOWN 0 |
| 88 | #define SUHOSIN_CODE_TYPE_COMMANDLINE 1 | 115 | #define SUHOSIN_CODE_TYPE_COMMANDLINE 1 |
| @@ -102,137 +129,65 @@ conts: | |||
| 102 | #define SUHOSIN_CODE_TYPE_WRITABLE 15 | 129 | #define SUHOSIN_CODE_TYPE_WRITABLE 15 |
| 103 | #define SUHOSIN_CODE_TYPE_MBREGEXP 16 | 130 | #define SUHOSIN_CODE_TYPE_MBREGEXP 16 |
| 104 | 131 | ||
| 105 | static int suhosin_check_filename(char *s, int len) | 132 | static int suhosin_check_filename(char *s, int slen) |
| 106 | { | 133 | { |
| 107 | char fname[MAXPATHLEN+1]; | ||
| 108 | char *t, *h, *h2, *index, *e; | ||
| 109 | int tlen, i, count=0; | ||
| 110 | uint indexlen; | ||
| 111 | ulong numindex; | ||
| 112 | zend_bool isOk; | ||
| 113 | |||
| 114 | /* check if filename is too long */ | 134 | /* check if filename is too long */ |
| 115 | if (len > MAXPATHLEN) { | 135 | if (slen > MAXPATHLEN) { |
| 116 | return SUHOSIN_CODE_TYPE_LONGNAME; | 136 | return SUHOSIN_CODE_TYPE_LONGNAME; |
| 117 | } | 137 | } |
| 118 | memcpy(fname, s, len); | 138 | |
| 119 | fname[len] = 0; | 139 | char fname[MAXPATHLEN+1]; |
| 120 | s = (char *)&fname; | 140 | |
| 121 | e = s + len; | 141 | memcpy(fname, s, slen); |
| 142 | fname[slen] = 0; | ||
| 143 | s = (char *)fname; | ||
| 144 | char *e = s + slen; | ||
| 122 | 145 | ||
| 123 | /* check if ASCIIZ attack */ | 146 | /* check if ASCIIZ attack */ |
| 124 | if (len != strlen(s)) { | 147 | if (slen != strlen(s)) { |
| 125 | return SUHOSIN_CODE_TYPE_0FILE; | 148 | return SUHOSIN_CODE_TYPE_0FILE; |
| 126 | } | 149 | } |
| 127 | 150 | ||
| 151 | SDEBUG("fn=%s", s); | ||
| 128 | /* disallow uploaded files */ | 152 | /* disallow uploaded files */ |
| 129 | if (SG(rfc1867_uploaded_files)) { | 153 | if (SG(rfc1867_uploaded_files)) { |
| 130 | if (zend_hash_str_exists(SG(rfc1867_uploaded_files), (char *) s, e-s+1)) { // <--- TODO: range check | 154 | if (zend_hash_str_exists(SG(rfc1867_uploaded_files), s, slen)) { // <--- TODO: range check |
| 131 | return SUHOSIN_CODE_TYPE_UPLOADED; | 155 | return SUHOSIN_CODE_TYPE_UPLOADED; |
| 132 | } | 156 | } |
| 133 | } | 157 | } |
| 134 | 158 | ||
| 135 | /* count number of directory traversals */ | 159 | /* count number of directory traversals */ |
| 136 | for (i=0; i < len-3; i++) { | 160 | int traversal_conut = 0; |
| 137 | if (s[i] == '.' && s[i+1] == '.' && (s[i+2] == '/' || s[i+2] == '\\')) { | 161 | for (int i = 0; i < slen-3; i++) { |
| 138 | count++; | 162 | if (s[i] == '.' && s[i+1] == '.' && IS_SLASH(s[i+2])) { |
| 139 | i+=2; | 163 | traversal_conut++; |
| 164 | i += 2; | ||
| 140 | } | 165 | } |
| 141 | } | 166 | } |
| 142 | if (SUHOSIN7_G(executor_include_max_traversal) && SUHOSIN7_G(executor_include_max_traversal)<=count) { | 167 | if (SUHOSIN7_G(executor_include_max_traversal) && traversal_conut > SUHOSIN7_G(executor_include_max_traversal)) { |
| 143 | return SUHOSIN_CODE_TYPE_MANYDOTS; | 168 | return SUHOSIN_CODE_TYPE_MANYDOTS; |
| 144 | } | 169 | } |
| 145 | 170 | ||
| 146 | SDEBUG("xxx %p %p",SUHOSIN7_G(include_whitelist),SUHOSIN7_G(include_blacklist)); | 171 | SDEBUG("include wl=%p bl=%p", SUHOSIN7_G(include_whitelist), SUHOSIN7_G(include_blacklist)); |
| 147 | /* no black or whitelist then disallow all */ | 172 | /* no black or whitelist then disallow all */ |
| 148 | if (SUHOSIN7_G(include_whitelist)==NULL && SUHOSIN7_G(include_blacklist)==NULL) { | 173 | if (SUHOSIN7_G(include_whitelist) == NULL && SUHOSIN7_G(include_blacklist) == NULL) { |
| 149 | /* disallow all URLs */ | 174 | /* disallow all URLs */ |
| 150 | if (strstr(s, "://") != NULL || suhosin_strcasestr(s, "data:") != NULL) { | 175 | if (strstr(s, "://") != NULL || suhosin_strcasestr(s, "data:") != NULL) { |
| 151 | return SUHOSIN_CODE_TYPE_BADURL; | 176 | return SUHOSIN_CODE_TYPE_BADURL; |
| 152 | } | 177 | } |
| 153 | } else | 178 | } else { |
| 154 | /* whitelist is stronger than blacklist */ | 179 | if (SUHOSIN7_G(include_whitelist) != NULL) { |
| 155 | // if (SUHOSIN7_G(include_whitelist)) { | 180 | if (match_include_list(SUHOSIN7_G(include_whitelist), s, slen) == 0) { |
| 156 | // | 181 | return SUHOSIN_CODE_TYPE_BADURL; |
| 157 | // do { | 182 | } |
| 158 | // isOk = 0; | 183 | } else if (SUHOSIN7_G(include_blacklist) != NULL) { |
| 159 | // | 184 | if (match_include_list(SUHOSIN7_G(include_blacklist), s, slen) == 1) { |
| 160 | // h = strstr(s, "://"); | 185 | return SUHOSIN_CODE_TYPE_BLACKURL; |
| 161 | // h2 = suhosin_strcasestr(s, "data:"); | 186 | } |
| 162 | // h2 = h2 == NULL ? NULL : h2 + 4; | 187 | } |
| 163 | // t = h = (h == NULL) ? h2 : ( (h2 == NULL) ? h : ( (h < h2) ? h : h2 ) ); | 188 | } |
| 164 | // if (h == NULL) break; | 189 | |
| 165 | // | 190 | check_filename_skip_lists: |
| 166 | // while (t > s && (isalnum(t[-1]) || t[-1]=='_' || t[-1]=='.')) { | ||
| 167 | // t--; | ||
| 168 | // } | ||
| 169 | // | ||
| 170 | // tlen = e-t; | ||
| 171 | // | ||
| 172 | // zend_hash_internal_pointer_reset(SUHOSIN7_G(include_whitelist)); | ||
| 173 | // do { | ||
| 174 | // int r = zend_hash_get_current_key_ex(SUHOSIN7_G(include_whitelist), &index, &indexlen, &numindex, 0, NULL); | ||
| 175 | // | ||
| 176 | // if (r==HASH_KEY_NON_EXISTANT) { | ||
| 177 | // break; | ||
| 178 | // } | ||
| 179 | // if (r==HASH_KEY_IS_STRING) { | ||
| 180 | // if (h-t <= indexlen-1 && tlen>=indexlen-1) { | ||
| 181 | // if (strncasecmp(t, index, indexlen-1)==0) { | ||
| 182 | // isOk = 1; | ||
| 183 | // break; | ||
| 184 | // } | ||
| 185 | // } | ||
| 186 | // } | ||
| 187 | // | ||
| 188 | // zend_hash_move_forward(SUHOSIN7_G(include_whitelist)); | ||
| 189 | // } while (1); | ||
| 190 | // | ||
| 191 | // /* not found in whitelist */ | ||
| 192 | // if (!isOk) { | ||
| 193 | // return SUHOSIN_CODE_TYPE_BADURL; | ||
| 194 | // } | ||
| 195 | // | ||
| 196 | // s = h + 1; | ||
| 197 | // } while (1); | ||
| 198 | // } else { | ||
| 199 | // | ||
| 200 | // do { | ||
| 201 | // int tlen; | ||
| 202 | // | ||
| 203 | // h = strstr(s, "://"); | ||
| 204 | // h2 = suhosin_strcasestr(s, "data:"); | ||
| 205 | // h2 = h2 == NULL ? NULL : h2 + 4; | ||
| 206 | // t = h = (h == NULL) ? h2 : ( (h2 == NULL) ? h : ( (h < h2) ? h : h2 ) ); | ||
| 207 | // if (h == NULL) break; | ||
| 208 | // | ||
| 209 | // while (t > s && (isalnum(t[-1]) || t[-1]=='_' || t[-1]=='.')) { | ||
| 210 | // t--; | ||
| 211 | // } | ||
| 212 | // | ||
| 213 | // tlen = e-t; | ||
| 214 | // | ||
| 215 | // zend_hash_internal_pointer_reset(SUHOSIN7_G(include_blacklist)); | ||
| 216 | // do { | ||
| 217 | // int r = zend_hash_get_current_key_ex(SUHOSIN7_G(include_blacklist), &index, &indexlen, &numindex, 0, NULL); | ||
| 218 | // | ||
| 219 | // if (r==HASH_KEY_NON_EXISTANT) { | ||
| 220 | // break; | ||
| 221 | // } | ||
| 222 | // if (r==HASH_KEY_IS_STRING) { | ||
| 223 | // if (h-t <= indexlen-1 && tlen>=indexlen-1) { | ||
| 224 | // if (strncasecmp(t, index, indexlen-1)==0) { | ||
| 225 | // return SUHOSIN_CODE_TYPE_BLACKURL; | ||
| 226 | // } | ||
| 227 | // } | ||
| 228 | // } | ||
| 229 | // | ||
| 230 | // zend_hash_move_forward(SUHOSIN7_G(include_blacklist)); | ||
| 231 | // } while (1); | ||
| 232 | // | ||
| 233 | // s = h + 1; | ||
| 234 | // } while (1); | ||
| 235 | // } | ||
| 236 | 191 | ||
| 237 | /* disallow writable files */ | 192 | /* disallow writable files */ |
| 238 | if (!SUHOSIN7_G(executor_include_allow_writable_files)) { | 193 | if (!SUHOSIN7_G(executor_include_allow_writable_files)) { |
| @@ -247,57 +202,116 @@ static int suhosin_check_filename(char *s, int len) | |||
| 247 | } | 202 | } |
| 248 | 203 | ||
| 249 | 204 | ||
| 250 | // ZEND_API static int (*old_zend_stream_open)(const char *filename, zend_file_handle *handle); | 205 | static void suhosin_check_codetype(zend_ulong code_type, char *filename) |
| 251 | // | 206 | { |
| 252 | // static int suhosin_zend_stream_open(const char *filename, zend_file_handle *fh) | 207 | switch (code_type) { |
| 253 | // { | 208 | case SUHOSIN_CODE_TYPE_EVAL: |
| 254 | // zend_execute_data *exd; | 209 | if (SUHOSIN7_G(executor_disable_eval)) { |
| 255 | // exd=EG(current_execute_data); | 210 | suhosin_log(S_EXECUTOR|S_GETCALLER, "use of eval is forbidden by configuration"); |
| 256 | // if (EG(in_execution) && (exd!=NULL) && (exd->opline != NULL) && (exd->opline->opcode == ZEND_INCLUDE_OR_EVAL)) { | 211 | if (!SUHOSIN7_G(simulation)) { |
| 257 | // int filetype = suhosin_check_filename((char *)filename, strlen(filename)); | 212 | zend_error(E_ERROR, "SUHOSIN - Use of eval is forbidden by configuration"); |
| 258 | // | 213 | } |
| 259 | // switch (filetype) { | 214 | } |
| 260 | // case SUHOSIN_CODE_TYPE_LONGNAME: | 215 | break; |
| 261 | // suhosin_log(S_INCLUDE, "Include filename ('%s') is too long", filename); | 216 | |
| 262 | // suhosin_bailout(); | 217 | // case SUHOSIN_CODE_TYPE_REGEXP: |
| 263 | // break; | 218 | // if (SUHOSIN7_G(executor_disable_emod)) { |
| 264 | // | 219 | // suhosin_log(S_EXECUTOR|S_GETCALLER, "use of preg_replace() with /e modifier is forbidden by configuration"); |
| 265 | // case SUHOSIN_CODE_TYPE_UPLOADED: | 220 | // if (!SUHOSIN7_G(simulation)) { |
| 266 | // suhosin_log(S_INCLUDE, "Include filename is an uploaded file"); | 221 | // zend_error(E_ERROR, "SUHOSIN - Use of preg_replace() with /e modifier is forbidden by configuration"); |
| 267 | // suhosin_bailout(); | 222 | // } |
| 268 | // break; | 223 | // } |
| 269 | // | 224 | // break; |
| 270 | // case SUHOSIN_CODE_TYPE_0FILE: | 225 | |
| 271 | // suhosin_log(S_INCLUDE, "Include filename contains an ASCIIZ character"); | 226 | case SUHOSIN_CODE_TYPE_MBREGEXP: |
| 272 | // suhosin_bailout(); | 227 | if (SUHOSIN7_G(executor_disable_emod)) { |
| 273 | // break; | 228 | suhosin_log(S_EXECUTOR|S_GETCALLER, "use of /e modifier in replace function is forbidden by configuration"); |
| 274 | // | 229 | if (!SUHOSIN7_G(simulation)) { |
| 275 | // case SUHOSIN_CODE_TYPE_WRITABLE: | 230 | zend_error(E_ERROR, "SUHOSIN - Use of /e modifier in replace function is forbidden by configuration"); |
| 276 | // suhosin_log(S_INCLUDE, "Include filename ('%s') is writable by PHP process", filename); | 231 | } |
| 277 | // suhosin_bailout(); | 232 | } |
| 278 | // break; | 233 | break; |
| 279 | // | 234 | |
| 280 | // case SUHOSIN_CODE_TYPE_BLACKURL: | 235 | case SUHOSIN_CODE_TYPE_ASSERT: |
| 281 | // suhosin_log(S_INCLUDE, "Include filename ('%s') is a URL that is forbidden by the blacklist", filename); | 236 | break; |
| 282 | // suhosin_bailout(); | 237 | |
| 283 | // break; | 238 | case SUHOSIN_CODE_TYPE_CFUNC: |
| 284 | // | 239 | break; |
| 285 | // case SUHOSIN_CODE_TYPE_BADURL: | 240 | |
| 286 | // suhosin_log(S_INCLUDE, "Include filename ('%s') is a URL that is not allowed", filename); | 241 | case SUHOSIN_CODE_TYPE_LONGNAME: |
| 287 | // suhosin_bailout(); | 242 | suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename is too long: %s", filename); |
| 288 | // break; | 243 | suhosin_bailout(); |
| 244 | break; | ||
| 245 | |||
| 246 | case SUHOSIN_CODE_TYPE_MANYDOTS: | ||
| 247 | suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename contains too many '../': %s", filename); | ||
| 248 | suhosin_bailout(); | ||
| 249 | break; | ||
| 250 | |||
| 251 | case SUHOSIN_CODE_TYPE_UPLOADED: | ||
| 252 | suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename is an uploaded file"); | ||
| 253 | suhosin_bailout(); | ||
| 254 | break; | ||
| 255 | |||
| 256 | case SUHOSIN_CODE_TYPE_0FILE: | ||
| 257 | suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename contains an ASCIIZ character"); | ||
| 258 | suhosin_bailout(); | ||
| 259 | break; | ||
| 260 | |||
| 261 | case SUHOSIN_CODE_TYPE_WRITABLE: | ||
| 262 | suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename is writable by PHP process: %s", filename); | ||
| 263 | suhosin_bailout(); | ||
| 264 | break; | ||
| 265 | |||
| 266 | case SUHOSIN_CODE_TYPE_BLACKURL: | ||
| 267 | suhosin_log(S_INCLUDE|S_GETCALLER, "Included URL is blacklisted: %s", filename); | ||
| 268 | suhosin_bailout(); | ||
| 269 | break; | ||
| 270 | |||
| 271 | case SUHOSIN_CODE_TYPE_BADURL: | ||
| 272 | suhosin_log(S_INCLUDE|S_GETCALLER, "Included URL is not allowed: %s", filename); | ||
| 273 | suhosin_bailout(); | ||
| 274 | break; | ||
| 275 | |||
| 276 | case SUHOSIN_CODE_TYPE_BADFILE: | ||
| 277 | // cs.type = IS_STRING; | ||
| 278 | // #define DIE_WITH_MSG "die('disallowed_file'.chr(10).chr(10));" | ||
| 279 | // cs.value.str.val = estrndup(DIE_WITH_MSG, sizeof(DIE_WITH_MSG)-1); | ||
| 280 | // cs.value.str.len = sizeof(DIE_WITH_MSG)-1; | ||
| 281 | // new_op_array = compile_string(&cs, "suhosin internal code"); | ||
| 282 | // if (new_op_array) { | ||
| 283 | // op_array = new_op_array; | ||
| 284 | // goto continue_execution; | ||
| 285 | // } | ||
| 286 | suhosin_bailout(); | ||
| 287 | break; | ||
| 288 | |||
| 289 | case SUHOSIN_CODE_TYPE_COMMANDLINE: | ||
| 290 | case SUHOSIN_CODE_TYPE_SUHOSIN: | ||
| 291 | case SUHOSIN_CODE_TYPE_UNKNOWN: | ||
| 292 | case SUHOSIN_CODE_TYPE_GOODFILE: | ||
| 293 | break; | ||
| 294 | } | ||
| 295 | |||
| 296 | } | ||
| 297 | |||
| 298 | ZEND_API static int (*old_zend_stream_open)(const char *filename, zend_file_handle *handle) = NULL; | ||
| 299 | |||
| 289 | // | 300 | // |
| 290 | // case SUHOSIN_CODE_TYPE_MANYDOTS: | 301 | ZEND_API static int suhosin_zend_stream_open(const char *filename, zend_file_handle *handle) |
| 291 | // suhosin_log(S_INCLUDE, "Include filename ('%s') contains too many '../'", filename); | 302 | { |
| 292 | // suhosin_bailout(); | 303 | zend_execute_data *execute_data = EG(current_execute_data); |
| 293 | // break; | 304 | |
| 294 | // } | 305 | if ((execute_data != NULL) && (execute_data->opline != NULL) && (execute_data->opline->opcode == ZEND_INCLUDE_OR_EVAL)) { |
| 295 | // } | 306 | int filetype = suhosin_check_filename((char *)filename, strlen(filename)); |
| 296 | // return old_zend_stream_open(filename, fh); | 307 | suhosin_check_codetype(filetype, (char*)filename); |
| 297 | // } | 308 | } |
| 309 | |||
| 310 | return old_zend_stream_open(filename, handle); | ||
| 311 | } | ||
| 298 | 312 | ||
| 299 | 313 | ||
| 300 | static int suhosin_detect_codetype(zend_op_array *op_array) | 314 | static inline int suhosin_detect_codetype(zend_op_array *op_array) |
| 301 | { | 315 | { |
| 302 | if (op_array->filename == NULL) { | 316 | if (op_array->filename == NULL) { |
| 303 | return SUHOSIN_CODE_TYPE_UNKNOWN; | 317 | return SUHOSIN_CODE_TYPE_UNKNOWN; |
| @@ -305,7 +319,7 @@ static int suhosin_detect_codetype(zend_op_array *op_array) | |||
| 305 | 319 | ||
| 306 | char *s = (char *)ZSTR_VAL(op_array->filename); | 320 | char *s = (char *)ZSTR_VAL(op_array->filename); |
| 307 | 321 | ||
| 308 | /* eval, assert, create_function, preg_replace */ | 322 | /* eval, assert, create_function, mb_ereg_replace */ |
| 309 | if (op_array->type == ZEND_EVAL_CODE) { | 323 | if (op_array->type == ZEND_EVAL_CODE) { |
| 310 | 324 | ||
| 311 | if (s == NULL) { | 325 | if (s == NULL) { |
| @@ -365,8 +379,13 @@ static int suhosin_detect_codetype(zend_op_array *op_array) | |||
| 365 | * This function provides a hook for execution */ | 379 | * This function provides a hook for execution */ |
| 366 | ZEND_API static void suhosin_execute_ex(zend_execute_data *execute_data) | 380 | ZEND_API static void suhosin_execute_ex(zend_execute_data *execute_data) |
| 367 | { | 381 | { |
| 368 | // SDEBUG("X------------------------->") | 382 | if (execute_data == NULL) { |
| 369 | // TODO: check execute_data + execute_data->func | 383 | return; |
| 384 | } | ||
| 385 | if (execute_data->func == NULL) { | ||
| 386 | old_execute_ex(execute_data); | ||
| 387 | return; | ||
| 388 | } | ||
| 370 | 389 | ||
| 371 | zend_op_array *new_op_array; | 390 | zend_op_array *new_op_array; |
| 372 | int op_array_type;//, len; | 391 | int op_array_type;//, len; |
| @@ -509,98 +528,11 @@ not_evaled_code: | |||
| 509 | */ | 528 | */ |
| 510 | 529 | ||
| 511 | op_array_type = suhosin_detect_codetype(&execute_data->func->op_array); | 530 | op_array_type = suhosin_detect_codetype(&execute_data->func->op_array); |
| 512 | 531 | char *filename = execute_data->func->op_array.filename ? ZSTR_VAL(execute_data->func->op_array.filename) : "<unknown>"; | |
| 513 | switch (op_array_type) { | 532 | suhosin_check_codetype(op_array_type, filename); |
| 514 | case SUHOSIN_CODE_TYPE_EVAL: | ||
| 515 | if (SUHOSIN7_G(executor_disable_eval)) { | ||
| 516 | suhosin_log(S_EXECUTOR|S_GETCALLER, "use of eval is forbidden by configuration"); | ||
| 517 | if (!SUHOSIN7_G(simulation)) { | ||
| 518 | zend_error(E_ERROR, "SUHOSIN - Use of eval is forbidden by configuration"); | ||
| 519 | } | ||
| 520 | } | ||
| 521 | break; | ||
| 522 | |||
| 523 | // case SUHOSIN_CODE_TYPE_REGEXP: | ||
| 524 | // if (SUHOSIN7_G(executor_disable_emod)) { | ||
| 525 | // suhosin_log(S_EXECUTOR|S_GETCALLER, "use of preg_replace() with /e modifier is forbidden by configuration"); | ||
| 526 | // if (!SUHOSIN7_G(simulation)) { | ||
| 527 | // zend_error(E_ERROR, "SUHOSIN - Use of preg_replace() with /e modifier is forbidden by configuration"); | ||
| 528 | // } | ||
| 529 | // } | ||
| 530 | // break; | ||
| 531 | |||
| 532 | case SUHOSIN_CODE_TYPE_MBREGEXP: | ||
| 533 | if (SUHOSIN7_G(executor_disable_emod)) { | ||
| 534 | suhosin_log(S_EXECUTOR|S_GETCALLER, "use of /e modifier in replace function is forbidden by configuration"); | ||
| 535 | if (!SUHOSIN7_G(simulation)) { | ||
| 536 | zend_error(E_ERROR, "SUHOSIN - Use of /e modifier in replace function is forbidden by configuration"); | ||
| 537 | } | ||
| 538 | } | ||
| 539 | break; | ||
| 540 | |||
| 541 | case SUHOSIN_CODE_TYPE_ASSERT: | ||
| 542 | break; | ||
| 543 | |||
| 544 | case SUHOSIN_CODE_TYPE_CFUNC: | ||
| 545 | break; | ||
| 546 | |||
| 547 | case SUHOSIN_CODE_TYPE_LONGNAME: | ||
| 548 | suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') is too long", ZSTR_VAL(execute_data->func->op_array.filename)); | ||
| 549 | suhosin_bailout(); | ||
| 550 | break; | ||
| 551 | |||
| 552 | case SUHOSIN_CODE_TYPE_MANYDOTS: | ||
| 553 | suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') contains too many '../'", ZSTR_VAL(execute_data->func->op_array.filename)); | ||
| 554 | suhosin_bailout(); | ||
| 555 | break; | ||
| 556 | |||
| 557 | case SUHOSIN_CODE_TYPE_UPLOADED: | ||
| 558 | suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename is an uploaded file"); | ||
| 559 | suhosin_bailout(); | ||
| 560 | break; | ||
| 561 | |||
| 562 | case SUHOSIN_CODE_TYPE_0FILE: | ||
| 563 | suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename contains an ASCIIZ character"); | ||
| 564 | suhosin_bailout(); | ||
| 565 | break; | ||
| 566 | |||
| 567 | case SUHOSIN_CODE_TYPE_WRITABLE: | ||
| 568 | suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') is writable by PHP process", ZSTR_VAL(execute_data->func->op_array.filename)); | ||
| 569 | suhosin_bailout(); | ||
| 570 | break; | ||
| 571 | |||
| 572 | case SUHOSIN_CODE_TYPE_BLACKURL: | ||
| 573 | suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') is a URL that is forbidden by the blacklist", ZSTR_VAL(execute_data->func->op_array.filename)); | ||
| 574 | suhosin_bailout(); | ||
| 575 | break; | ||
| 576 | |||
| 577 | case SUHOSIN_CODE_TYPE_BADURL: | ||
| 578 | suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') is a URL that is not allowed", ZSTR_VAL(execute_data->func->op_array.filename)); | ||
| 579 | suhosin_bailout(); | ||
| 580 | break; | ||
| 581 | |||
| 582 | case SUHOSIN_CODE_TYPE_BADFILE: | ||
| 583 | // cs.type = IS_STRING; | ||
| 584 | // #define DIE_WITH_MSG "die('disallowed_file'.chr(10).chr(10));" | ||
| 585 | // cs.value.str.val = estrndup(DIE_WITH_MSG, sizeof(DIE_WITH_MSG)-1); | ||
| 586 | // cs.value.str.len = sizeof(DIE_WITH_MSG)-1; | ||
| 587 | // new_op_array = compile_string(&cs, "suhosin internal code"); | ||
| 588 | // if (new_op_array) { | ||
| 589 | // op_array = new_op_array; | ||
| 590 | // goto continue_execution; | ||
| 591 | // } | ||
| 592 | suhosin_bailout(); | ||
| 593 | break; | ||
| 594 | |||
| 595 | case SUHOSIN_CODE_TYPE_COMMANDLINE: | ||
| 596 | case SUHOSIN_CODE_TYPE_SUHOSIN: | ||
| 597 | case SUHOSIN_CODE_TYPE_UNKNOWN: | ||
| 598 | case SUHOSIN_CODE_TYPE_GOODFILE: | ||
| 599 | goto continue_execution; | ||
| 600 | } | ||
| 601 | 533 | ||
| 602 | continue_execution: | 534 | continue_execution: |
| 603 | old_execute_ex (execute_data); | 535 | old_execute_ex(execute_data); |
| 604 | 536 | ||
| 605 | /* nothing to do */ | 537 | /* nothing to do */ |
| 606 | SUHOSIN7_G(in_code_type) = orig_code_type; | 538 | SUHOSIN7_G(in_code_type) = orig_code_type; |
| @@ -938,8 +870,10 @@ void suhosin_hook_execute() | |||
| 938 | /* Add additional protection layer, that SHOULD | 870 | /* Add additional protection layer, that SHOULD |
| 939 | catch ZEND_INCLUDE_OR_EVAL *before* the engine tries | 871 | catch ZEND_INCLUDE_OR_EVAL *before* the engine tries |
| 940 | to execute */ | 872 | to execute */ |
| 941 | // old_zend_stream_open = zend_stream_open_function; | 873 | if (old_zend_stream_open == NULL) { |
| 942 | // zend_stream_open_function = suhosin_zend_stream_open; | 874 | old_zend_stream_open = zend_stream_open_function; |
| 875 | } | ||
| 876 | zend_stream_open_function = suhosin_zend_stream_open; | ||
| 943 | 877 | ||
| 944 | } | 878 | } |
| 945 | /* }}} */ | 879 | /* }}} */ |
| @@ -966,7 +900,7 @@ void suhosin_unhook_execute() | |||
| 966 | zend_hash_clean(&ihandler_table); | 900 | zend_hash_clean(&ihandler_table); |
| 967 | 901 | ||
| 968 | /* remove zend_open protection */ | 902 | /* remove zend_open protection */ |
| 969 | // zend_stream_open_function = old_zend_stream_open; | 903 | zend_stream_open_function = old_zend_stream_open; |
| 970 | 904 | ||
| 971 | } | 905 | } |
| 972 | /* }}} */ | 906 | /* }}} */ |
