Implement Security to this application? - php

At the moment I am attempting to create an application that passes on data to delete a row in my database. This row will be known by the ID passed on by the html file to js.
Currently I have a Html file, Javascript and PHP file which all work together to get this data passed in.
What im looking to do is secure it so no-one unauthorised can just send data to the javascript document in-order to delete the row.
HTML -- > JS --> PHP
JS:
function deleteListing(id) {
var answer = confirm("Are you sure you want to delete this listing?")
if (answer) {
$.post("assets/scripts/deleteListing.php", {
id: id
},
function (result) {
var response = jQuery.parseJSON(result);
if (response.available === true) {
location.reload();
} else if (response.available === false) {
// alert("FAILURE DELETING USER");
} else if (response.root === true) {
// alert("Cannot Delete Root User..");
}
});
} else {
return;
}
}
PHP:
<?
require("../../../assets/config/config.php");
$id_retrieve = $_POST['id'];
$data = new stdClass();
$sth= $dbh-> prepare("SELECT * FROM listings WHERE id='".$id_retrieve."'");
$sth -> execute();
$row = $sth -> fetch();
$data->available = true;
$dbh->exec("DELETE FROM listings WHERE id = '".$id_retrieve."'");
echo json_encode($data);
?>
Before anyone says the statement is not created using the prepared statement, I am aware of this and will fix it asap. Apart from that, is there anyway I can secure the Javascript file from unauthorised access? or could I limit it somehow?
Thanks!

There are a couple of solutions.
As #Tobias said above: Use sessions to handle the authentication. That will protect you some.
However, that alone doesn't stop Cross-Session attacks.
Take a look at this page: http://phpsec.org/projects/guide/2.html
It suggests putting a token value on the form and saving it in the session. That way, when the form is submitted you can compare the incoming token against the one in your session and verify that the form did, indeed, come from your site.
<?php
session_start();
if (isset($_POST['message']))
{
if (isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token'])
{
$message = htmlentities($_POST['message']);
$fp = fopen('./messages.txt', 'a');
fwrite($fp, "$message<br />");
fclose($fp);
}
}
$token = md5(uniqid(rand(), true));
$_SESSION['token'] = $token;
?>
<form method="POST">
<input type="hidden" name="token" value="<?php echo $token; ?>" />
<input type="text" name="message"><br />
<input type="submit">
</form>
<?php
readfile('./messages.txt');
?>

Related

Why can't i fetch data from my SQL database, in a html document, using php?

So I am writing a API, on the front-end it uses HTML, JS and CSS, and on the back end it uses PHP which will have access to my SQL database.
My task is once a button is clicked, create a function that will send information that is encoded in JSON off to the .php file, there I need to decode that object from JSON to PHP, then connect to the SQL database, and return relevant information encoded in JSON back to the HTML page, and later functionality will be able to update/delete certain data.
This API uses two main pages being the HTML and PHP files, along with the SQL database. Can somebody tell me why this is not working and how I can fix it? To clarify I would like to be able to select a radio button option, then press the app_list_button, which will return all Applications sorted by app_name or their review rating. Any help will be greatly appreciated and if I am able to structure anything better please let me know.
index.html
<div id='app_content'>
<label>Refine search by</label>
</br>
<input type="radio" id="name_radio">
<label>Name</label>
</br>
<input type="radio" id="rating_radio">
<label>Rating</label>
</br>
<button id="app_list_button" onclick="load_list_function()">View App List</button>
</br>
<p id='app_list_p'></p>
<input type="submit" name="app_detail_button" value="View App
Details">
</br>
</div>
</div>
</body>
<script>
var app_list_bttn = document.getElementById('app_list_button');
var radio = {};
//List apps
function load_list_function() {
var xhr = new XMLHttpRequest();
//name radio checked
radio.sortByName = document.getElementById('name_radio').checked;
//rating radio checked
radio.sortByRating =
document.getElementById('rating_radio').checked;
document.getElementById('app_list_p').innerHTML = this.responseText;
xhr.open('GET', 'API.php', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(radio));
}
</script>
API.php
<?
$conn = mysqli_connect('localhost', '30319329', 'password', 'Application');
$errors = array();
$json_response = array();
$radio_req = file_get_contents('php://input');
$radio_result = json_decode($radio_req);
//get a list of all apps
//encode into json to send back
if ($radio_result - > sortByName == true) {
//order by name
$results = mysqli_query($conn, "SELECT app_name FROM App");
while ($row = mysqli_fetch_assoc($results)) {
// You can modify the $row here as well, or filter out certain rows
$json_response[] = $row;
}
header("Content-Type: application/json");
echo json_encode($json_response);
} else($radio_result - > sortByRating == true) {
//order by rating
//order by name
$results = mysqli_query($conn, 'SELECT app_name, rating FROM App, App_Review ORDER BY rating ');
while ($row = mysqli_fetch_assoc($results)) {
// You can modify the $row here as well, or filter out certain rows
$json_response[] = $row;
}
header("Content-Type: application/json"); echo json_encode($json_response);
}
$conn - > close();
?>
Most likely the issue is this:
file_get_contents('php://radio');
That will not give you anything, it needs to be:
file_get_contents('php://input');
Also, when you do:
document.getElementById('app_list_p').innerHTML = this.responseText;
you are setting the innerHTML before you've even done the ajax request - this in this context is the window, so this.responseText will always be undefined.
You need to do it more like:
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
document.getElementById('app_list_p').innerHTML =xhr.responseText;
}
}

Login form fails to login client

I've been trying to create an admin panel for my website. I created a login form but whenever I try to log in, it says that the user does not exist. I can't seem to find where I made a mistake.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login - Admin panel</title>
</head>
<body>
<?php
include 'db.php';
?>
<?php
include 'functions.php';
?>
<?php
include 'title_bar.php';
?>
<h3>Login Here: </h3>
<?php
if(isset($_POST['submit'])) {
$username = $_POST['username'];
$password = $_POST['password'];
if(empty($username) or empty($password)){
echo "<p>Fields should not be empty</p>";
} else {
$check_login=mysqli_query($con,"SELECT id, type FROM users WHERE username='$username' AND password='$password'");
if(mysqli_num_rows($check_login) == 1){
$run=mysqli_fetch_array($check_login);
$user_id=$run['id'];
$type=$run['type'];
if($type =='d') {
echo "<p>Your acount is deactivated by an admin!</p>";
} else {
$_SESSION['user_id'] = $user_id;
header('location: adminpanel.php');
}
} else {
echo "<p>Wrong Username or Password</p>";
}
}
}
?>
<form method='post'>
User name:
<input type ='text' name = 'username' />
<br/><br/>
Password:
<input type = 'password' name = 'password' />
<br/><br/>
<input type = 'submit' name = 'submit' value='Login' />
</form>
</body>
</html>
Any help would be appreciated.
Just because I see this all the time on SO, I will address some of my comments. There are a lot of reasons why it could fail based on what you have. First off, a solid framework would do almost all this for you, you would just have to do basic logic but not all the grunt work. Second, just because you want to echo some text in a specific part of your page, doesn't mean you should do a bunch of logic that leads up to echo in the same part of the page. The idea is that the browser output is the last thing to happen so you will want to do the bulk of your logic before the page outputs.
First break up your logic into a specific-task functions/class/methods that will be easily understood and ready to be re-used:
/functions.php
<?php
// I am going to use PDO because I am more familiar with it
function verifyUser($username,$password,$con)
{
// Get the basics from the database
$query = $con->prepare("SELECT `password`,`type`,`id` FROM `users` WHERE `username` = :0");
// Bind the value for security
$query->execute(array(":0"=>$username));
// Get the results
$result = $query->fetch(PDO::FETCH_ASSOC);
// If empty, return false
if(!$result)
return array('verified'=>false);
// You need to store the password using password_hash()
$verified = password_verify($password,$result['password']);
// If user is revoked
$revoked = is_deactivated($result);
// Return all the validation settings
return array(
'type'=>$result['type'],
'id'=>$result['id'],
'revoked'=> $revoked,
'verified'=>$verified,
'valid'=>($verified && !$revoked)
);
}
function getUserById($id,$con)
{
$query = $con->prepare("SELECT * FROM `users` WHERE `id` = :0");
$query->execute(array(":0"=>$id));
$result = $query->fetch(PDO::FETCH_ASSOC);
if(!$result)
return false;
return $result;
}
function is_deactivated($userArr = false,$con = false)
{
// Set default user empty
$user = false;
// If value is numeric (id)
if(is_numeric($userArr)) {
// Get the data by from database, assign to user
$user = getUserById($userArr,$con);
}
// If the value is an array, just assign to user
elseif(is_array($userArr))
$user = userArr;
// If the value is still empty, stop, return deactivated
if(empty($user))
return true;
else
// If user is valid (in db), return bool if they are revoked
return ($user['type'] == 'd');
}
function loginObserver(&$error,$con)
{
// See if the action to log in is set
if(isset($_POST['action']) && $_POST['action'] == 'login') {
// Run the verify function
$verify = verifyUser($_POST['username'],$_POST['password'],$con);
// If user is in db
if($verify['verified']) {
// See if they are revoked, send back error
if($verify['revoked']) {
$error = 'revoked';
return false;
}
// Assign your session id
$_SESSION['user_id'] = $verify['id'];
// Return true for success
return true;
}
else {
// User was not in system, send invalid error
$error = 'invalid';
return false;
}
}
else
// Return a string so the subsequent logic knows that
// no attempt was made to log in.
return 'invalid';
}
Secondly, now that you have all your business logic stored away in contained functions (classes/methods) you can cleanly apply them to the page.
/login.php
<?php
// Put this at the very beginning. I would consider putting it on a config page and
// including it would be better because then you will have some consistency
// through your site
session_start();
// Add your functions and or classes, better yet would be to have an autoloader
// to load classes and a pseudo-autoloader to load functions
include('functions.php');
// Put your database connection at the top, on the config page would be better
include('db.php');
// Move logic to the top and pass errors to the page
$error = false;
// Run the observer function
$login = loginObserver($error,$con);
// Invalid means no attempt was made to login
if($login != 'invalid')
// If there are no errors (empty), redirect
if(!$error) {
// This needs to go before output of html to browser
header('location: adminpanel.php');
// Stops the script from processing the rest of the page
exit;
}
}
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login - Admin panel</title>
</head>
<body>
<?php
// This is probably fine, it's likely just html
include('title_bar.php');
?>
<h3>Login Here: </h3>
<?php if($error) {
echo ($error == 'invalid')? 'Wrong username or password.':'Your access has been revoked by admin.';
} ?>
<form method='post'>
<!-- add an action here -->
<!-- You should do a token system for verifying submission authenticity -->
<input type="hidden" name="action" value="login" />
User name:
<input type='text' name='username' />
<br/><br/>
Password:
<input type='password' name='password' />
<br/><br/>
<input type='submit' name='submit' value='Login' />
</form>
</body>
</html>
Finally, this code is not tested so there may be errors in logic. It is intended to show you how to apply my (and perhaps other's comments practically). I don't want to say "Don't do this and don't do that" but don't show an alternative. This script is based on yours so you can identify similarities easier, but is no way implied this is the only way, or the correct way to do a login.

PHP Form must be submitted twice to update checkbox

I'm still relatively new to PHP. I'm trying to build a privacy settings page for members to opt out of automatic emails for triggered events (i.e. private message notification). I want the checkbox set automatically based on the database setting. As of now, the form does update the database correctly, but the checkbox status does not show the correct setting unless the Submit button is pressed twice, or the page is reloaded. Setting would be '0' for unchecked, '1' for checked. I'd love to use Ajax or jQuery to handle this, but I don't know those at all.
privacysettings.php
<?php
$id = "";
$pm_mail_able = "";
$pm_email = "";
if (isset($_GET['id'])) {
$id = preg_replace('#[^0-9]#i', '', $_GET['id']); // filter everything but numbers
} else if (isset($_SESSION['idx'])) {
$id = $logOptions_id;
} else {
header("location: index.php");
exit();
}
//query to get checkbox status
$sql = mysql_query("SELECT * FROM members WHERE id='$id'");
while($row = mysql_fetch_array($sql)){
$pm_mail_able = $row['pm_mail_able'];
}
switch ($pm_mail_able) {
case 0:
$pm_setting = NULL;
break;
case 1:
$pm_setting = "checked=\"checked\"";
break;
}
if(isset($_GET['pm_email']) && !empty($_GET['pm_email'])) {
$updateqry = mysql_query("UPDATE members SET pm_mail_able='1' WHERE id='$id'");
} else {
$updateqry = mysql_query("UPDATE members SET pm_mail_able='0' WHERE id='$id'");
}
?>
<html>
Email Notifications<br />
<form name="testform" method="get" action="PvResult.php">
When a friend sends me a private message
<input type="checkbox" name="pm_email" value="on"<?php echo $pm_setting;?> />
<br /><br />
<input type="submit" value="Submit" />
</form>
</html>
PvResult.php
<?php
$url = 'http://www.mywebsite.com';
//If the form isn't submitted, redirect to the form
if(!isset($_GET['Submit']))
header('Location: '.$url.'/privacysettings.php');
//Redirect to the correct location based on form input
$pm_email = $_GET['pm_email'];
$url .= '/privacysettings.php?pm_email='.$pm_email;
header('Location: '.$url);
?>
Okay, hopefully this won't just answer your question, but give you a few best practices you might want to consider.
You can combine these two scripts into one relatively easily. Also, I'd highly suggest using a POST instead of GET; GET is very limited and is not intended to submit data like you're using it. If you're going to be changing data in a back-end store, using GET will bite you. Maybe not today, maybe not tomorrow, but it will, trust me.
You really should consider moving to PDO instead of the mysql_ functions. PDO is a lot better in handling parameterized queries, which you really should have here for better security, and it's more portable if someday you want to move to a different database system.
I'm still a little hazy on how your app is getting the $id. Most apps get it from a $_SESSION variable, making sure that the user has successfully validated a login. If you're not doing that, please do. You might want to thoroughly digest this article, it's got a lot of juicy best practices regarding authentication and "remember me"-type functionality.
Here's a bit of a rewrite. I haven't actually tested it, but it should give you a pretty good idea on where to go with your immediate needs. If it throws any errors (remember the disclaimer: I haven't actually tested it!), let me know and I'll try to debug it.
<?php
$message = '';
$pm_setting = '';
$id = 0;
// Put your $id retrieval logic here. It should look something like:
if (isset($_SESSION['id'])) {
$id = $_SESSION['id'];
if (!preg_match('/^\\d{1,10}$/', $id) > 0) {
// Someone is trying to hack your site.
header("location: scum.php");
exit();
}
$id = intval($id);
}
// Quick security note: You might want to read up on a topic called
// session hijacking if you want to ensure your site is secure and
// this $id isn't spoofed.
if (isset($_POST['Submit'])) {
// The form is being submitted. We don't need to read the current
// pm_mail_able setting from the database because we're going to
// overwrite it anyway.
if ($id > 0) {
$pm_mail_able = 0;
if (isset($_POST['pm_email']) && $_POST['pm_email'] === 'on') {
$pm_mail_able = 1;
$pm_setting = 'checked ';
}
$query = 'UPDATE members SET pm_mail_able='.$pm_mail_able.
' WHERE id = '.$id;
mysql_query($query);
// Another quick security note: You REALLY need to consider
// updating to PDO so that you can bind these parameters
// instead. The mysql_ functions are probably going to be
// deprecated soon anyway.
if (mysql_affected_rows($query) > 0)
$message = '<p style="color: #00a000;">Settings saved!</p>';
else
$message = '<p style="color: #a00000;">User id not valid.</p>';
}
else
$message = '<p style="color: #a00000;">User id not valid.</p>';
}
else {
// This is the first load of the form, we need to just display it
// with the existing setting.
if ($id > 0) {
$query = mysql_query('SELECT * FROM members WHERE id = '.$id);
if (($row = mysql_fetch_array($query, MYSQL_ASSOC)) !== FALSE)
if ($row['pm_mail_able'] === 1) $pm_setting = 'checked ';
}
}
?>
<html>
<body>
<?= $message ?>
<!-- Without action parameter, form submitted to this script. -->
<form name="testform" method="post">
E-mail notifications<br />
<input type="checkbox" name="pm_email" value="on" <?= $pm_setting ?>/>
When a friend sends me a private message
<br /><br />
<input type="submit" value="Submit" />
</form>
</body>
</html>
Try to do these settings and see if it will work:
1) You need to add an space between "on" and "checked=checked"
<input type="checkbox" name="pm_email" value="on" <?php echo $pm_setting;?> />
2) You have to reference the submit button by its name, not its value
<input type="submit" name="Submit" value="Send" />
3) When the setting is "0", set $pm_setting as a empty string, instead of NULL
case 0:
$pm_setting = '';
4) Maybe there is some problem with $_GET['pm_email'] and the else is always being executed
5) If the things work when you press the Submit button twice, it means that the form is passing some GET var that make the code work, so try to discover what var is this

how to avoid Form Re submission in php

I have a form in dashboard.php to create invoice and this is submitted to invoice.php
Now my invoice.php inserts the Invoice and the customer into the database and then shows me a invoice order filling form.
if i refresh this page, it inserts a new invoice for the same customer, how do i avoid this.
I was reading that we could avoid it by redirection, but in my case how do i use it. Some thing like a PRG(post/redirect/get) how to use it?
Do i need to make an intermediate page before going to insert items to invoice
The pattern you've heard about is this: Post/Redirect/Get.
In general, POST is for actions, GET is for views. So you never show a user a page on a POST request. Instead, you redirect them to a page they'll request with GET, which will not cause any changes in your database.
after successful form submission do a redirect to the same page and optionally indicate that the submission was successful
Example: invoice.php
if (count($_POST)) {
if (/*post data is valid*/) {
/*do whatever is needed*/
header('Location: invoice.php?success');
}
} else if (isset($_GET['success'])) {
echo "Form successfuly submitted";
}
Let dashboard.php post the form data to insert.php, which will process the data and then forward to invoice.php. Use sessions to transport the data from one file to another. Here is insert.php:
<?php
session_start();
if (session_is_registered("invoiceVars"))
session_unregister("invoiceVars");
if (!session_is_registered("errors"))
session_register("errors");
$errors = array();
if (!session_is_registered("formVars"))
session_register("formVars");
foreach($_POST as $f_varname => $f_value)
$formVars[$varname] = trim(EscapeShellCmd(stripslashes($value)));
// process your data and write it to the database or return to dashboard.php with errors, then:
session_unregister("errors");
session_register("invoiceVars");
$invoiceVars = array();
foreach ($formVars as $i_varname => $i_value)
$invoiceVars[$i_varname] = $i_value;
session_unregister("formVars");
// add additional variables
$invoiceVars["coupon"] = 'unique_coupon_code';
// invoice.php will process the data and display it
// it has session_start(); at the top, to have $invoiceVars available
header('Location: invoice.php');
exit();
?>
header(); and exit(); will flush $_POST, so it is no longer available when the user hits back on his browser.
Here is an example code for you:
# database.php
$db = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
session_start();
# dashboard.php
require_once("database.php");
function getSavedValue() {
global $db;
$sql = "SELECT input_text FROM temp_table WHERE sess_key='?'";
$query = $db->prepare($sql);
$query->bindParam(session_id());
$query->execute();
if ($query->rowCount() == 1)
return $query->fetch();
else
return " ";
}
<form action="invoice.php" method="POST">
<input type="text" name="getThisInfo" value="<?php echo getSavedValue(); ?>"/>
<input type="submit" value="Send"/>
</form>
# invoice.php
if (isset($_POST["getThisInfo"]) && /* validation check */ 1) {
require_once("database.php");
$textInput = $_POST["getThisInfo"];
$sql = "INSERT INTO perm_table(invoice_info) VALUES('?');";
$query = $db->prepare($sql);
$query->bindParam($textInput);
$query->execute();
$rows = $query->rowCount();
echo "$rows invoices were inserted.";
unset($_POST["getThisInfo"]);
header("success.php");
} else {
header("dashboard.php");
}

Getting variable value from PHP with jQuery

So how do i get variable value from php file with jquery...?
the jquery code is in other file (tpl)
for example i have register.php and register.tpl (template file for register.php)
register.php
...some includes here...
if(isset($_POST['submit'])) {
$username = mysql_real_escape_string(trim($_POST['username']));
$email = mysql_real_escape_string(trim($_POST['email']));
$check = $mysql->query("SELECT username FROM ".TBL_USERS." WHERE username = '".$username."' OR email = '".$email."'");
$rows_check = mysql_num_rows($check);
if($rows_check > 0) {
echo 1;
} else {
$password = mysql_real_escape_string($_POST['password']);
$salt = generate_salt($email);
$hash = hash_password($password, $salt);
$q = $mysql->query("INSERT INTO ".TBL_USERS." (username, password, email, salt) VALUES ('".$username."', '".$hash."', '".$email."', '".$salt."')");
if($q) {
header("Location: index.php");
} else {
die(mysql_error());
}
}
} else {
.. calling parse template function ...
}
register.tpl
..jquery library included..
<form id="register" action="register.php" method="post">
<tr>
<td>Username</td>
<td><input type="text" id="username" name="username" class="register" style="width: 200px;" />
</td>
email
...other inputs...
$("#username").blur(function()
{
var email_v = $("#email").val();
$("#msgbox").removeClass().addClass('messagebox').text('Checking...').fadeIn("slow");
$.post("register.php",{ username:$(this).val(), email: email_v, submit: true } ,function(data)
{
if(data=="1")
{
$("#msgbox").fadeTo(200,0.1,function()
{
$(this).html('This User name Already exists').addClass('messageboxerror').fadeTo(900,1);
});
}
else
{
$("#msgbox").fadeTo(200,0.1,function()
{
$(this).html('Username available to register').addClass('messageboxok').fadeTo(900,1);
});
}
});
});
</script>
when i changed the whole register.php for testing purposes to
or
the script worked...however with the original version it shows always that username is available...
Best bet is to output the PHP variable as a hidden field or a JavaScript variable:
<input type="hidden" id="my_var" name="my_var" value="<?php echo($my_var); ?>" />
// access it like this:
alert($('#my_var').val());
or
<script type="text/javascript">
var my_var = <?php echo($my_var); ?>;
</script>
// access it like this
alert(my_var);
That should do it :-)
Either you make a Jquery Ajax Request that will request a php page which will return whatever you want or you echo a javascript variable with php
<?php
echo '<script> var javascript_variable = "whatever"; </script>';
?>
It will work if you do
echo "1";
and then
if(result == "1") {
If it doesn't (but I've checked on a code of mine without the quotes, it didn't work, with, it was ok), check the response from Firebug console.
In situations where my company's application needs to call Jquery on a dynamic element and we have the Jquery call IN the php file we'll directly call php in the Jquery call.
For example:
alert($('#').val());
Not for all situations, certainly. If you have to call a variable where you don't have PHP access to the file (possibly such as a .tpl file, depending on your setup) you might resort to setting a hidden input as detailed above.

Categories