People who exploit sites are well beyond my knowledge; I wouldn't even know where to begin testing other than just the basics.
I just try to cover my bases.
- Plenty of reading online on PHP security and configuring the server properly (including php.ini file, such as having register globals off, etc).
- If you're on shared hosting, you'll have to be extra careful with logins/authentication and where you store your sessions. Use session_regenerate_id() when escalating privileges.
- Validate ALL input, and sanitize all output with something like html_entities()
This point is one of the most important. Never trust anything you didn't explicitly define yourself, even in the $_SERVER superglobal. If you have a form, and are expecting a zip code, validate it before going any further. If you have a one-line text input as a form field, ensure there are no newlines as there is no reason for there to be. Etc. If you validate every input field, malicious users can manipulate your form, and post it to your server and you'll be fine. Never rely solely on client-side validation.
Use mysql_real_escape_string() on anything that goes into Mysql (or similar function if you're using another db)
Ensure images are images by using exif_imagetype() - don't just rely on the extension or mime type.
When handling file uploads, ensure size, file type, extension, etc are all okay. If the user has any sort of control over the location of where the file will be stored, check that path before you upload. For example, I always ensure '..' is nowhere in the path. Use is_uploaded_file() before actually moving the file anywhere.
Be careful with your errors. With SQL injection, malicious users will try to break your code and get error messages. This will allow them to determine what your field names are and other sensitive information. Make sure that if something does break, you handle it properly rather than having your code break and spew out error messages.
Some other good functions are strip_tags(). I use htmlspecialchars() when grabbing info from the URL.
If you're expecting an id value to use in a query like this:
WHERE id = 7
and you grab the id value (in this case 7) using $GET['id'], then you can use
$id = (int) $_GET['id']
or verify that it's valid using ctype_digit() before putting it in your database.
And here's a great article on sql injection with plenty of examples. If you use mysql_real_escape_string(), you should be fine though.