zoukankan      html  css  js  c++  java
  • 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/

  • 相关阅读:
    Oracle 11g SQL Fundamentals Training Introduction02
    Chapter 05Reporting Aggregated data Using the Group Functions 01
    Chapter 01Restriicting Data Using The SQL SELECT Statemnt01
    Oracle 11g SQL Fundamentals Training Introduction01
    Chapter 04Using Conversion Functions and Conditional ExpressionsConditional Expressions
    Unix时代的开创者Ken Thompson (zz.is2120.bg57iv3)
    我心目中计算机软件科学最小必读书目 (zz.is2120)
    北京将评估分时分区单双号限行 推进错时上下班 (zz)
    佳能G系列领军相机G1X
    选购单反相机的新建议——心民谈宾得K5(转)
  • 原文地址:https://www.cnblogs.com/lovebing/p/6823826.html
Copyright © 2011-2022 走看看