Direct URLs & delete confirmation forms - php

I am seeking a best practice advice for implementing delete confirmation forms.
The following page, among other options, contains delete button...
/website/features/f/123
...when clicked a simple form gets loaded under following url:
/website/features/f/delete/123
A user has to confirm deletion in a simple delete confirmation form. Delete button gets enabled after the 'check to confirm' checkbox is checked.
All good and clear, however I am concerned that providing direct URLs to delete options may lead to... say, situations that could be avoided.
Is there a better way of handling this scenario? Perhaps referer validation?

The most common "situations that could be avoided" are:
Bots following links (e.g. to precache results). Avoid this problem by ensuring that the URL requires a request to use an HTTP method that is not safe such as POST and not GET.
CSRF attacks as covered by this other question

Actually deleting something should required the user to be logged in to the site and you should check that this user has the necessary permission to actually delete something. If your use case permit that something can be delete publicly, then it doesn't really matters if the confirm is checked or not (think trolls). If your user has the permission to delete something, then there shouldn't be any problem except if mistype something in the URL.
To avoid this you can also implement the DELETE http request (think REST). A combination of permission and DELETE should be enough to avoid bypassing the confirm dialog.
Another solution could be to implement validation token. The confirm dialog generate a secret token that needs to be validated by the delete action.

I implemented my initial referer idea. But as always I am open for suggestions and constructive criticism.
if(empty($_SERVER['HTTP_REFERER'])) $this->_app->redirect('/website/features', 302);
Note that this is a slim based redirect.

Related

Protect backend from multiple form submits in Laravel

I'm trying to protect my backend from multiple post requests to avoid duplicate data on the database and the server overload.
I've already blocked the frontend disabling the submit button after a first click, but it will not prevent some "smart user" to submit my form from the console or disable javascript from the page and try something.
So I want to know if Laravel has some solution for this case.
PS: I've already tried some solutions on the backend too if you want I can post here.
As requested:
So one of my alternatives is check if the incoming data is already on the database and denied the request if is it, it will prevent the duplicate data but not the server overload.
Another alternative is to create a token in session for one use only on Create() method from the controller, send the token to the view and put it on a hidden field, retrieve it from post request and check the post token with the session token. If the two tokens are the same, then unset it to avoid others requests try using it and if they try I deny the request.
If you know who your users are (because they have an ID) then this is somewhat easy to do. Possibly use some sort of quick-access system such as Reddis to check-in that a user is in a state of edit while the action is being carried out.
However that creates complications of its own. Also doesn’t work if you don’t know who your users are.
The safer thing would be to make sure that your requests can handle potential problems. Consider using database transactions to ensure the integrity of the data.
It would depend really on what you’re trying to avoid, why you are, and what kind of data you’re worried about duplicating.
if it's too important for you to protect for multiple submit u can put a random string in hidden input in your form and also put it in a special session for each form you have and check it every time and after that try to change your session after each time you end your proccess

How to prevent someone misusing routing systems?

I'm using a routing system. You can use the url to do some quick updates etc, without having to create a page for it. I believe this to be very effective. Though, how can I prevent a user misusing it?
This line updates a users account:
http://localhost:8080/Basic/Route/User/update/permissions>1/29
Class: User
Method: update
Set permissions => 1
Where id is 29
It works very nice, but any user could be able to type this in his URL if he knew in what way the system works.
Are there any ways to prevent misuses like this one?
Thanks!
You should implement User Authentication, then check if user is logged in and if he has required permissions. I don't see any other way to do it simpler.
Add a CSRF token and it might be fine. I would also make it a POST request instead of GET if it isn't already.
If you don't secure your URLs/forms this way users might be tricked into performing actions they didn't intend to (e.g. by visiting a link from another website or an email).

php security & marking mysql records for deletion using a html link (GET)

Just wondering if people think it is safe for a website to use a html link to allow users to mark their documents for deletion from their secure account page?
I have a website where users can create documents once they have registered and logged in to the website. To delete a document I include links on their account page for each document to be marked for deletion as follows :
http://www.examplewebsitename.com/delete_document.php?docid=5
The delete_document script makes sure the docid parameter is numeric, then checks using a session variable of their user id set when they logged in, wether this person actually created this document by looking up the user id of the creator of the document. If they where the creator, then it marks the document for deletion, otherwise if the current logged in person wasnt the creator then it doesnt mark the document for deletion and returns an error page.
Do you think this is a valid and safe way to mark documents for deletion, or should I be using a form and Post to do this more securely?
Three main concerns I can think of about using GET as a delete operation for your app.
Semantic reason, GET, according to http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html, should be an idempotent method
the side-effects of N > 0 identical requests is the same as for a single request.
More prone to CSRF, someone could post a link to http://www.examplewebsitename.com/delete_document.php?docid=5 and wrap the link into a harmless looking anchor
Click here for free puppy!
If by any chance the user is logged in and clicked on that link on his trusted website, it would inadvertently get the user to delete the document.
Browser addon / plugin that crawls web pages and cache links might accidentally crawl the link, opens it and again, delete the document without your user knowing.
Generally I advice against using GET requests to manipulate data because that's not what GET is designed to do if you stick to the HTTP Spec. If you would go completely restful you should be using a DELETE request but in most cases i use a confirmation page with a form that performs a POST request to delete the record.
Read Why should you delete using an HTTP POST or DELETE, rather than GET? for the reasoning behind this. It's been asked before in some other contexts.
The main reason is because GET is meant to be a safe method that is used for retrieval only:
In particular, the convention has been established that the GET and
HEAD methods SHOULD NOT have the significance of taking an action
other than retrieval. These methods ought to be considered "safe".
This allows user agents to represent other methods, such as POST, PUT
and DELETE, in a special way, so that the user is made aware of the
fact that a possibly unsafe action is being requested.
User agents expect this method to have no side-effects:
Naturally, it is not possible to ensure that the server does not
generate side-effects as a result of performing a GET request; in
fact, some dynamic resources consider that a feature. The important
distinction here is that the user did not request the side-effects,
so therefore cannot be held accountable for them.
This means GET should no cause any server-side state change.
Another reason, but rather a minor one, is that GET is easier to exploit that POST as there are more ways to trigger GET request than to trigger POST request. But no matter which method, both are vulnerable to CSRF attacks.
So if you make sure you’re protected against CSRF, you could even use GET for state changing requests.

Dealing with people modifying ID's in links

I'm writing a web app in PHP (using Codeigniter). I'm just wanting some security advice here. I have a task controller with a delete method. The link to delete the task is then http://localhost/task/delete/12345
So I'm wondering how to handle the fact that people have the ability to modify the link, thus deleting another task (probably not their own).
So my options I guess are to always do a check that the user owns that particular task before deleting it, or some sort of ID hashing?
Does anyone have any suggestions?
So my options I guess are to always do a check that the user owns that particular task before deleting it
that is the usual, and best, approach, yes. Hashing the ID is too insecure for many use cases: The link containing the hash is stored in the browser's history, might get E-Mailed around, be present in REFERER headers for outgoing links....
Either check ownership, or use a full-blown Access Control List, depending on how complex the permissions are.
Yes, check whether the user is allowed to delete that task and respond with an
HTTP/1.1 403 Forbidden if he isn't. Also, make destructive actions like deleting records POST requests. Otherwise watch Google (or some other fetcher-type client) happily triggering all your delete actions.
It is not recommended to update/delete your data via an http get request. Use post instead.
So my options I guess are to always do
a check that the user owns that
particular task before deleting it
Yup, that's it. There's no point in hashing an id, as if some user guesses another hash id he might delete a task from another user (that would be security through obscurity, and it's not a great security method). So, yes, chech that the task belongs to the user before deleting it.
Also, it isn't clear from your question, but to delete something, the user should go to blablah.com/tasks/delete/1234, and then confirm to delete the task via POST (submitting a form by clicking a button probably).
You can use session to store the item's id to delete and then on the delete page you check that the id given is equal to the session stored id.
Hope it helps you

Preventing erroneous AJAX Calls by the user

I have a webpage in which the user is awarded X points on clicking a button. The button sends a AJAX request(JQuery) to a PHP file which then awards the points. It uses POST.
As its client side, the php file, parameters are visible to the user.
Can the user automate this process by making a form with the same fields and sending the request ?
How can I avoid this type of CSRF ? Even session authentication is not useful.
You should handle that on the server-side, If you really want to prevent multi-vote or prevent the same people from voting several time on the same subject.
This is why real votes always use authenticated users and never anonymous votes.
By checking the request is really a XmlHttpRequest (with #Shaun Hare response code or with the linked stackoverflow question in your questions comments) you will eventually block some of the CSRF but you won't prevent a repost from the user, using tools like LiveHttpHeaders 'replay' and such. Everything coming from the client side can be forged, everything.
edit* if it's not a voting system as you commented, the problem is teh same, you nedd 'something' to know if the user is doing this action for the first time, or if he can still do this action. There's a lot of different things available.
You can set a token on your page, use that token in the ajax requests, and invalidate this token for later usage server side. This is one way. the problem is where to store these tokens server-side (sessions, caches, etc)
Another way is to check on the server side the situation is still a valid situation (for example a request asking to update 'something' should maybe handle a hash/marker/timestamp that you can verify with current server side state.
This is a very generic question, solutions depends on the reality of the 'performed action'.
Check it is an ajax call in php by checking
$_SERVER['HTTP_X_REQUESTED_WITH']

Categories