
It was some days ago when, working on my practice project - a simple file uploader in PHP, I wanted to unable the users to delete any of the files they had previously uploaded on the server.
My first thought was to create a “delete” link, after each file or folder on the list displayed to the user.
This implied of course using the GET method to send the file id, in order to appear a message asking the user either to confirm the deletion or to keep the file.
<a href="index.php?show_dltfile=4">[x]</a>
To do that I would be using another set of links and the GET method once again, this time sending the id of the file together with the confirmation for the action.
<a href="index.php?confirm_dltfile=4">Delete</a>
<a href="index.php?">Keep</a>
The first of these links would eventually result in the call of the appropriate functions to delete the file.
It’s simple and it works, but at the same time it’s quite wrong.
Whilst in the first case I used the GET method only to show the confirmation message, in the second one it was used to delete a file located on the server. This practice can be proved dangerous especially if used in procedures like file deletion or for the process of sensitive data.
GET is a safe method. It should be used only to retrieve data and never to alter it. GET will send the information given as part of the URL (making it visible to the user and but also giving him the capacity to bookmark the page). This is pretty useful when we want to display a specific content and we want the user to be able to quickly access the information.
However if there is a need for a user to request an action that is considered “risky” and that changes the state of the server, it is preferable to use the POST method. Makes it possibly easier to sleep at nights ![]()
This one is pretty old. I didn’t first publish it, thinking it was way too common and simple, but, now that it happened to re-read this text, I finally realised it actually contains some thoughts and information one could find useful. Credit goes once again to my friend Dionyziz for sharing his knowledge and experience with me.
Edit:
A while after I posted this text, it happened to find another great example to demonstrate my point above, a bit more simple this time:
When a user registers on www.deezer.com , he is soon prompted to activate his account through an email sent to the account he has provided (a standard procedure in most user registration procedures nowadays). On the email the user receives there is a link similar to http://www.deezer.com/confirm.php?email=name@mailserver.com
As you can see, they use the GET method to tell their script that the user has confirmed the existence of his email address.
Lets suppose now that one creates a new account, and that this time he provides a non-existent email. none@nowhere.com for instance. The confirmation mail will never arrive on a valid email address. However, if the user then visits the page http://www.deezer.com/confirm.php?email=none@nowhere.com, the script will still confirm his registration and email validity. In this case it might not seem as a real security risk, but there might be other cases where the same thing could prove destructive for a site’s security.
Well, that’s all for now.
Note that the information above is given for educational purpose only and is not to encourage anyone into acts of questionable decency. (Deezer.com will soon be notified about the issue)
Στη μάνα σου το είπες?
Όχι, αλλά νομίζω θα πανικοβληθεί λίγο αν το μάθει
The Deezer.com issue is not really a GET/POST issue. They should be using GET indeed to verify your e-mail address (as there is no other technical way of having you open POST links in e-mails). Furthermore, even if it were POST, it wouldn’t have solved the problem, as one could easily craft a POST request to their page by simply incorporating a custom HTML form.
The correct way of solving this would be to generate a random hash for every user account (for example a 32-character-long hex string) that would be passed as a parameter along with the e-mail address in the link. That way, if you don’t get the e-mail, you won’t be able to know the secret hash, and hence won’t be able to fake an e-mail validation.
Seems like Deezer.com has read your blog post and fixed the issue, but they fixed it wrong. The confirmation link now looks like this:
http://www.deezer.com/confirm.php?email=ZGlvbnl6aXpAZ21haWwuY29t&c=1
Security through obscurity! Any geek would easily be able to find that this is a base64-encoded e-mail address; how lame. Apparently they don’t realize that encrypting the e-mail address won’t help them, as one can easily decrypt any kind of encryption since they’re able to have access to as large a dataset they like (by making as many accounts as they like). The only way to solve this properly is through a hash.
dionyziz@orion:~$ php -r “echo base64_decode( ‘ZGlvbnl6aXpAZ21haWwuY29t’ );”
dionyziz@gmail.com
So yeah. Thanks for the post! I’ll also let the Deezer.com guys know about the second security issue.
heheh, right, it’s a stupid-get-usage-issue
Actually I never really liked email confirmation for this type of sites, it just slows you down. Especially if the mail goes to spam for some reason, or doesn’t get delivered at all. Or/And if you have to put unreadable Captchas, The Deezer guys didn’t answer me actually when I told them, and took them quite a while (years? :P) to “fix” this.
(how do you like the new blog theme btw? ^^)
It’s awesome (even though I use RSS :-))