diff --git a/core/includes/batch.inc b/core/includes/batch.inc
index 0b07d8e..1eff19d 100644
--- a/core/includes/batch.inc
+++ b/core/includes/batch.inc
@@ -14,7 +14,10 @@
  * @see batch_get()
  */
 
-use \Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 
 /**
  * Loads a batch from the database.
@@ -27,12 +30,13 @@ use \Symfony\Component\HttpFoundation\JsonResponse;
  *   An array representing the batch, or FALSE if no batch was found.
  */
 function batch_load($id) {
-  $batch = db_query("SELECT batch FROM {batch} WHERE bid = :bid AND token = :token", array(
+  $result = db_query('SELECT batch, token FROM {batch} WHERE bid = :bid', array(
     ':bid' => $id,
-    ':token' => drupal_get_token($id),
   ))->fetchField();
-  if ($batch) {
-    return unserialize($batch);
+  if ($result) {
+    $batch = unserialize($result->batch);
+    $batch['token'] = $result->token;
+    return $batch;
   }
   return FALSE;
 }
@@ -46,7 +50,7 @@ function _batch_page() {
   $batch = &batch_get();
 
   if (!isset($_REQUEST['id'])) {
-    return FALSE;
+    throw new NotFoundHttpException();
   }
 
   // Retrieve the current state of the batch.
@@ -56,6 +60,9 @@ function _batch_page() {
       drupal_set_message(t('No active batch.'), 'error');
       drupal_goto();
     }
+    if (!isset($batch['token']) || $batch['token'] !== drupal_get_token($_REQUEST['id'])) {
+      throw new AccessDeniedHttpException();
+    }
   }
 
   // Register database update for the end of processing.
@@ -92,7 +99,12 @@ function _batch_page() {
       break;
   }
 
-  return $output;
+  // Force a page without blocks or messages to display a list of collected
+  // messages later.
+  drupal_set_page_content($output);
+  $page = element_info('page');
+  $page['#show_messages'] = FALSE;
+  return $page;
 }
 
 /**
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index d956f05..2c66a1c 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -2293,29 +2293,6 @@ function system_php() {
 }
 
 /**
- * Default page callback for batches.
- */
-function system_batch_page() {
-  require_once DRUPAL_ROOT . '/core/includes/batch.inc';
-  $output = _batch_page();
-
-  if ($output === FALSE) {
-    throw new AccessDeniedHttpException();
-  }
-  elseif ($output instanceof Response) {
-    return $output;
-  }
-  elseif (isset($output)) {
-    // Force a page without blocks or messages to
-    // display a list of collected messages later.
-    drupal_set_page_content($output);
-    $page = element_info('page');
-    $page['#show_messages'] = FALSE;
-    return $page;
-  }
-}
-
-/**
  * Returns HTML for an administrative block for display.
  *
  * @param $variables
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 14cc390..5fe55b0 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -1115,11 +1115,12 @@ function system_menu() {
 
   // Default page for batch operations.
   $items['batch'] = array(
-    'page callback' => 'system_batch_page',
+    'page callback' => '_batch_page',
     'access callback' => TRUE,
     'theme callback' => '_system_batch_theme',
     'type' => MENU_CALLBACK,
-    'file' => 'system.admin.inc',
+    'file path' => 'core/includes',
+    'file' => 'batch.inc',
   );
 
   // Localize date formats.
