David Williamson
asked on
more secure way of deleting db record than url variable?
I have a page that lets admins delete users. The way I've got it configured right now, the userid is passed in the url, where an if statement deletes the user record if it's present. But, it occurred to me that doing that is not very secure. If anyone ever wanted to, they could easily delete all the user records by just visiting that URL with a userid attached.
Is there a better way to manage that? I'm already using the cflogin framework (which should prevent any non-logged in user from hitting the delete url), and I suppose I could check for a certain user role in the delete code so I make sure the person doing the deleting is authorzied.
Is there a better way to manage that? I'm already using the cflogin framework (which should prevent any non-logged in user from hitting the delete url), and I suppose I could check for a certain user role in the delete code so I make sure the person doing the deleting is authorzied.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
by the &code, it will definately differencentiable betwen the hashed code and the user_id!
The best is to use the cfqueryparam param or the val function because if someone will try to excecute any sql injection attack, the cfqueryparam with cfsqltype=numeric or val function will handle it and it will not let it exceute the error!
Wrap the whole functionality around the cftry catch block and log that errors in the file!
Your Oprions!
1. use <cfqueryparam> Tag
2. use the Val Function
3. Store the url value in a session Scope or Form Scope and then execute behind the scenes.
Hope you Get What you need
The best is to use the cfqueryparam param or the val function because if someone will try to excecute any sql injection attack, the cfqueryparam with cfsqltype=numeric or val function will handle it and it will not let it exceute the error!
Wrap the whole functionality around the cftry catch block and log that errors in the file!
Your Oprions!
1. use <cfqueryparam> Tag
2. use the Val Function
3. Store the url value in a session Scope or Form Scope and then execute behind the scenes.
Hope you Get What you need
<cfqueryparam will protect against SQL injection, but will not protect the user from changing user_id=123 to user_id=456. To do that, you need something like the hash
well if the user has the ID as not a PK, then he can encrypt it and decrypt it, elsewith for securing the change in the URL, the best way is to pass the value either through form or session rather than URL, should not use any HASH or something because
<cfset code = hash(user_id & "secret_phrase")>
<a href="deleteUser.cfm?user_ id=#user_i d#&code=#c ode#">Dele te Me</a>
in this way, he can change the url ID number and that will be verified on the action page too! without even touching the hash!
<cfset code = hash(user_id & "secret_phrase")>
<a href="deleteUser.cfm?user_
in this way, he can change the url ID number and that will be verified on the action page too! without even touching the hash!
yes, encryption would work as well, just a bit slower
passing through a form can be hacked almost as easily as the URL, so you would still need hash or encryption
using a session variable is not good because multiple pages can share the same session and you cannot ensure the variable will not be over written by a different session
> he can change the url ID number and that will be verified on the action page too! without even touching the hash
I don't understand this. You need the hash to verify the URL ID has not changed.
Encryption is not a bad idea
but tell me one thing do your app has many administrators or just one , if it is just one then any way you will check for the existence of the session and then only allow to go further to delete the records . this should be checked in each every page of the admin and then proceed to the next action else redirect to log in page .
If multiple administrators then first check for session and then check if this user is authorized to delete this record .
For example If i am an admin of one Zone so I can only delete records of that zone it self etc
So you can maintain another check to see if authorized to delete that record or not .
but tell me one thing do your app has many administrators or just one , if it is just one then any way you will check for the existence of the session and then only allow to go further to delete the records . this should be checked in each every page of the admin and then proceed to the next action else redirect to log in page .
If multiple administrators then first check for session and then check if this user is authorized to delete this record .
For example If i am an admin of one Zone so I can only delete records of that zone it self etc
So you can maintain another check to see if authorized to delete that record or not .
That's a good point by srikanthmadis.
Another check could be to ensure the user (administrator) has rights to delete the user_id. He mentions admin rights to a zone, but it could be rights by company or any other way your site divides priviledges. For example, users may belong to an organization, and you have 2-3 admins for each org. When the admin goes to delete a user, you can do a quick query to ensure that the admin and the user being deleted are both part of the same organization.
I disagree, however, about the session variable; even if there is one admin, the admin could have multiple pages open attempting multiple tasks. The session variable could conflict between his own pages. This is not a good place to use session variables.
@gdemaria
"I disagree, however, about the session variable; even if there is one admin, the admin could have multiple pages open attempting multiple tasks. The session variable could conflict between his own pages. This is not a good place to use session variables."
I never said to use session variable my point was if it is a single admin we just check if the admin has logged in or not and then continue with next step of deleting the record
So my point is to check if the admin has logged in and that session exists .
ex:
isloggedin()
isuserinrole (admin)
then go and delete the record .
naturally in admin portal we keep this check for all the pages and if the user has not logged in we redirect to log in page.
"I disagree, however, about the session variable; even if there is one admin, the admin could have multiple pages open attempting multiple tasks. The session variable could conflict between his own pages. This is not a good place to use session variables."
I never said to use session variable my point was if it is a single admin we just check if the admin has logged in or not and then continue with next step of deleting the record
So my point is to check if the admin has logged in and that session exists .
ex:
isloggedin()
isuserinrole (admin)
then go and delete the record .
naturally in admin portal we keep this check for all the pages and if the user has not logged in we redirect to log in page.
I see, my mistake. Of course you want to be sure the admin is logged in
well said experts! btw i think the author already knows this and might have implemented the functionlity, he is just asking the secure way to delete!
well said by all!
1. By encyption
2. Use the hidden form and pass the url value inside it! and then make a cross check on the action like isurl eq form.hiddenparamer, then go for delete.
3. use the cfqueryparam tag or the val function to delete the record.
4. My suggestion will just do not delete the record. just add one column to the DB, isDeleted and set its value to 0 if it is deleted and 1 if not, rather than delete, just update it
Choice is urs
Cheers
well said by all!
1. By encyption
2. Use the hidden form and pass the url value inside it! and then make a cross check on the action like isurl eq form.hiddenparamer, then go for delete.
3. use the cfqueryparam tag or the val function to delete the record.
4. My suggestion will just do not delete the record. just add one column to the DB, isDeleted and set its value to 0 if it is deleted and 1 if not, rather than delete, just update it
Choice is urs
Cheers
@myselfrandhawa
You can easily hack the hidden form variables too .
how does cfqueryparam helps you in this scenario , for example if there is a url like
http://test.com/delete.php?id=2
and i change it to
http://test.com/delete.php?id=3 how does cfqueryparam solves this .
always delete option will be in a admin area and in admin it is better to have role check to see if the logged in admin has the option of deleting that particular row then only we go a head and delete it.
That is why in most of the delete functionality we give and alert first saying are you sure you want to delete so and so record and then delete it.
My point is if it is an admin and already we check if the correct user is logged in and he is authorized to do this action that check should be enough i guess
4th suggestion is good and also for delete you can add an audit kind of stuff like this record has been deleted by user logged in IP date and time etc .
You can easily hack the hidden form variables too .
how does cfqueryparam helps you in this scenario , for example if there is a url like
http://test.com/delete.php?id=2
and i change it to
http://test.com/delete.php?id=3 how does cfqueryparam solves this .
always delete option will be in a admin area and in admin it is better to have role check to see if the logged in admin has the option of deleting that particular row then only we go a head and delete it.
That is why in most of the delete functionality we give and alert first saying are you sure you want to delete so and so record and then delete it.
My point is if it is an admin and already we check if the correct user is logged in and he is authorized to do this action that check should be enough i guess
4th suggestion is good and also for delete you can add an audit kind of stuff like this record has been deleted by user logged in IP date and time etc .
ASKER
Lots of great info, everyone, thanks for the ideas. I like the hash + salt idea in addition to the things I already have in place (admin checking before deleting, SSL). With the hash+salt idea, no would be able to intercept and alter the id that's about to be deleted.
If it is an internal admin url , you don't need to do all these checks , First make it in such a way that the url is not accessed from out side and make it secure and other steps which i mentioned in my comment id :35222007.
As i mentioned in my previous comments cfqueryparam will not help in any way in this scenario .
how does cfqueryparam helps you in this scenario , for example if there is a url like
http://test.com/delete.php?id=2
and i change it to
http://test.com/delete.php?id=3
how does cfqueryparam solves this .
Encrypting / hash with salt mentioned by gdemaria should solve this
you need to take certain steps if u want to use encrypted value probably has characters that the browser doesn't know how to display in the URL box
you could use URL Encode/Decode the var as well, or possibly try using Base64 encoding on it before you pass the var through the URL.
ex:
<!--- Encrypt String --->
<cfset encryptstring= 'your val'>
<cfset TheKey = 'secret key phrase'>
<cfset Encrypted = Encrypt(encryptstring, TheKey)>
<cfset encryptstring64 = ToBase64(Encrypted)>
you can pass encryptstring64 to the url
and decrypt by .
<!--- Decrypt String --->
<cfset UnlockedSecret = Decrypt(ToString(ToBinary(
ASKER