php make hidden fields tamper proof ? - php

I'm not wanting to use a framework when in this project there is only a single value that needs verifying, I want to make sure however that the method I'm using is reasonably safe and sane!
I have a $secret value set in an include that is outside the web root
the form looks like this ( $salt is a random integer a new one for each form)
<form name="deleteform" action="#" method="get">
<input type="hidden" name="check" value="<?=sha1($salt.$secret.$songid)?>"/>
<input type="hidden" name="songid" value="<?=$songid?>"/>
<input type="hidden" name="salt" value="<?=$salt?>"/>
<input type="hidden" name="action" value="delete"/>
<input type="submit" value="Delete"/></form>
when the form is returned I use the returned values for $salt $songid along with $secret to calculate a new sha1 and compare it to $check
if they are equal I assume that the returned $songid hasn't been tampered with

Using $_SESSIONS is the way to go. Even if you wanted to still do the tamper proof hidden field idea. To make it tamper proof you'd have to set the value on the server side after hitting submit. You could do this using jQuery's .preventDefault(), set the value of the hidden fields at that point, and then continue with the submission. But why do the extra step?
Just use sessions from the get go, eg:
session_start();
$_SESSION['name'] = value;
echo $_SESSION['name'];

$_SESSION is the way to go... the downside of your design is that one can still temper with the form by simply copy/pasting values.
Also, if they figure out what kind of check you are doing, there is absolutely nothing stopping them from putting in their own songid, computing their own sha1 hash and stuffing it into your check field.
General intro to sessions:
session_start();
$_SESSION['songid']=your song id;
and you are done... Now the songid value is stored on server, and nothing can tamper with it besides you... unless openSSL breaks again.

Related

How can I insert HTML label in databse using PHP

I'm facing problem in inserting HTML label to database and found no way to do so. My code is as under
<html>
<body>
<form name = "myForm" >
<label name = 'q1'>Question 01: what Jorge do according to the story</label>
</form>
<?php
require "connection.php";
$qst = $_POST['q1'];
mysql_query("insert into xxx values('$qst')") or die(mysql_error);
?>
any help will be appreciated please.
You have a slew of problems here. First let's talk about the things that are actually preventing this from working.
First, you need to set the method property of the <form> element to POST to have the form perform a POST action upon submittal instead of the default GET action.
<form name="myForm" method="post">
Note, that it is usually considered good form to also specify the action property of the form, though in this case the default behavior of posting to the currnet URI just happens to work for you.
Second, you need to actually create an input field in the form. This is where the data that is posted is input:
<label for="q1">Question 01: what Jorge do according to the story?</label>
<input type="text" name="q1" />
Third, You need a submit button to actually make the form POST:
<input name="submit" type="submit" value="submit" />
Now, let's talk about the stuff that should be fixed that doesn't actually prevent this from working, but just represents good programming practice.
First, you should not be using mysql_* functions. They are deprecated. I would suggest mysqli or PDO as widely used alternatives.
Second, you have a significant vulnerability to SQL injection. You should NEVER use user input data without validating and sanitizing it. This means you should probably check to see if a value was even POSTed (not an empty string) before trying to do the insert and then you need to escape the value before using it in SQL, or better yet, learn how to use parametrized prepared statements which prevents the need for input escaping.
Third, I would recommend getting in the habit of putting your code logic at the beginning of your script (before HTML) output. In your case this means moving the logic where you read in the PST content and perform the database insert before the HTML. WHy? Because this allow you to do things like conditionally print out error messages if the user did not provide input or to otherwise change the page in response to the POST. This also help build a good habit in that, when you start doing more complex things in PHP, you might need to do things like redirect users from one page to another, or totally separate out the logic form the display into separate files. This is not possible with code stuck at the end of the HTML output.
$_POST variables do not correspond to label elements, they correspond to input elements. The key to your post array is the name of your input element.
<input type="text" name="mytext" />
After post will be $_POST['mytext']
However, you're vulnerable to SQL Injection. You should not be using mysql_query() but rather PDO or Mysqli with prepared statements, but if you insist on using it, escape it first with mysql_real_escape_string()
$qst = mysql_real_escape_string($_POST['q1']);
mysql_query("insert into xxx values('$qst')") or die(mysql_error);
Fred made a good point in the comments though. This bit of code is going to execute the first time you load the page before the form is submitted and throw an error (or warning) because $_POST['q1'] doesn't exist yet. You'll want to make sure it does exist before doing things with it.
if(!empty($_POST['q1'])){
$qst = mysql_real_escape_string($_POST['q1']);
mysql_query("insert into xxx values('$qst')") or die(mysql_error);
}
Further, you need to tell the form where to submit to and what method to use:
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<label for = 'q1'>Question 01: what Jorge do according to the story</label>
<input type='text' name='q1' value='' />
</form>
BTW, label does not have a name attribute, it has a "for" attribute.
Also, <form> elements use "GET" by default and submit to the current page if an action is not set, so it's technically not necessary to even have the action set in this case, but it's good practice.
You need add input field for your form and change form sumbit method. By default it's "GET", so you can't have input value in $_POST.
Or you can get input value from $_GET.
<html>
<body>
<form name = "myForm" method="post">
<label for = 'inp'>Question 01: what Jorge do according to the story</label>
<input type="text" name="q1" id="inp" />
<input type="submit" value="Submit">
</form>
<?php
require "connection.php";
$qst = $_POST['q1'];
mysql_query("insert into xxx values('$qst')") or die(mysql_error);
?>
And also you need to have sumbit input field to submit form or can sumbit it with js or on keyup enter key.
<input type="submit" value="Submit">

PHP Passing a variable to another page then pass it back to the original page

This is a little bit quite confusing to explain. I want to know how to store a string into a variable and pass it to the next page and in that next page pass that variable again to another variable then that variable will pass it back to the original page.
Example:
I have two PHP pages. lets call them form1.php and form2.php
In form1.php, I will input Hello and it will be stored in var1.
var1 will be sent to form2.php and it is stored in var2 in form2.php as well.
in form2.php, var2 is passed to var3 and var3 will be sent back to form1.php.
And output Hello in form1.php using var3 not var1.
This is where I got stuck. Can't figure out how to do this. Please comment if the question is a little vague, even I cant seem to figure it out myself. Thanks.
You want to use Sessions. With sessions you can pass variables to a different page.
You have to start sessions on both pages.
session_start();
After that you can store variables in a session.
For example:
$var1 = $_SESSION['name'];
Now you can use IT in every page with session_start();
Well if you are actually using forms then you should be able to just grab the values of the variables in $_GET or $_POST (depending on the method used by the forms). You could just store the values in hidden inputs the user doesn't see and use that to pass things around:
<input type = "hidden" value = "<?php echo $_GET['var2'];?>" />
If this isn't what you need you may want to look at sessions to maintain state throughout your site.
My understanding is that you want to pass some data between two distinct forms - you need to consider that these forms are completely independent form each other so you will need to pass data back to the browser or leverage a server side session.
Depending on your use case you could:
Submit data to form1.php - this would then return a form with additional fields ready for submision to form2.php
The trick here - is that data that needs to be passed between forms would be included in the generation of the second form as hidden elements.
<input type="hidden" id="var1" value="data from form1" />
You can have as many hidden types as you need.
Be aware this approach is not very secure - so you may need consider defences e.g. csrf - or using sessions and tracking the data on the server side.
From what I understand, you need two forms to send data from the first to the second and from the second back to the first. In this communication, you don't need the third var, how about this?
form1.php
<form method=POST action="form2.php">
<input type="text" name="var1" value="<?=#$_POST["var2"];?>">
<input type="submit" value="Continue">
</form>
form2.php
<form method=POST action="form1.php">
<input type="text" name="var2" value="<?=#$_POST["var1"];?>">
<input type="submit" value="Continue">
</form>

PHP, pass array through POST

Which is the most secure way to send an array through POST?
foreach ($id as $array)
{
<input type="hidden" name="prova[]" value="<?php echo $array; ?>"/>
}
<input type="submit" name="submit"/>
or using implode() to create a single variable, pass the variable and then use explode() to get back the values into a new array?
Edit If you are asking about security, see my addendum at the bottom Edit
PHP has a serialize function provided for this specific purpose. Pass it an array, and it will give you a string representation of it. When you want to convert it back to an array, you just use the unserialize function.
$data = array('one'=>1, 'two'=>2, 'three'=>33);
$dataString = serialize($data);
//send elsewhere
$data = unserialize($dataString);
This is often used by lazy coders to save data to a database. Not recommended, but works as a quick/dirty solution.
Addendum
I was under the impression that you were looking for a way to send the data reliably, not "securely". No matter how you pass the data, if it is going through the users system, you cannot trust it at all. Generally, you should store it somewhere on the server & use a credential (cookie, session, password, etc) to look it up.
http://php.net/manual/en/reserved.variables.post.php
The first comment answers this.
<form ....>
<input name="person[0][first_name]" value="john" />
<input name="person[0][last_name]" value="smith" />
...
<input name="person[1][first_name]" value="jane" />
<input name="person[1][last_name]" value="jones" />
</form>
<?php
var_dump($_POST['person']);
array (
0 => array('first_name'=>'john','last_name'=>'smith'),
1 => array('first_name'=>'jane','last_name'=>'jones'),
)
?>
The name tag can work as an array.
You could put it in the session:
session_start();
$_SESSION['array_name'] = $array_name;
Or if you want to send it via a form you can serialize it:
<input type='hidden' name='input_name' value="<?php echo htmlentities(serialize($array_name)); ?>" />
$passed_array = unserialize($_POST['input_name']);
Note that to work with serialized arrays, you need to use POST as the form's transmission method, as GET has a size limit somewhere around 1024 characters.
I'd use sessions wherever possible.
There are two things to consider: users can modify forms, and you need to secure against Cross Site Scripting (XSS).
XSS
XSS is when a user enters HTML into their input. For example, what if a user submitted this value?:
" /><script type="text/javascript" src="http://example.com/malice.js"></script><input value="
This would be written into your form like so:
<input type="hidden" name="prova[]" value="" /><script type="text/javascript" src="http://example.com/malice.js"></script><input value=""/>
The best way to protect against this is to use htmlspecialchars() to secure your input. This encodes characters such as < into <. For example:
<input type="hidden" name="prova[]" value="<?php echo htmlspecialchars($array); ?>"/>
You can read more about XSS here: https://www.owasp.org/index.php/XSS
Form Modification
If I were on your site, I could use Chrome's developer tools or Firebug to modify the HTML of your page. Depending on what your form does, this could be used maliciously.
I could, for example, add extra values to your array, or values that don't belong in the array. If this were a file system manager, then I could add files that don't exist or files that contain sensitive information (e.g.: replace myfile.jpg with ../index.php or ../db-connect.php).
In short, you always need to check your inputs later to make sure that they make sense, and only use safe inputs in forms. A File ID (a number) is safe, because you can check to see if the number exists, then extract the filename from a database (this assumes that your database contains validated input). A File Name isn't safe, for the reasons described above. You must either re-validate the filename or else I could change it to anything.
Why are you sending it through a post if you already have it on the server (PHP) side?
Why not just save the array to s $_SESSION variable so you can use it when the form gets submitted, that might make it more "secure" since then the client cannot change the variables by editing the source.
It all depends on what you really want to do.

How can I only allow request from my form

I have a form on a server and the php to process it, on an other server, this configuration cannot be changed.
I receive a lot of SPAM, and tried to fix it. SESSION couldn't works due to cross-domain, so no token and no captcha, $_SERVER["HTTP_REFERER"] is not reliable. I'm thinking to implement an encrypted key which change once a day, but i think it's limited. Any better idea?
exemple of encrypted key:
$key = "string".date("d");
A lot of bots doesn't run javascript, so you could just inject an arbitrary field into your form:
<form id="douchebag" action="http://yourotherserver.com/process.php" method="post">
<input type="text" name="name" />
.. bunch of other inputs
</form>
Then your js:
var bugSpray = document.createElement('input');
bugSpray.setAttribute('type', 'hidden');
bugSpray.setAttribute('name', 'aa');
bugSpray.value = 'bb';
document.getElementById('douchebag').appendChild(bugSpray);
then in your process.php
if(empty($_POST['aa']) || $_POST['aa'] != 'bb') // bot
You don't need a session to use CAPTCHA.
Many kinds of CAPTCHA exist.
Even the following will probably keep 99% of spambots out:
<form action="...">
<input type="hidden" name="thequestion1" value="23">
<input type="hidden" name="thequestion2" value="-">
<input type="hidden" name="thequestion3" value="5">
How much is 23-5?
<input type="text" name="theanswer">
<input type="submit">
</form>
Most spambots don't look any futher than input fields and submitbuttons.
I bet this kind of CAPTCHA will keep most spam out.
PS: Be sure to safely evaluate the values of thequestion1, thequestion2, thequestion3 on the server.
One technique I've used before is similar to what #SiGanteng suggested but rather than adding a new field you can change the name attributes on exiting ones, to either remove or add a prefix.
<script>
var inputs = document.getElementById('myform').getElementsByTagname('input');
for(i=0; i<inputs.length; i++) {
inputs[i].name = "antispam_" + inputs[i].name;
}
</script>
You could for example add a new resource on the server which generates a key and stores it in a database. When the web page is loaded you request a new key from the server and insert it into a hidden form field.
Then, when a request has been made, you check the value of this field and see that there is a corresponding key in your database. If not, discard the request.
Of course, it is still possible for bots to circumvent it (by also requesting a key), but it will be harder.
Another way you could do it is using a simple check,
take two text inputs and concatenate them,
make an md5 of them and send this through POST.
On the other server check this and Voila.

php secure comment logic?

Ok, this might be obvious but its not clicking quite yet. I am creating a forum/blog esque app.
I grab the posts from the database rather securely but commenting is beginning to be a little more difficult. (I could just be paranoid, right?).
How do I add a comment without exposing the id of the parent message? (like in a hidden form field or query string, or something).
I guess I am a bit paranoid that someone might go into the code with firebug or something and change the hidden form field value to something else before submitting. I guess I would have to make sure the user has permission to comment to that particular post/category?
Things to note :
The user is already logged in.
Its not a public post
I would recommend that you setup your database like so:
Comments
---------
id
encodedID
authorID
parentID
message
Then, for the form field have two hidden values, one will be the encodedID, and the second will be a hash that you make. I would recommend the hash to be:
<?php
$hash = sha1(md5($encodedID . $userID . $_SERVER['REMOTE_ADDR'] . "abc1234"));
?>
Then, when the user submits the form, validate that the hash is valid for the specific encodedID and user. Here is a brief code write up:
<?php
if(isset($_POST['submit']))
{
//Get the variables and all and sanitize the input of 'message'
if(sha1(md5($_POST['value1']. $userID . $_SERVER['REMOTE_ADDR'] . "abc1234")) == $_POST['value2'])
{
//User is valid.
}
else
{
//Invalid user.
//Document this.
}
}
$value1 = $encodedID; //Grab this from your database
$value2 = sha1(md5($value1 . $userID . $_SERVER['REMOTE_ADDR'] . "abc1234"));
?>
<form method="post" action="comment.php">
<input type="text" name="message" />
<input type="hidden" name="value1" value="<?php echo $value1; ?>" />
<input type="hidden" name="value2" value="<?php echo $value2; ?>" />
<input type="submit" name="submit" value="Comment" />
</form>
Edit: Just a small tip, but I would recommend that you change value1 and value2 to something abstract, don't call it encodedID or anything like that, just so that it confuses any users that will attempt to try and break it.
And yes md5 and sha1 are not completely secure, but for this case it will work since you want to be able to process the comments fast and efficiently.
That might be an overkill but if you really want to hide the post_id of the current message then you should consider using session. So instead of using something like this on your form:
<form action="/postcomment.php" method="post" >
<input name="post_id" type="hidden" value="123" />
<textarea name="message"></textarea>
</form>
Reduce it to something like this:
<?php $_SESSION['post_id'] = '123'; ?>
<form action="/postcomment.php" method="post" >
<textarea name="message"></textarea>
</form>
Of course this is "yucky" coding but at least you get the idea.
Oh, don't forget to validate EVERYTHING on postcomment.php. Also escape ALL string input values and make sure all numeric inouts are numbers indeed (multiply them by one?).
[EDIT: Due to insistent public demand, may I, if you please, amend the aforementioned:]
Instead of:
<?php $_SESSION['post_id'] = '123'; ?>
Generate a form id:
<?php $_SESSION['form_id'] = $_SESSION['user_id'].'_'.md5(time()); ?>
Then generate the unique post_id:
<?php $_SESSION[$_SESSION['form_id'].'_post_id'] = '123'; ?>
After submitting get the post_id:
<?php $post_id = $_SESSION[$_SESSION['form_id'].'_post_id']; ?>
you could assign the form an "id" as a hidden field and create a database table to track form ids and their associated post ids, that way when the form gets submitted you could check the post id in the db without ever sending it to the client based on the form id that is returned with the post
You're asking the wrong question here: instead of being concerned about the user getting some internal ID that means nothing outside your application, your primary concern should be about keeping them from doing anything unpleasant with it.
Imagine I just started sending POST requests to add a comment for every ID between 1 and 10,000. I'm sure to hit a real post sooner or later.
Rule #1 about writing secure web applications: Don't trust the user.
In other words, yes, you should check to make sure that they have permission to comment when you receive the results back from the from.

Categories