12

In PHP I retrieve a user's IP address ($_SERVER['REMOTE_ADDR']) to use it in some MySQL queries, but I do not validate them to be true IP addresses.

Should I validate user IP addresses before using them in MySQL queries, or will they always be valid IP addresses when I use $_SERVER['REMOTE_ADDR']? I'm trying to prevent an SQL injection.

If I should validate, which PHP function do you recommend to use? Should I send the IP address through mysqli_real_escape_string(), etc?

Andrei Botalov
  • 5,267
  • 10
  • 45
  • 73
Hope4You
  • 333
  • 3
  • 10
  • 1
    There are cases when this variable is passed not from Apache but some rough script and eventually can be overwritten by adding other headers which value is not validated, like forwarded-for, so you have to actually parse it that it's valid ip address. – Andrew Smith Jul 26 '12 at 10:27

3 Answers3

14

You should use prepared statements to prevent SQL injections. Take a look at this question.

However, $_SERVER['REMOTE_ADDR'] should be a valid IP address as it comes from the server, as verified by the TCP handshake. See this question for an extended discussion on this.

Oleksi
  • 4,809
  • 2
  • 19
  • 26
  • 3
    Only variables prefixed with `HTTP_` are pulled from the HTTP header (hence the prefix): http://stackoverflow.com/questions/6474783/which-server-variables-are-safe – msanford Jul 25 '12 at 16:00
  • 1
    @msanford My mistake. I've updated my answer accordingly. – Oleksi Jul 25 '12 at 16:30
  • @Oleski Yes, I always use prepared statements, etc to validate user inputs, this was just my one exception. Thanks for the help. – Hope4You Jul 25 '12 at 19:02
  • 3
    As a general note, I do not recommend saying something is "safe". That's too broad. You have to ask: "safe for what purpose?". To pick a silly example: I may trust my sister with my kids but not my car keys, and trust my neighbor with my car keys but not my kids. Get yourself into the habit of, whenever you say "safe", articulating what purpose it is safe for -- that will help you steer clear of security problems. – D.W. Jul 25 '12 at 19:23
6

From this page it looks like the REMOTE_ADDR element of the $_SERVER array is populated by the server as opposed to being passed by the client, so it should (absent any bugs) be a reasonable assumption that it is the IP address of the remote client (or a proxy server acting on behalf of the remote client).

As @Lucb1e commented below some elements of the $_SERVER array come from the client and should be less trusted

As @Oleksi mentions not trusting input to SQL queries is a good idea in general.

Rory McCune
  • 60,923
  • 14
  • 136
  • 217
  • "_parameterization of queries rather than the use of prepared statements_" performance? – curiousguy Jul 25 '12 at 18:24
  • 1
    +1 I agree. Also I have verified that at least with PHP+Apache this variable comes from Apache's socket and cannot be influenced. Also CSRF is still a problem with an ip address check. – rook Jul 25 '12 at 18:38
  • $_SERVER also contains data inputted by the user: all HTTP headers, the query_string, and perhaps others. You shouldn't trust $_SERVER["HTTP_REFERER"] for example. The remote address should be fine though, as said by others. – Luc Jul 25 '12 at 19:52
  • 1
    @Lucb1e ta, updated to reflect that – Rory McCune Jul 25 '12 at 20:07
  • @curiousguy sure could an issue, somewhat out of scope of the question to try and address that though (also I'm not qualified to answer on the performance front :) ) – Rory McCune Jul 25 '12 at 20:07
  • @RoryMcCune What is "parameterization of queries" -- code example? – Hope4You Jul 26 '12 at 14:00
  • @Hope4You if you look at the answer from Oleski the Stackoverflow page that he links to has information about parameterization of queries... – Rory McCune Jul 26 '12 at 18:35
  • @RoryMcCune aren't prepared statement and parameterized query the same thing? http://stackoverflow.com/questions/4712037/what-is-parameterized-query – Hope4You Jul 26 '12 at 21:14
  • @Hope4You actually good point, I think I was confusing prepared statement and stored procedures in my mind (D'oh) :op I'll edit my answer.. – Rory McCune Jul 26 '12 at 21:28
3

REMOTE_ADDR is determined by the receiving TCP stack - it's not data 'sent' by the client. Neither IPv4 nor ipv6 use characters which are unsafe / delimit expressions in SQL.

However there's very little point in storing the IP address (i.e. xxx.xxx.xxx.xxx or xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx) the numeric value is far more useful and requires less storage - see the manual for the inet_aton() and inet6_aton() functions.

symcbean
  • 18,278
  • 39
  • 73