summaryrefslogtreecommitdiff
path: root/ifilter.c
diff options
context:
space:
mode:
Diffstat (limited to 'ifilter.c')
-rw-r--r--ifilter.c726
1 files changed, 726 insertions, 0 deletions
diff --git a/ifilter.c b/ifilter.c
new file mode 100644
index 0000000..7160f10
--- /dev/null
+++ b/ifilter.c
@@ -0,0 +1,726 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007-2015 SektionEins GmbH |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
16 | Author: Stefan Esser <sesser@sektioneins.de> |
17 +----------------------------------------------------------------------+
18*/
19/*
20 $Id: ifilter.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $
21*/
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "php.h"
28#include "php_ini.h"
29#include "ext/standard/info.h"
30#include "php_suhosin7.h"
31#include "php_variables.h"
32#include "ext/standard/php_var.h"
33
34
35static void (*orig_register_server_variables)(zval *track_vars_array TSRMLS_DC) = NULL;
36
37#if !HAVE_STRNLEN
38static size_t strnlen(const char *s, size_t maxlen) {
39 char *r = memchr(s, '\0', maxlen);
40 return r ? r-s : maxlen;
41}
42#endif
43
44size_t suhosin_strnspn(const char *input, size_t n, const char *accept)
45{
46 size_t count = 0;
47 for (; *input != '\0' && count < n; input++, count++) {
48 if (strchr(accept, *input) == NULL)
49 break;
50 }
51 return count;
52}
53
54size_t suhosin_strncspn(const char *input, size_t n, const char *reject)
55{
56 size_t count = 0;
57 for (; *input != '\0' && count < n; input++, count++) {
58 if (strchr(reject, *input) != NULL)
59 break;
60 }
61 return count;
62}
63
64
65/* {{{ normalize_varname
66 */
67void normalize_varname(char *varname)
68{
69 char *s=varname, *index=NULL, *indexend=NULL, *p;
70
71 /* overjump leading space */
72 while (*s == ' ') {
73 s++;
74 }
75
76 /* and remove it */
77 if (s != varname) {
78 memmove(varname, s, strlen(s)+1);
79 }
80
81 for (p=varname; *p && *p != '['; p++) {
82 switch(*p) {
83 case ' ':
84 case '.':
85 *p='_';
86 break;
87 }
88 }
89
90 /* find index */
91 index = strchr(varname, '[');
92 if (index) {
93 index++;
94 s=index;
95 } else {
96 return;
97 }
98
99 /* done? */
100 while (index) {
101
102 while (*index == ' ' || *index == '\r' || *index == '\n' || *index=='\t') {
103 index++;
104 }
105 indexend = strchr(index, ']');
106 indexend = indexend ? indexend + 1 : index + strlen(index);
107
108 if (s != index) {
109 memmove(s, index, strlen(index)+1);
110 s += indexend-index;
111 } else {
112 s = indexend;
113 }
114
115 if (*s == '[') {
116 s++;
117 index = s;
118 } else {
119 index = NULL;
120 }
121 }
122 *s++='\0';
123}
124/* }}} */
125
126static unsigned char suhosin_hexchars[] = "0123456789ABCDEF";
127
128static const char suhosin_is_dangerous_char[256] = {
129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,
130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
131 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
135 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
137 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
138 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
140 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
141 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
142 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
145};
146
147/* {{{ suhosin_server_encode
148 */
149static void suhosin_server_strip(HashTable *arr, char *key, int klen)
150{
151 zval **tzval;
152 unsigned char *s, *t;
153
154 if (zend_hash_find(arr, key, klen, (void **) &tzval) == SUCCESS &&
155 Z_TYPE_PP(tzval) == IS_STRING) {
156
157 s = t = (unsigned char *)Z_STRVAL_PP(tzval);
158 for (; *t; t++) {
159 if (suhosin_is_dangerous_char[*t]) {
160 *t = '?';
161 }
162 }
163 Z_STRLEN_PP(tzval) = t-s;
164 }
165}
166/* }}} */
167
168/* {{{ suhosin_server_encode
169 */
170static void suhosin_server_encode(HashTable *arr, char *key, int klen)
171{
172 zval **tzval;
173 unsigned char *temp = NULL, *t, *newv, *n;
174 int extra = 0;
175
176 if (zend_hash_find(arr, key, klen, (void **) &tzval) == SUCCESS &&
177 Z_TYPE_PP(tzval) == IS_STRING) {
178
179 temp = (unsigned char *)Z_STRVAL_PP(tzval);
180
181 for (t = temp; *t; t++) {
182 if (suhosin_is_dangerous_char[*t]) {
183 extra += 2;
184 }
185 }
186
187 /* no extra bytes required */
188 if (extra == 0) {
189 return;
190 }
191
192 n = newv = emalloc(t - temp + 1 + extra);
193 t = temp;
194 for (t = temp; *t; t++, n++) {
195 if (suhosin_is_dangerous_char[*t]) {
196 *n++ = '%';
197 *n++ = suhosin_hexchars[*t >> 4];
198 *n = suhosin_hexchars[*t & 15];
199 } else {
200 *n = *t;
201 }
202 }
203 *n = 0;
204
205 /* XXX: we leak memory here, but only for the duration of the request */
206 Z_STRVAL_PP(tzval) = (char *)newv;
207 Z_STRLEN_PP(tzval) = n-newv;
208 }
209}
210/* }}} */
211
212/* {{{ suhosin_register_server_variables
213 */
214void suhosin_register_server_variables(zval *track_vars_array TSRMLS_DC)
215{
216 HashTable *svars;
217 int retval = 0, failure = 0;
218
219 orig_register_server_variables(track_vars_array TSRMLS_CC);
220
221 svars = Z_ARRVAL_P(track_vars_array);
222 if (!SUHOSIN_G(simulation)) {
223 retval = zend_hash_del(svars, "HTTP_GET_VARS", sizeof("HTTP_GET_VARS"));
224 if (retval == SUCCESS) failure = 1;
225 retval = zend_hash_del(svars, "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"));
226 if (retval == SUCCESS) failure = 1;
227 retval = zend_hash_del(svars, "HTTP_COOKIE_VARS", sizeof("HTTP_COOKIE_VARS"));
228 if (retval == SUCCESS) failure = 1;
229 retval = zend_hash_del(svars, "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS"));
230 if (retval == SUCCESS) failure = 1;
231 retval = zend_hash_del(svars, "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"));
232 if (retval == SUCCESS) failure = 1;
233 retval = zend_hash_del(svars, "HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"));
234 if (retval == SUCCESS) failure = 1;
235 retval = zend_hash_del(svars, "HTTP_POST_FILES", sizeof("HTTP_POST_FILES"));
236 if (retval == SUCCESS) failure = 1;
237 retval = zend_hash_del(svars, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"));
238 if (retval == SUCCESS) failure = 1;
239 } else {
240 retval = zend_hash_exists(svars, "HTTP_GET_VARS", sizeof("HTTP_GET_VARS"));
241 retval+= zend_hash_exists(svars, "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"));
242 retval+= zend_hash_exists(svars, "HTTP_COOKIE_VARS", sizeof("HTTP_COOKIE_VARS"));
243 retval+= zend_hash_exists(svars, "HTTP_ENV_VARS", sizeof("HTTP_ENV_VARS"));
244 retval+= zend_hash_exists(svars, "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"));
245 retval+= zend_hash_exists(svars, "HTTP_SESSION_VARS", sizeof("HTTP_SESSION_VARS"));
246 retval+= zend_hash_exists(svars, "HTTP_POST_FILES", sizeof("HTTP_POST_FILES"));
247 retval+= zend_hash_exists(svars, "HTTP_RAW_POST_DATA", sizeof("HTTP_RAW_POST_DATA"));
248 if (retval > 0) failure = 1;
249 }
250
251 if (failure) {
252 suhosin_log(S_VARS, "Attacker tried to overwrite a superglobal through a HTTP header");
253 }
254
255 if (SUHOSIN_G(raw_cookie)) {
256 zval *z;
257 MAKE_STD_ZVAL(z);
258 ZVAL_STRING(z, SUHOSIN_G(raw_cookie), 1);
259 zend_hash_add(svars, "RAW_HTTP_COOKIE", sizeof("RAW_HTTP_COOKIE"), (void **)&z, sizeof(zval *), NULL);
260 }
261 if (SUHOSIN_G(decrypted_cookie)) {
262 zval *z;
263 MAKE_STD_ZVAL(z);
264 ZVAL_STRING(z, SUHOSIN_G(decrypted_cookie), 0);
265 zend_hash_update(svars, "HTTP_COOKIE", sizeof("HTTP_COOKIE"), (void **)&z, sizeof(zval *), NULL);
266 SUHOSIN_G(decrypted_cookie) = NULL;
267 }
268
269 if (SUHOSIN_G(server_encode)) {
270 /* suhosin_server_encode(svars, "argv", sizeof("argv")); */
271 suhosin_server_encode(svars, "REQUEST_URI", sizeof("REQUEST_URI"));
272 suhosin_server_encode(svars, "QUERY_STRING", sizeof("QUERY_STRING"));
273 }
274 if (SUHOSIN_G(server_strip)) {
275 suhosin_server_strip(svars, "PHP_SELF", sizeof("PHP_SELF"));
276 suhosin_server_strip(svars, "PATH_INFO", sizeof("PATH_INFO"));
277 suhosin_server_strip(svars, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"));
278 suhosin_server_strip(svars, "HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT"));
279 }
280}
281/* }}} */
282
283
284/* Old Input filter */
285unsigned int (*old_input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC) = NULL;
286
287/* {{{ suhosin_input_filter_wrapper
288 */
289unsigned int suhosin_input_filter_wrapper(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
290{
291 zend_bool already_scanned = SUHOSIN_G(already_scanned);
292 SUHOSIN_G(already_scanned) = 0;
293
294 if (SUHOSIN_G(do_not_scan)) {
295 if (new_val_len) {
296 *new_val_len = val_len;
297 }
298 return 1;
299 }
300
301 if (!already_scanned) {
302 if (suhosin_input_filter(arg, var, val, val_len, new_val_len TSRMLS_CC)==0) {
303 SUHOSIN_G(abort_request)=1;
304 return 0;
305 }
306 if (new_val_len) {
307 val_len = *new_val_len;
308 }
309 }
310 if (old_input_filter) {
311 return old_input_filter(arg, var, val, val_len, new_val_len TSRMLS_CC);
312 } else {
313 return 1;
314 }
315}
316
317/* {{{ suhosin_input_filter
318 */
319unsigned int suhosin_input_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)
320{
321 char *index, *prev_index = NULL;
322 unsigned int var_len, total_len, depth = 0;
323
324 /* Mark that we were called */
325 SUHOSIN_G(already_scanned) = 1;
326
327 if (new_val_len) {
328 *new_val_len = 0;
329 }
330
331 /* Drop this variable if the limit was reached */
332 switch (arg) {
333 case PARSE_GET:
334 SUHOSIN_G(att_get_vars)++;
335 SUHOSIN_G(att_request_variables)++;
336 if (SUHOSIN_G(no_more_get_variables)) {
337 return 0;
338 }
339 break;
340 case PARSE_POST:
341 SUHOSIN_G(att_post_vars)++;
342 SUHOSIN_G(att_request_variables)++;
343 if (SUHOSIN_G(no_more_post_variables)) {
344 return 0;
345 }
346 break;
347 case PARSE_COOKIE:
348 SUHOSIN_G(att_cookie_vars)++;
349 SUHOSIN_G(att_request_variables)++;
350 if (SUHOSIN_G(no_more_cookie_variables)) {
351 return 0;
352 }
353 break;
354 default: /* we do not want to protect parse_str() and friends */
355 if (new_val_len) {
356 *new_val_len = val_len;
357 }
358 return 1;
359 }
360
361 /* Drop this variable if the limit is now reached */
362 switch (arg) {
363 case PARSE_GET:
364 if (SUHOSIN_G(max_get_vars) && SUHOSIN_G(max_get_vars) <= SUHOSIN_G(cur_get_vars)) {
365 suhosin_log(S_VARS, "configured GET variable limit exceeded - dropped variable '%s' - all further GET variables are dropped", var);
366 if (!SUHOSIN_G(simulation)) {
367 SUHOSIN_G(no_more_get_variables) = 1;
368 return 0;
369 }
370 }
371 break;
372 case PARSE_COOKIE:
373 if (SUHOSIN_G(max_cookie_vars) && SUHOSIN_G(max_cookie_vars) <= SUHOSIN_G(cur_cookie_vars)) {
374 suhosin_log(S_VARS, "configured COOKIE variable limit exceeded - dropped variable '%s' - all further COOKIE variables are dropped", var);
375 if (!SUHOSIN_G(simulation)) {
376 SUHOSIN_G(no_more_cookie_variables) = 1;
377 return 0;
378 }
379 }
380 break;
381 case PARSE_POST:
382 if (SUHOSIN_G(max_post_vars) && SUHOSIN_G(max_post_vars) <= SUHOSIN_G(cur_post_vars)) {
383 suhosin_log(S_VARS, "configured POST variable limit exceeded - dropped variable '%s' - all further POST variables are dropped", var);
384 if (!SUHOSIN_G(simulation)) {
385 SUHOSIN_G(no_more_post_variables) = 1;
386 return 0;
387 }
388 }
389 break;
390 }
391
392 /* Drop this variable if it begins with whitespace which is disallowed */
393 if (isspace(*var)) {
394 if (SUHOSIN_G(disallow_ws)) {
395 suhosin_log(S_VARS, "request variable name begins with disallowed whitespace - dropped variable '%s'", var);
396 if (!SUHOSIN_G(simulation)) {
397 return 0;
398 }
399 }
400 switch (arg) {
401 case PARSE_GET:
402 if (SUHOSIN_G(disallow_get_ws)) {
403 suhosin_log(S_VARS, "GET variable name begins with disallowed whitespace - dropped variable '%s'", var);
404 if (!SUHOSIN_G(simulation)) {
405 return 0;
406 }
407 }
408 break;
409 case PARSE_POST:
410 if (SUHOSIN_G(disallow_post_ws)) {
411 suhosin_log(S_VARS, "POST variable name begins with disallowed whitespace - dropped variable '%s'", var);
412 if (!SUHOSIN_G(simulation)) {
413 return 0;
414 }
415 }
416 break;
417 case PARSE_COOKIE:
418 if (SUHOSIN_G(disallow_cookie_ws)) {
419 suhosin_log(S_VARS, "COOKIE variable name begins with disallowed whitespace - dropped variable '%s'", var);
420 if (!SUHOSIN_G(simulation)) {
421 return 0;
422 }
423 }
424 break;
425 }
426 }
427
428 /* Drop this variable if it exceeds the value length limit */
429 if (SUHOSIN_G(max_value_length) && SUHOSIN_G(max_value_length) < val_len) {
430 suhosin_log(S_VARS, "configured request variable value length limit exceeded - dropped variable '%s'", var);
431 if (!SUHOSIN_G(simulation)) {
432 return 0;
433 }
434 }
435 switch (arg) {
436 case PARSE_GET:
437 if (SUHOSIN_G(max_get_value_length) && SUHOSIN_G(max_get_value_length) < val_len) {
438 suhosin_log(S_VARS, "configured GET variable value length limit exceeded - dropped variable '%s'", var);
439 if (!SUHOSIN_G(simulation)) {
440 return 0;
441 }
442 }
443 break;
444 case PARSE_COOKIE:
445 if (SUHOSIN_G(max_cookie_value_length) && SUHOSIN_G(max_cookie_value_length) < val_len) {
446 suhosin_log(S_VARS, "configured COOKIE variable value length limit exceeded - dropped variable '%s'", var);
447 if (!SUHOSIN_G(simulation)) {
448 return 0;
449 }
450 }
451 break;
452 case PARSE_POST:
453 if (SUHOSIN_G(max_post_value_length) && SUHOSIN_G(max_post_value_length) < val_len) {
454 suhosin_log(S_VARS, "configured POST variable value length limit exceeded - dropped variable '%s'", var);
455 if (!SUHOSIN_G(simulation)) {
456 return 0;
457 }
458 }
459 break;
460 }
461
462 /* Normalize the variable name */
463 normalize_varname(var);
464
465 /* Find length of variable name */
466 index = strchr(var, '[');
467 total_len = strlen(var);
468 var_len = index ? index-var : total_len;
469
470 /* Drop this variable if it exceeds the varname/total length limit */
471 if (SUHOSIN_G(max_varname_length) && SUHOSIN_G(max_varname_length) < var_len) {
472 suhosin_log(S_VARS, "configured request variable name length limit exceeded - dropped variable '%s'", var);
473 if (!SUHOSIN_G(simulation)) {
474 return 0;
475 }
476 }
477 if (SUHOSIN_G(max_totalname_length) && SUHOSIN_G(max_totalname_length) < total_len) {
478 suhosin_log(S_VARS, "configured request variable total name length limit exceeded - dropped variable '%s'", var);
479 if (!SUHOSIN_G(simulation)) {
480 return 0;
481 }
482 }
483 switch (arg) {
484 case PARSE_GET:
485 if (SUHOSIN_G(max_get_name_length) && SUHOSIN_G(max_get_name_length) < var_len) {
486 suhosin_log(S_VARS, "configured GET variable name length limit exceeded - dropped variable '%s'", var);
487 if (!SUHOSIN_G(simulation)) {
488 return 0;
489 }
490 }
491 if (SUHOSIN_G(max_get_totalname_length) && SUHOSIN_G(max_get_totalname_length) < total_len) {
492 suhosin_log(S_VARS, "configured GET variable total name length limit exceeded - dropped variable '%s'", var);
493 if (!SUHOSIN_G(simulation)) {
494 return 0;
495 }
496 }
497 break;
498 case PARSE_COOKIE:
499 if (SUHOSIN_G(max_cookie_name_length) && SUHOSIN_G(max_cookie_name_length) < var_len) {
500 suhosin_log(S_VARS, "configured COOKIE variable name length limit exceeded - dropped variable '%s'", var);
501 if (!SUHOSIN_G(simulation)) {
502 return 0;
503 }
504 }
505 if (SUHOSIN_G(max_cookie_totalname_length) && SUHOSIN_G(max_cookie_totalname_length) < total_len) {
506 suhosin_log(S_VARS, "configured COOKIE variable total name length limit exceeded - dropped variable '%s'", var);
507 if (!SUHOSIN_G(simulation)) {
508 return 0;
509 }
510 }
511 break;
512 case PARSE_POST:
513 if (SUHOSIN_G(max_post_name_length) && SUHOSIN_G(max_post_name_length) < var_len) {
514 suhosin_log(S_VARS, "configured POST variable name length limit exceeded - dropped variable '%s'", var);
515 if (!SUHOSIN_G(simulation)) {
516 return 0;
517 }
518 }
519 if (SUHOSIN_G(max_post_totalname_length) && SUHOSIN_G(max_post_totalname_length) < total_len) {
520 suhosin_log(S_VARS, "configured POST variable total name length limit exceeded - dropped variable '%s'", var);
521 if (!SUHOSIN_G(simulation)) {
522 return 0;
523 }
524 }
525 break;
526 }
527
528 /* Find out array depth */
529 while (index) {
530 char *index_end;
531 unsigned int index_length;
532
533 /* overjump '[' */
534 index++;
535
536 /* increase array depth */
537 depth++;
538
539 index_end = strchr(index, ']');
540 if (index_end == NULL) {
541 index_end = index+strlen(index);
542 }
543
544 index_length = index_end - index;
545
546 /* max. array index length */
547 if (SUHOSIN_G(max_array_index_length) && SUHOSIN_G(max_array_index_length) < index_length) {
548 suhosin_log(S_VARS, "configured request variable array index length limit exceeded - dropped variable '%s'", var);
549 if (!SUHOSIN_G(simulation)) {
550 return 0;
551 }
552 }
553 switch (arg) {
554 case PARSE_GET:
555 if (SUHOSIN_G(max_get_array_index_length) && SUHOSIN_G(max_get_array_index_length) < index_length) {
556 suhosin_log(S_VARS, "configured GET variable array index length limit exceeded - dropped variable '%s'", var);
557 if (!SUHOSIN_G(simulation)) {
558 return 0;
559 }
560 }
561 break;
562 case PARSE_COOKIE:
563 if (SUHOSIN_G(max_cookie_array_index_length) && SUHOSIN_G(max_cookie_array_index_length) < index_length) {
564 suhosin_log(S_VARS, "configured COOKIE variable array index length limit exceeded - dropped variable '%s'", var);
565 if (!SUHOSIN_G(simulation)) {
566 return 0;
567 }
568 }
569 break;
570 case PARSE_POST:
571 if (SUHOSIN_G(max_post_array_index_length) && SUHOSIN_G(max_post_array_index_length) < index_length) {
572 suhosin_log(S_VARS, "configured POST variable array index length limit exceeded - dropped variable '%s'", var);
573 if (!SUHOSIN_G(simulation)) {
574 return 0;
575 }
576 }
577 break;
578 }
579
580 /* index whitelist/blacklist */
581 if (SUHOSIN_G(array_index_whitelist) && *(SUHOSIN_G(array_index_whitelist))) {
582 if (suhosin_strnspn(index, index_length, SUHOSIN_G(array_index_whitelist)) != index_length) {
583 suhosin_log(S_VARS, "array index contains not whitelisted characters - dropped variable '%s'", var);
584 if (!SUHOSIN_G(simulation)) {
585 return 0;
586 }
587 }
588 } else if (SUHOSIN_G(array_index_blacklist) && *(SUHOSIN_G(array_index_blacklist))) {
589 if (suhosin_strncspn(index, index_length, SUHOSIN_G(array_index_blacklist)) != index_length) {
590 suhosin_log(S_VARS, "array index contains blacklisted characters - dropped variable '%s'", var);
591 if (!SUHOSIN_G(simulation)) {
592 return 0;
593 }
594 }
595 }
596
597 index = strchr(index, '[');
598 }
599
600 /* Drop this variable if it exceeds the array depth limit */
601 if (SUHOSIN_G(max_array_depth) && SUHOSIN_G(max_array_depth) < depth) {
602 suhosin_log(S_VARS, "configured request variable array depth limit exceeded - dropped variable '%s'", var);
603 if (!SUHOSIN_G(simulation)) {
604 return 0;
605 }
606 }
607 switch (arg) {
608 case PARSE_GET:
609 if (SUHOSIN_G(max_get_array_depth) && SUHOSIN_G(max_get_array_depth) < depth) {
610 suhosin_log(S_VARS, "configured GET variable array depth limit exceeded - dropped variable '%s'", var);
611 if (!SUHOSIN_G(simulation)) {
612 return 0;
613 }
614 }
615 break;
616 case PARSE_COOKIE:
617 if (SUHOSIN_G(max_cookie_array_depth) && SUHOSIN_G(max_cookie_array_depth) < depth) {
618 suhosin_log(S_VARS, "configured COOKIE variable array depth limit exceeded - dropped variable '%s'", var);
619 if (!SUHOSIN_G(simulation)) {
620 return 0;
621 }
622 }
623 break;
624 case PARSE_POST:
625 if (SUHOSIN_G(max_post_array_depth) && SUHOSIN_G(max_post_array_depth) < depth) {
626 suhosin_log(S_VARS, "configured POST variable array depth limit exceeded - dropped variable '%s'", var);
627 if (!SUHOSIN_G(simulation)) {
628 return 0;
629 }
630 }
631 break;
632 }
633
634 /* Check if variable value is truncated by a \0 */
635
636 if (val && *val && val_len != strnlen(*val, val_len)) {
637
638 if (SUHOSIN_G(disallow_nul)) {
639 suhosin_log(S_VARS, "ASCII-NUL chars not allowed within request variables - dropped variable '%s'", var);
640 if (!SUHOSIN_G(simulation)) {
641 return 0;
642 }
643 }
644 switch (arg) {
645 case PARSE_GET:
646 if (SUHOSIN_G(disallow_get_nul)) {
647 suhosin_log(S_VARS, "ASCII-NUL chars not allowed within GET variables - dropped variable '%s'", var);
648 if (!SUHOSIN_G(simulation)) {
649 return 0;
650 }
651 }
652 break;
653 case PARSE_COOKIE:
654 if (SUHOSIN_G(disallow_cookie_nul)) {
655 suhosin_log(S_VARS, "ASCII-NUL chars not allowed within COOKIE variables - dropped variable '%s'", var);
656 if (!SUHOSIN_G(simulation)) {
657 return 0;
658 }
659 }
660 break;
661 case PARSE_POST:
662 if (SUHOSIN_G(disallow_post_nul)) {
663 suhosin_log(S_VARS, "ASCII-NUL chars not allowed within POST variables - dropped variable '%s'", var);
664 if (!SUHOSIN_G(simulation)) {
665 return 0;
666 }
667 }
668 break;
669 }
670 }
671
672 /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */
673 /* This is to protect several silly scripts that do globalizing themself */
674 if (suhosin_is_protected_varname(var, var_len)) {
675 suhosin_log(S_VARS, "tried to register forbidden variable '%s' through %s variables", var, arg == PARSE_GET ? "GET" : arg == PARSE_POST ? "POST" : "COOKIE");
676 if (!SUHOSIN_G(simulation)) {
677 return 0;
678 }
679 }
680
681 /* Okay let PHP register this variable */
682 SUHOSIN_G(cur_request_variables)++;
683 switch (arg) {
684 case PARSE_GET:
685 SUHOSIN_G(cur_get_vars)++;
686 break;
687 case PARSE_COOKIE:
688 SUHOSIN_G(cur_cookie_vars)++;
689 break;
690 case PARSE_POST:
691 SUHOSIN_G(cur_post_vars)++;
692 break;
693 }
694
695 if (new_val_len) {
696 *new_val_len = val_len;
697 }
698
699 return 1;
700}
701/* }}} */
702
703
704
705/* {{{ suhosin_hook_register_server_variables
706 */
707void suhosin_hook_register_server_variables()
708{
709 if (sapi_module.register_server_variables) {
710 orig_register_server_variables = sapi_module.register_server_variables;
711 sapi_module.register_server_variables = suhosin_register_server_variables;
712 }
713}
714/* }}} */
715
716
717/*
718 * Local variables:
719 * tab-width: 4
720 * c-basic-offset: 4
721 * End:
722 * vim600: noet sw=4 ts=4 fdm=marker
723 * vim<600: noet sw=4 ts=4
724 */
725
726