I have some pages in my web app which deal with the sent data from a form. I want to avoid the following situation:
An user creates (in the client side) a form with the same fields that my original form and sends it to the url which process the forms. Then, my process page receives the form sent by the user and processes it.
Is there any way to do that only forms sent via my web application get processed?
An easy way is to generate a random token, set that in a session variable when you generate the form and add is as a hidden field to the form.
When the form is sumbmitted, you can check the session variable against the form field value.
That ensures that a visitor would need to request the form first but of course they could still to that programmatically, get the token and add that to the form submission.
Are the users not authenticated?
You might want to research around CSRF. There are many articles detailing how to go about that, see below:
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet
http://blog.ircmaxell.com/2013/02/preventing-csrf-attacks.html
Related
Lets say we have a certain endpoint in a Symfony CMS application for receiving form submissions (e.g. of a contact form). This endpoint sends a copy of the contact form contents to the E-Mail entered within the contact form.
As soon as an attacker finds out about how the endpoint works (which is pretty easy) he could just go behind the Captcha after validating it once and use the endpoint directly in order to send thousands of E-Mails using the sender address of the companys' mailserver (server side Captcha validation will help, but it is not a full answer to this question).
Therefore a mechanism is needed in order to prevent attackers from doing this - at least to easily. The first solution which came to my mind was tokens. The problem with tokens is that they do not play very well together with caching, implementing an ajax endpoint for tokens would just require an attacker to fetch a new token from the first endpoint and send it to the other endpoint among with new data.
So my idea is like this:
Create an ajax endpoint which creates a PHP session. It is
called via JavaScript everytime a page with a form is opened (so
there will be a PHP session whenever a form is submitted)
If the form is submitted and there is no valid session the server
instantly returns an error after sending the form
The form ID will be saved within the session. On the server side it
is validated if the form was sent by this user within e.g. the last
two minutes and if yes, form processing is denied.
The SessionService class which does session_start(); is only included in
the ajax endpoint for creating sessions as well as in the ajax
endpoint for form submissions. Therefore normal CMS pages can still be
cached as session_start(); is never called.
Is there a serious issue with this kind of implementation or is it a good solution to the problem? If you see a problem how would you solve it instead?
I have created this function:
function blacklisted_ip() {
$('form').remove();
$('.wrapper').removeClass('form-success');
$(".login_text").html("Your IP has been blacklisted");
}
that removes a HTML form - I remove the form to stop users with a blacklisted IP logging in.
I have a php script at the top of the same page that processes the login when the form is posted.
Is there also a way i can stop other pages posting to this page?
the php starts like this:
if($_POST) {
}
I thought about adding a hidden field with a value in but then thought someone will be able to view the source and just copy it?
Best way to do this is using CSRF tokens. If you're suing any frameworks the they're already implemented out of the box, if not and if you want to implement it on your own you can do it.
CSRF stands for Cross-Site Request Forgery, which is a type of attack that occurs when a malicious web site, email, blog, instant message, or program causes a user’s web browser to perform an unwanted action on a trusted site for which the user is currently authenticated.
Reference: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
Solution to prevent this is to have a unique CSRF tokens for each users for each form. When ever user opens the page and form is loaded you assign a token/key to that (page+form) and save that in session with expairy of your choice.
Add this token along with the form as hidden field and post that along with other datas, now when you process the form compare the token received from client side along with your sessions's token. If they match they're authenticated and if not don't process the form.
You can use any method to generate the CSRF tokens, in your case they would be just unique keys for each page+form.
I am currently having an issue with using a nonce as a security solution in PHP
i read this post about
How to check if a request if coming from the same server or different server?
about using an hidden input form field to hash a random value and At the same time, store that random value into the session that correspond to the user.
When the form is submitted, check that the hidden field has the same value as the one that's stored in session. (I think am having a problem with this)
Example
<?
$_SESSION['formhash'] = md5('any value to be hashed');
?>
<input type="hidden" name="hashed" id="hashed" value="<?php echo $_SESSION['formhash']; ?>" />
A user having an Mozilla Firebug and inspecting the element will still find out my hidden field and then copy it. And then create his/her own form then post it to my url and the Login will still be Bypassed.
Image showing example
Is there any more secure way to do this ?
Any help will be appreciated thanks !
The bottom line is that you cannot prevent a user from manipulating the form data prior to submitting the form. What your solution does is confirms that the form data is coming from the user you sent it to.
Regardless of whether or not a user is "logged in", you will probably start a session each time a new visitor hits your site. This means you can store the hash value each time you send them a form and you should, in theory, be able to associate the hash value on the returned form data with the hash value in the session (just like your code is doing).
Armed with that knowledge, we can consider the following scenarios:
The typical use case is that a user submits a form without modifying the data. Your approach will allow you to confirm that the form has been posted by that very user. Your validation code should confirm that the POST data is acceptable.
If a user modifies the form data and submits it, your approach will allow you to confirm that the form has been posted by that user, but not that the form has been messed with. This is why you need to validate forms very, very carefully.
If a user grabs a form that was actually sent to someone else and posts it - modified or not - your system will allow you to confirm that the form did not come from the user that it was originally sent to and you should reject it.
Scenario 3 is what is known as a CSRF attack and your solution is the standard defense against this attack.
PS As #cHao says, you should regenerate the hash for every form you generate.
I need to check the request Url in php. Basically i need check whether the form is post from the same server or not. I need to get the action of form in php
There is no reliable way to tell what an HTTP request was constructed in response to.
What you can do is implement defences against CSRF. This won't guarantee that the submission comes from a form on your own server, but it will prevent a third party (Mallory) from tricking a user (Alice) of your site into submitting bad data on their behalf.
When Alice arrives at your site, generate a random token and give it to her (e.g. in a session). Put a copy of that token in a hidden input in your form. If, when the form is submitted, the tokens don't match, then the request is coming from Mallory.
If the problem is that you don't trust Alice not to edit the form herself, then you can't use that as a defence.
Don't give Alice data you don't trust her with in the first place. Check the identify of users making requests before you give them access to the relevant bits of the site.
For example, if the form is the "Delete message" form and your concern is "Alice might change the ID of the message to be deleted" then check that Alice is the owner of the message with that ID when you get the request to delete it.
You are in need of a CSRF token.
When the page is requested add a string to the form, like
<input type=hidden name=token value=$token>
and save it in the database as well.
The token can be generated using something like hash of timestamp.
When the form is submitted, verify whether the token was generated by the server itself.
I have a ton of data collection forms on my website, and I wrote a PHP script to handle all the data. All the forms have that one script as their action, and POST as the method. The handler emails a copy of the data to me, and I'd like for the emails I get to contain the URL of the form where they originated. Is there any way in PHP to get the url of the form which was submitted to the script? Or do I have to add an extra hidden field in every form with its URL?
Send the following variable in the email as well:
$_SERVER['HTTP_REFERER']
If you want to ensure that posts only arrive from your own form, you could put a one-time token on the form in a hidden field to validate.