Secure solution to hidden forms - php

I have this code:
<? if ($cur_post['poster_id'] == $forum_user['id']) { ?>
<div class="txt-box textarea required">
<label for="fld<?php echo ++ $forum_page['fld_count'] ?>"><span><?php echo $lang_post['Write message'] ?> <em><?php echo $lang_common['Required'] ?></em></span></label>
<div class="txt-input"><span class="fld-input"><textarea id="fld<?php echo $forum_page['fld_count'] ?>" name="req_message" rows="14" cols="95"><?php echo forum_htmlencode(isset($_POST['req_message']) ? $message : $cur_post['message']) ?></textarea></span></div>
</div>
</div>
<? }
else { ?>
<? } ?>
I need a more secure solution to hidden forms, because currently with this code when I press submit (as an admin) it says I must enter a value for the written message.
I can bypass this using hidden forms under the ELSE bit - but people with any knowledge can just bypass this using Inspect Element or Firebug and then post that value.
I need a more secure solution to this, so that people cannot edit Hidden forms. Do I post the old variable somehow to the form?
It's for a PunBB page (edit.php): http://punbb.informer.com/svn/punbb/tags/punbb-1.3.3/edit.php (original).
Thanks

This is always an interesting problem.
I suggest storing private data in the users $_SESSION with an index unique to the form + page call. I just came into a similar problem at work where I was starting to pass way too much private data through hidden form fields. Now I simply pass a unique id which I use to index the specific private form data in the session.
It's not a 100% solution. Storing the data in the session rather than in the form means a stale form can timeout (ie if the session is killed/timed out), but it's a worth while trade off I think.

I'm not entirely sure I understand the question. Are you trying to control how the form renders, or trying to figure out how to add 'sensitive' data the a form?
First, if you're worried about what parts of the form are being rendered on the page, anything in the else clause would only render if the conditions in the if clause were not true. The else is not 'hiding' part of the form.
Second, there is no such thing as a 'secure' client-side form. Generally speaking, you cannot control what data is submitted to your application, and anyone can submit any POST or GET data they want. Instead you have to handle it on the server-side by properly filtering to ensure that a user has the proper authorization to do what they're trying to do. It sounds like you need to require the user to identify as an admin when the form is processed (most likely through session data).

Related

Simple Honeypot Form Check with PHP and AJAX

I've been trawling through all the suggested posts for this topic but can't seem to find a solution that either works for me or I quite understand.
I am just trying to do a simple honeypot which checks if a hidden field is filled in by bots and breaks the form if so. My problem seems to be when it comes to using AJAX to see if the PHP value cleared. Hope that makes sense as I'm not well versed in coding languages.
My original idea was to disable the submit button for any bots that fill out the field. However seeing as the field is blank straight out the form loads the submit button and the point is lost.
This is the part of the form checking for the bots:
<!-- THE HONEYPOT -->
<li id="artificial-detect">
<label for="artificials">If you see this, leave this form
field blank and invest in CSS support.</label>
<input name="artificials" type="text" value="">
</li>
<!-- /HONEYPOT -->
<?php
$spam = $_POST['artificials']; // This is our Honeypot field
if($spam) { // If the Honeypot field has been filled in
die("No spamming allowed bitch!");
} else { ?>
<li class="last">
<input class="submit" type="submit" name="submit">
</li>
<?php } ?>
I don't understand what to do now:
jQuery.('#salesforce-crm-form .submit').click(function(){
jQuery.ajax({
// Get PHP function that determines whether the honeypot has been snatched.
});
});
I am using an external URL for the action="" so I thought maybe that could only be inserted if the PHP returns clean of bots.
You cannot do the things in the order you think.
First PHP runs to deliver your form.
Then the browser acts, displays the form to the user. He might enter data and send it back.
Then PHP is on again, checking the form values.
You pretty much have the code you want to check if the honeypot field is filled. You should not try to use AJAX, because this PHP check can only be taking place after sending the form. Simply don't do what the form is intended to do if you detect spam.
BTW, Bots dont press submit buttons. Bots send Request based on parsing forms, disabling all Javascript.
[EDIT]
If your form goes to an external URL, then you cannot control any spam detection. Because bots do not use Javascript, anything on this level will not work, either, but thats what you are trying to do.
Only thing that will work is to NOT send the form to the external URL directly, but to a PHP script on your server that will check for spam an then send it to the original destination. Don't know if this will mess up anything else because now it is not the users browser sending the form, but your server. If there is any detection and/or usage of request metadata on that side, you are interfering with this.
Put default value in honey pot input and ask user to delete it before post. Also there is no use for disabling submit button:) Bots do not work this way, they will simply submit form without clicking anything.
If you change the type of the input box to hidden, and give it an ID, like so
<input name="artificials" type="hidden" id="honeypot" value="">
then users will not be able to see the input but bots will fill it in.
Then in your javascript, using jquery you can check for a value like so
var honeypot = $('#honeypot').val();
if(honeypot == '' || honeypot == null) {
// Call ajax function
}
Note, that has not been tested and is only an example.

How to cause a form field to be required

Is there a way to make a field required for form submission?
I can use HTML, Javascript or PHP to do this - whichever works.
I want to ensure that a form is not submitted with a blank value. Also it would be nice if I could make it so that users HAD to input values into certain fields.
EDIT: I don't really want to use jQuery at the moment as I'm not sure that my boss wants me to use jQuery.
Tried to do this:
<script type="text/javascript">
$('addorg').submit(function(){
if($('orgname').val()==""){
alert("Organization Name must be Filled");
return false;
}
})
</script>
And here's the HTML it is working on:
<form name="addorg" action="addorg.php" enctype="multipart/form-data" method="POST">
<div id="orgdiv"> <fieldset><label for="orgname">Organization Name</label>
<input type="text" name="orgname" id="orgname"/>
</fieldset>
</div>
This is for client-side validation. I can handle server-side validation, my PHP is far better than my Javascript or jQuery.
The client-side validation did not seem to work.
Nothing will ever prevent a form from being submitted to your web server. You can submit anything you like using tools like Curl. Therefore, you must always validate on the server. For normal users, you can put JavaScript in your page that blocks submitting invalid forms.
Therefore:
Is there a way to make a field required for form submission?
No.
I want to ensure that a form is not submitted with a blank value. Also it would be nice if I could make it so that users HAD to input values into certain fields.
You cannot. However, #Nicolas's answer shows how you can add client-side validation to block typical users from submitting the form and server-side validation to block everything else. His approach is correct.
You can do this in either JavaScript or PHP. JS is more user friendly and easier to code, but can be bypassed by determined users. It also may not function on some browsers or with some settings allowing users to continue as if there were no validation, but those cases are usually rare. I would recommend a JS solution unless this is a corporate website or has no room for error.
You can do this by modifying your form tag with an onSubmit function:
<form action="whatever" method="post" onSubmit="checkStuff();">
<input id="field_1" name="field_1"...>
You then need to create that function and place it in the head of your page. It should read something like:
function checkStuff() {
// By default, we plan to submit the form.
var formOkay = 1;
// Check to see if field_1 has a value. If not, we note that by changing our variable.
if (document.getElementById('field_1').value == '') formOkay = 0;
...
// Let the user know something is wrong somehow. An alert is easiest.
alert('fill out everything, ya goof!');
// If you return true the form will submit. If you return false it will not.
if (formOkay == 1) {
return true;
} else {
return false;
}
}
Note that your inputs must have an id attribute for this approach to work (though it's possible to modify my code to work with names too). I would make the id the same value as the field name. You can add additional checks for more fields where I placed the ellipsis. This code could be written more efficiently and cleanly, but I thought this approach would be easiest to understand and modify.
This is off the top of my head and hasn't been tested, but should get you working down the right track. If you have additional questions, please let me know.
EDIT:
I just wanted to follow up to agree with others that if you have the time and inclination, or this is a work related issue, you should validate both ways. JS provides a better, more user friendly method, while PHP insures nobody can just circumvent the JS to break your rules.
I don't know PHP, but your pseudo code would be something like this:
if field_1 = "" then
// Option 1
Print("Please press back and fill out field 1!")
AbortPage()
// Option 2
Redirect("form.php?error=Please fill out field 1&[other form values]")
end if
In the case of option 2 you would modify the form page to detect url variables and place them into the inputs. You would also modify it to look for a url variable called 'error' and display the contents if found.
Javascript should do it easily. Here's an example in jquery.
<input id="required" type="text />
Then, in your javascript library, you have something like:
if($("#required").val().length!=0)
{
formsubmit();
}
else
{
alert("You left the required field blank");
}
$('form').submit(function(){
if($('thisemptyfield').val()==""){
//do stuff
return false; //will cancel form submission
}
})
Makes that if thisemptyfield is empty, the submission of the form is cancelled. I encourage putting up a flag telling your user to fill in the field before submitting. Because with that code only, nothing will happen on the page. It just wont submit until the form is submitted with a value in the field.
Edit: This is using jQuery.

Who sent you?

I have a series of input forms, all of them take a different form action. Each of those validates input. If ok, they go to different success pages. If fail, I want the form action/validation pages to set $_SESSION['error_messages'] and go to a common page which displays the errors and has a "resubmit" button.
Question ... how to get error form the resubmit button back to one of many possible input forms?
Edit: I don't see how $_SERVER['HTTP_REFERER'] is going to work. Again: form --> validation --> error_page
So, I guess that validation has to set a session variable from $_SERVER['HTTP_REFERER']
USing HTTP_REFERER is an option, but possibly not the most viable one, as the referrer header is easily spoofable (and not all the browsers will send it). This may or may not interfere with your process.
The easiest thing to do, as you are already setting error messages in $_SESSION is to also add a $_SESSION['redirect_url'] value.
Using $_SERVER['HTTP_REFERER'].
But, as per http://php.net/manual/en/reserved.variables.server.php
The address of the page (if any)
which referred the user agent to the
current page. This is set by the user
agent. Not all user agents will set
this, and some provide the ability to
modify HTTP_REFERER as a feature. In
short, it cannot really be trusted.
So, like Neal Donnan has suggested, passing the module_name in a hidden field and then resubmitting to http://project/'.$_POST['module_name'] would be best
You can use the HTTP_REFERER header, but this is not always reliable as the browser needs to set this.
A more reliable way would be to set a hidden field in each form with the url to redirect back to.
I'm assuming that you're using the same script, if not please post your code:
Input page:
<?php
/* this is the form page header */
/* parsing & filtering input */
if( my_form_is_valid($input_data) )
give_the_answer();
else
header('Location:' . $_POST['request_uri'] . '&status=error'); //make sure that's the first output
/* follow the DOM */
?>
<form id="myform">
<!-- some fields -->
<input type="hidden" name="request_uri" id="request_uri" value=<?=$_SERVER['REQUEST_URI']; ?>" />
</form>

GET and POST on the same page?

EDIT: Answer found! Thank you very much people, a lot of answers worked, I chose the hidden field answer as it was easiest :D
I am creating a commenting script and I came across a problem. I am having to use $_POST and $_GET on the same page, which I don't think makes sense.
I am very new to php and am training myself.
I have a page named viewVerses.php - this has a lists of verses. When someone follows the reply link,
echo '<br />Reply';
I'm passing the verseid (commenting on bible verses) into the reply.php, so that a query may be made with that verseid. (This is so that the user can still see the verse he/she is commenting on).
Now reply.php has the form in it for posting a reply. The form goes to postReply.php
This is in postReply.php
$title = $_POST['title'];
$body = $_POST['body'];
$verseid = $_GET[verseid];
Can I get the verseid from the url and the POST the values from the form in the same page?
If not, is there a way I can do this better? Remember, I am new at php and probably won't implement a solution that is super hard. I have to get it for my to put it in my site.
I hope this is clear
I would add a hidden input to the comment form:
<input type="hidden" name="verseid" value="
<?php echo $_GET['verseid']; ?>
" />
That way, in postReply.php, you can access it using $_POST['verseid'].
Yes you can. The method of a form (in a html page) can be POST and the action URL can contain "GET" arguments being something like process.php?vid=1001 so to say. So in process.php you'll have vid as $_GET and the rest of data from the form as $_POST.
Sure you can, just set the action of the form to postReply.php?verseid=id_of_the_verse this way when an user submits a reply, in the POST array will be the reply related data and in the GET the id of the verse.
Yes, it is possible to mix both GET and POST values with one request. The problem you have is probably that you pass the GET value to reply.php, which then passes POST values to postReply.php. So, unless you tell reply.php to send that GET value as well, it will get lost.
You can do this by either specifying the GET value in the action parameter of the form tag, or you could even switch to a POST value with that, by adding a <input type="hidden" name="verseid" value="<?php echo $verseid; ?>" /> to the form.
Although it may seem counter-intuitive an HTTP request can come in with both Form and QueryString data. Like robertbasic says you can access them both via there respective arrays.
Using a form with a hidden input (<input type="hidden" name="verseid" value="..." />) is probably the cleanest way of doing things.
PHP also defines the $_REQUEST global array in addition to $_GET and $_POST. In general you should use either $_GET or $_POST but in this case where verseid is being passed for both methods, it might be more convenient to use $_REQUEST['verseid']. This way you need not care about the HTTP method being used on your script.

Is it better to implement a FORM and its ACTION with a single PHP file or two files?

I'm creating a FORM with PHP for an intranet webpage. Another PHP script is called by submitting the form.
Before anyone asks, the form does not allow any uploads, and although the values entered in the form find their way into an SQL query, I strip out everything but numbers.
I'm wondering if there would be a advantage in using the same PHP file for both the FORM and the ACTION?
Obviously, increased complexity is the penalty — ie, figuring out, when invoked, if the FORM is to be created, or if the SUBMIT button has been clicked — but what would be the benefits?
EDIT: Note, the PHP in 'submit' mode does not redisplay the form, it does something entirely different. This is the source of the complexity I was worried about.
The form is used to enter values which are checked against values in a DB, but there are no changes made to the DB.
I tend to find it more maintainable to have the php that creates the form separate from the php that is called by the form.
It will also reduce (though it isn't noticeable) one if statement to determine if this is a form request or filling in the form.
But, the problem is that unless you are going to take them to a new page, you will have to get the values back into the form which can be more complicated.
So, if you want to keep the values in the form, even after the form is processed, then leave the form processing logic at the beginning of the file, otherwise I would opt for maintainability and have them in two files.
In most case, I prefer that.
Keeping both together make the code more 'cohesive' as the code of accepting value (via form) is in the same php file (called it View and Control). To me this is an advantage.
However, the code that manipulate database should be separated in other file as it not the same as accepting value (called it a model library). This make it less-coupling as accepting and manipulation is separated. This decoupling will reduce the complexity you are worrying about.
Another advantage of is the URL. The users will see it as from the same page.
However, this is totally depends on your overall system metaphor and work flow. For example, it make better sense to the users that addBook.php handle book adding form and show that the adding has success or fail. Comparing that too having two addBook.php, addBookProcess.php.
What I am trying to say is that the flow of pages should be a more important factor to determine if you want to separate or combine them. Decoupling interface/logic code will helps you reduce the complexity if pages need to be combine into one php file.
Just my though.
Form is about user interface, action is about doing something with data.
The part of code that actually processes user input must certainly be separate from the form structure.
The form code must accept default values (or values previously entered and found to be invalid), error messages etc. It must have nothing to do with usage of successfully submitted form data.
If you allow user to change invalidated input, then you must have action URL the same as form.
If successful submission leads to something unrelated, then its URL must be different from that of the form. Basically, you must redirect user from the URL where the form got accepted to the next URL.
If you're doing AJAX, none of this applies.
It depends!
The upside to having them in one file is that it puts a single block of functionality into one place and allows you to handle form validation. The downside is increased complexity. It really starts to suck if you have the markup for both pages in one file.
I would suggest having 3 files - the main PHP handler, the template for the form and the template for the result page. The main PHP file would look something like this:
<?php
$error_message = "";
if ($form_submitted){
if ($form_validated){
include("inc-result.txt");
exit;
}else{
$error_message = "something went wrong!";
}
}
include("inc-form.txt");
?>
if validation fails, the logic drops you back to the form, where you can display the previously entered values, along with the relevant error message.
it does depend but in the long-term I would suggest separation of forms and business logic.
For quick projects I do understand the short-term gain of keeping it in the same page but you never know when the form you did needs to be added with features or needs to be turned to an ajax form. If you keep your logic separate from the form you would be ready for these changes quicker.
Well, mainly if you want to re-show the form to the users without losing data, then you can just write something like this:
<input type="text" name="myInput" value="<?php
echo htmlspecialchars(isset($_POST["myInput"]) ? $_POST["myInput"] : "");
?>">
Update: here is an example of this method:
<?php
$error = "";
$result = "";
$a = isset($_POST["a"]) ? $_POST["a"] : "";
$b = isset($_POST["b"]) ? $_POST["b"] : "";
if ($a !== "" && $b !== ""){
if (is_numeric($a) && is_numeric($b))
$result = sprintf("%s + %s = %s", $a, $b, $a + $b);
else
$error = "You must enter two numbers!";
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head><title>Sum numbers</title></head>
<body><form method="post" action="<?php print htmlentities($_SERVER["REQUEST_URI"]); ?>">
<p><strong>Enter two numbers to add them together.</strong></p>
<?php if ($error){ printf ("<p><em>%s</em></p>", htmlspecialchars($error)); } ?>
<p>
<input type="text" name="a" value="<?php print htmlspecialchars($a); ?>">
+
<input type="text" name="b" value="<?php print htmlspecialchars($b); ?>">
<input type="submit">
</p>
<?php if ($result){ printf("<p><strong>%s</strong></p>", htmlspecialchars($result)); } ?>
</form></body>
</html>
It seems like you should do 2 things:
1) create controller that steps in to see if you are doing an edit action or a display action
you already have the start of one at the top of your file there, just make it include "form.php" (your form) after it does it's business. So yes, make 2 files.
2) pull all that crappy formatting code up into the controller. Calculate all your values before the form is ever loaded. This includes running htmlspecialchars on all your form elements that need it. You can even loop through them to save lines of code:
i.e.
$cleanTheseVars = array ($a, $b, $c $error, $result);
array_walk($cleanTheseVars, 'htmlspecialchars' );

Categories