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;
}
After successful login, the user should be redirected to the page he came from, let's say he's been browsing a post and wants to log in so he can leave a comment, so he should be redirected to the post he was browsing. So here is what I have:
login.php shows the login form:
<form method="post" action="login-check.php">
... //input for username and password
</form>
The login-check.php checks if the username and pass are entered, does the user exist, or if he's already logged in, and a p parameter is sent to login.php:
<?php
session_start();
if((empty($username) OR empty($password) AND !isset($_SESSION['id_login']))) {
header("Location:login.php?p=1");
exit();
}
elseif (!user_exists($username,$password) AND !isset($_SESSION['id_login'])) {
header("Location:login.php?p=2");
exit();
}
elseif(isset($_SESSION['id_login'])) {
header("Location:login.php?p=3");
exit();
}
?>
then parameter p is sent back to login.php and displays the according message:
<?php
if(isset($_GET['p'])) {
$p = $_GET["p"];
if($p=="1")
echo "<p class=\"red\">You didn't fill the form.</p><br></br>";
if($p=="2")
echo "<p class=\"red\">User exists.</p><br></br>";
if($p=="3")
header("Location: index.php");
}
?>
BUT, instead of going to index.php after successful login, it should go to the page the user has previously been. I've tried in different ways, but it either doesn't work at all or returns to login.php.
A common way to do this is to pass the user's current page to the Login form via a $_GET variable.
For example: if you are reading an Article, and you want to leave a comment. The URL for comments is comment.php?articleid=17. While comment.php is loading, it notices that you are not logged in. It wants to send you to login.php, like you showed earlier. However, we're going to change your script so that is also tells the login page to remember where you are:
header("Location:login.php?location=" . urlencode($_SERVER['REQUEST_URI']));
// Note: $_SERVER['REQUEST_URI'] is your current page
This should send the user to: login.php?location=comment.php%3Farticleid%3D17. login.php should now check to see if $_GET['location'] is populated. If it is populated, then send the user to this location (in this case, comment.php?articleid=17). For example:
// login.php
echo '<input type="hidden" name="location" value="';
if(isset($_GET['location'])) {
echo htmlspecialchars($_GET['location']);
}
echo '" />';
// Will show something like this:
// <input type="hidden" name="location" value="comment.php?articleid=17" />
// login-check.php
session_start();
// our url is now stored as $_POST['location'] (posted from login.php). If it's blank, let's ignore it. Otherwise, let's do something with it.
$redirect = NULL;
if($_POST['location'] != '') {
$redirect = $_POST['location'];
}
if((empty($username) OR empty($password) AND !isset($_SESSION['id_login']))) {
$url = 'login.php?p=1';
// if we have a redirect URL, pass it back to login.php so we don't forget it
if(isset($redirect)) {
$url .= '&location=' . urlencode($redirect);
}
header("Location: " . $url);
exit();
}
elseif (!user_exists($username,$password) AND !isset($_SESSION['id_login'])) {
$url = 'login.php?p=2';
if(isset($redirect)) {
$url .= '&location=' . urlencode($redirect);
}
header("Location:" . $url);
exit();
}
elseif(isset($_SESSION['id_login'])) {
// if login is successful and there is a redirect address, send the user directly there
if($redirect) {
header("Location:". $redirect);
} else {
header("Location:login.php?p=3");
}
exit();
}
Gotchas
You should run some validation against $_GET['location'] before sending the user there. For example, if I tell people who use your site to click on this link: login.php?location=http%3A%2F%2Fmalice.com%2Fevilpage.php... then they will be sent to a foreign URL that will try to do something bad.
Always make sure to use urlencode when passing URLs as $_GET parameters. This encodes special URL characters (such as ?, &, and %) so that they don't break your url (e.g.: login.php?location=comment.php?id=17 <- this has two ?'s and will not work correctly)
When user gets to the login page use this to see where is come from
$_SERVER['HTTP_REFERER']
Then set this value into the session, and when he is authenticated use url from the session to redirect him back. But you should do some checking before, if the url is your site. Maybe he come from another site directly to login :)
You can save a page using php, like this:
$_SESSION['current_page'] = $_SERVER['REQUEST_URI']
And return to the page with:
header("Location: ". $_SESSION['current_page'])
You should probably place the url to redirect to in a POST variable.
Since the login page is a separate page, I am assuming that you want to redirect to the page that the user reached the login page from.
$_SERVER['REQUEST_URI'] will simply hold the current page. What you want to do is use $_SERVER['HTTP_REFERER']
So save the HTTP_REFERER in a hidden element on your form <input type="hidden" name="referer" value="<?= $_SERVER['HTTP_REFERER'] ?>" /> but keep in mind that in the PHP that processes the form you will need some logic that redirects back to the login page if login fails but also to check that the referer is actually your website, if it isn't, then redirect back to the homepage.
Another way, using SESSION
Assign current URL to session (use it on every page)
$_SESSION['rdrurl'] = $_SERVER['REQUEST_URI'];
and in your login page, use
if(isset($_SESSION['rdrurl']))
header('location: '.$_SESSION['rdrurl']);
else
header('location: http://example.com');
use something like
$_SERVER['HTTP_REFERER'];
And if it's a successful login, display a link saying "Click here to go back" and a link to the referrer, and when the page loads, use some javascript to automatically load that page (don't use back() or whatever that function is as it won't re-load the page and it'll appear like the user never logged in.
You can use session to to store the current page on which you want to return after login and that will work for other pages if you maintain session properly. It is very useful technique as you can develop your breadcrumb using it.
you can use this:
$refererpage = $_SERVER['HTTP_REFERER']; //get referer stored in a variable
if (strpos($refererpage, $_SERVER['SERVER_NAME']) == TRUE) { //if the start position of the referer and the server name is equal
$refvar= $refererpage; //create a mew variable to be used to locate header
} else { //if referer's address is not the same as server name
$refvar= "index.php"; //set the variable to another direction for this request
}
and add the header where ever u want as:
header('location: '. $refvr); //set the header location to the referer varaible
You should try something like $_SERVER['HTTP_REFERER'].
You should first get user refer page in a variable using $_SERVER['HTTP_REFERER']; in your login page.
LIKE:
<?php
session_start();
$refPage = $_SERVER['HTTP_REFERER'];
?>
And now when the user clicks to Login then change header location to user refer page
LIKE:
<?php
if(isset($_POST[login])){
session_start();
header('location:' . $refPage);
}
?>
And in this time you should first check that user refers page empty or not because your user can visit direct your login page then your $refPage variable will be empty so after Click to Login page stays here
LIKE:
<?php
if(isset($_POST[login])){
session_start();
$refPage = $_SERVER['HTTP_REFERER']; // get reffer page url
if(empty($refPage)){
header('location: yourredirectpage'); // if ref page is empty then set default redirect page.
}else{
header('location:' . $refPage); // or if ref page in not empty then redirect page to reffer page
}
}
?>
Or you can use input type hidden where you can set value $_SERVER['HTTP_REFERER'];
LIKE:
<input type="hidden" name="refPage" value="<?php echo $_SERVER['HTTP_REFERER']; ?>">
And when a user clicks to Login then you can get the refPage value and redirect the previous page. And you should also check empty refer page. Because your user can visit direct your login page.
Thank you.
I have created a function to store URL of previous page
//functions.php
function set_previous_page_url(){
$current_url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
$previous_url = $_SERVER['HTTP_REFERER'];
if (!($current_url === $previous_url)){
$_SESSION['redirect_url'] = $previous_url;
}
if(isset($_SESSION['redirect_url'])){
$url = $_SESSION['redirect_url'];
return $url;
} else {
$url = "index.php";
return $url;
}
}
And call this function in login.php
// login.php
<?php
// set previous page url to redirect after login
$url = set_previous_page_url();
if(ifItIsMethod('post')){
if(isset($_POST['username']) && isset($_POST['password'])){
if (login_user($_POST['username'], $_POST['password'])) {
redirect($url);
//unset session defined in set_previous_page_url() function
if(isset($_SESSION['redirect_url'])){
unset($_SESSION['redirect_url']);
}
}
}
}
?>
Construct the form action such that it 'remembers', or persists, the previous page by writing out a returnurl=value query string key/value pair to the URL - this can be passed from any page that redirects to login.
I think you might need the $_SERVER['REQUEST_URI'];
if(isset($_SESSION['id_login'])) {
header("Location:" . $_SERVER['REQUEST_URI']);
}
That should take the url they're at and redirect them them after a successful login.
how about this :: javascript+php
echo "<script language=javascript> javascript:history.back();</script>";
it will work same as the previous button in your browser
Use hidden input in your login page.
Like:
<input name="location" value="<?php if(!empty($_SERVER['HTTP_REFERER'])) echo $_SERVER['HTTP_REFERER']; else echo 'products.php'; ?>" type="text" style="display: none;" />
You can try
echo "<SCRIPT>alert(\"Login Successful Redirecting To Previous Page \");history.go(-2)</SCRIPT>";
Or
echo "<SCRIPT>alert(\"Login Successful Redirecting To Previous Page \");history.go(-1)</SCRIPT>";
#philipobenito's answer worked best for me.
I first created a hidden input that contain the user's HTTP referer
<input type="hidden" name="referer" value="<?= $_SERVER['HTTP_REFERER'] ?>" />
and after a successful login i redirected the users to whatever value was stored in that hidden input
$_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
if(!empty($_POST['referer'])){
header('Location: '.$_POST['referer']);
}
else{
header('Location: members.php'); //members.php is a page used to send a user to their profile page.
}
exit;
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");
?>
Hey guys am trying to determine if two minutes are over in php..I have an input box and a php script that checks if 5 seconds are over or not..What i need is when the user inserts the correct value i just want to display password is correct and you are now logged in with the existing token.
After 5 seconds i want to display the message like you cant login with this token id anymore.
But the problem is everytime am geting the message you are now logged in with the existing token after 5 seconds. its not showing up the message you cant login .....
The code i have used..
<?php
session_start();
$_SESSION['logintime'] = time();
$name = $_POST['fname'];
$tokenvalue = 'sample';
if($name != $tokenvalue) {
echo 'the token is incorrect<br>';
} else {
echo "the token is correct<br>";
}
if (time() > $_SESSION['logintime'] + 5) {
echo 'you cant login with this token id anymore<br>';
} else {
echo 'you are now logged in with the existing token';
}
Hope can i diplay the message you cant login with this token id anymore after 5 seconds ??..
Where am i doing wrong ??..Any help would be apreciated..Thanx
A PHP script is executed by the server. As soon as you see something in your browser, there is no action on the server anymore (at least in this script).
To accomplish what you are trying here, you need to use AJAX (asynchronous javascript and xml).
There are some things that are eglible in this case:
Hardcoded request after x-seconds with javascript (I would recommend using jQuery for this):
setTimeout(function(){$('#message').load('myScript.php');}, 5000);
You could use SSE (Sever-Sent Events), where you open a persistent connection to the server and push the event after x-seconds. There are good tutorials on HTML5rocks and MDN.
You could use only javascript, because the message will only be on the client side - you need to validate the time anyways, before you save a user input. For this you could also use jQuery:
setTimeout(function(){$('#message').html('you cant login with this token id anymore<br>');}, 5000);
Update: there are some things strange in your code (I will try to explain what I mean using comments):
<?php
session_start();
// you set the login, before you validate the users input
$_SESSION['logintime'] = time();
// thats okay, but actually not really necessary
$name = $_POST['fname'];
// thats okay for a test only :)
$tokenvalue = 'sample';
if($name != $tokenvalue) {
// you should use exit() or die() when the login fails to end the script
echo 'the token is incorrect<br>';
} else {
// first you use the word "token" now "password"
echo "the password is correct<br>";
}
if (time() > $_SESSION['logintime'] + 5) {
echo 'you cant login with this token id anymore<br>';
} else {
echo 'you are now logged in with the existing token';
}
Update2: Maybe this helps you - it does what you described in the question:
<html>
<head>
</head>
<body>
<?php
$tokenvalue = 'sample';
if(isset($_POST['token'])){
if($_POST['token'] === $tokenvalue) {
echo '<div id="success">The password is correct.<br>You are now logged in with the existing token.</div>';
}
}
?>
<form action="" method="post">
Token: <input type="text" name="token"><br>
<input type="submit" value="Submit">
</form>
<script>
if(typeof(document.getElementById('success')) != 'undefined') {
setTimeout(function(){document.getElementById('success').innerHTML = "You can't login with this token anymore."},5000);
}
</script>
</body>
</html>
I am building a website and i would like to secure it against Session Hijacking. Reading for this i came across someone saying that:
A general rule of thumb is to generate the session ID each time a user changes his access level.
1.When a user log in
2.When a user log out
3.When a user get administrative access
For what is worth, my website will be seperating the access levels into users logged-in and users logged-out. All forms are submitted using the POST method.
index.php
<?php
session_start();
//Setting the variable initialy to false
$_SESSION['LOGGED_IN'] = FALSE;
//to use SSL
$serverport = $_SERVER['SERVER_PORT'];
$server_http_host = $_SERVER['HTTP_HOST'];
$server_request_uri = $_SERVER['REQUEST_URI'];
if (headers_sent())
{
die("HTTP headers have already been sent ");
}
else
{
if($serverport != '443')
{
ob_start();
exit(header('Location: https://'.$server_http_host.$server_request_uri));
}
}
if(isset($_POST['SUBMIT']))
{
if(isset($_POST['TOKEN']) && $_POST['TOKEN'] == $_SESSION['TOKEN'])
{
//Open database connection
require_once('connect_db.php');
//Calling functions.php that includes all custom functions
//ErrorHandler()
require_once('functions.php');
$email = $_POST['EMAIL'];
$password = $_POST['PASSWORD'];
$statement = $DBH->prepare("SELECT * FROM user_details WHERE email=:email AND pwd=:password ");
$statement->bindParam(':email',$email);
$statement->bindParam(':password',$password);
$statement->setFetchMode(PDO::FETCH_ASSOC);
try{
$result = $statement->execute();
$rows = $statement->rowCount(); // shows how many times the user is available in the user_details table
$data = $statement->fetch(); //fetches the data related to that user from user_details table
}
catch(PDOException $e)
{
//this is custom function
echo ErrorHandler($e);
}
if($rows == 1)
{
//this means that the user has inserted the correct credentials
//regenerate session_id each time there is a change in the level of privilege to mitigate SESSION FIXATION
session_regenerate_id(true);
//turning logged in variable to true as soon as it finds a match
$_SESSION['LOGGED_IN'] = TRUE;
//saves the email into a session so it can be used in mainpage.php
$_SESSION['EMAIL'] = $email;
//redirect to main page
header('Location:https://www.example.com/mainpage.php');
}
else
{
echo "<br />Wrong username or password!<br />";
}
}//closing *if(isset($_POST['TOKEN']) && $_POST['TOKEN'] == $_SESSION['TOKEN'])*
}//closing *if($_POST['SUBMIT'])*
//creating a random token to inject in our HTML form
$token = base64_encode(openssl_random_pseudo_bytes(32));
//store the random token in the session variable so we can later compare it to the one in the HTML form
$_SESSION['TOKEN'] = $token;
?>
<form action="index.php" method="POST" accept-charset="UTF-8">
<p>Email: <input type="email" name="EMAIL" /> </p>
<p><input type="hidden" name="TOKEN" value="<?php echo $token; ?>" /></p>
<p>Password <input type="password" name="PASSWORD" /> </p>
<p><input type="submit" name="SUBMIT" value="Submit" /></p>
</form>
The script accepts input email and password from the user,checks the database and if it finds a match it redirects the user to the mainpage.php.
mainpage.php
<?php
ob_start();
//the code to set the header must be called before output begins
session_start();
$serverport = $_SERVER['SERVER_PORT'];
$server_http_host = $_SERVER['HTTP_HOST'];
$server_request_uri = $_SERVER['REQUEST_URI'];
if (headers_sent())
{
die("HTTP headers have already been sent ");
}
else
{
if($serverport != '443')
{
ob_start();
exit(header('Location: https://'.$server_http_host.$server_request_uri));
}
}
if(($_SESSION['LOGGED_IN'] == TRUE) && isset($_SESSION['LOGGED_IN']))
{
$email = $_SESSION['EMAIL'];
echo $email;
//Calling functions.php that includes all custom functions
//LogOut()
require_once('functions.php');
if(isset($_POST['LOGOUT']))
{
//its a custom function that is used for logging out
LogOut();
}
echo '
<form method="POST" action="mainpage.php">
<p><input type="submit" name="LOGOUT" value="Log Out" /></p>
</form>
';
}
else
{
echo "Please login in order to use example.com";
}
?>
Is there a way for me to check if the way i have built these 2 scripts really regenerate the Session ID? I am using Firefox's extension LIVE HTTP headers but i am not sure if i am reading it correctly.
Also, i cannot find a way to track down and read the content of COOKIES stored while using my browser (either Chrome or Firefox or even IE11). How can i do that?
Another question that is related with security:
Implementing an anti-CSRF token:
Do i need to implement an anti-CSRF token for each form in my website [i guess the answer is Yes but i want to confirm it]? Should each token be different than the token used in a previous form? For example the token in index.php to be different than the token used in mainpage.php if it had a form as well.
Does the token technique prevent against any other kind of attack?
I would be glad if you indicate wrong programming in the code above, so i can correct it and learn at the same time.
Thanks!
I'm going to focus on your questions and not necessarily a thorough code review, since I think your questions are the main reason you're posting.
A simple way to check your current session id or PHPSESSID is to check under Chrome's Developer Tools > Resources > Cookies. You'll see the (initially-generated) session ID. You can check this value before and after a user logs in. If the value changes, your session id has actually been regenerated.
You can also view cookies in Firefox by right-clicking the current page, going to View Page Info and using the Cookies tab.
On CSRF (prevention) tokens, the answer varies. People use different methods to go about them. I would say a majority of websites set a token in $_SESSION upon any regenerate of the session id. So for the duration of the current session, the CSRF token will remain the same and check against hidden inputs for that CSRF token.
On the other hand, I've also heard of regenerating a CSRF token for every single form that is client-facing. Your way of doing it is up to you. Nothing is 100% bulletproof, but getting as close to 100% as you can is the idea.
Take a few minutes to read up on CSRF tokens and the Synchronizer Token Pattern.
Best of luck!