request-sanitizer.inc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <?php
  2. /**
  3. * @file
  4. * Contains code for sanitizing user input from the request.
  5. */
  6. /**
  7. * Sanitizes user input from the request.
  8. */
  9. class DrupalRequestSanitizer {
  10. /**
  11. * Tracks whether the request was already sanitized.
  12. */
  13. protected static $sanitized = FALSE;
  14. /**
  15. * Modifies the request to strip dangerous keys from user input.
  16. */
  17. public static function sanitize() {
  18. if (!self::$sanitized) {
  19. $whitelist = variable_get('sanitize_input_whitelist', array());
  20. $log_sanitized_keys = variable_get('sanitize_input_logging', FALSE);
  21. // Process query string parameters.
  22. $get_sanitized_keys = array();
  23. $_GET = self::stripDangerousValues($_GET, $whitelist, $get_sanitized_keys);
  24. if ($log_sanitized_keys && $get_sanitized_keys) {
  25. _drupal_trigger_error_with_delayed_logging(format_string('Potentially unsafe keys removed from query string parameters (GET): @keys', array('@keys' => implode(', ', $get_sanitized_keys))), E_USER_NOTICE);
  26. }
  27. // Process request body parameters.
  28. $post_sanitized_keys = array();
  29. $_POST = self::stripDangerousValues($_POST, $whitelist, $post_sanitized_keys);
  30. if ($log_sanitized_keys && $post_sanitized_keys) {
  31. _drupal_trigger_error_with_delayed_logging(format_string('Potentially unsafe keys removed from request body parameters (POST): @keys', array('@keys' => implode(', ', $post_sanitized_keys))), E_USER_NOTICE);
  32. }
  33. // Process cookie parameters.
  34. $cookie_sanitized_keys = array();
  35. $_COOKIE = self::stripDangerousValues($_COOKIE, $whitelist, $cookie_sanitized_keys);
  36. if ($log_sanitized_keys && $cookie_sanitized_keys) {
  37. _drupal_trigger_error_with_delayed_logging(format_string('Potentially unsafe keys removed from cookie parameters (COOKIE): @keys', array('@keys' => implode(', ', $cookie_sanitized_keys))), E_USER_NOTICE);
  38. }
  39. $request_sanitized_keys = array();
  40. $_REQUEST = self::stripDangerousValues($_REQUEST, $whitelist, $request_sanitized_keys);
  41. self::$sanitized = TRUE;
  42. }
  43. }
  44. /**
  45. * Removes the destination if it is dangerous.
  46. *
  47. * Note this can only be called after common.inc has been included.
  48. *
  49. * @return bool
  50. * TRUE if the destination has been removed from $_GET, FALSE if not.
  51. */
  52. public static function cleanDestination() {
  53. $dangerous_keys = array();
  54. $log_sanitized_keys = variable_get('sanitize_input_logging', FALSE);
  55. $parts = drupal_parse_url($_GET['destination']);
  56. // If there is a query string, check its query parameters.
  57. if (!empty($parts['query'])) {
  58. $whitelist = variable_get('sanitize_input_whitelist', array());
  59. self::stripDangerousValues($parts['query'], $whitelist, $dangerous_keys);
  60. if (!empty($dangerous_keys)) {
  61. // The destination is removed rather than sanitized to mirror the
  62. // handling of external destinations.
  63. unset($_GET['destination']);
  64. unset($_REQUEST['destination']);
  65. if ($log_sanitized_keys) {
  66. trigger_error(format_string('Potentially unsafe destination removed from query string parameters (GET) because it contained the following keys: @keys', array('@keys' => implode(', ', $dangerous_keys))));
  67. }
  68. return TRUE;
  69. }
  70. }
  71. return FALSE;
  72. }
  73. /**
  74. * Strips dangerous keys from the provided input.
  75. *
  76. * @param mixed $input
  77. * The input to sanitize.
  78. * @param string[] $whitelist
  79. * An array of keys to whitelist as safe.
  80. * @param string[] $sanitized_keys
  81. * An array of keys that have been removed.
  82. *
  83. * @return mixed
  84. * The sanitized input.
  85. */
  86. protected static function stripDangerousValues($input, array $whitelist, array &$sanitized_keys) {
  87. if (is_array($input)) {
  88. foreach ($input as $key => $value) {
  89. if ($key !== '' && is_string($key) && $key[0] === '#' && !in_array($key, $whitelist, TRUE)) {
  90. unset($input[$key]);
  91. $sanitized_keys[] = $key;
  92. }
  93. else {
  94. $input[$key] = self::stripDangerousValues($input[$key], $whitelist, $sanitized_keys);
  95. }
  96. }
  97. }
  98. return $input;
  99. }
  100. }