Forum Moderators: coopster
if(isset($_SERVER['REMOTE_ADDR']) && strlen($_SERVER['REMOTE_ADDR']) > 0)
echo $_SERVER['REMOTE_ADDR'];
else
echo 'Unknown.';
register_globals is Off.
Can I trust that $_SERVER['REMOTE_ADDR'] will always be either a valid value set by the server, or blank?
I want to be sure it's impossible for a user to inject a value through the query string (or any other way) that would cause something other than the real IP to be displayed on the page.
Do I need to use anything like htmlspecialchars() or strip_tags()?
I know this won't detect proxies, but I don't want to deal with anything like HTTP_X_FORWARDED_FOR, which apparently can be easily spoofed.
I'll be satisfied with $_SERVER['REMOTE_ADDR'] as long as I know it might be right or wrong, but never maliciously spoofed.
----
Can I assume that all the various $_SERVER[] variables are always safe to use, and can't be manipulated from the outside?
from what I have seen I don't think REMOTE_ADDR is possible to inject anything but a spoofed ip. I would think injecting js or some such cause some issues with the routing of the request but I'm sure someone will figure something out.
I guess it depends on what you are doing with it but if you are just spitting it back at them then it shouldn't be a huge issue.
if you are writing $_SERVER data to anywhere then standard precautions should apply depending on where it is being written to.
Can I assume that all the various $_SERVER[] variables are always safe to use, and can't be manipulated from the outside?
No. As stated, many are user-supplied. In the case of REMOTE_ADDR you can use a regular expression to check for an IP address. If it doesn't look like one, discard it, send an error message, log the issue, ... however you decide to handle it. Bare minimum, I strip_tags() before using htmlentities() to display the information.
Such as what? If your writing it to a datebase, but the user is unaware that you're writing their ip address to a database on completion of a form or something. What are the standard precautions?
:)
If you are writing it to your database, use the appropriate functions such as mysql_real_escape_string [php.net] for a MySQL database.
The address might be faked
... faked by the user, therefore user-supplied. Do yourself a favor and treat it as such.
'REMOTE_HOST' is only available if "HostnameLookups" is set to "on" in apache's configuration.
This is not entirely true. But don't feel bad, there are very few people that realize if you use Allow [httpd.apache.org]/Deny directives with a partial domain-name match Apache will indeed populate the
REMOTE_HOSTenvironment variable, regardless of the setting of the HostnameLookups directive. This happens because it causes Apache to perform a double reverse DNS lookup on the client IP address.
The address might be faked
... faked by the user, therefore user-supplied. Do yourself a favor and treat it as such.
This is not entirely true. But don't feel bad
The mistake I apparently made was assuming, without thinking about it, that the server has an independent means of knowing the remote IP, sort of like Caller ID. But if I understand correctly now, it doesn't. It's sent as part of the request. It's almost always reliable because the requestor can't get a page back if it provides the wrong IP or injection data where the IP should be. But a malicious requestor might not care about getting a page back. Without looking at the Apache source code, I'd bet that it does some validity checking before assigning the value to REMOTE_ADDR, but I won't count on that.
On closer examination, a number of the $_SERVER variables are similarly user-supplied. If I'd entered into this with my attention focused on HTTP_USER_AGENT, for example, I would have known right away that some of these can't be trusted because I've spoofed that on occasion myself.
So I took this opportunity to get introduced to data scrubbing, which I haven't needed to do until now, and came up with this (comments and criticism welcome):
if(isset($_SERVER['REMOTE_ADDR']) &&
(strlen($_SERVER['REMOTE_ADDR']) > 0) &&
(ereg('[^0-9\.]', $_SERVER['REMOTE_ADDR']) === false))
{
// This variation should be bulletproof, but ereg has already rejected input
// containing anything except numerals and periods, so it's also unnecessary.
// echo htmlentities(strip_tags($_SERVER['REMOTE_ADDR']), ENT_QUOTES);
// Thus, this should do.
echo $_SERVER['REMOTE_ADDR']);
}
else
echo 'Unknown';