你是否能够伪造IP地址?测试IP地址是否安全?

10

我在一个网站上添加了一些额外的功能,员工可以使用,但是不允许客户查看。

所有员工都将在一系列域上。

我的做法是像这样获取用户IP:

$user_ip = gethostbyname($_SERVER['REMOTE_ADDR']);

我使用gethostbyname获取用户所在域名的所有IP地址数组。

然后,我检查用户是否在其中一个域名上:

in_array($user_ip,$allowedIPS)

如果用户在其中一个域上,则可以看到用于内部使用的其他功能。否则,他们只能看到面向公众的内容。

我的问题是,这是否安全?或者有人可能欺骗他们的IP地址,以似乎他们在我们的域上,并获得访问这些功能的权限吗?


@Shrapnel上校,我认为这不是问题所在。 - RobertPitt
$_SERVER['REMOTE_ADDR'] 是用户的 IP 地址,您正在对其使用 gethostbyname,如果我没看错的话。 - Your Common Sense
@Col. Shrapnel,我明白你的意思了。我之前使用gethostbyname来从域名(例如example.com)获取IP地址,我想我不必要把它添加到REMOTE_ADDR中。谢谢。 - JD Isaacks
10个回答

9
我的问题是,这安全吗?或者有人可能欺骗他们的IP地址以显示他们在我们的域上并获得访问这些功能的权限吗?
不,除非他们还可以访问允许IP地址之一的网络,或者其中一个IP地址下的任何允许机器被攻击并代理流量。
在您的情况下,似乎已经足够好了。好吧,除了特权用户将不被允许从其他IP访问内容,除非使用某种VPN。
请注意,IP欺骗通常具有与您使用的不同的含义。它仅意味着伪造数据包的源地址。这本身是毫无价值的,因为要访问服务,还必须接收来自服务器的响应。即使是这种意义上的“IP欺骗”由于更好的路由而变得很少见。

1
是和否 - 如果您只想更改某些内容(并已知道要提交的正确请求),则不一定需要回复。这将防止探索,但不一定会阻止开发利用。 - Amber
1
@Amber 我所指的响应是SYN/ACK数据包,而不是HTTP响应... 它不会到达那一步。 - Artefacto
1
虽然这可能超出了问题的范围,但如果您有恶意,就有可能使它走得更远 - TCP序列号是可预测的,因此您可以预先发送一个ACK以响应您知道另一端服务器将要发送的数据包。 - Amber
@Amber 那大部分早在多年前就已经解决了(参见RFC 1948),即使那时你也需要严重不当行为的路由器... - Artefacto

8
无法通过开放互联网欺骗TCP连接,由于三次握手。但是,可能可以使用CSRF访问此功能。
PHP直接从Apache的TCP套接字中提取$_SERVER['REMOTE_ADDR'],因此无法受到攻击者的影响。是的,我已经查看了这段代码。

所以如果我理解CSRF。一个拥有允许IP的员工访问不同网站,在那里有人使用CSRF来欺骗员工的浏览器,以访问带有隐藏功能的页面。因此,通过员工的IP获得访问权限。但攻击者仍然无法看到这些功能,对吧?因为这是一种盲目攻击。他们只能盲目地尝试“使用”这些功能。对吧? - JD Isaacks
1
@John Isaacks 这是正确的。但是,“使用csrf欺骗”是不恰当的措辞。CSRF攻击使用<img>标签生成GET请求和<form>,当页面或iframe被查看时自动执行.submit()。我仍然会防范CSRF以防止内部攻击。这可以简单地检查referer来实现。 - rook

3

如果不是微不足道的话,IP欺骗是可能的。

为什么不让你的员工登录以获得访问仅限员工的功能呢?


当你说“可能,如果非平凡”的时候,你的意思是,这不适合存储像银行账户之类的敏感信息,但对于像产品供应商之类的不太敏感的信息来说是可以的吗? - JD Isaacks
1
一个非常好的理由是支持成本。拥有自己凭据的应用程序可能会快速变成一件大麻烦事。如果可以与现有的 LDAP 或其他身份验证服务器连接,那就没什么问题了;但如果不能,它可能会产生大量持续的工作。密码丢失、更改、需要添加新员工,需要删除离职员工等等......听起来不像什么,但在中型或更高规模的公司中,随着时间的推移,这肯定会累积起来。 - Serapth
[a] 如果这是一个他们不经常使用的系统,或者他们在一天内从多台计算机访问该系统,那么每次都要登录就很麻烦。 [b] 他将需要提供注册、登录、"忘记密码"和"忘记用户名"页面。 - egrunin
1
@John Isaacks - 是的,就是这个意思。 - egrunin
1
-1 在公共互联网上无法欺骗TCP连接。 - rook

2
我不认为这是可能的,因为当您向服务器发出请求时,实际上是要求您的ISP向服务器发出请求。
只要您验证ISP转发给您的所有HTTP元数据,例如X-FORWARDED-FOR和代理元数据,您应该能够保持紧密的系统。
这是一个可能有助于您理解我的图示: alt text 阅读此处以获取更多信息。 http://www.astahost.com/info.php/hacker39s-view-easy-spoofing-ip-address_t13807.html

我想你把OSI堆栈的网络层中的路由(routing)和应用层中的代理(proxying)混淆了。现在很少有ISP使用真正的代理了。 - Daniel Pryden

2
如果您要这样做,请使用Apache配置,而不是代码。您基本上正在重新发明内置功能。
至于直接问题,正如其他人所说,欺骗IP是可能的,但并不容易。也希望您没有任何不安全的接入无线点。
编辑:Apache访问控制说明。这是我假设您正在使用Apache,因为使用PHP,如果您实际上正在使用IIS,则仍然是一种配置驱动的设置,但在执行上显然不同。

谢谢,Apache版本只能允许整个页面访问,对吧?我想要在页面上允许特定的功能。 - JD Isaacks
是的。从最佳实践来看,与其混合使用安全和非安全的网站,你几乎肯定会更受益于拥有一个安全的网站。否则,我向你保证,在系统复杂度增加时,你会在某个时候泄露机密信息,或者带来后续的维护噩梦。 - Serapth

0

我在这个问题上点赞了ROOK。你不能欺骗TCP连接并仍然从进行欺骗的同一台机器访问你的网站。为什么?因为你的Web服务器将会对欺骗的IP地址做出响应(最初),以尝试建立套接字连接(TCP三次握手)。

如果你有两台计算机(A和B)位于两个不同的公共IP地址,并且你使用其中一台计算机(A)欺骗或发送数据包到你的Web服务器,使用B的IP地址,以便当你的Web服务器回复时,它会将数据包发送到B。

如果欺骗调用中使用的IP地址是你子网内部的,则内部工作站将收到未初始化的TCP SYN数据包的TCP ACK数据包并拒绝或忽略它们。我不知道任何TCP/IP堆栈实现会尝试针对ACK数据包完成三次握手;这违反了标准协议。

欺骗是一种UDP洪水攻击技术,攻击者使用虚假的IP地址进行DoS(拒绝服务)攻击,以尝试隐藏他们的踪迹。

希望这可以帮助你。


0

$_SERVER['REMOTE_ADDR'] 是由您的 Web 服务器提供的,直接欺骗它是不可能的。我唯一能想到的解决方法是通过允许的 IP 地址之一代理连接。


0
当我们面对类似的问题时,我们得出结论:如果用户通过http访问我们,我们不能完全依赖其IP地址,因为他们可能使用代理。但是https始终是直接连接;它不允许代理,因此我们可以确定我们看到的IP地址是正确的。因此,我们基于IP地址将我们的用户锁定,并且他们必须通过https访问网站(当然还要登录到他们的账户)。
你的情况听起来有点不同,但我认为上述内容对你也应该有用。
即使你不按照这个确切的路径进行,你仍需要注意代理。理论上,代理可以允许任意数量的不同用户从单个IP地址访问您的站点,因此,如果您在允许的地址列表中添加了代理的IP,则会打开一个安全漏洞,因此您需要确保任何添加到列表中的IP地址都是合法的(这就是https可以帮助的地方)。
此外,如果您的用户是从家用电脑访问的,请注意他们的IP地址可能会随时间而变化。大多数ISP将向其客户分配动态IP,这些IP可以重新分配,这意味着每次连接到互联网时,都有可能获得不同的IP地址。如果是这种情况,则没有欺骗行为,但您仍然无法通过IP地址可靠地识别用户。

0

正如之前所讨论的,TCP在互联网上进行IP欺骗是不可能的,但存在攻击Web应用程序的其他方法。

请注意,许多Web实现(无论是使用PHP还是不使用)都容易受到X-Forwarded-For注入的攻击。 X-Forwarded-For是一个HTTP头,它指定了当请求通过代理时的原始IP地址。Apache2中没有验证(可能的),在某些配置中,这就是传递给PHP的REMOTE_ADDR的IP地址。因此,是的,IP欺骗是通过这种方式实现的。

假设攻击者设置一个请求头X-Forwarded-For,并将其值设置为127.0.0.1。如果HTTP服务器的配置允许此操作,则127.0.0.1将传递给PHP-FPM的REMOTE_ADDR,而不是实际攻击者的IP。当我浏览互联网时,我总是添加此标头来测试网页的安全性。其中很多在我的IP设置为本地主机时会显示附加的管理工具栏。即使是stackoverflow在测试阶段也存在此错误,一些主要软件今天仍然默认情况下“容易受到”此攻击。


-1

一切皆有可能,但成本始终是个问题。
在大多数情况下,这种欺骗行为并不值得。


6
可能是因为你的语法很糟糕。 - davr
@davr - 那不应该是“teh suk”吗? - Joel Etherton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接