How can I only allow request from my form - php

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.

Related

How to get around people changing form submit methods

I've got the following HTML
<form action="/home" method="post">
<input type="hidden" name="_method" value="POST">
<input type="text" name="var">
<button type="submit">Submit</button>
</form>
on the server side, I trigger different actions based on the type of request I get. The _method hidden field governs that action. Can users not simply change the value to, say DELETE and cause mayhem? I tried it on my local Apache server, and it does in fact trigger the delete route, which could potentially be disastrous.
I also know that I'm not the only one using this practice, as I've seen it on official documentations for various frameworks, so what am I missing?
You can check the method name on the server side with:
<?php
if ($_SERVER["REQUEST_METHOD"] == "GET") {
// collect value of input field
}
else{
// Do nothing
}
?>
Note: Change "GET" as you see fit.
Note2: $_SERVER["REQUEST_METHOD"] is generated by the server. User can not edit it. So, you can check with this variable what kind of request you have (GET, POST, PUT,...).
Hope it helps you!

php make hidden fields tamper proof ?

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.

honeypot thinks im a robot, why?

I'm using simple honeypot
my HTML
<input type="text" name="mail" id="mail">
my CSS
#mail{display:none;}
my PHP
if(isset($_POST["mail"])){
$honeycomb_passed = "No";
} else {
$honeycomb_passed = "Yes";
}
When I submit the form always outputs No. To my understanding it should output yes, right? Where is the problem?
Thanks
Just because the field is hidden in CSS doesn't mean it isn't send to the server.
If you don't want the email value to be sent to the server - try to user something like:
$('input[name=email]').remove();
to remove the element from the dom
be sure to wrap in:
$().ready(function(){});
If you're not using jQuery let me know!
You're doing it wrong.
A working honeypot
HTML
<form>
<input type="text" name="mail" id="mail">
<input type="submit">
</form>
<style>
#mail{display:none;}
</style>
PHP
if($_POST && $_POST["mail"] != ""){
die("Sorry, no robots");
}
How does it work
You have a hidden field inside your form. Typically, a robot will attempt to fill any form field available with data in the hope that it will not get rejected. Once it submits that form, your script will detect the input and die. If a human was filling it out, they would not see the hidden input (type=text style=display:none) and leave it empty. Thus the php would allow the submit to go ahead.
If you PHP script dies as soon as it detects the honeypot field, then you are saving yourself cpu cycles (because there is no need to reply reasonably to a robot).
For more information on honeypot, see this question:
How do I add Honey pot fields to my forms?

how to enable the submit button in real time depending on text validation?

I have a HTML form in list.php that submits the data from text box ("item" in below code) to check.php. This check.php validates the text entered to be not empty or white spaces only. After validation, it redirects to list.php for the entered text to be displayed. list.php is below. I want the "add" button to be enabled only when valid text is entered in the text box. I would like this feature to be done with php and probably not with javascript.
I can use "disabled=\"disabled\" in the form, but this does not work in real-time disabling depending on validation.
<form action="check.php" method="post">
<input name="item" type="text" size="25" autofocus="autofocus" />
<input type="submit" value="Add" id="add" />
</form>
You say:
I would like this feature to be done with php and probably not with javascript.
Unfortunately, if you want "real-time" then you're gonna need JavaScript. You'll need it to make AJAX calls to your PHP code to check for validation.
So either A) you don't validate in "real-time" at all, or B) You use JavaScript in one shape or another.
Let's say you opt for B), to use JavaScript, and presuming ALL you need to do is check for an empty string or whitespace, then you can do all of this client-side in JavaScript and not require a server call at all, also making it truly "real-time".
And so, here is my solution, using JavaScript (jQuery) without relying on server calls. This may not be suitable for your current implementation, but just in case it is, this might be helpful.
JSFiddle:
http://jsfiddle.net/VKfrw/1/
JavaScript:
function hasWhiteSpaceOrEmpty(s)
{
return s == "" || s.indexOf(' ') >= 0;
}
function validateInput()
{
var inputVal = $("#myInput").val();
if(hasWhiteSpaceOrEmpty(inputVal))
{
//This has whitespace or is empty, disable the button
$("#add").attr("disabled", "disabled");
}
else
{
//not empty or whitespace
$("#add").removeAttr("disabled");
}
}
$(document).ready(function() {
$("#myInput").keyup(validateInput);
});
HTML:
<!-- give this guy an ID -->
<input id="myInput" name="item" type="text" size="25" autofocus="autofocus" />
This implementation uses jQuery.
As mentioned, if you want this done in real time some javascript will be needed.
However I think this problem is actually more suited to javascript in general. PHP validation can be useful if you need to cross reference for data with data in your database.
eg. In a sign up form, checking a user is not already registered with the entered email address.
But in your case, depending on what you mean by "valid text" it is probably easier and better to use javascript.
There are some great jQuery plugins which make javascript validation really simple.
http://docs.jquery.com/Plugins/Validation/validate

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.

Categories