PHP安全:如何正确的取得使用者 IP?
PHP安全:如何正确的取得使用者 IP?
很多网站都会有侦测用户 IP 的功能,不管是判断使用者来自哪边,或者是记录用户的位置。但是你知道吗?网络上大多数的教学全部都是「错误」的。正确的程序写法可以确保知道访客的 IP,但是错误的写法却可能让网站管理者永远不知道犯罪者的来源。
这次我们单就侦测 IP 的议题来探讨各种错误的写法。
你知道网络上的教学是不安全的吗?
我们先来看一下网络上的教学,让我们 Google 找一下「PHP 取得 IP」,就可以看到许多人热心的教学,我们随意挑一个常见的教学来看看。
以 PHP 为例:
<?php
if(!empty($_SERVER['HTTP_CLIENT_IP'])){
$myip
=
$_SERVER['HTTP_CLIENT_IP'];
}else
if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
$myip
=
$_SERVER['HTTP_X_FORWARDED_FOR'];
}else{
$myip=
$_SERVER['REMOTE_ADDR'];
}
echo
$myip;
?>
以 ASP.NET 为例:
Dim ClientIP As String = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
IF ClientIP = String.Empty Then
ClientIP = Request.ServerVariables("REMOTE_ADDR")
End IF
这是一个很基本的写法、很正确的想法,如果 HTTP Header 中包含「Client-IP」,就先以他当作真实 IP。若包含「X-Forwarded-For」,则取他当作真实 IP。若两者都没有,则取「REMOTE_ADDR」变量作为真实 IP。因为当用户联机时透过代理服务器时,REMOTE_ADDR 会显示为代理服务器 Proxy 的 IP。部分代理服务器会将用户的原始真实 IP 放在 Client-IP 或 X-Forwarded-For header 中传递,如果在变量中呼叫则可以取得真实 IP。
但是你知道吗?网络上 80% 的教学写法全部都是「错误」的。
为什么这样说呢?请大家记得一件事情:「任何从客户端取得的资料都是不可信任的!」
窜改 HTTP Header
「X-Forwarded-For」这个变量虽然「有机会」取得使用者的真实 IP,但是由于这个值是从客户端传送过来的,所以「有可能」被使用者窜改。
举例来说,我写了一个小程序,侦测这些常见的 HTTP Header 判断 IP。并且使用 Burp Suite 这个工具来修改 HTTP Request。
页面上显示目前我目前的 IP「49.50.68.17」,并且其他的 header 是空的。但如果我今天使用 Burp Suite 之类的 Proxy 工具自行窜改封包,加上 X-Forwarded-For 或是 Client-IP header:
修改完毕之后,再到原本的显示 IP 接口,会发现网页错将我窜改的 header 当作正确的数据填入。
使用代理服务器 Proxy 的情况
使用代理服务器的情况下,HTTP Header 会有不同的行为。例如 Elite Proxy 如何隐藏客户端的真实 IP。以下简单介绍几种常见的状况给各位参考。
直接联机
(没有使用 Proxy)
- REMOTE_ADDR: 客户端真实 IP
- HTTP_VIA: 无
- HTTP_X_FORWARDED_FOR: 无
Transparent Proxy
- REMOTE_ADDR: 最后一个代理服务器 IP
- HTTP_VIA: 代理服务器 IP
- HTTP_X_FORWARDED_FOR: 客户端真实 IP,后以逗点串接多个经过的代理服务器 IP
Anonymous Proxy
- REMOTE_ADDR: 最后一个代理服务器 IP
- HTTP_VIA: 代理服务器 IP
- HTTP_X_FORWARDED_FOR: 代理服务器 IP,后以逗点串接多个经过的代理服务器 IP
High Anonymity Proxy (Elite Proxy)
- REMOTE_ADDR: 代理服务器 IP
- HTTP_VIA: 无
- HTTP_X_FORWARDED_FOR: 无 (或以逗点串接多个经过的代理服务器 IP)
实际情况
在我们测试的过程中,通常我们都会让浏览器自带 X-Forwarded-For,并且自行填入 IP。常常会发现有一些网站出现如下的警告…
有没有搞错?「上次登入位置 127.0.0.1」?没错,这个是知名论坛套件「Discuz!」的功能,抓取 IP 的功能也是不安全的写法。也有这样的经验,之前开着 X-Forwarded-For 的 header 到一些网站,竟然直接出现管理者后台!
你觉得只有一般人撰写的程序会有这样的问题吗?其实大型网站也可能会有类似的问题:
先不论为什么 127.0.0.1 会在美国,这样的写法可能会让管理者永远抓不到犯罪者的真实 IP,甚至攻击者可以窜改 header 插入特殊字符,对网站进行 SQL Injection 或者 Cross-Site Scripting 攻击。
正确又安全的方式
「任何从客户端取得的资料都是不可信任的!」
请各位开发者、管理者记住这个大原则,虽然这些 Request Header 可能含有真实 IP 的信息,但是因为他的安全性不高,因此我们绝对不能完全信赖这个数值。
那我们该怎么处理呢?我的建议是记录所有相关的 header 字段存入数据库,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件发生时,就可以调出所有完整的 IP 信息进行人工判断,找出真正的 IP。当然从 header 存入的数值也可能会遭到攻击者窜改插入特殊字符尝试 SQL Injection,因此存入值必须先经过过滤,或者使用 Prepared Statement 进行存放。
可以参考的 HTTP Header(依照可能存放真实 IP 的顺序)
- HTTP_CLIENT_IP
- HTTP_X_FORWARDED_FOR
- HTTP_X_FORWARDED
- HTTP_X_CLUSTER_CLIENT_IP
- HTTP_FORWARDED_FOR
- HTTP_FORWARDED
- REMOTE_ADDR (真实 IP 或是 Proxy IP)
- HTTP_VIA (参考经过的 Proxy)
「黑客思维」就是找出网站任何可能窜改的弱点,从网页上的元素到 HTTP Header 都是尝试的对象。因此身为防御者一定要清楚的知道哪些数值是不能信赖的,不要再参考网络上错误的教学了!
来源:http://devco.re/blog/2014/06/19/client-ip-detection/
PHP安全:如何正确的取得使用者 IP?的更多相关文章
- 【翻译自mos文章】怎么正确的计算一个ip地址的subnet id?
怎么正确的计算一个ip地址的subnet id? 来源于: How to calculate the correct subnet for an interface (文档 ID 1059759.1) ...
- VM中ubuntu已经正确配置了静态IP仍无法上网
情况描述:正确配置了ubuntu的IP,getway,DNS..无法ping通getway. 环境:宿主机:win7 32Bit 虚拟机:ununtu 10.04 VM:9.0.1 build-8 ...
- 微信支付报ip错,怀疑是因为不能正确获取$_Server[addr])ip导致的
报如下错误,应该是本地测试环境不能正确获取客户ip导致的错误 果然 放到服务器上在测试就好了
- nginx反向代理下thinkphp、php获取不到正确的外网ip
在记录用户发送短信需要获取用户ip时,tp一直获取的是内网ip:10.10.10.10 tp框架获取ip方法:get_client_ip /** * 获取客户端IP地址 * @param intege ...
- Java正确获取客户端真实IP方法整理
在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...
- 干货:Java正确获取客户端真实IP方法整理
在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...
- C# 验证IP是否正确简易方法 源代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- Asp.Net Core2.0获取客户IP地址,及解决发布到Ubuntu服务器获取不到正确IP解决办法
1.获取客户端IP地址实现方法(扩展类) using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.ModelBinding; u ...
- TCP/IP 和 Socket 的关系
要写网络程序就必须用Socket,这是程序员都知道的.而且,面试的时候,我们也会问对方会不会Socket编程?一般来说,很多人都会说,Socket编程基本就是listen,accept以及send,w ...
随机推荐
- HDU 5669 Road(线段树建树)(分层图最短路)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5669 [分析]线段树建树+分层图最短路 #include <cstdio> #includ ...
- UGUI的优点新UI系统四 开源
UGUI的优点新UI系统四 开源 新UI系统是开源的,所以开发者可以看到新UI系统实现的源码,并加以修改和使用. 开源授权协议——MIT/X11 Unity所搭载的新UI系统,是在开源授权协议MIT/ ...
- [BZOJ4815][CQOI2017]小Q的表格(莫比乌斯反演)
4815: [Cqoi2017]小Q的表格 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 832 Solved: 342[Submit][Statu ...
- 【动态规划+二分查找】POJ2533&POJ1631最长上升子序列(LIS)
POJ2533裸的LIS,时间复杂度为O(n^2) #include<iostream> #include<cstdio> using namespace std; +; in ...
- java 的环境搭建
java.JDK 的搭建__本人是在360里下载的.也可以去其它的网站. java.jdk官网地址下载: https://download.oracle.com 二.也可以下载地址:http://do ...
- datatable无法设置横向滚动条(设置无效)
datatable设置横向滚动条无效 js如下: 页面如下: 设置 scrollx 属性为true时,还需在 table 添加 style="white-space: nowrap; &qu ...
- 条件注释判断浏览器<!--[if !IE]>
<!--[if !IE]><!--> 除IE外都可识别 <!--<![endif]--><!--[if IE]> 所有的IE可识别 <![e ...
- 20172333 2017-2018-2 《Java程序设计》第3周学习总结
20172333 2016-2017-2 <Java程序设计>第3周学习总结 教材学习内容总结 1.String类.Random类.Math类.NumberFormat类和DecimalF ...
- QPS相关的概念收集(吞吐量(TPS)、QPS、并发数、响应时间(RT))
一.概念: 1.响应时间(RT) 响应时间是指系统对请求作出响应的时间.直观上看,这个指标与人对软件性能的主观感受是非常一致的,因为它完整地记录了整个计算机系统处理请求的时间.由于一个系统通常会提供许 ...
- 新浪微博宋琦:PHP在微博优化中的“大显身手”
摘要:2013中国软件开发者大会编程语言与工具专题论坛中,新浪微博架构师宋琦介绍了PHP在新浪微博中的应用,并且分享了很多微博主站所做的性能优化的工作. [CSDN报道] 2013中国软件开发者大会( ...