Pass generated ID to next page using POST method - php

In my system when users add a reservation to the database, a transaction ID will be automatically generated:
$insertID = mysql_insert_id() ;
$transactionID = "RESV2014CAI00". $insertID ;
$insertGoTo = "action.php?trans=" . $transact;
But it is very dangerous to pass the $transactionID via address bar. (GET Method) So I need to send transaction to action.php via the POST method.
How can I pass this data using the POST method?

Another approach would be to hash the id as shown below.
$salt = 'your secret key here';
$hash = sha1(md5($transactionID.$salt));
Now you can pass the hash along with the transaction id on the next page and check it match. If it matches then the id wasn't changed. If not then the id was changed. Something like.
$salt = 'your secret key here';
$hash = sha1(md5($_GET['transectionId'].$salt));
if($hash == $_GET['hash']){
//do something
} else {
//Error, id changed
}

If you want to pass the $transactionID from one page to another in your website you can also use $_SESSION.
Information in the basic usage can be found here

Related

PHP how to remove item from session when not in use

On my website, I allow users to view a users information by simply clicking their name. Once they click the persons name, they can schedule the person to come to an event. When the user clicks "schedule me" I take the them full name from the "user_id" and send it as a "$_SESSION['speaker']" to the next file that pretty much checks if the user came from the last file and takes the name and uses it as the input value for the calendar. The problem I am having is that when the user didn't "click schedule" from the other file and goes to the calendar website alone, the name from the previous person they clicked stays there and I want it to be blank in case they want to put a different name. So pretty much i would access the calendar website just by typing the URL and the name would still be in the session. I want to clear the session without logging the user out so they don't see the name of the previous person they clicked. Here is some of my code
First file
$_GET['speaker'] = $_SESSION['speaker_id'];
$speaker_id = $_GET['speaker'];
$stmtSpeaker = $handler->prepare("SELECT * FROM formdata WHERE user_id= :speaker_id");
$stmtSpeaker->bindParam(':speaker_id', $speaker_id, PDO::PARAM_INT);
$stmtSpeaker->execute();
$formData = $stmtSpeaker->fetch();
if(isset($_POST['schedule_me'])){
$_SESSION['admin'] = $adminBoolean;
$_SESSION['speaker'] = $formData['fullname'];
$_SESSION['speaker_came'] = true;
header("Location: admincalendar.php");
exit;
}
Second file
$adminBoolean = $resultChecker['admin'];
if($_SESSION['speaker_came'] = true){
$speaker = $_SESSION['speaker'];
}else{
$speaker = "";
}
Unset will destroy a particular session variable whereas session_destroy() will destroy all the session data for that user.
It really depends on your application as to which one you should use. Just keep the above in mind.
unset($_SESSION['name']); // will delete just the name data
session_destroy(); // will delete ALL data associated with that user.
You can unset session variable
$adminBoolean = $resultChecker['admin'];
if($_SESSION['speaker_came'] = true){
$speaker = $_SESSION['speaker'];
}else{
unset($_SESSION['speaker']);
unset($_SESSION['speaker_came']);
$speaker = '';
}
You need to first get the tempkey of the element and then unset it. Try this:
if(($tempkey = array_search($speaker_id, $_SESSION['speaker'])) !== FALSE)
unset($_SESSION['speaker'][$tempkey]);

parse password reset key from emailed weblink

Since I switched to using hashed passwords in my demo website, I needed to provide a way reset forgotten passwords.
I've got the pages and php setup to send an email with a url+key that the user will need in order to setup new password. The email contains the url to click on and the link brings the user to the reset password page.
The part I'm having a bit of trouble with is pulling the key information from the url so I can use it to compare to the key generated from the reset password submission. The database correctly inserts the key when the forgot password form is submitted.
I'm assuming I need to use parse_url to extract this information from the link but I'm not quite sure how to pull only the key information from the link.
I think PHP_URL_QUERY gets me to the correct part of the URL. From here I'm not quite sure what to do next since PHP_URL_QUERY gives me all of this:
key='.$2y$10$q53hrjswTfXnkxg8QeJysezbBi91t4yJcbV9bH3addOSiotr6kE1
when what I really want is this to do the comparison:
'.$2y$10$q53hrjswTfXnkxg8QeJysezbBi91t4yJcbV9bH3addOSiotr6kE1
Here's the code I've got right now....
<?php
require_once '../php/connect.php';
function URL() {
$purl = 'http';
if ($_SERVER["SERVER_PORT"] == "80") {
$purl .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
return $purl;
}
$key = parse_url($purl, PHP_URL_QUERY)
$qry = mysqli_query($link, "SELECT id FROM planner WHERE rkey = '$key'");
$array = mysqli_fetch_array($qry);
}
}
I think I just need a way to strip the key= part from the rest, but I'm not sure that is quite right.
Any assistance is greatly appreciated.
Got this working with the following....this is just a start. Thanks again everyone.
<?php
require_once '../php/connect.php';
$sub = htmlspecialchars($_GET["key"]);
$ser = "'.";
$rkey = str_replace($ser,'',$sub);
$qry = mysqli_query($link, "SELECT id FROM planner WHERE rkey = '$rkey'");
$row = mysqli_num_rows($qry);
echo $row;
?>

Protect your delete.php links sended by email

How to protect my delete.php files
$id = (int) $_GET['id'];
$delete = $connection->prepare("DELETE FROM `articles` WHERE `id` = :id");
$delete->execute(['id' => $id]);
if($delete->rowCount() > 0){
echo 'SUCCESS';
}else{
echo 'ERROR';
}
Lets say am logged in my website panal and my session is on
$_SESSION['user_id'] = My_ID;
And some hacker send a link in my email while i am logged in
<img src="http://my.website.com/panel/articles/delete.php?id=353">
That link is going to delete my article OR WORST a complete main section of my website and that is VERY DANGEROUS. So how can i secure my delete links from that
This is a very good example, why it is stated in the HTTP RFC, that GET method should be used only to request the data, while for the data manipulation it's POST method should be used.
And to protect POST forms from this kind of fraud, a usual CSRF protection have to be used. In short, each form should be signed with a secret token, stored in the session as well. So a site will be able to verify, whether the form was issued by the engine.
An example can be found here, preventing csrf in php
You can build two step confirm form
When user going to articles/delete.php?id=353, you just calculate some hash 'qweadasdasdqw' and provide link just like this articles/delete.php?id=353&hash=qweadasdasdqw
And just build some form with question 'Do you really want to delete article?'
button 'yes' will provide user to url articles/delete.php?id=353&hash=qweadasdasdqw ,
button 'no' wil provide user to list of article.
so if hash is correct, you will be delete this article
Take a look on the code
$hash = isset($_GET['hash']) ? $_GET['hash'] : null;
$id = (int) $_GET['id'];
if (isset($hash) && (md5($id) == $hash)) { // Check hash
$delete = $connection->prepare("DELETE FROM `users` WHERE `id` = :id");
$delete->execute(['id' => $id]);
if($delete->rowCount() > 0){
echo 'SUCCESS';
}else{
echo 'ERROR';
}
} else {
$hash = md5($id); // Generate hash todo use more security function
echo 'Do you really want to delete this article? yes';
}
You could do few things ,
Use post method for data manipulations instead of get.
You can also make use of tokens, make sure you ,regenerate your tokens
Don't just check if user is logged in but also make sure the logged in user has permission to delete / update that record .

transferring data by get, php in the url and security

Here is the first question and I need your help.
I transfer form data from first page using header location method in php to second page.
On the second page I accept the data using get.
Now here the url of 2nd page, after the data is sent (i.e. form is submitted)
http://mydomain.com/site1/form1_conf.php?id=123
When user is on second page, the data on second page is being displayed according the id number from the mysql database.
Now the problem is that when the user is on second page and he changes the number (for ex. 123 to say 78) the data of id=78, from the database is displayed, which is no good.
How can I stop that?
Please Note: I can't use post, nor can I use sessions.
EDITE:
php code on first page, to transfer to second page:
// after all validations are okay
$insert = //insert into database
$result = mysql_query($insert);
if($result)
{
echo("<br>Input data is succeed");
$lastInsertedId = mysql_insert_id();
header('Location:form1_conf.php?id='.$lastInsertedId); //THIS IS THE IMPORTANT LINE
}
else
{
$message = "The data cannot be inserted.";
$message .= "<br />" . mysql_error();
}
Your problem is not with the URLs: to a power user changing cookies or POST-variables is as trivial as editing GET-variables for a regular user. You'll need some way to 'sign' the requests as being valid.
Easiest to do this is with a "pre-shared key", which you use with one-way hashes to validate requests.
Redirector:
$newURL = '/newpage?id='.$id.'&hash='.sha1('mypresharedkey'.$id);
header('HTTP/1.1 303 See other');
header('Location: '.$newURL);
die;
The other page:
$idToShow = $_GET['id'];
$hash = sha1('mypresharedkey'.$id);
if($hash != $_GET['hash'])
die("Tssss, don't play with the address bar!");
else
RenderThePage();
This ensures end users can only access pages they've been allowed to by the submit.
For your specific code:
...all prior code
$lastInsertedId = mysql_insert_id();
$timestamp = time();
header('Location:form1_conf.php?'.http_build_query([
'id' => $lastInsertedId,
'time' => $timestamp,
'hash' => sha1('some-generated-key'.$timestamp.$lastInsertedId)
]);
In the other page, including a timebomb if you want (otherwise just comment it out):
$id = $_GET['id'];
$time = $_GET['time'];
if($_GET['hash'] != sha1('some-generated-key'.$time.$id))
die('URL was tampered with');
if(time() - $time > 300)
die('URL was only valid for 5 minutes');
You need to track the user and the id that they have in your database to make sure that they haven't changed the number. So when you get the information via the GET you make sure that it is legit.
Users can change the id or even attempt to go directly to that page via the url. So you need some sort of server-side check to verify that it is ok.
You could complicate this "cheating" a bit, if you didn't pass the ID number directly, but somehow encrypted it.
Let's say, you define a salt:
define(SALT, 'long weird salt with special characters etc.');
Here comes the first part you want:
$lastInsertedId = mysql_insert_id();
$querytag = base64_encode($lastInsertedId); // just to make it less readable
$checksum = md5($querytag . SALT); // and make a hash
header('Location:form1_conf.php?id=' . $querytag . '&checksum=' . $checksum);
At the beginning of form1_conf.php, you put this:
$encodedId = $_GET['id'];
$oldChecksum = $_GET['checksum'];
$newChecksum = md5($encodedId . SALT);
$id = base64_decode($encodedId);
if($newChecksum != $oldChecksum) {
die('You Are Cheating!');
}
... do something with the $id ...
The point is that since you add SALT to the hash, some user can't simply use md5 on a changed ID, because he's missing the SALT you used.
It'd be even better if the salt wasn't the same every time.
You should never trust the url because there is always a way to manipulate the data.
So you should do validation after retreiving the data. If the result does not fit you: for example the loggedin user with the ID = 1 requests the settings page from the userid = 3 you do not show the result.
<?php
$userID = $_GET['id'];
if($userID != $expectedResult)
{
//show errormessage, redirect or show the page with the users data
}
?>

Keep a given ID in URL upon successful login

if(!$_POST['username'] || !$_POST['password'])
$err[] = 'All the fields must be filled in!';
if(!count($err))
{
$_POST['username'] = mysql_real_escape_string($_POST['username']);
$_POST['password'] = mysql_real_escape_string($_POST['password']);
$_POST['rememberMe'] = (int)$_POST['rememberMe'];
// Escaping all input data
$row = mysql_fetch_assoc(mysql_query("SELECT id,usr FROM tz_members WHERE usr='{$_POST['username']}' AND pass='".md5($_POST['password'])."'"));
if($row['usr'])
{
// If everything is OK login
$_SESSION['usr']=$row['usr'];
$_SESSION['id'] = $row['id'];
$id = $row['id'];
$_SESSION['rememberMe'] = $_POST['rememberMe'];
// Store some data in the session
setcookie('tzRemember',$_POST['rememberMe']);
}
else $err[]='Wrong username and/or password!';
}
if($err)
$_SESSION['msg']['login-err'] = implode('<br />',$err);
// Save the error messages in the session
$goHere = 'Location: /index2.php?id=' . $id;
header($goHere);
exit;
}
I have the following code that once logged in, it $_GET the id and prepends to the url like index2.php?id=5 . How do I keep this id=5 in the URL no matter WHAT link they click on??
This id is grabbed from this:
$_SESSION['usr']=$row['usr'];
$_SESSION['id'] = $row['id'];
$id = $row['id'];
What I want to do
Well way i have it setup, you login, it then sends you to the homepage such as index2.php?id=[someint] , if you click another link say 'prof.php', it removes the id=[someint] part, I want to keep it there in the url, so as long as a user is LOGGED in -- using my code above, the url might read: index.php?id=5, then go to another page it might read prof.php?id=5, etc, etc. This integer would obviously be dynamic depending on WHO logged in
Instead of passing around an ID in the URL, consider referring to the id value in the $_SESSION variable. That way the user can't modify the URL and see data they aren't supposed to see (or much worse), and you don't have to worry over appending it to every URL and reading it into a value every time you go to process a script. When the user logs in, you determine their ID - read it from a database, determine it realtime, whatever. Then store it in the $_SESSION and refer to it as needed. You can even use this as part of a check to see if the user is logged in - if they have no $_SESSION['id'] value, something is wrong and you make them log in.
The query string isn't the place for that, for a whole host of reasons. The most obvious one is that I can log in with a valid account, then change the number in the URL and it'll think I'm someone else.
Instead, just continue using the session as it's the proper way.
If you REALLY want to do it, you'd probably want to write a custom function for generating links
function makeLink ($link, $queryString = '')
{
return $link . '?id=' . (int) $_SESSION['id'] . ((strpos($queryString, '?') === 0) ? substr($queryString, 1) : $queryString);
}
called like
Click me
As a basic auth example using the ID...
<?php
// Session start and so on here
if (!isset($_SESSION['id']))
{
// Not logged in
header('Location: /login.php');
exit;
}
http://www.knowledgesutra.com/forums/topic/7887-php-simple-login-tutorial/ is a pretty straightforward full example of it.

Categories