检测 iPhone 应用程序仅访问 Web 服务的最佳实践是什么?

11

我正在开发一款与 Web 服务配合的 iPhone 应用程序。iPhone 应用程序将使用 GET 或 POST 方法从 Web 服务中检索数据,例如http://www.myserver.com/api/top10songs.json以获取前十首歌曲的数据。

iPhone 应用程序没有用户帐户和密码。如何确保只有我的 iPhone 应用程序可以访问 Web API http://www.myserver.com/api/top10songs.json 是最佳实践?iPhone SDK 的 UIDevice uniqueueIdentifier 不足以满足要求,因为任何人都可以伪造设备 ID 作为参数使用 wget、curl 或 Web 浏览器调用 API。

Web 服务 API 不会公开。Web 服务的数据不是机密和私有的,我只想防止滥用,因为还存在一些 API 可以向服务器写入一些数据,如使用日志。

8个回答

6
你可以做的是获取一个只有你知道的秘钥,将其包含在md5哈希签名中。通常情况下,你可以将签名结构化为参数和值的字符串,并在末尾添加秘钥,然后对此进行md5哈希。在客户端和服务端都这样做,并匹配签名字符串,只有在签名匹配时才被授予权限。由于秘钥仅存在于签名中,因此很难逆向工程和破解。

1
那会有多难破解呢?你只需要读取HTTP请求并读取参数的MD5值即可。 - erotsppa
2
如果你嗅探HTTP请求并像原样重新发送它,那么你肯定会得到一些响应,但是没有人能够生成自己的请求,因为他们不知道密钥。 - Daniel
为了解决这个问题,可以使用一些传输层安全性来加密数据,以便在被嗅探时保护数据的安全。 - Daniel
1
你也可以将密钥和当前时间进行哈希。将时间以明文形式与哈希一起发送到服务器。服务器可以检查时间是否与现在有合理的偏移量,以防止重放攻击。由于服务器知道密钥,因此可以通过对客户端发送的密钥+时间进行哈希来验证哈希。虽然不是完美的,但可以提供一定程度的重放保护。 - Matt Dotson

5

以下是对Daniel建议的进一步扩展。

使用一些服务器和客户端都知道的共享密钥,例如一些长随机字符串。

当客户端连接时,让客户端生成另一个随机字符串,将其附加到共享字符串的末尾,然后计算MD5哈希值。

将两个随机生成的字符串和哈希值作为请求参数发送。服务器知道共享字符串,因此可以生成自己的哈希值并确保它与从客户端接收到的哈希值匹配。

这种方法不是完全安全的,因为有人可能会反编译您的应用程序以确定共享密钥,但是如果不想做太多额外的工作,这可能是最好的方法。


Herms,你能举个例子说明一下你如何发送请求吗?据我所知,你是在网络上发送md5(secretkey+anotherrandom)的。但是,有人不是可以解密该请求并直接读取secretkey吗? - erotsppa
由于MD5是一种单向哈希算法,因此无法进行“反向MD5”。他们能做的最好事情(在这个方面)就是哈希一个字符串并寻找碰撞点(使用所谓的“彩虹表”)。但随机性加上秘密密钥使“彩虹表”攻击变得不可行。 - bbrown
bbrown是正确的。MD5是单向哈希,所以您不必担心有人解密它来找出秘密。 - Herms
如果有人捕获了发送的哈希和随机字符串的一组组合,他们可以仅使用该对进行请求。或者我漏掉了什么?编辑:我可以将URL用作随机字符串的一部分。这样至少他们不能重放任何请求,只能重放他们捕获的那些请求。 - oberhamsi

3

在您的请求中使用某种形式的数字签名。虽然要完全防篡改(与安全相关的任何内容都是如此)相当困难,但只要足够好,就可以防止大多数滥用。

当然,这高度取决于数据的敏感性,如果您的数据交易涉及数百万美元的交易,您将希望它比一些简单的使用统计记录更加安全(如果它足够难以篡改,并且攻击者除了惹你生气之外几乎没有任何收益,那么可以安全地假设人们不会费心去尝试...)


没错。数据的价值将决定你需要多少保护。 - bbrown

3
我在WWDC上向一位苹果安全工程师询问了这个问题,他说没有绝对可靠的方法来实现这一点。你能做的最好的事情就是让攻击者觉得不值得投入精力。
我还向他询问了可能使用推送通知作为这种方式的手段,他认为这是一个非常好的想法。基本思路是,第一次访问会触发服务器上的推送通知,该通知将发送到用户的iPhone。由于你的应用程序已经打开,它会调用application:didReceiveRemoteNotification:方法,并传递自己选择的有效负载。如果你将有效负载设置为nonce,则你的应用程序可以在下一次请求中发送nonce并完成循环。
之后你可以存储UDID,并且丢弃任何带有未验证UDID的请求。无论如何,你都应该实现速率限制算法以防止暴力猜测必要的参数。

如果推送通知不是你的菜,那么我遇到的唯一其他足够提高安全级别的行动就是密钥交换。查看CryptoExercise示例应用程序,了解如何在iPhone上生成随机对称密钥,并使用公钥加密并发送到另一个iPhone。虽然不完美,但与其他防范措施结合使用,你有一些保护资产的希望。 - bbrown

1

一个非常便宜的方法是让iPhone软件在查询时发送额外的数据,例如长密码字符串,以便某人无法访问该信息流。

有人可能会反向工程您所做的事情,或者监听通过网络发送的数据以发现密码。如果带宽限制是进行此操作的原因,则简单的密码就足够了。

当然,这种方法也存在问题,基于证书的身份验证实际上会更安全,尽管编码会更加困难。


1

最安全的解决方案可能是在请求上使用数字签名。您可以在iPhone应用程序中保留一个秘密密钥,并使用它对请求进行签名,然后在服务器端验证。这避免了将密钥/密码发送到服务器,从而允许某人使用网络嗅探器捕获它。

一个简单的解决方案可能只是使用HTTPS-尽管存在潜在的窃听者,但保持消息内容安全是HTTPS的全部意义。我不确定是否可以使用标准的NSURLConnection工具进行自签名证书,但如果您有服务器端证书,则至少受到保护免受窃听。而且对于您来说,需要编写的代码要少得多(实际上是没有)。

我想,如果您将HTTPS作为唯一的安全性,则有可能向某人猜测URL。如果这是一个问题,那么向Web服务添加任何类型的参数验证都会解决这个问题。


0
大多数解决方案的问题在于,一旦您将代理添加到混合中,它们就很容易出现故障。如果代理连接到您的 Web 服务,这样做是否可以?毕竟,它可能是代表某个 iPhone 连接的 - 也许是在中国?如果允许代理冒充 iPhone,那么如何确定哪些冒充是可以接受的呢?


代理应该将iPhone发送到代理的所有数据发送到服务器,所以我不认为有问题。 - Herms

0

有一种钥匙,每5分钟根据使用当前时间(GMT)的算法而改变。始终允许最后两个钥匙进入。当然,这并不完美,但它可以使目标移动,并且您可以将其与其他策略和战术相结合。

我假设您只是想阻止使用您的服务。显然,您还没有设置您的应用程序以确保安全。


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