如何保护应用程序 - 后端通信? [英] How to secure app - backend communications?

查看:23
本文介绍了如何保护应用程序 - 后端通信?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 iOS 应用程序和一个小型后端,我目前使用它来管理 apns(Apple 推送通知).注册过程只是一个带有参数的 GET 调用到我的后端,并且由于没有身份验证"或任何其他类型的控制,我担心任何人都可以通过虚假设备注册使我的后端过载.

所以主要问题是:在没有身份验证的情况下,我如何才能使这种应用发送信息到后端的传输安全?

我想到的一个简单想法是使用应用程序在注册设备时必须提供的令牌生成某种 HASH...

解决方案

没有办法彻底解决这个问题.不可能知道连接的是您的应用程序.您所能做的就是添加一些混淆.

您最好的第一步是使用带有固定证书的 SSL 来制作 Man-in-the- 中间攻击更难.客户端证书可以提供帮助,但设置起来有点麻烦,而且与其他解决方案相比,它不会给您带来很多好处.

如果您有固定证书和 SSL,只需随 GET 一起发送共享机密可能就可以满足您的需求.更改从发布到发布的秘密,以便您可以老化旧的.如果有人对您的应用进行了逆向工程,足以破解固定证书(或直接读取共享机密),那么他们也将破解所有其他方法.

即便如此,这里还有一些可以增加一点额外层次的内容:

使用 AES 进行双向共享秘密验证 是一种很好且简单的方法,但需要握手(即您不能使用单个 GET 来完成).你当然可以只用一种方式来实现(所以服务器验证密钥,而不是客户端),但你仍然需要握手.

如果您想将您的身份验证令牌保留到单个 GET 并且无法固定您的 SSL 证书,并且您可以使您的 GET 具有幂等性(无论如何都应该是好的 REST 调用),那么这是一个简单的实现:

  • 构造GET请求
  • 计算 HMAC(SHA-256,shared-secret,get-request,16 字节)
  • 将 HMAC 与 GET 请求一起发送

在 iOS 上,这看起来像:

NSData *key = ...与服务器共享的随机 32 字节...;NSURLRequest *request = ...;//为 HMAC 分配一些内存NSMutableData *hmac = [NSMutableData dataWithCapacity:CC_SHA256_DIGEST_LENGTH];//将您的 URL 转换为数据.这假设这是一个 GET 请求,所以 URL//拥有一切.这也假设 GET 是幂等的,所以如果有人//重放这个 GET 请求,你不在乎.NSData *requestData = [[[请求 URL] absoluteString] dataUsingEncoding:NSUTF8StringEncoding];//计算 HMACCCHmac(kCCHmacAlgSHA256,[关键字节],[密钥长度],[请求数据字节],[请求数据长度],[hmac mutableBytes]);//截断 HMAC(这是常见的做法.稍微好一点,至少没有//更糟糕的是,发送一半的 HMAC 而不是整个 HMAC).NSData *token = [hmac subdataWithRange:NSMakeRange(0, [hmac length]/2)];NSURLRequest *finalRequest = ... 将令牌添加到您的请求中 ...

你当然会在服务器端计算同样的事情.您可以将其视为签署 GET".如果您的请求不是幂等的,那么无论如何您真的应该努力解决这个问题.如果您无法修复它,您可以将时间戳集成到哈希中并丢弃太旧或您以前见过的请求.(这样做,你已经让你的 GET 是幂等的......)

升级应用时,您可能应该更改共享密钥.这样,您最终可以淘汰已发现的旧共享秘密.

是的,这些都可以逆向工程.任何尝试对应用(而不是用户)进行身份验证的事物都可以进行逆向工程.因此,请保持简单,并更多地关注如果发生这种情况您将如何恢复.

如果可能,添加用户身份验证.它更强大.

I have one iOS app and also a small backend that I use so far to manage the apns (Apple Push Notifications). The registration process is just a GET call with parameters to my backend, and since there is no 'authentication' or any other kind of control, I fear that anybody could just overload my backend with fake devices registering.

So the main question is: how could I make this kind of app-sending-info-to-backend transmissions secure when there is no authentication?

One simple idea that comes to my mind is generating some kind of HASH using the token that the app must supply when registering the device...

解决方案

There is no way to completely solve this problem. It is not possible to know that it is your app that is connecting. All you can do is add a little obfuscation.

Your best first step is to use SSL with a pinned certificate to make Man-in-the-Middle attacks harder. Client-side certs can help, but are a bit of a pain to set up and aren't going to buy you a lot over other solutions.

If you have a pinned certificate and SSL, just sending a shared secret along with the GET is probably as good as you need. Change the secret from release to release so you can age out old ones. If someone has reverse-engineered your app enough to beat the pinned certificate (or to read the shared secret directly), then they're going to break all the rest of these approaches, too.

Even so, here are some more that add a little extra layer:

Bidirectional shared-secret verification with AES is a good and simple approach, but requires a handshake (i.e. you can't do it with a single GET). You can of course just implement this one-way (so the server verifies the key, but not the client), but you still need a handshake.

If you want to keep your auth token to a single GET and can't pin your SSL certificate, and you can make your GETs idempotent (which good REST calls should be anyway), then this is a simple implementation:

  • Construct GET request
  • Calculate HMAC(SHA-256, shared-secret, get-request, 16 bytes)
  • Send HMAC along with GET request

On iOS, this would look something like:

NSData *key = ...random 32 bytes shared with server...;
NSURLRequest *request = ...;

// Allocate some memory for the HMAC
NSMutableData *hmac = [NSMutableData dataWithCapacity:CC_SHA256_DIGEST_LENGTH];

// Convert your URL into data. This assumes that this is a GET request, so the URL
// has everything. This also assumes that the GET is idempotent, so if someone
// replays this GET request, you don't care.
NSData *requestData = [[[request URL] absoluteString] dataUsingEncoding:NSUTF8StringEncoding];

// Compute the HMAC
CCHmac(kCCHmacAlgSHA256,
       [key bytes],
       [key length],
       [requestData bytes],
       [requestData length],
       [hmac mutableBytes]);

// Truncate the HMAC (this is common practice. It's slightly better, and at least no
// worse, to send half the HMAC rather than the whole HMAC).
NSData *token = [hmac subdataWithRange:NSMakeRange(0, [hmac length] / 2)];

NSURLRequest *finalRequest = ... add the token to your request ...

You would of course compute the same thing on the server side. You can think of this as "signing the GET." If your requests are not idempotent, you really should be working on fixing that anyway. If you can't fix it, you can integrate a timestamp into the hash and throw away requests that are too old or you've seen before. (In doing this, you've made your GET idempotent....)

When you upgrade your app, you should probably change your shared secret. That way you can eventually age out old shared secrets that have been discovered.

Yes, these can all be reverse engineered. Anything that tries to authenticate the app (rather than the user) can be reverse engineered. So keep it simple, and focus more on how you would recover if it did happen.

And if at all possible, add user authentication. It's much more powerful.

这篇关于如何保护应用程序 - 后端通信?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆