Pretty simple setup: When the page is loading, a random session token is generated and saved in $_SESSION["token"]. A Form contains this token in a hidden input field. No problems until this point. I submit the form to the very same page (action="") and then I try to check if the $_SESSION["token"] is equal to the token that has been sent via POST. A variable is changed accordingly, and then I generate a new session token that replaces the old $_SESSION["token"] before the page loads again.
Problem is: The $_SESSION["token"] is changed again the moment the page is called (Before I can compare both SESSION and POST tokens) Therefore, both tokens never match. And I can't figure out WHY it changes. It's not the lines of code I wrote, because these are executed aswell, replacing the random token of unknown origin once again, before the page loads.
INDEX:
<?php
session_start();
date_default_timezone_set("Europe/Berlin");
$BASE_URL = "http://" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
$form_valid = false;
if (isset($_POST["token"]) && isset($_SESSION["token"])) {
if ($_POST["token"] == $_SESSION["token"]) {
$form_valid = true;
}
}
//Set (new) session token
$token = bin2hex(random_bytes(10));
$_SESSION["token"] = $token;
//Load actual page
include ("/backend/admin.php");
?>
INCLUDED PAGE:
<?php echo "FORM VALID:"; var_dump($form_valid); ?>
<?php if (!isset($_SESSION["admin"]) || !$_SESSION["admin"]) { ?>
<form id="verify" method="POST" action="">
<label>Password</label>
<input type="password" name="access">
<input type="hidden" name="token" value="<?= $_SESSION['token'] ?>">
<input type="submit" value="Senden">
</form>
<?php } else { ?>
...
<?php } ?>
any help is appreciated. thank you.
There was a problem in your logic, session token updates every time regardless the form is submitted is not,
$token = bin2hex(random_bytes(10));
$_SESSION["token"] = $token
Try this,
<?php
session_start();
date_default_timezone_set("Europe/Berlin");
$BASE_URL = "http://" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
$form_valid = false;
if(empty($_SESSION["token"] )){
$_SESSION["token"]= bin2hex(random_bytes(10));
}
if (isset($_POST["token"]) && isset($_SESSION["token"]))
{
if ($_POST["token"] == $_SESSION["token"]) {
$form_valid = true;
unset($_SESSION["token"]);
}
}
include ("/backend/admin.php");
?>
Related
What is the best method to stop other websites from sending data to my website in PHP?
I googled it and found I need to use Hash. But there are different Hashes, which one to use? Let's say, I pick sha1
Now, how exactly can I prevent other websites from sending post data to my website with sha1
I am bit confused, can someone show me a little demo code.
This is the code, I thought, but it is not flawless..
Index.php page:
$password = sha1("toby123");
<form method="post" action="insert.php" />
<input type="text" name="username"/>
<input type="password" name="password"/>
<input type="hidden" name="hiddenpass" value=" ".$password." "/>
</form>
Insert Into Database PHP Page:
$hiddenpass = "toby123"
if ( $_POST["hiddenpass"] == "sha1($hiddenpass )" )
{
// INSERT THE DATA
}
But the problem here is, hash code in the form will be visiable to everyone. What if someone crack it?
I mean, by using a Hit & Trial method???
Is my method 100% safe??
Edit:
This is my new code after looking at one of the answer, but the If condition is always false.
Index.php Page
<?php
// Start the session
session_start();
$token = bin2hex(random_bytes(32));
if (!isset($_SESSION['token'])) {
$_SESSION['token'] = $token;
}
?>
Insert.php Page:
session_start();
echo $_SESSION['token'];
echo '<br/>';
echo $_POST['token'];
if ( ( isset($_SESSION['token']) ) && ( $_POST['token'] == $_SESSION['token'] ) )
{
// Insert Data
}
else
echo "<br/>Something went wrong";
unset($_SESSION['token']);
Output:
055442be59701631db6ed88dc341027ebf2238507bb9a72f1caefd6d3b126a4b
055442be59701631db6ed88dc341027ebf2238507bb9a72f1caefd6d3b126a4b
Something went wrong
You should be securing your forms by adding using CSRF tokens. The CSRF token should always be random. CSRF stands for (Cross Site Request Frogery)
Here is a good and secure method:
<?php
function random_token()
{
$token = bin2hex(random_bytes(32));
return $token;
}
function gentoken()
{
if (!isset($_SESSION['token'])) {
$_SESSION['token'] = random_token();
}
}
function checktoken($token)
{
if (isset($_SESSION['token']) && $token === $_SESSION['token']) {
deletetoken();
return true;
}
return false; // default
}
function deletetoken()
{
unset($_SESSION['token']);
}
?>
And here should be your form
<form method="post" action="insert.php"/>
<input type="text" name="username"/>
<input type="password" name="password"/>
<input type = "hidden" name="token" value="' . $_SESSION['token'] . '">
<input type = "submit" name="submit" value="Insert"/>
</form>
When the page starts, write this:
gentoken();
**And to check for the token do this**
if (isset($_POST['submit'])) {
$token = $_POST['token'];
if (checktoken($token)) {
} else {
echo "Something wrong happened"; //When the token is changed or doesn't match!
}
}
Notes:
random_bytes() generates secure cryptographical bytes and doesn't need to be hashed!
I hope this helped. Good luck!
Instead of using "toby123" use much cmplex and long random generated string.
For more security you can use two hashes.
session_start();
// if there is data submitted
if(isset($_POST['submit'])){
$password1 = $_SESSION['password1'];
$password2 = $_SESSION['password2'];
//check these passwords
if($_POST['password1']==$password1 && $_POST['password2']==$password2){
// code to pe processed
}else{
echo '<h1>FORBIDDEN</h1>';
}
}else{
$rand1 = md5(uniqid().mt_rand());
$rand1 = md5(uniqid().mt_rand().uniqid());
$password1 = sha1($rand1);
$password2 = sha1($rand2);
$_SESSION['password1'] = $password1;
$_SESSION['password2'] = $password2;
}
I have a very simple php single page, that requires the user to insert a specific username and pass in order to access its contents.
It generates a cookie that allows the user to access that page for one day.
If the user is logged in, the list of contents appear. If it's not, it shows the form.
It is all inside a single index.php page.
This single "protected" page contains a form where the user can put some information and save it. After the user logs in, all the content is shown as intended. But when the user tries to submit that form and reloads the page (the new content should be added to that page), it gets kicked out and the information contained in the form gets lost, and it's not saved.
This are the specific parts of the index.php page:
<?php session_start(); ?>
<!DOCTYPE html>
[...]
<?php
if(isset($_POST['loguearse'])) {
$_SESSION['user']=strip_tags($_POST['user']);
$_SESSION['pass']=strip_tags($_POST['pass']);
if($_SESSION['user'] == 'myuser' && $_SESSION['pass'] == 'mypass') {
if (isset($_SESSION['user'])) {
session_start();
setcookie ("usuario",$_POST['user'], time()+24*60*60);
setcookie ("clave",$_POST['pass'], time()+24*60*60);
}
[HERE IT GOES THE CONTENT THAT WORKS OK IF I STRIP THE LOGIN CONTROL]
}
} else {
setcookie("usuario","");
setcookie("clave","");
echo '
<form method="post">
<div class="form-group">
<input type="text" class="form-control" name="user" id="user" placeholder="Usuario">
</div>
<div class="form-group">
<input type="password" class="form-control" name="pass" id="pass" placeholder="clave">
</div>
</div>
<div class="modal-footer">
<input type="submit" name="loguearse" class="btn btn-primary">
</div>
</div>
</form>
';
echo 'No puedes entrar sin poner la clave correcta!';
}
?>
My question is: How do I keep that user logged in and with an active session for 24 hours?
Your testing order is the problem here. You are originally testing for the POST variable, not the SESSION variable. Try this:
Test for logout to see if the user tried to logout. If so, delete the session.
Test for the session variables to indicate they're already logged in.
IF 1 and 2 are false, test for login. If so, initialize session.
It's the way you construct your if-conditions. Every time the user doesn't submit a post form you overwrite the cookie. The condition isset($_SESSION['user']) has to be on the highest level (at first) and then the post form check.
Also you run twice session_start(), one time is enough.
I use this for this exact thing and just include this in the header of any page.
<?php
#session_start();
// DB DEFINITIONS
require_once($_SERVER['DOCUMENT_ROOT'].'/includes/db.php');
$db = db_connect();
if(isset($_GET['logout'])){
session_unset();
session_destroy();
if (isset($_COOKIE['cookuhash']) && isset($_COOKIE['cookfhash'])){
setcookie("cookuhash", "", time()-2592000,"/");
setcookie("cookfhash", "", time()-2592000,"/");
$uhash=$db->real_escape_string($_COOKIE['cookuhash']);
$fhash=$db->real_escape_string($_COOKIE['cookfhash']);
$db->query("DELETE FROM tblsessions WHERE USER_HASH='$uhash' AND FORM_TOKEN='$fhash'");
}
header("Location: /index.php");
exit();
}
if(!isset($_SESSION['loggedIn'])){
$_SESSION['loggedIn']=false;
$_SESSION['username'] = 'Anonymous';
$_SESSION['userid'] = 0;
$_SESSION['userlevel'] = 0;
$_SESSION['formToken'] = sha1(microtime());
}
if (!$_SESSION['loggedIn'] && isset($_COOKIE['cookuhash']) && isset($_COOKIE['cookfhash'])){
$uhash=$db->real_escape_string($_COOKIE['cookuhash']);
$fhash=$db->real_escape_string($_COOKIE['cookfhash']);
$result = $db->prepare("SELECT u.id,uname, lvl, user_lvl_expires FROM tblusers u LEFT JOIN tblsessions s ON s.USER_ID=u.ID WHERE USER_HASH='$uhash' AND FORM_TOKEN='$fhash'");
$result->execute();
$result->bind_result($id,$uname,$ads,$lvl,$expires);
$result->store_result();
if($result->num_rows > 0){
while ($result->fetch()) {
$_SESSION['loggedIn']=true;
$_SESSION['username'] = $uname;
$_SESSION['userid'] = $id;
$_SESSION['userlevel'] = $lvl;
$_SESSION['expires'] = $expires;
$_SESSION['formToken'] = sha1(microtime());
}
}
}
?>
Then in any page, just check:
#session_start();
if((!isset($_SESSION['loggedIn']) || $_SESSION['loggedIn']==0) && !isset($_COOKIE['cookuhash'])){
header("Location: /login.php");
exit();
}
i'm generate a token for my form like this:
/*** set a form token ***/
$token = md5( uniqid(rand(), true) );
/*** set the session form token ***/
$_SESSION['form_token'] = $token;
and put hidden input in my form like this:
<input type="hidden" name="token" value="<?php echo $token; ?>" />
but when i submit the pages and compare the token it give me a different token id. can anyone tell me am i doing something wrong?
Make sure you only (re)generate a token if the form is not submitted yet.
<?php
// Process request OR show form..
if($_SERVER['REQUEST_METHOD'] === 'POST')
{
// check if we receive a token
if(isset($_POST['form_token']))
{
// compare the token
if($_POST['form_token'] === $_SESSION['form_token'])
{
// do the magic here...
unset($_SESSION['form_token']);
} else {
die('No token match');
}
} else {
die('No token found');
}
} else {
$token = md5( uniqid(rand(), true));
$_SESSION['form_token'] = $token;
// print form with hidden token..
}
Try visiting your site in an incognito window. If this works, you need to delete all your browsers' cookies and other site plugins because your session has been cached. It's trying to match sessions from an earlier time.
I have a problem with a file that involves session in PHP.
I have the following two php files:
confirm_save.php
<?php
include("confirm.php");
$_SESSION = array();
$token = $_SESSION['logout'];
if ($token && $_POST['token']==$token) {
if(isset($_COOKIE["id"]) && isset($_COOKIE["user"]) && isset($_COOKIE["pass"])) {
setcookie("id", '', strtotime( '-5 days' ), '/');
setcookie("user", '', strtotime( '-5 days' ), '/');
setcookie("pass", '', strtotime( '-5 days' ), '/');
}
// Destroy the session variables
session_destroy();
/*// Double check to see if their sessions exists
if(isset($_SESSION['username'])){
header("location: message.php?msg=Error:_Logout_Failed");
} else {
header("location: index.php");
exit();
}*/
header("location: index.php");
}
else {
// log potential CSRF attack.
}
unset($_SESSION["logout"]);
?>
Then, I have the confirm.php
<?php
session_start();
$token= md5(uniqid());
$_SESSION['logout'] = $token;
?>
<html>
<body>
<form method="post" action="confirm_save.php">
<input type="hidden" name="token" value="<?php echo $token; ?>" />
Do you really want to log out?
<input type="submit" value=" Yes " />
<input type="button" value=" No " onclick="history.go(-1);" />
</form>
</body>
</html>
After clicking "yes" in confirm.php, I get the following error:
Undefined index: logout in C:\wamp\www\confirm_save.php on line 4
Line 4 is
$token = $_SESSION['logout'];
I really do not know what the error may be.
You empty your $_SESSION by
$_SESSION = array();
and then try to fill $token
$token = $_SESSION['logout'];
with no value.
There shouldn't be a reason to empty $_SESSION, nor to define $token as you include confirm.php which also includes your $token with value
EDIT
Don't include confirm.php
But do:
<?php
session_start();
$token = $_SESSION['logout'];
if ($_POST['token']==$token) {
...
On line 3 you set $_SESSION to an empty array, meaning that $_SESSION['logout'] doesn't exist;
$_SESSION = array();
$token = $_SESSION['logout'];
I can't see a reason why you would want to empty the array, so you can remove that line.
You don't need the second line anyway. $token will be available as set in confirm.php.
I have 3 pages:
index.php
login.php
display.php
index.php
Sets up AngularJS using the ngRoute module to navigate my pages.
login.php
Loaded by default and sets PHP $_SESSION variables.
display.php
Echos the contents of $_SESSION.
I navigate to display.php from login.php using a link setup with ngRoute.
Problem
display.php does not show $_SESSION variables no matter how many times I navigate to and from it. It will only display them if I manually navigate to the page such as refreshing the page or entering the address in the browser.
I know the php code is executed because I can echo other things to the screen it just doesn't access the $_SESSION variables.
Why is this?
I think i might see where your problem is. You try to access php session in your single page angularJS HTML templates am i right? like:
<div ng-repeat="n in <?php $_SESSION['someSessionArray'] ?>">
That is not how it works. Your $_SESSION will never be available in your templates.
What you can do, is use an ajax request for your login authentication and have that request give you a session id.
Then use that session id when starting your session in further ajax requests (as already mentioned).
Then, when you want to store something to the php session, access the data via ajax request and php service.
a VERY, VERY, VERY, simple Example:
inside getFromSession.php
session_start($_GET['session_id']);
$key = $_GET['key']
echo json_encode($_SESSION[$key]);
inside storeToSession.php
session_start($_GET['session_id']);
$key = $_GET['key'];
$value = $_GET['value'];
$_SESSION[$key] = $value;
inside your login.php
$user = yourAuthMechanism($_GET['username'],$_GET['password']);
if($user) {
session_start();
echo json_decode(array('status' => 'success','sid' => session_id()));
}
else { ... error handling
inside anywhere in your angular where you need to access session data:
$promise = $http.get('pathtoyourphp/getFromSession.php?key=foo');
$http.set('pathtoyourphp/getFromSession.php?key=bar&value=4');
// now use promise to acces the data you got from your service
In general, no reason exists, why AngularJS apps, which request
PHP-based server-side stuff, won't be able to read $_SESSION.
That said, please provide at least the core concepts of of your AngularJS code, so we can provide further details.
Additionally, put just this in display.php:
<?
echo __FILE__
. '<br />' . date( DATE_RFC822 )
. '<br />' . var_dump( $_SESSION )
;
// intentionally skipped dangerous closing PHP-tag
Now run your AngularJS app and tell what comes out.
Make sure you start the session before reading the SESSION variables.
<?php
session_start();
echo $_SESSION["user9"];
?>
I don't think you're looking for angularJS.
I think you're looking for something more like this.
index.php:
<html>
<header>
<title>Login</title>
</header>
<body>
<form method="POST" action="login.php">
<input type="username" name="username" placeholder="username" />
<input type="password" name="password" placeholder="password" />
<input type="submit" value="Login" />
</form>
</body>
</html>
login.php
<?php
session_start();
if(empty($_POST)) {
die("You don't have permission to be here.");
} elseif(empty($_POST['username']) or empty($_POST['password'])) {
die("All fields are required.");
}
$username = "admin";
$password = "password";
if($_POST['password'] == $password && $_POST['username'] == $username) {
$_SESSION['loggedIn'] == "true";
header("Location: show.php");
} else {
die("Invalid login");
}
?>
show.php
<?php
if($_SESSION['loggedIn'] == "true") {
echo "You are logged in";
} else {
die("You don't have permission to be here.");
}
?>