You are here

function _seckit_origin in Security Kit 6

Same name and namespace in other branches
  1. 7 seckit.module \_seckit_origin()

Aborts HTTP request upon invalid 'Origin' HTTP request header.

When included in an HTTP request, the Origin header indicates the origin(s) that caused the user agent to issue the request. This helps to protect against CSRF attacks, as we can abort requests with an unapproved origin.

Applies to all HTTP request methods except GET and HEAD.

Requests which do not include an 'Origin' header must always be allowed, as (a) not all user-agents support the header, and (b) those that do may include it or omit it at their discretion.

Note that (a) will become progressively less of a factor over time -- CSRF attacks depend upon convincing a user agent to send a request, and there is no particular motivation for users to prevent their web browsers from sending this header; so as people upgrade to browsers which support 'Origin', its effectiveness increases.

Implementation of Origin is based on specification draft available at http://tools.ietf.org/html/draft-abarth-origin-09

1 call to _seckit_origin()
seckit_init in ./seckit.module
Implements hook_init().

File

./seckit.module, line 378
Allows administrators to improve security of the website.

Code

function _seckit_origin() {

  // Allow requests without an 'Origin' header, or with a 'null' origin.
  $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
  if (!$origin || $origin === 'null') {
    return;
  }

  // Allow command-line requests.
  // TODO: Should this test be in seckit_init() ?
  // (i.e. Should this module do *anything* in the case of cli requests?)
  if (_seckit_drupal_is_cli()) {
    return;
  }

  // Allow GET and HEAD requests.
  $method = $_SERVER['REQUEST_METHOD'];
  if (in_array($method, array(
    'GET',
    'HEAD',
  ), TRUE)) {
    return;
  }

  // Allow requests from localhost.
  $remote_addr = $_SERVER['REMOTE_ADDR'];
  if (in_array($remote_addr, array(
    'localhost',
    '127.0.0.1',
    '::1',
  ), TRUE)) {
    return;
  }

  // Allow requests from whitelisted Origins.
  global $base_root;
  $options = _seckit_get_options();
  $whitelist = explode(',', $options['seckit_csrf']['origin_whitelist']);
  $whitelist[] = $base_root;

  // default origin is always allowed
  if (in_array($origin, $whitelist, TRUE)) {
    return;
  }

  // The Origin is invalid, so we deny the request.
  // Clean the POST data first, as drupal_access_denied() may render a page
  // with forms which check for their submissions.
  $_POST = array();
  drupal_access_denied();

  // send 403 response and show Access Denied page
  $args = array(
    '@ip' => $remote_addr,
    '@origin' => $origin,
  );
  watchdog('seckit', 'Possible CSRF attack was blocked. IP address: @ip, Origin: @origin.', $args, WATCHDOG_ERROR);
  exit;

  // abort request
}