Symfony Security - delete button in loop - php

I am wondering about the security of my application. I'm simply using twig loop to display all of my records in database. And everything is all right when I make separate site to display the details and there are buttons to e.g. delete this thing. It usually happens DELETE method and somebody can display only own details. But I want to have button to delete specific record in basic view where every records displayed e.g. next to title of item.
I cant do this by CreateFormBuilder because I cannot send the current id of the item from the form (or I just don't know how to do it). But is it secure? Everyone can change the id parameter of button and delete other record.
I can use AJAX and simply button in twig but this is the same case. Everyone can change e.g. data-id parameter in button and delete other record.
What I should to do in this situation? How you usually solve this problem?
Summarising I want to make a secure button to delete item next to each displayed record.
Have a nice day!

One of the way to secure AJAX routes is to use JWT (json-Web-Token) (see this : https://jwt.io/) instead of random string token. This token is crypted with the user's information to ensure the person who clicked on the button is allowed to do someting (and the token is send with the request in header of the request).
Anyway, you have to send something to identify the id of the element you want to erase or modify in your database. I would personnaly implement this JWT system, but the access to the page where you can see and click on these buttons must be protected too. This way, you can assume that the users don't have bad intentions.
Theis bundle (https://github.com/lexik/LexikJWTAuthenticationBundle/blob/master/Resources/doc/index.md#getting-started) can help you to implement this on symfony very easily (i'm new to this framework and i did this in a few hours - just a thing: if you use Apache, don't forget to allow override in your Apache configurations to allow the .htaccess of symfony to do his job, or headers will be strip by Apache - it makes me several hours to find why things did not work !).
Hope this will help !

It really boils down to what kind of app you want to build:
more traditional app - with full page refresh/navigation cycle
AJAX based - with all sorts of async calls to your server
In any case you choose, it is your responsibility to check whether the current user is authorized to make any change (deletion included) to an object. This comes as especially important in case of id being integer, which is predictable.
So, first, make sure your routes are protected from anonymous users, and second, make sure that you put in place permission strategy which allows/denies user's specific action.
Most of the permission-related stuff can be achived via Voters, but if you are really in need of heavy-lifting you can turn to ACL.
Hope this helps...

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

Redirect after user switching (impersonating) in Symfony 2

I searched everywhere but it seems impossible thing to do.
I was able to catch SwitchEvent coming from SwitchEventListener and get both impersonator and target user objects (one being impersonated as) but I would really like, based on target user roles to redirect request to some other URL.
Example:
I have two restricted areas: "/basic" and "/elevated" where first one requires ROLE_BASIC and the other one ROLE_ELEVATED role. Now, if I am currently logged in as ROLE_ELEVATED user and want to switch to some ROLE_BASIC user using URL:
/basic/?_switch_user=some_basic_user
that would result in AccessDeniedException, and I'm forced to navigate first to:
/?_switch_user=some_basic_user.
Only after that I can navigate to /basic as token has been written to session.
Now, the question, as subject suggests: Is there any way to redirect user using SwitchEvent (or any other) after doing user switching?
Ok, I finally got access to my dev computer and looked up the the solution to this problem.
And, I got to say, it is not as clean as I wanted it to be but delivery date was critical and this was the only way to achieve it back then.
So, what I basically did was to send AJAX (although, I set async to false) request to URL /?_switch_user=some_basic_user, wait for an answer and if it was successful I would navigate forward to /basic/?_switch_user=some_basic_user URL. I know, it's quick and dirty, and is pretty much unreliable...
Hope this helps....
You can just generate the right link to begin with:
...
Of course, the URL can be generated by twig's path helper too:
...

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

Form inputs stored as you type

Hey guys, I have a form with 3 fields 1 input, 1 select and 1 textarea. Is there a way to store the information as they type?
The reason why I need this is because if you are not logged in the submit button will take you to a fancybox with another login form or a signup one. So of course if the user logs in the page is refreshing and they loose the text they inputed.
Thanks.
You can totally use YUI's Storage module, it'll hold everything in 1) HTML5 memory, 2) SWf memory 3) Google Gears memory 4) ysql or something, so I read.
I've tested HTML5 mem and Swfstore, both ace.
Edit: Here's an excellent YUI Storage example, it counts every 5 keystrokes, perhaps you'd call the same save method when focus leaves the form handles you're working with.
AJAX could do this, though you are probably better off passing the contents of the inputs in POST and retrieving them if the page is reloaded as a postback from the login page.
There is no trivial solution to this problem. The simplest way to overcome would be asking login screen before asking for user input.
YUI storage module answer is a great option. Otherwise, you're going to have to change the behaviour of the authentication logic which automatically redirects you to the login page. You would have to store the posted values in some temporary server-side location, and re-post those values after the user logs in.
Another option would be to authenticate the user via a dynamic HTML login form and Ajax before actually submitting the form. Either way it changes the authentication logic of your application a lot.
Actually, I think the root of the problem is that you're presenting the user with a form which requires authentication to use before they are authenticated. I think you should either force the user to authenticate before presenting them with the form, or don't require authentication for posting the form (which probably isn't a good idea).
The most straight forward and simplest way that first comes to mind:
Store the information in a cookie - first thing when they hit submit so you have what they typed at any time, logged in - out - hour later, maybe even next time they visit etc.
If you can't use a cookie, maybe save it to the database in a temp table of some sort, relative to a specific session or anonymous user....
as you mention i think you can use simple SESSION variables for all your fields OR you can use AJAX.where you can popup one light-box at the same page and then login and process further you want.
Thanks.

What's the safest way to remove data from mysql? (PHP/Mysql)

I want to allow users as well as me(the admin) to delete data in mysql.
I used to have remove.php that would get $_GETs from whatever that needed to be deleted such as... remove.php?action=post&posting_id=2. But I learned that anyone can simply abuse it and delete all my data.
So what's the safest way for users and me to delete information without getting all crazy and hard? I am only a beginner :)
I'm not sure if I can use POSTs because there is no forms and the data isn't changing.
Is sessions good? Or would there be too many with postings, user information, comments, etc.
Ex: James wants to delete one of his postings(it is posting_id=5). So he clicks the remove link and that takes him to remove.php?action=post&posting_id=5.
EDIT: Alright, so now I am a little confused. While I can't be 100% secure, how do I do this with $_POSTs?
SOO I should use GETs to get all the data to remove.php, THEN have a confirmation submit button and when users click on it, it put all the data into POSTs and delete from the dbc?
Deleting records is a kind of a scary practice. If you or someone makes a mistake there's no real recourse to resolve the issue. Expunged records are very hard to resurrect.
Instead of deleting records, you could add an "active" bit (e.g. Boolean) column that is toggled off when users "delete" records. Essentially your users would be suspending records by toggling them off and the records would be saved in case mistakes or abuse but appear "deleted" to the user. To make this work with your other queries, just add a where clause of active = 1.
You could then have a utility script that's run at some specific date interval that would clean out deprecated, past dated records. You'd also need some type of timestamp for this type of maintenance.
Just a thought. Take if for what it's worth.
I'll echo gurun8 in preferring to 'mark' records as deleted, instead of actually removing data. And then obviously, you'll need to check that the authenticated user has permission to delete the post.
However, it seems very important to mention that $_GET is not safe even with authentication because of cross-site request forgery.
Imagine if Amazon adding things to your cart based on a GET request. All I'd have to do is put an image on my page with that URL, and everyone who visited that page and logged into Amazon will have products added automatically.
To match your example, I don't like Jame's post, so i put an image on my site like this:
<img src='http://example.com/remove.php?action=post&posting_id=5'>
And I send him a link to my page, and ask him to check it out, hoping that at the time he's logged in to your site. Because, of course, he clicked that little 'keep me logged in' button.
So you are right to be concerned about using GET. If you don't want to litter pages with forms, then confirm the action by POST.
Well you have to start by authenticating the users with a login script.
If you want the simplest solution possible, then I'd suggest protecting the directory in which you have remove.php with a simple .htaccess username and password.
If different users have different rights for deleting database entries, then you probably should create a PHP login script and use PHP session.
Bonk me if I'm stupid, but I searched for quite some time for a simple PHP login tutorial that could be placed on a real site (doesn't use session_register(), uses mysql_real_escape_string(), htmlspecialchars() etc) and I simply couldn't find one!
Probably this one comes the closest, you just have to replace session_register() variables with $_SESSION ones for it to work without register_globals (default in PHP5).

Categories