The $_SERVER superglobal is weird in PHP because some of it is provided by the user, and some is provided by the environment. You should always validate user inputs in any script. So let’s take a look at the possible elements of this array with an eye towards which are safe and which are not.
argc Only shows up when the script is invoked from the command line. If anyone who is logged into your machine can invoke the script this is a point of attack.
GATEWAY_INTERFACE Provided by the CGI interface - safe. SERVER_ADDR Provided by the OS or webserver - safe. SERVER_NAME Provided by the webserver - safe. SERVER_SOFTWARE Provided by the webserver - safe. SERVER_PROTOCOL Set by the webserver, though it’s possible for the user to choose a protocol. The value itself isn’t under user control though - so safe.
REQUEST_METHOD As above, the user can control which method they use, but the string itself is set by the webserver software. REQUEST_TIME Set by the Zend engine. Safe. REQUEST_TIME_FLOAT Set by the Zend Engine. Safe. QUERY_STRING User controlled, not safe. DOCUMENT_ROOT Provided by the webserver - safe. HTTP_* Any server variable starting with HTTP_ is under the user’s control and is not safe. HTTPS Set by the webserver - safe. REMOTE_* All of these come from the user’s machine. They aren’t easily spoofed, but it can be done - not safe. REDIRECT_REMOTE_USER As above. SCRIPT_FILENAME Set by the webserver or shell. Safe. SERVER_ADMIN Arises from the webserver config. Safe. SERVER_PORT Provided by the webserver. Safe. Usually 80 or 443. SERVER_SIGNATURE Provided by the webserver. Safe. PATH_TRANSLATED I’m not sure. SCRIPT_NAME Safe. REQUEST_URINot safe. PHP_AUTH_DIGESTNot safe. PHP_AUTH_USERNot safe. PHP_AUTH_PWNot safe AUTH_TYPE I don’t know for sure. PATH_INFONot safe. ORIG_PATH_INFONot safe. REDIRECT_STATUS Set by the webserver, safe. All other REDIRECT_* variables are not safe.
PATH_INFO used by different frameworks like CodeIgniter to determine which controller, model and arguments to invoke. Of course users can set some of the variables, but it doesn’t mean that it’s not safe. It’s the same to say that _GET and _POST not safe (of course it not safe), any input not safe, even the life is not always in safe. It’s only the matter how good you’re checking the data.
What’s “PHP Gotcha! #(\d*)”? PHP in details, or PHP for newbies?
REQUEST_METHOD As above, the user can control which method they use, but the string itself is set by the webserver software.
This one can be considered not safe too. Usually it’s get, but with help of cURL or other utilities it can be changed easily.
Generally I agree. Just be careful that you’re escaping appropriately for the data’s destination. The way we escape for a shell command, for example, is different than the way we escape for SQL, which is different than the way we escape for JSON, which is different than the way we escape for HTML, and so on. There’s no such thing as a general, all-purpose escaper. If you’re about to use data in SQL, then you should merely addslashes (or, even better, prepare). And if you’re about to use data in HTML, then you should merely htmlspecialchars. But it doesn’t make much sense to use the two together.
Fully agree on it. However for json you don’t need to escape manually, you can use json_encode, _decode for that. For SQL it’s either prepare, or something like mysqli_real_escape_string. For HTML it’s only htmlspecialchars, but you’re right. Generally, it’s like in my previous post, htmlspecialchars and addslashes (and probably htmlentities).
But never together, was my point. addslashes(htmlspecialchars($string)) is something you should almost certainly never do. If this string is destined for SQL, then htmlspecialchars shouldn’t be called. Or if this string is destined for HTML, then addslashes shouldn’t be called.
I agree. You use htmlspecialchars on data read FROM a database when outputting it into the HTML.
There is no real need for addslashes. The correct function to use with the now nearly dead mysql_ interface was mysql_real_escape_string.Now with mysqli_ or PDO you use prepare/bind and keep the data completely separate from the SQL.
For validating input before writing to the database you make sure that the content is valid for whatever the specific field is allowed to contain - casting, built in functions such as is_numeric(), filters or where none of those are available regular expressions.
Something to consider is that the server itself handles the large majority of website security.
A crude example of that would be even perfectly “sanitized” data is rendered useless if I can modify (or create) an .htaccess file on your site, or if I can force the script to throw an error to the screen, giving me hints on the structure, environment, etc.
Not to mention overlooked things such as file permissions and such.