• 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

    页面上显示目前我目前的 IP49.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/

  • 相关阅读:
    最原始不用代理服务器的设置
    实现开启和关闭android移动网络(转)
    Android快捷键
    如何终止java线程
    电脑上安装的android虚拟机,能进行基站定位和GPS定位吗?要怎么做才能定位?(转)
    C语言标量类型(转)
    Android种 adb是什么(转)
    ☆☆在Eclipse中编译NDK的so文件(普通安卓项目转换为NDK项目的设定)
    androidSDK也要配置环境变量(转)
    Android控件系列之RadioButton&RadioGroup(转)
  • 原文地址:https://www.cnblogs.com/lovebing/p/6823826.html
Copyright © 2020-2023  润新知