如何在不login的情况下保护Web服务

我有一个移动应用程序(目前IOS和即将安卓),它谈到一个Web服务。 没有login,数据不是私人的。 基本上,应用程序发布标记(lon,lat),并获取最近的25个标记以在地图上显示。

这是一个非常微不足道的应用程序,我无法想象任何人会付出巨大的努力滥用networking服务。 不过,我可以看到有人在张贴多个标记时很有趣。 最让我担心的是有人在运行一个脚本,它推动了很多请求(使用昂贵的带宽并且废my我的应用程序数据)。

我正在慢慢得出结论,这是不可靠的。 最好的答案是“不要这样做”。 不要提供没有身份validation的Web服务。 没有太多的服务如此开放。 Google的You Tube API是开放的,但大部分都不是。 不幸的是,我没有select。 所以在看了这几天之后,这是我的想法。 注意我离安全专家很远,我相信我的方法可以改进。 但是这可能会使你指向正确的方向。 希望有更多经验的人可以join并纠正/改善这一点。 我发现这篇文章和评论特别有用。

消息级别安全性

我将使用散列encryption来保护邮件。 客户端和Web服务都保留一个共享密钥的副本,这个密钥用来作为一个salt来从URL和所有的POST参数创build一个哈希。 散列作为附加parameter passing,哈希被重build并在另一端进行比较(使用共享密钥作为盐)。 这是相当不错的,直到你明白,任何移动客户端代码可以在几分钟内逆向工程。 在这一点上,这条防线完全没用。

客户端措施

客户端包括消息速率限制作为限制诚实用户发送的消息数量的措施。 再次,这对于越狱移动设备的攻击者来说毫无用处。

服务器端安全

因此,服务器端必须尽可能多地采取额外的安全措施,只要您的客户端(和共享的秘密)被破坏就可以独立运行。 这是我有什么:

一个味精属于UTC时间,用于限制重播攻击。 这应该防止攻击者反复在服务器上触发相同的消息。

服务器通过IP执行速率限制。 是的,IPs很容易被欺骗,代理交换是小孩玩,但是当你有这么less的时候,一切都会有帮助。

当然,服务器严格validation所有的参数,使用参数化的查询,并不会返回exception。

运输级别安全

不幸的是,我相当确信,如果没有注册过程,发布个人客户端SSL证书是不可能的。 而且因为我正在使用msg散列检查(而且我的数据不是私有的),所以我不完全确定SSL带到表中。 但是,我可能会使用SSL(只有一个应用程序范围的证书),因为它增加了另一个级别的安全性,易于部署,而且价格便宜(尽pipe每个msg需要花费额外的连接时间)。

我的方法中的巨大的大洞

我被警告,如果应用程序变得stream行,有人会妥协的客户共享的秘密。 只是因为他们可以,他们可能会在互联网上发布。 所以真的这一切都归结于服务器端。 不幸的是, 我无法识别和阻止攻击者 。 这我会深深的爱。

最后的请求

经过几天的研究,这是我所有的。 但我想要更多。 我特别感谢任何想法来加强服务器端。 所以,我把所有的SO点作为赏金。 是的,先生,全部97分!

实际上,在您的具体情况下,因为它目前只有iOS应用程序,所以有一个解决scheme。

  1. 在用户第一次下载并运行应用程序后,应用程序会/access_token/create一个带有GUID的/access_token/create API,并通过Apple的“推送通知”将其中继到应用程序。

  2. 应用程序存储此access_token,并将其用于所有后续请求。 您的实际API可以在access_token的基础上进行速率限制。

基本上,你让苹果公司做了所有的努力,确保最初的请求来自实际的iOS设备。

将其扩展到桌面客户端是可能的,但有些遗留了UX。 只需更改第1步,以允许/access_token/create接受任意请求,如果请求不是来自iOS设备,则强制用户validation其电子邮件地址/解决validation码等,然后发出access_token。

Android设备(不太熟悉它们)可能有类似的推送通知机制,在这种情况下,您可以使用该设备,或者可能没有推送通知机制,在这种情况下,您可以让Android用户受到上述不便。

我曾经听说过这个想法,当谈到find一个解决SPAM问题的全球解决scheme时:强迫你的客户执行一些耗时的计算。

准确地说:find一些计算algorithm,它可以在眨眼之间计算一对xy z ,但计算z只需要x就需要相当多的时间。 我不能提供实际的algorithm,但我相信有很多这样的标准。

现在整个程序应该如下所示:

  1. 在第一个客户端请求生成一些session_id和这个session_id一对xy
  2. 为您的客户提供session_idx
  3. 客户端可以在收到数据后立即开始计算(在某些后台线程中与用户交互无关)。
  4. 要请求标记,客户端必须提供session_id和计算的z
  5. 您可以快速validation客户端的z是否正确,因为您已经有了xy ,可以轻松完成。
  6. (选项1)每个session_id商店多less/经常被请求。 您怀疑它被滥用的那一刻 – 强制重新生成xy
  7. (选项2)在连续请求session_id时强制新的xy

6到7之间的select实际上是调整,这取决于algorithm的复杂性与期望的“公平”使用标记数据库的复杂性。 如果你的估计是好的 – 邪恶的客户端不应该获得太多的数据或超载你的服务器。

希望能帮助到你。

在客户端没有什么可以做的。 您必须将整个应用程序(包括任何密钥或任何其他保护机制)提供给您的用户。 如果恶意用户想要与您的Web服务一起恶作剧,他将不得不做一些逆向工程来访问您的Web服务。 你可以做得更难,但不pipe怎么努力,你都无法阻止这一点。

我只是实现了一些服务器端速率限制(每个IP地址),不用担心这个。 这是一场你无法取胜的战斗。 如果有人真的想伤害你的服务器,他可能只是DDOS它不知道任何有关您的Web服务协议。

而且,在第一次连接时自动为每个用户生成一个唯一的密钥或证书根本没有任何帮助。 在攻击者逆向工程你的协议后,他知道如何处理所有这些,不必按照你的规则来玩。 每次遇到速率限制时,都不会阻止他从服务器请求新的密钥。

Kuba Wyrostek描述的方法可以工作 – 使客户端执行一些耗时的计算,您可以在允许请求被处理之前快速检查。 但这不能太长,否则用户会抱怨电池寿命缩短。 另外攻击者可能会使用更强大的桌面硬件,而不是另一个iPhone。

最后一点 – 你真的认为这是必要的吗? 你不希望你的用户必须注册,所以你的数据或服务不能太重要。 那么有什么人可以通过逆向工程来获得应用程序,并用请求淹没你的服务器呢?

实际上我一直在寻找一个理由去实现其中的一些想法。 好的问题和答案到目前为止。

我同意@Kuba Wyrostek将其视为垃圾邮件问题是解决scheme的一部分。 特别是如果您的应用程序将有文本消息(添加商店,服务或消息),您可能会发现一个常见的理由来垃圾你的应用程序将是做广告的东西。 这将导致我的第一个build议:

1)将每封邮件的有效性从0%到100%有效 。 在服务器端开发一个过程,使用heurestics将消息标记为或多或less有效。 这将允许您将某些其他方法(例如强制客户端计算复杂值)仅定位到需要的地方。 您还可以更轻松地logging和查看可能的滥用情况(并在发现问题后更容易清除滥用情况)。

您的应用程序在垃圾邮件战争中确实比电子邮件服务器具有强大的优势,但是,您可以控制双方的对话。 这种情况实际上让我想起了另外两种相关的情况:卫星收费电视“战争”和即时通讯软件克隆“战争”。 (例如,参考黑色星期天黑客的 Jeff Atwoods博客)。 这里有一些来自这些僵局的想法可能会帮助你在猫和老鼠的游戏中领先一点:

2)要求客户发送额外的数据 – 尽可能多的有关请求的数据是有道理的。 在iOS上,发送位置的准确性指标。 在Android上,您实际上可以获取原始GPS数据,例如星历信息。 您可以(也许不是马上,但稍后),开始检查这些数据的有效性。 这迫使某人逆向工程要求更难工作。 例如,如果他们发送GPS卫星,你可以检查公众已知的数据来确认。

3)强迫你的对手进入移动设备 – 正如@Sven所说,你的攻击者可能会使用台式电脑,这意味着“计算成本昂贵”的请求可能会变得微不足道。 不要让他们这样做(或者至less让他们更努力)。 例如,您可以让客户端计算一些math函数(由服务器发送),并根据手机型号查看是否需要正确的毫秒数来完成。 或者使用来自服务器的数据执行小型3D渲染任务,这依赖于硬件剪切行为。 散列结果并将其发回。 所有这些都将在一个范围内 – 这是一个多任务操作系统。 但这会有很大的帮助。

4)对它们进行dynamic化 – 发送需要在客户端上下文中计算的algorithm位。 苹果得到一个有趣的远程代码被解释,但像发送一些JavaScript不呈现给用户可能工作。 该代码可能会提出各种独特的问题(屏幕分辨率,浏览器版本,WebKit怪癖),这是很难预测的。 当他们赶上,你可以得到更多的创意与这些。

5)validation码 – 如果你的启发式技术开始看到可疑数据,强迫他们进行validation。 如果你有一个多语言的应用程序,它可以像一个图片或unicode字符匹配到另一个简单。 以稍后更新的方式呈现它。

无论如何 – 一些额外的想法。 祝你好运!

在服务器端实现速率限制最简单的方法就是使用Web服务器插件/模块。 例如,如果您的服务在apache上运行,请安装并configurationmod_evasive。 这将允许您根据IP地址,服务/ URL等等进行评级限制。Mod Evasive将比您自己可以实施的更有效。

如果你使用密钥,你需要有一种基于validation码的方式,让客户端在注册时获得密钥。 你可以让它放弃滥用用户的帐户。 没错,当然一个参数就是最近和过去在服务器端validation的时间戳。 密钥将随时间戳一起encryption整个有效负载,并作为附加参数添加。 按照密钥存储请求的频率最终需要某种循环数据库,除非您只检查最近一次请求的新近程度。

纯粹的客户端速度限制不会有任何区别。 有人可以在网上发现你的API,甚至没有看到你的客户端。 我怀疑一个共同的秘密会长久有效。

你会发现大量的Web服务,不需要密码,只是速度有限…例如,Twitter API提供了许多速率限制的未经validation的API服务。

这是另一个“解决scheme”:

  • 不要在这个问题上浪费时间。

因为:

  • 你不会暴露一个公共的接口,所以你可以随时通过更新web服务和更新你的应用程序来改变你的web服务接口。
  • 该应用程序“非常微不足道”(就像你所说的那样),目前可能用得不多
  • 你现在可能有更好的事情,只是消耗时间

如果有可疑的性能或查询峰值是耗时最less的解决scheme:

  • 引入保存在你的应用程序中的密码(clientid)(块95%的这些用户),如果其他程序员想要合法访问你的服务,这个密码可以被用来识别不同的客户端
  • 引入速率限制(如上所述)

这将在99,99%解决你的问题,你现在可以开始工作,并写出令人敬畏的新function。

这是棘手的,你不希望有人篡改数据…所以你的关注不是关于诚信。 而且,既然你没有保留任何客户名单,那么真实性就不会有任何顾虑吗?

而对于所有众所周知的Web服务攻击(如DoS或重放攻击),您可以使用防火墙来阻止它们。 所以我觉得你不需要为此烦恼

但是,你不希望发送纯文本数据,并希望确保你的下载应用程序是什么推动数据。

如果你看看你正在评估的方法:

安全密钥 :据我所知服务器和应用程序将共享相同的密钥,如果我是正确的所有设备上的所有应用程序将共享相同的密钥。 当应用程序推送数据时,它会散列实际的提要,并通过实际提要+散列提要发送。 在服务器端,您将使用密钥并散列实际提要,并validation它是否与散列提要匹配。 而在我看来,这个解决scheme主要是针对数据完整性方面,这不是你主要关心的问题。 RGT! (是的,反向工程可能很容易。)

在上面的方法中,服务器需要存储密钥,所以如果你的密钥被破坏,你的整个服务将会是,并且将很难用新密钥更新所有的应用程序。 否则,如果应用程序生成一个密钥,它将不得不将密钥连同消息一起作为摘要或其他东西(如时间戳+一些随机数)发送。 不是很难打破。

证书:即使有了证书,你也可以获得相同的安全性,但是很难破解,但是容易上手:)。 如果你保持私钥与设备(当然,那么你将不得不在服务器上维护一个公钥)。 您将不得不为每个客户端分配一个私钥,然后服务器需要维护所有分配的私钥的公钥。 如果私钥被破解,那么只有该单个应用程序可能被红色标记并请求更新。

所以从应用程序开发的angular度来看,您希望避免伪造数据。 为了防止恶作剧检查这种事情的唯一的一点是在应用程序逻辑。 你需要caching最后十个(甚至是最佳数目)的feed(来自同一个IP),并且有某种逻辑validation是否有缺陷。

你可以使用速率限制+客户端“软”注册。

基本上,您将生成一个设备ID,您可以在第一次请求时将其存储在用户默认设置中。 对于每个请求,您都会跟踪有多less请求已发送到服务器,并将其限制在服务器端。 这可以很快实现。

你也可以通过生成的设备ID + post / get参数来使用某种共享机密来签名