如何限制对PHP文件的访问?

时间:2012-07-13 08:48:34

标签: php http

我想限制访问我服务器上的PHP文件。此PHP文件从HTTP GET请求获取数据并将其附加到文件。简单。但我不希望执行这个PHP文件,除非从我开发的智能手机应用程序中生成HTTP请求。

我不想单独验证每个用户。我希望我的应用程序,只有我的应用程序能够将请求发送到PHP文件。我不希望人们在浏览器中输入类似形式的请求(http://www.mydomain.com/check.php?string=blahblahblah)并产生同样的影响。

我考虑过检查HTTP_USER_AGENT或其他一些变量,但我担心它们也可能很容易被欺骗。我可以将一个密钥嵌入到我想要的应用程序中,但该密钥也可能会受到损害。

下一步是让服务器向我发送一个我正确回应的挑战。或者我甚至可以看看PKI。但是,这是一个相对简单的方法,因为我并不是想保护任何真正有价值的东西,只是为了防止轻微的破坏行为。

我想在这里重新发明轮子吗?是否已经有一种简单,经过验证的方法可以做到这一点?

7 个答案:

答案 0 :(得分:4)

FWIW,这是我能想到的最安全的方法,而不会严重影响性能 - 本质上是RESTful(ish)方式,因为需要进一步提升它需要存储在服务器上的多个请求和连接状态信息:

  • 应用程序和服务器具有相同的硬编码盐字符串,对于每个后续版本的移动应用程序都是唯一的。此字符串必须保密。
  • 当用户在他们的设备上安装应用程序时,该应用程序会联系您的服务器并通知其应用程序的版本以及设备的IMEI,您使用的任何移动平台的API都应该启用你要检索。
  • 服务器为应用程序实例生成一个唯一密钥,该密钥将发送回应用程序并存储在设备上,并使用IMEI和已安装的版本将其存储在服务器端数据库中。
  • 在日常操作期间(即在提出问题中概述的请求时),应用程序遵循以下程序:
    • 检索以下信息:
      1. 设备IMEI
      2. App键
      3. 应用版本
      4. 硬编码盐字符串
      5. 随机生成的附加盐字符串(当前时间戳的衍生值,以微秒为单位,对于合理数量的熵总是有用的。)
    • 将所有这些信息连接在一起,最好在它们之间使用硬编码填充,并生成结果字符串的哈希值。
    • 向服务器发送以下信息以及实际请求数据(可能在Cookie中提供<​​em> tiny 额外的安全性):
      1. 生成哈希
      2. App键
      3. 随机生成的字符串用作附加盐
  • 服务器现在使用App密钥从数据库中检索该实例的设备IMEI和应用程序版本,并将该信息与硬编码的salt字符串一起用于版本ID和设备发送的附加salt字符串构造哈希。如果服务器上生成的哈希与移动设备生成的哈希匹配,则请求是好的,如果不拒绝它。
  • 此过程中的所有通信均通过HTTPS进行。

为了突破这个系统并成功欺骗请求,攻击者需要知道以下内容:

  1. 设备IMEI
  2. App键
  3. 应用版本
  4. 硬编码盐
  5. 用于生成哈希的机制(输入字符串的精确格式和哈希算法)。
  6. 显然,如果你正在使用移动设备1-3很容易提取,但如果没有逆向工程应用程序就无法找到4和5(对于有知识和知识的人来说,实际上没有什么可以阻止的耐心去做。)

    中间人攻击基本上是不可能的 - 即使在突破SSL之后(这是非常重要的,至少可以说)和逆向工程应用程序得到4和5,1-3不能在没有对哈希进行强力攻击的情况下进行检索,这非常复杂,平均需要几亿年(参见this page看看我是如何得出这个数字的),特别是如果其中一个是可变长度 - 应用程序版本字符串很容易。

答案 1 :(得分:3)

在app和php文件中定义一个salt,然后将该盐与当前时间相结合。这不太可能被欺骗。

$hash = sha1(time() . 'bladieblasalt');

if($_GET['hash'] == sha1(time() . 'samehash'))
{
    echo 'valid';
}

答案 2 :(得分:2)

首先你需要在你的应用程序中实现ssl,否则一个知之甚少的人可以简单地将那里的手机连接到wifi上,并通过wireshark或者cain和abel等来嗅探应用程序和你的站点之间的流量。并获取url和任何传递的参数,无需反汇编任何内容。

应用程序连接到您的站点和用户登录,无论是访客还是服务器成员,您的服务器都会为应用程序分配一个请求ID,并且此密钥/令牌随每个请求一起传递。在服务器上的会话中验证。

令牌看起来像: UNIQUE_REQUEST_ID_ASSIGNED_BY_SERVER:APPsIP:APPsTIME加密此字符串并将其作为$_GET['token']

发送

然后在您的服务器上解密字符串并将explode()字符串解析为其部分,并检查数据库或会话中的请求ID,ip和时间是否匹配等,如果一切正常的话。

就像安全登录系统为每个用户分配一个唯一的盐,并在用户请求ID旁边存储。

最重要的是,让滥用者滥用系统变得困难。 99%的人甚至不会想到要小提琴,另外1%的人会因此而被阻止。

答案 3 :(得分:2)

如果您不想要每个用户,但只需要每个应用程序,您将不得不依赖应用程序内置的秘密。任何反汇编应用程序的人最终都能找到它,因此一些混淆可能有所帮助,但它不会让确定的人离开你的页面。

也就是说,使用任何公钥加密都没什么意义。由于应用程序端是欺骗者可能感兴趣的东西,他们已经可以访问一对密钥对中更有价值的一半。所以你不妨使用一些使用共享秘密的方法。

您真正想要检查的是传输数据的真实性。因此,只需获取该数据的核心(即所有真正重要的字段),将它们与共享密钥连接起来,对结果进行散列并将其作为消息摘要传输。服务器执行相同的计算并检查计算的摘要是否与传输的摘要匹配。如果是,则该消息的发送者必须已知共享密钥。

仍有一些机会进行重播攻击,即有人录制有效消息并稍后重复播放。您可以在服务器端检测确切的重复项,并通过在消息的签名部分中包含时间戳来防止延迟重播。如果您的服务器允许客户端和服务器时间戳之间存在巨大差异,则必须在相同的时间内保留重复信息。如果它只接受小的差异,它可以使用较小的重复缓存,但是配置错误的设备的用户可能会感到烦恼,因为服务器更可能拒绝他们的请求太旧。

还有一点需要注意:您写了一篇GET请求,导致写入某个文件。我总是将一些状态改变操作与POST相关联。如果应用程序是您自己的,那么这并不重要,但是已知浏览器在不询问用户的情况下重新发送GET请求,从而导致重复请求某些操作。

答案 4 :(得分:1)

没有保证方法。您可以使用oauth身份验证...根据您使用的平台以及将应用程序部署到手机的方式,也许您可​​以将密钥编译到应用程序本身?任何东西都可以&amp;永远都会被破解,没有100%的安全......但是没有羞耻的尝试。 :)

我个人使用的移动应用程序是RESTful身份验证,使用常规登录/传递对基于令牌的通信,直到它过期。 :)

答案 5 :(得分:0)

HTTP请求可以按发件人想要的方式逐个字符地构建。欺骗总是可能的。

答案 6 :(得分:0)

只需向PHP应用程序添加授权(登录,密码,会话等和/或“API密钥”),然后在发送所需请求之前让手机应用程序先进行授权。你可能没有考虑到这一点,因为如果你的脚本很简单,可能会给它添加一些混乱,但几乎每个网络系统都需要这样,你最终也会面对它。

让您致电应用程序,通过HTTPS登录您的PHP应用程序以排除拦截。