A brief into to HTTPs natural insecurities:
You have probably heard this term many, many times. You probably even know that it means Hyper Text Transfer Protocol, but how much more than that do you know? HTTP does a heck of a lot more than just send a returnable request to a URL. HTTP is responsible for sending this data (among many other things):
-User Agent (browser type)
These are just a few of the many things that are sent with every HTTP request. These values are generated by your browser and sent off; the server can read it since it is a standard protocol that they both conform to (and amazingly a standard Microsofts IE has managed to stick to). Did you catch the security hole that I made apparent in the last sentence? I just said that the browser sends off this data. Since it is client side data, the user can make it whatever they want to. While no major browsers comes stock with advanced editing of this data, there is an extension for Firefox called Tamper that can do this very well.
Another inherit insecurity is that HTTP is a stateless connection, meaning there is no way of knowing that you are talking to the same person over a number of requests. This means that HTTP provides no sure-fire way to know you are talking to the same person. While stated connections exist, they just use complex methods to make it darn near impossible to jump in. In theory, the universe is stateless. In application to computers, electrons have to travel across a wire to another place. Since there is no possible way to ascertain the origin of the electron, a truly stated connection is physically impossible. But I am getting into physics here, back on track.
There is no sure-fire way to secure these types of things since every script is different. But the two best tips I can give you are:
Many sites use the referrer as a validation tool to confirm they started form the site. The misconception of this is that this data comes from the server. As mentioned before, HTTP is a stateless connection. This means that there is no way to know where a user was last. Referrer data is sent from the browser to the server via HTTP, it has no real relation to where the last site was except for the browser being nice enough to correctly state it. This being said, it can be very easily edited.
The most dangerous implementation I have seen of this is a method around using Paypal IPN. Instead of actually validating the data, they just check if the referrer is Paypal to see if it is legit. This can be easily hacked so that the user modified his referrer and appears to have come from paypal. Without paying anything, the script will assume he passes and give him the paid credentials.
Another Common misconception is that POST data can only come from legit sources. This is not true, POST data can be attached on to any request the client chooses to. When passing hidden variables via post, be aware that they can very easily be forged between point A and point B. While there are countless examples of this, a good example of one is post editing on forums. When you edit a post, it is stored on a hidden field which post ID you are going to edit. Under the assumption that this can not be edited, some people do not validate this. The user can then switch the POST data and edit any forum message he wants to.
The way around this is to validate the data at the end. It shouldn't matter what anyone puts in there, nothing should be able to hurt your system.
MIME Data for Uploads
While this does fall under POST data insecurities, most people do not put this together. Lots of upload sites validate their files via MIME type. Little do they know that the following about a file is passed via POST:
What upload box it came from
An example of me trying to upload zlib1.dll to a server would be
-----------------------------3118758771150\r\nContent-Disposition: form-data; name="userfile"; filename="zlib1.jpg"\r\nContent-Type: application/x-msdownload\r\n\r\nMZp
Now, if I wanted to upload this to a server which only goes off of MIME type, I would just change application/x-msdownload to image/jpeg. The server would then read the MIME type and let that DLL right though. The same thing can go for PHP files or ANY other thing you want on there.
There are two ways to get around this. One is to check extension; to correctly do this you must get the letters after the last period. While this does not guarantee the files validity, it ensures that it can do no harm*. The most secure way is to check if the file is actually a valid file of that type. ImageGD provides checks for some image formats, there should be third party extensions for most anything else. This method gets cumbersome for the little extra good it adds, I tend to not do this unless a client specifically asks to.
*Nothing is ever (ever) completely secure, server errors could play a role in a bad file actually doing harm. As for the image virus talk, a valid image could do the same thing since there is no real malicious code in the image; it just triggers the virus which is already on the clients machine.
This one is not sent by HTTP, but is still worth talking about nonetheless. The clients IP is not a good way of validating users due to a few reasons. The first is that ISPs, as a way to save bandwidth, rout requests in such a way that the IP of a user may be different in two different requests.
The next is that most IPs are shared by many users. Unless you have a dedicated IP, multiple computers (most notably on a network) may share the same external IP address. Lets say Bob is in his room on your custom made forums which uses IP to validate sessions. Jimmy is in the basement and loges on to the same site. If you use IP alone to validate users, Jimmy could easily hijack Bobs session and become Bob to the server. Now Jimmy and Bob got in to a fight that day, Jimmy promptly posts obscene messages on the forum and gets Bob banned.
A more likely example would be an extremely popular site at a computer lab. Go into a larger computer lab at any given time and you will probably have a lot of people on facebook. That would become a really big mess because the entire computer lab may function on as little as one IP address. If facebook validated by IP, the second person to get on could accidentally hijack your session. Lets hope he is nice enough to hit log out and log you both out.
As you can see, validating logins by IP is not a good way. Chapters of books speak of how to do this well, I will not cover this due to its size. I recommend reading Advanced PHP Programming by George Schlossnagle.
I do not claim to cover every type of attack, there are certainly more ways to forge data. The only way to be sure of security is to validate every piece of data given by anything from the outside.