csrf Token class - php

can someone explain me how to protect the profile page from the wrong user editing the URL to see some other users profile page. i am using a token class to generate a random number to protect against Cross Site Request Forgery. for some reason it doesn't work any suggestion or other way to do that
Also i get the following error : Undefined index: token in PhpProject22_CSRF\profile.php on line 12
<?php
session_start();
require_once 'Classes/Token.php';
$tk = new Token();
if(isset($_POST['username'],$_POST['product'],$_POST['token'])){
$username = $_POST['username'];
$product = $_POST['product'];
if(!empty($product) && !empty($username)){
if(Token::check($_POST['token'])){
echo $_POST['token'].'<br>';
$tk->get('username');
$_SESSION['user'] = $tk->name();
echo 'Process Order';
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>CSRF Protection</title>
</head>
<body>
<form action="" method="POST">
<div class="product">
<strong>Profile</strong>
<div class='field'>
Username: <input type='text' name='username'>
</div>
<input type='submit' value='Order'>
<input type='hidden' name='product' value='1'>
<input type='hidden' name='token' value='<?php echo Token::generate();?>'>
</div>
</form>
<?php
if(isset($_POST['username'])){
?>
<p>Hello <a href = 'profile.php?user=<?php echo $tk->name();?>'><?php echo $tk- >name();?></a>!</p>
<?php
}
?>
</body>
</html>
<?php
class Token{
private $_data;
public static function generate(){
return $_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32));
}
public static function check($token){
if(isset($_SESSION['token']) && $token === $_SESSION['token']){
unset($_SESSION['token']);
return true;
}
return false;
}
public function get($item){
if(isset($_POST[$item])){
$this->_data = $_POST[$item];
}
}
public function name(){
return $this->_data;
}
}
?>
<?php
require_once 'Classes/Token.php';
session_start();
?>
<form action="" method="POST">
<input type='hidden' name='token' value='<?php echo Token::generate();?>'>
</form>
<?php
echo 'Hello '.$_SESSION['user'].'!<br>';
if(isset($_GET['user'])){
if(Token::check($_POST['token'])){
echo $_GET['user'];
}
}
?>

When checking post you need to do the following:
if($_POST){
if(isset($_POST['token']) && Token::check($_POST['token']){
code
}else{
error
}
}
If someone spoof the post, and doesn't include the token, you're going to get an undefined index error, because $_POST['token'] doesn't exist and you are referencing it.

Related

PHP always evaluates $_POST array isset/!empty/sizeof>0 to true for html form input

I have a basic form to upload an image:
<?php
if(!empty($_POST['?upload_img'])) {
echo "true<br>";
} else { echo "false<br>"; }
?>
<html>
<form action='' method='post' enctype='multipart/form-data'>
<input type='file' name='input_img' id='input_img'><br>
<input type='submit' value='Upload Image' name='?upload_img'>
</form>
</html>
I would like a PHP boolean/evaluation pair to run only once for each upload.
I have tried evaluating using !empty,isset,sizeof(foo)>0
I have also tried to find a solution using $_SESSIONs
Is there are correct use of unset or $_POST=array()/$_FILE=array() that I have missed?
I can achieve the desired behaviour with sessions:
<?php
session_start();
if(!empty($_SESSION['foo'])) {
echo "true<br>";
} else { echo "false<br>"; }
?>
<html>
<?php
if(!sizeof($_SESSION['foo'])) {
$_SESSION['foo']=array();
$_SESSION['foo']['bar']="path/to/the/file.png";
} else { $_SESSION=array(); }
?>
</html>
How can I achieve the same with input from a <form> instead?
Any help is much appreciated!
For completeness, an outline approach specific to my issue:
<!--filename:foo.php-->
<?php
session_start();
if(isset($_POST['?confirm'])) {
$_SESSION['input']=$_FILES['input'];
header("HTTP/1.1 303");
header("Location: http://$_SERVER[HTTP_HOST]/foo.php");
die;
} else if(!empty($_SESSION['input'])) {
echo "true<br>";
session_unset();
session_destroy();
} else { echo "false<br>"; }
?>
<html>
<form action='foo.php' method='post' enctype='multipart/form-data'>
<input type='file' name='input' id='input'><br>
<input type='submit' value='confirm' name='?confirm'>
</form>
</html>
Based on Post-Redirect-Get Pattern in PHP
use a token
$token = md5(session_id().mt_rand().time());
$_SESSION['token'] = $token;
<input type="hidden" name="token" value="<?php echo $token; ?>" />
later when you process the image delete the token with unset()

while making login page, I am unable to redirect to another page

There is an error while redirecting the page from login to index(i.e server error // error 500). I used redirect_to function to call function.php from login.php file and i have included header function in function.php file. unfortunately, there is server error.I tried to solve it but i could not.i have posted my all four file.
login.php
<?php
require_once("../../includes/function.php");
require_once("../../includes/database.php");
require_once("../../includes/session.php");
require_once("../../includes/user.php");
if($session->is_logged_in()){
redirect_to("index.php");
}
//remember to give your form's submit tag a name= "submit" attribute
if(isset($_POST['submit'])){
$username = trim($_POST['username']);
$password = trim($_POST['password']);
//check database to see if username/password exit.
$found_user = User::authenticate($username,$password);
if($found_user){
$session->login($found_user);
redirect_to("index.php");
}else{
//username/password combo was not found in the database
$message ="Username/password incorrect.";
echo $message;
}
}
else{//form has not been submitted
$username = "";
$password = "";
}
?>
<?php if(isset($database)) {
$database->close_connection();
}
?>
<html>
<head>
<title>Photo Gallery</title>
<link href="boot/css/bootstrap.css" media="all" rel ="stylesheet" type
="text/css"/>
</head>
<body>
<div id="header">
<h1>Photo Gallery</h1>
</div>
<div id ="main">
<h2>staff login</h2>
</div>
<form action="login.php" method="post">
<table>
<tr>
<td>Username:</td>
<td>
<input type = "text" name = "username" maxlength="30" value="<?php echo
htmlentities($username);?>"/>
</td>
</tr>
<tr>
<td>Password:</td>
<td>
<input type = "password" name= "password" maxlength = "30" value ="
<?php echo htmlentities($password);?>"/>
</td>
</tr>
<tr>
<td>
<input type="submit" name="submit" value = "login"/>
</td>
</tr>
</table>
</form>
</body>
</html>
index.php
<?php
require_once('../../includes/function.php');
require_once('../../includes/session.php');
if(!$session->is_logged_in()) {
redirect_to("login.php");
}
?>
<html>
<head>
<title>Photo Gallery</title>
<link href="boot/css/bootstrap.css" media="all" rel ="stylesheet" type
="text/css"/>
</head>
<body>
<div id="header">
<h1>Photo Gallery</h1>
</div>
<div id ="main">
<h2>staff login</h2>
</div>
<div id = "footer">Copyright<?php echo date("Y", time());?>,prayash
bhari</div>
</body>
</html>
function.php
<?php
ob_start();
function strip_zeros_from_data($marked_string =""){
//first remove the marked zeros
$no_zeros = str_replace('*0','',$marked_string);
//then remove any remaining marks
$cleaned_string = str_replace('*','', no_zeors);
return $cleaned_string;
}
function redirect_to($location = NULL){
if ($location != NULL){
header("Location : {$location}");
exit;
}
}
function output_message($message = ""){
if($empty($message)){
return "<p class = \"message\">{$message}</p>";
}
else{
return "";
}
}
function __autoload($class_name){
$class_name = strtolower($class_name);
$path = "../includes/{$class_name}.php";
if(file_exists($path)){
require_once($path);
}else{
die("the file {$class_name}.php could not found.");
}
}
ob_end_flush();
?>
sesssion.php
<?php
// A class to help work with Sessions
//In our case, primarily to mange logging users in and out
//keep in mind when working with sessions that it is generally
//inadvisable to store DB-relate objects in sessions
class Session{
private $logged_in = false;
public $user_id;
function __construct(){
session_start();
$this->check_login();
if($this->logged_in){
//actions to take right away if user is logged in
}else{
//actions to take right away if user is not logged in
}
}
public function is_logged_in(){
return $this->logged_in;
}
public function login($user){
//database should find user based on username/password
if($user){
$this->user_id = $_SESSION['user_id'] = $user -> id;
$this->logged_in = true;
}
}
public function logout(){
unset($_SESSION['user_id']);
unset($this->user_id);
$this->logged_in = false;
}
private function check_login(){
if(isset($_SESSION['user_id'])){
$this->user_id = $_SESSION['user_id'];
$this->logged_id = true;
}else{
unset($this->user_id);
$this->logged_in = false;
}
}
}
$session = new Session()
?>
error message
remove {} and put".." in
header("Location : {$location}");
instead of
header("Location:".$location);
You have to redirect to full URL so Try this,
$url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
redirect_to($url."index.php");
As Gyandeep Mentioned above change your function,too.
function redirect_to($location){
header('Location:'.$location);
exit();
}
Hope this helps.

Read from textbox into array php

file index.php
<html>
<head>
<title>Guset Book</title>
</head>
<body>
<h3>Guest book</h3>
<a href="/addNew.php">
<p><input type="button" value="Add in book" ></p>
</a>
<a href="/readAll.php">
<p><input type="button" value="Read all"></p>
</a>
</body>
file addNew.php
<html>
<head>
<title>Guset Book</title>
</head>
<body>
<h3>New</h3>
<form name='formAddNew' method='post' action="ControllerAdd.php">
<p>Author: <input type="text" name="nameAuthor"></p>
<p>Comment:</p>
<p><textarea rows="5" cols="40" name="commentAuthor" style="resize: none;"></textarea></p>
<p><input type="submit" name="submitAuthor" value="Submit"></p>
</form>
</body>
file Model.php
<?php
class GuestBook
{
private $author;
private $comment;
function __construct($author, $commment)
{
$this->author = $author;
$this->comment = $commment;
}
public function getAuthor()
{
return $this->author;
}
public function getComment()
{
return $this->comment;
}
}
$guestBookList = new ArrayObject();
$guestBookList[] = new GuestBook("Author", "Comment");
function addInList($author, $comment)
{
$guestBookList[] = new GuestBook($author, $comment);
}
?>
file ControllerAdd.php
<html>
<head>
<title>Add</title>
</head>
<body>
<?php
require_once "Model.php";
addInList($_POST["nameAuthor"], $_POST["commentAuthor"]);
?>
<h3>Succes</h3>
<input type="button" value="On main">
</body>
file readAll.php
<html>
<head>
<title></title>
</head>
<body>
<?php
require_once "Model.php";
foreach($guestBookList as $value)
{
echo("<br>-----------<br>");
echo($value->getAuthor());
echo("<br>");
echo($value->getComment());
}
?>
</body>
The problem is that complier don't throws a mistakes, but don't write the code into array from textboxes. It read in right way the info from textboxes, but don't write into array Plz help.
I suggest in your particular case you need to change behaviour of your Model, something like this:
it's only an example, and must not be used as is
I guess, this code don't crash OP source
<?php
class GuestBook {
private $source;
private $book;
function __construct($filename) {
$this->book = array();
$this->source = $filename;
$this->restore();
}
function getBook() {
return $this->book;
}
function restore() {
if (file_exists($this->source)) {
$records = file($this->source);
if (is_array($records)) {
while (count($records)) {
$line = trim(array_shift($records));
list($author, $comment) = explode(':splitter:',$line);
$this->book[] = new GuestBookRecord($author, $comment);
}
}
}
}
function save() {
$fd = fopen($this->source, 'w');
foreach ($this->book as $record) {
fwrite($fd, $record->getAuthor().':splitter:'.$record->getComment().PHP_EOL);
}
fclose($fd);
}
function addComment($author, $comment) {
$this->book[] = new GuestBookRecord($author, $comment);
$this->save();
}
}
class GuestBookRecord {
private $author;
private $comment;
function __construct($author, $commment) {
$this->author = $author;
$this->comment = $commment;
}
public function getAuthor() {
return $this->author;
}
public function getComment() {
return $this->comment;
}
}
$guestBook = new GuestBook('sample.txt');
// compatibility with OP source
$guestBookList = $guestBook->getBook();
// compatibility with OP source
function addInList($author, $comment) {
global $guestBook;
$guestBook->addComment($author, $comment);
}
But it's not so good. Here is minimum 2 problems, first - the code reads all of the records into memory, second - concurrent accessing. It's just an example.
Session are best way to pass variables in this case
if i understand properly then you want to pass text filds value from two page and use them in 3rd page in array.
Use this as reference
index.php
<?php
session_start();
if(isset($_POST['submit'])){
if(!empty($_POST['tex1'])){
$_SESSION['tex1'] = $_POST['tex1'];
header('location:form.php');
}
}
?>
<form method="POST">
<input type="text" name="tex1">
<input type="submit" name="submit" value="submit">
</form>
form.php
<?php
session_start();
if(isset($_POST['submit'])){
if(!empty($_POST['tex2'])){
$_SESSION['tex2'] = $_POST['tex2'];
header('location:final_page.php');
}
}
?>
<form method="POST">
<input type="text" name="tex2">
<input type="submit" name="submit" value="submit">
</form>
final_page.php
<?php
session_start();
print_r($_SESSION);
$_SESSION is global variable of php.
To read more about session. Please read http://php.net/manual/en/reserved.variables.session.php
file1.php
<form action="file2.php" method="POST">
<textarea rows="4" cols="50" name="data[]"> </textarea>
<input type="submit" value="Submit">
</form>
file2.php
<?php
session_start();
$formData = $_POST['data'];
//echo '<pre>'; print_r($formData); die;
$_SESSION['formData'] = $formData;
echo 'Open File 3 to check submitted data.'
?>
file3.php
<?php
session_start();
if(isset($_SESSION['formData']) && $_SESSION['formData'] != ''){
print_r($_SESSION['formData']);
} else {
echo 'Submit form first.';
}
session_destroy();
?>

On form submission the browser loads the php file that had the code for handling the form

I'm writing my first php code... I'm trying to submit a form.
I have two php files. index.php(which contains the form) and process.php(which contains the method that handles the form).
But on form submission, the browser heads to process.php, so nothing is displayed.
I'm trying to echo the result in index.php .
And keep in mind this is my very first php code... :-)
This is index.php
<!DOCTYPE html>
<html>
<?php
include 'process.php';
$newletter1 = new newsletter();
?>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<form action="process.php" method="post">
<input type="text" name="email" placeholder="Your Email Address..."><br><br>
<input type="submit">
</form>
<h4><?php $newletter1 -> abc(); ?></h4>
</body>
</html>
And this is process.php
class newsletter
{
public function abc()
{
if (isset($_POST["email"])) {
$input = $_POST["email"];
if (empty($input)) {
echo "Please provide an email address!";
}else{
echo "Thanks for subscribing " . $input;
}
}else{
echo "ELSE is running...";
}
}
}
Your script process.php is just a class definition.
A class does nothing unless it is instantiated and a method called.
As you are including it and instantiating it in your index.php I would suggest changing your <form> tag so it runs itself, leaving href="" will do that.
<?php
// run this only if we are being set info by the user
// so not when the form is first loaded.
$to_show_later = '';
if ($_SERVER['REQUEST_METHOD'] == 'POST' ) {
include 'process.php';
$newletter1 = new newsletter();
$to_show_later = $newsletter1->abc();
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<form action="" method="post">
<input type="text" name="email" placeholder="Your Email Address..."><br><br>
<input type="submit">
</form>
<h4><?php echo $to_show_later; ?></h4>
</body>
</html>
It's also bad practice to echo directly out of a class method, so change this so it return the data.
class newsletter
{
public function abc()
{
$reply = '';
if (isset($_POST["email"])) {
$input = $_POST["email"];
if (empty($input)) {
$reply = "Please provide an email address!";
}else{
$reply = "Thanks for subscribing " . $input;
}
}else{
$reply = "ELSE is running...";
}
return $reply;
}
}
In your process.php replace it by:
if (isset($_POST["email"])) {
$input = $_POST["email"];
if (empty($input)) {
echo "Please provide an email address!";
}else{
echo "Thanks for subscribing " . $input;
}
}else{
echo "ELSE is running...";
}
It will work, and you dont have to include process.php to submit form only

Variable either not getting passed to or from the function

The point of the code is to edit a specific user which is determinded by which edit button has been pressed.
I'm getting the following error:
Undefined variable: user_id in EditUser.php on line 15.
No this in not an undefined variable issue. If I remove $user_id when calling the function it complains that the function calling has no arguments.
I only want the return of the function, but it doesn't want to get called.
EditUser.php:
<?php
session_start();
include_once 'Functions.php';
$user = new User();
?>
<html>
<head>
<title></title>
</head>
<body>
<?php
if (isset($_SESSION['EditUser']))
{
$result = User::Edit_User($user_id); //The line which gives me the error
while(list($user_id, $username, $password, $emailadres, $admin) = mysql_fetch_array($result ))
{
$urid = $user_id;
$urnm = $username;
$pw = $password;
$eml = $emailadres;
$an = $admin;
echo "It worked"; //Just aline for debugging. Will remove later
}
}
else
{
echo "error";
}
?>
<form method="post" action="EditUserDef.php">
user_id: </br>
<input readonly="readonly" name="user_id" value=<?php echo $urid ?>></br>
username: </br>
<input type="input" name="username" value=<?php echo $urnm ?>></br>
password: </br>
<input type="input" name="password" value=<?php echo $pw ?>></br>
emailadres: </br>
<input type="input" name="emailadres" value=<?php echo $eml ?>></br>
admin: </br>
<input type="input" name="admin" value=<?php echo $an ?>></br>
<input type="submit" name = "submit" value="edit data">
<input type="button" value="back" onClick="history.go(-1);return true;"></br>
</br>
</form>
</body>
</html>
The file with the class and funcitons, Functions.php:
<?php
include_once 'Config.php'; //Class to connect with database, not really important for this question
class User
{
public function Edit_User($user_id)
{
$query = mysql_query("SELECT * FROM useraccounts WHERE user_id = '$user_id'");
$rows = mysql_num_rows($query);
if (!$rows == 0)
{
$_SESSION['EditUser'] = true;
return $query;
}
}
public function Edit_DataSession()
{
return (isset($_SESSION['EditUser']));
}
And as last, the file from where the "user_id" gets send to Functions.php, Administration.php:
<?php
session_start();
include_once 'Functions.php';
$user= new User();
if ($_SERVER["REQUEST_METHOD"] == "POST")
{
$user_id = $_POST['hidden'];
$editing = $user->Edit_User($user_id);
if ($editing)
{
header("location:EditUser.php");
}
else
{
echo 'User doesn't exist anymore';
}
}
?>
<html>
<header>
<style>
table, td, th
{
border-style: solid;
border-width: 3px;
border-color: black;
}
</style>
</header>
<body>
<h1>overzicht gebruikers</h1>
<table border = 1>
<tr>
<td>user_id</td>
<td>username</td>
<td>password</td>
<td>emailadres</td>
<td>admin</td>
</tr>
<?php
if (isset($_SESSION['GetUser'])) //function not included in the code of the question, didn't seem necesarry
{
$result = user::get_user();
while(list($user_id, $username, $password, $emailadres, $admin) = mysql_fetch_array($resultaat))
{
echo "<tr><td>$user_id</td>";
echo "<td>$username</td>";
echo "<td>$password</td>";
echo "<td>$emailadres</td>";
echo "<td>$admin</td>";
echo "<td><form action='EditUser.php' method='post'><input type='hidden' name='hidden' value=$user_id><input type='submit' name='edit' value='edit'></form></td>";
echo "<td><form action='DeleteUser.php' method='post'><input type='hidden' name='hidden' value=$user_id><input type='submit' name='delete' value='delete'></form></td></tr>";
}
}
?>
</body>
</html>
Does anyone know how to fix this?
No this in not an undefined variable issue.
Um, yes it is. Error messages are pretty good at telling you the error:
Undefined variable: user_id in EditUser.php on line 15
So let's look at line 15:
$result = User::Edit_User($user_id);
You're trying to use a variable called $user_id. Looking above that line, I don't see that variable defined anywhere. You define a variable called $user:
$user = new User();
But where do you define a variable called $user_id? According to your code, and according to the PHP runtime, you don't. Hence the error.
You do define a similarly named variable on a completely different page, but variables don't persist across page contexts. You need to re-define it with each page request where you want to use it.
You need to define variables before you can use them. Maybe you meant to use a member of $user instead of $user_id? Maybe you meant to use $user itself? The code isn't going to be able to know what you mean, you have to explicitly define things.

Categories