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).
Related
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.
I have a big security problem with my program, and I need to make parts of my URL's hidden. I have searched on the net for a solution, with no luck. In my program I have admin and user accounts - the program is simply a database for workers dosie. Admins can see all dosies but the other users can only see dosies that are in their work group. So my problem is, when a user comes to see the dosie, the URL to access the information looks like this: "viewdosje.php?album=108. The problem being that the user can simply change album id and he can see other dosies, which is not good. For example:
"viewdosje.php?album=109"
By changing the number in the URL he can see other dosies. It would be great to hide that part of URL, or am I wrong? Please help me with an idea of some kind. I don't know where to start.
You should not hide the url, but validate the access to the resource in the application instead. When you receive the ID, before displaying content, perform a DB query to see if the current logged in user has access to that resource or not.
Relying on "hiding" URLs is a terrible solution - anyone who can get access to the URL can get access to your private data. URLs can be accessed in all sorts of ways - sniffing web traffic (e.g. at insecure WIFI points), through JavaScript, through guessing, through getting access to browser history, and through all kinds of even scarier routes like trojans, keyboard loggers etc.
If the data in these employee records is sensitive/private, in most countries you are legally obliged to protect it adequately; even if there's no legal requirement, your company probably wants to avoid putting everyone's salary into the public domain.
The correct solution is to design a login mechanism, and assign user rights; when a user tries to access a page to which they don't have access, you send them an appropriate error message. There are numerous solutions for this in PHP - PEAR has a good implementation.
I've no real experience with PHP so I can't help there, but if I was tackling this problem with JSP, or Rails I might do the following:
Perhaps store user identifiable information in a cookie, once authenticated, compare this information to the user database ? Prevent the page being served to unauthorised users if they manually edit the url.
Is there a way to only let a webpage be viewed if the link pointing to it is pressed. I am sending emails to members of my organization with links that attach values to the URL so I can use phps $_GET to figure out who they are on the webpage and update appropriately. What I am worried about is individuals changing the values of the link and changing other members data. If there is a better method for doing this, I am all ears. Using a log in system is not an option.
Not exactly, no.
What you could do is include some token that you keep associated with a particular user id and is very difficult to guess, and include that in the link as well - then, when you get a GET request, you check to make sure the token matches the one you know is correct for that userid. (You'd store the "correct" tokens locally in a database when sending out the emails.)
For instance, you might have...
/modify_info_script?user_id=123&token=aSDqWEqwejk2123salskq
And then you'd have a database table or some other storage that has...
user_id token
----------------------
... ...
122 klqwkejajwie8u8213nak
123 aSDqWEqwejk2123salskq
... ...
and thus if someone tried to change the user_id in the URL, the token wouldn't match and you could reject their request. For instance, this would get rejected...
/modify_info_script?user_id=122&token=aSDqWEqwejk2123salskq
since the right token for 122 would be klqwkejajwie8u8213nak, not aSDqWEqwejk2123salskq.
This is probably the best option if using a login system isn't an option. However, you should really make sure that using a login system isn't an option at all, because user data really should be protected by a login.
This is really not the proper way to secure your site.
However, the simple fix for you is to check the "referer" header and make sure it's not blank. If it's not blank, then it came from a click (or they spoofed it, which is why this isn't secure).
The real way to protect data is to implement a login system with a set of permissions.
To check, if someone came from a link, see $_SERVER['HTTP_REFERER'].
To protect the application against link manipulation, you can combine it with a secret passphrase (only internally, the passphrase must not be known to anyone) and use md5() on the result. Attach the MD5 to the url. If anyone manipulates the url, you will know because the MD5 of "the url plus your passphrase minus the MD5" will be different.
Quite a lot password reset systems work like this so you could say it's reasonably safe provided you use long enough random token. Something like 32 chars should be fine.
Just providing the token should be enough since you don't need the user ID to check it against issued tokens in database.
/modify_info_script?token=aSDqWEqwejk2123salskqfilltill32chars
The other alternative is to have login system where use has to type in their credentials in order to change information.
Also if you really fear that someone might try to guess it, just timeout/ban users after 3 wrong token attempts. No one should be trying to type them in by hand anyway.
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
I have a main controller to handle the very front-end of my authentication system, it handles login, logout, update user info, etc. functions that I anticipate calling by POST'ing from views/forms. What about something like a "delete_user" function though? My thoughts are a button in someones admin panel would say "Delete Account" and it would post to "/auth/delete", and the function would delete the user based on their session username or id. This seems a bit open ended, you could send out a link to someone and when they opened it while in that application it would delete their account.. Whats the best way to handle this?
What you are concerned about is actually called Cross Site Request Forgery, or XSRF. You can read more about it on the OWASP Website.
A few things that you should do overcome this problem -
Use POST for the delete operation. This doesn't protect you from XSRF, but protects you from link followers/page accelerators. Its also a http best practice.
Post your session identifier in the body of the request. On the server side, compare the session identifier from cookie and from the request - if they are different, reject the request. This is the "double submit cookie" method to prevent XSRF.
Alternatively, you can ask the user to solve a captcha.
Additionally, a "soft-delete" on the lines of what Tom mentions is also a good idea.
It sounds like adding some other piece of information to the function is the answer. Here is the function in question:
function delete() {
$id = $this->session->userdata('user_id');
$this->auth->delete_user($id);
redirect('home');
}
In code igniter this can be accessed by just visiting site.com/class/delete which is my problem. I think a good plan will be to post an authentication token (saved in cookie) with the delete button, so it can't take action via the URL:
function delete() {
if($this->input->post("token") == $this->session->userdata('token')) {
$id = $this->session->userdata('user_id');
$this->auth->delete_user($id);
}
redirect('home');
}
I don't think i need a soft-delete right now, but thank you for that good tip! If you see any other issues please explain, thank you.
The way i handle this is as follows. On your account page you have a link to delete the account. They click that page and are greeted with another page asking if they are really sure and if so please enter their password to confirm they are sure.
After they do that i deactivate their account (not delete) and send an email saying that their account was deactivated and if this was intended no other action is needed on their part. If it was not intended they can login to their account and it will reactivate it. (within 48 hours) after 48 hours i delete their account and information.
Have a look at one of the better known authentication libraries for CodeIgniter:
https://github.com/benedmunds/CodeIgniter-Ion-Auth
If you don't decide to just use it, you can at least get some good ideas about how to go about creating your own