I have a project that I am working on where subscribers will receive an update via email containing links to notices. These notices can only be viewed by registered members, so in order to do that I have a login page and script. I am using

$ticket = clean($_GET['ticket']);

to pull the value from the url. This shows up fine and when the script checks for authorization and they are not logged in, it sends them to the log in page where the "ticket" shows up no problem in the url. After they input their info, I run the script:

<?php
	//Start session
	session_start();
	
	//Include database connection details
	require_once('config.php');
	
	//Array to store validation errors
	$errmsg_arr = array();
	
	//Validation error flag
	$errflag = false;
	
	//Connect to mysql server
	$link = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
	if(!$link) {
		die('Failed to connect to server: ' . mysql_error());
	}
	
	//Select database
	$db = mysql_select_db(DB_DATABASE);
	if(!$db) {
		die("Unable to select database");
	}
	
	//Function to sanitize values received from the form. Prevents SQL injection
	function clean($str) {
		$str = @trim($str);
		if(get_magic_quotes_gpc()) {
			$str = stripslashes($str);
		}
		return mysql_real_escape_string($str);
	}
	
	//Sanitize the POST values
	$login = clean($_POST['login']);
	$password = clean($_POST['password']);
	
	//Input Validations
	if($login == '') {
		$errmsg_arr[] = 'Login ID missing';
		$errflag = true;
	}
	if($password == '') {
		$errmsg_arr[] = 'Password missing';
		$errflag = true;
	}
	
	//If there are input validations, redirect back to the login form
	if($errflag) {
		$_SESSION['ERRMSG_ARR'] = $errmsg_arr;
		session_write_close();
		header("location: login-form.php?ticket=$ticket");
		exit();
	}
	
	//Create query
	$qry="SELECT * FROM members WHERE login='$login' AND passwd='".md5($_POST['password'])."'";
	$result=mysql_query($qry);
	
	//Check whether the query was successful or not
	if($result) {
		if(mysql_num_rows($result) == 1) {
			//Login Successful
			session_regenerate_id();
			$member = mysql_fetch_assoc($result);
			$_SESSION['SESS_MEMBER_ID'] = $member['member_id'];
			$_SESSION['SESS_FIRST_NAME'] = $member['firstname'];
			$_SESSION['SESS_LAST_NAME'] = $member['lastname'];
			$_SESSION['SESS_ADMIN_LEVEL'] = $member['adminLevel'];
			session_write_close();
			header("location: read_notices.php?ticket=$ticket");
			exit();
		}else {
			//Login failed
			header("location: login-failed.php?ticket=$ticket");
			exit();
		}
	}else {
		die("Query failed");
	}
?>

Problem is that when it redirects to either read_notices.php?ticket=$ticket or login-failed.php?ticket=$ticket the "ticket" is no longer there.

I am using $ticket = clean($_GET['ticket']); on the login page which uses a form and executes the above file.

Maybe there is an easier way to store the "ticket" until the user is at the viewing page. Other than that, the ticket seems to get "lost" along the way. This is not my complete code because it is quite long, but if you need more then let me know. Thanks in advance!

Dani AI

Generated

Diagnosis and quick cause: as noted, the login processor never sees a value for $ticket because a GET query string on the page that shows the form is not automatically carried along when the form is submitted via POST. The form submission only sends the form fields (and cookies). That’s why the redirect ends up as read_notices.php?ticket= — the script is asking for a variable that was never passed to it.

Simplest fix (matches ): include the ticket as a hidden form field so the POST carries it forward. Example snippet to place inside the form (escape when echoing into HTML):

<input type="hidden" name="ticket" value="<?php echo htmlspecialchars($ticket, ENT_QUOTES); ?>">

Then in the login handler read $_POST['ticket'], validate/sanitize it, and use that value for the redirect. Alternatively the form action can include the ticket as a query string (action="login-exec.php?ticket=...") so the handler can use $_GET.

Session-based option (matches ): store the ticket server-side when rendering the login form (put it in a session key). The login handler then reads the session key and clears it after use. This is better for sensitive tokens because it avoids exposing the value in the page source or relying on client input. In all cases, regenerate the session identifier after successful authentication to reduce fixation risks.

Troubleshooting and security notes: confirm the hidden field appears by viewing the page source; ensure no output is sent before any header() redirects; always validate the ticket on the server (map it to a database record or expiry timestamp) rather than trusting raw input; prefer prepared statements for any DB lookup. These steps will keep the ticket intact across the login flow and avoid the blank query-string problem described by .

Recommended Answers

All 7 Replies

Maybe it's in the code that you omitted, but I don't see where you're declaring $ticket as a variable to be used in the header() calls. From the looks of it the header() function doesn't have access to a variable called $ticket. The URL that it's redirecting to, does it just look like this: "read_notices.php?ticket=" or does it omit everything after the ".php"?

No it does not omit everything after the .php? It actually says "read_notices.php?ticket=" but the ticket number does not exist.

As far as declaring the variable so that it is available to the header call, how do I do that? I thought that the variable were all available globally.

Here is the code for the form that executes the above script:

<h1> You need to log in to view this document. </h1>
<?php
function clean($str) {
	$str = @trim($str);
	if(get_magic_quotes_gpc()) {
		$str = stripslashes($str);
	}
	return mysql_real_escape_string($str);
}
$ticket = clean($_GET['ticket']);
echo $ticket;
?>
<form id="loginForm" name="loginForm" method="post" action="login-exec.php">
  <table width="300" border="0" align="center" cellpadding="2" cellspacing="0">
    <tr>
      <td width="112"><b>Login</b></td>
      <td width="188"><input name="login" type="text" class="textfield" id="login" /></td>
    </tr>
    <tr>
      <td><b>Password</b></td>
      <td><input name="password" type="password" class="textfield" id="password" /></td>
    </tr>
    <tr>
      <td>&nbsp;</td>
      <td><input type="submit" name="Submit" value="Login" /></td>
    </tr>
  </table>
</form>
</body>
</html>

Maybe it has something to do with the way it executes as opposed to being a require_once type of call that is in the rest of the other pages.

In the first code you posted, $ticket is never set to a value.

Right, so then that is the problem - how do I get $ticket set to a value in the first script that is running off of the form (that last code I posted) where it can pull the variable from the URL?

Add the ticket as a hidden input into the form, so you can read it again with $_POST

Gotcha, That should work. Thanks for helping my ignorant self!

Another option may be to start the session on the page with the form, instead of the second page. You could then store the ticket in the session.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.