AJAX hijacking Session data

JavaScript and client side scripting.

Moderator: General Moderators

Post Reply
User avatar
Chalks
Forum Contributor
Posts: 447
Joined: Thu Jul 12, 2007 7:55 am
Location: Indiana

AJAX hijacking Session data

Post by Chalks »

I have a piece of code on several of my pages that looks like this:

Code: Select all

if(isset($_SESSION['msg']) && !empty($_SESSION['msg']))
{
  echo $_SESSION['msg'] . "<br /><br />";
  $_SESSION['msg'] = "";
}
However, when I use ajax to place a message into my database, the session variable 'msg' is set to that value, and it shouldn't be! Here's the ajax I'm using:

Code: Select all

function send()
{
  try
  {
    var subj = document.forms['msg'].subject.value;
    var msg = document.forms['msg'].message.value;
    var to = "";
    var from = document.forms['msg'].from.value;
    var gameID = document.forms['msg'].gameID.value;
 
for (var i=0; i<document.forms['msg'].to.length; i++)
   if (document.forms['msg'].to[i].checked)
      to += document.forms['msg'].to[i].value + ",";
var L = to.length - 1;
to = to.substr(0, L);  // to get rid of the extra comma at the end
 
    reqsend.open("POST", "back/send.php", true);
    var stuff = "subject=" + subj + "&message=" + msg + "&to=" + to + "&from=" + from + "&gameID=" + gameID;
 
    reqsend.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // need for POST
    reqsend.setRequestHeader("Content-Length", stuff.length);
    reqsend.send(stuff);
 
    reqsend.onreadystatechange = function()
    {
      if (reqsend.readyState == 4 && reqsend.status == 200)
      {
        if(reqsend.responseText=="ok")
        {
          document.getElementById("msgResponse").innerHTML = "Message sent!";
          document.forms['msg'].subject.value = "";
          document.forms['msg'].message.value = "";
          for (var i=0; i<document.forms['msg'].to.length; i++)
             document.forms['msg'].to[i].checked = false;
        }
        else
          document.getElementById("msgResponse").innerHTML = reqsend.responseText;
      }
      else
        document.getElementById("msgResponse").innerHTML = "Loading...";
    };
  }
  catch(e){};
}
Here's back/send.php:

Code: Select all

<?php
include 'head.php';  // head has a line that basically keeps the session alive... needed?
include 'creation.php';  // contains $host, $user, $pass, and $databaseName
include '../toolkit/validator.php'; // used to easily validate strings
include '../toolkit/databaser.php';  // used to do stuff to my database without having to remember mysql code
$d = new databaser;
$v = new validator;
$d->connect($host, $user, $pass, $databaseName);
 
if(!$_SESSION['logged'])
  bad($d, "Please log in.");
 
// first make sure all variables are set and not empty
if(isset($_POST['subject']) && isset($_POST['message']) && isset($_POST['to']) && isset($_POST['from']) && isset($_POST['gameID']) && !empty($_POST['subject']) && !empty($_POST['message']) && !empty($_POST['to']) && !empty($_POST['from']) && !empty($_POST['gameID']))
{
// now escape data and make sure things are what they should be
  $subj = mysql_real_escape_string($_POST['subject']);
  $msg = mysql_real_escape_string($_POST['message']);
  $to = explode(",", $_POST['to']);
  $from = $_POST['from'];
  $gameID = $_POST['gameID'];
  $sendAll = false;
  $started = false;
  $allInGame = true;
  $checkTo = array();
 
// make sure it's either a valid user id, or is  "all"
  foreach($to AS $id)
    if(!is_numeric($id) && $id!="all")
      bad($d, "Invalid IDs.");
  if(!is_numeric($gameID) || !is_numeric($from))
    bad($d, "Invalid IDs.");
 
//make sure game exists, and user exists, and make sure user is actually in that game
  if($d->exists("games", "id=$gameID") && $d->exists("user", "id=$from"))
  {
    $data = $d->get("games", "aut, gbr, fra, deu, ita, rus, tur, pm, started", "id=$gameID");
    $checkFrom = $d->get("user", "id, name", "id=$from");
  }
  foreach($to AS $id)
    if($id=="all")
      $sendAll = true;
    else
      if($d->exists("user", "id=$id"))
        $checkTo[] = $d->get("user", "id, name", "id=$id");
 
//get game year
  $senton = $data['started'];
 
//make sure you can send pms.  $started is a misnamed variable
  if($data['pm']==1)
    $started = true;
 
//now make sure the people you're sending it to are actually in the game too
  if(!in_array($checkFrom['name'], $data))
    $allInGame = false;
  foreach($checkTo AS $ckTo)
    if(!in_array($ckTo['name'], $data))
      $allInGame = false;
  if(!$allInGame)
    bad($d, "The selected recipients aren't playing this game.  Something broke.");
 
//private messaging allowed?
  if(!$started && !$sendAll)
    bad($d, "Sorry, you can't send private messages right now.");
 
//if all the above passed, should get here.  If send to all, insert into the database with field 'tou' populated with -1 (i.e. everyone)
//if send to individuals, insert into database once for each recipient
  if($sendAll)
  {
    $values = "$gameID, -1, " . $checkFrom['id'] . ", '$subj', '$msg', NOW(), $senton";
    $d->insert("messages", "game, tou, fromu, subject, message, dated, senton", $values);
    good($d);
  }
  else
  {
    foreach($to AS $id)
    {
      $values = "$gameID, $id, " . $checkFrom['id'] . ", '$subj', '$msg', NOW(), 0, $senton";
      $d->insert("messages", "game, tou, fromu, subject, message, dated, reade, senton", $values);
echo mysql_error();
    }
    good($d);
  }
}
else
  bad($d, "Make sure you have filled in all parts of the form.");
 
 
function bad($d, $err="")
{
  $d->disconnect();
  echo "There was an error.  $err";
  die();
}
 
function good($d)
{
  $d->disconnect();
  echo "ok";
  die();
}


SO. Why is the $_SESSION['msg'] getting the value from the javascript var msg?
Why, how, and where is the javascript getting confused with SESSION values?

edit: I found a workaround. If I remove the following three lines from send.php, it doesn't get the session variable screwed up. Why not? Also, I don't really want to remove those three lines... if I did, would it be possible to send a message using an offsite form without being logged in? i.e. making it look as if user ID 19 sent a message to user ID 20 even though he really didn't?

Code: Select all

//include 'head.php';
//if(!$_SESSION['logged'])
//  bad($d, "Please log in.");
Post Reply