安全建议:SSL 和 API 访问
我的 API(桌面应用程序)使用基于 SSL 的基本 HTTP 身份验证与我的 Web 应用程序进行通信(基本上我只是在请求中使用 https 而不是 http)。我的 API 实现了确保用户不会发送错误信息的逻辑,但我遇到的问题是有人可以绕过 API 并使用curl 来可能发布不正确的数据(获取凭据很简单,因为在我的网络应用程序上注册是自由的)。
我考虑过以下选项:
在 Web 应用程序中复制 API 的逻辑,这样即使用户尝试使用curl 或其他工具欺骗系统,他们也会遇到相同的情况。
实施进一步的身份验证检查,以确保只有我的 API 可以与我的 Web 应用程序通信。 (也许是 SSL 客户端证书?)。
加密数据(Base 64?)
我知道我对用户使用类似curl的工具欺骗我的网络应用程序有点偏执,但我宁愿安全比抱歉。重复逻辑确实很痛苦,我宁愿不这样做。我对 SSL 客户端证书不太了解,我可以将它们与基本 HTTP 身份验证结合使用吗?他们会让我的请求需要更长的时间来处理吗?我还有什么其他选择?
提前致谢。
My API (a desktop application) communicates with my web app using basic HTTP authentication over SSL (Basically I'm just using https instead of http in the requests). My API has implemented logic that makes sure that users don't send incorrect information, but the problem I have is that someone could bypass the API and use curl to potentially post incorrect data (obtaining credentials is trivial since signing up on my web app is free).
I have thought about the following options:
Duplicate the API's logic in the web app so that even if users try to cheat the system using curl or some other tool they are presented with the same conditions.
Implement a further authentication check to make sure only my API can communicate with my web app. (Perhaps SSL client certificates?).
Encrypt the data (Base 64?)
I know I'm being a little paranoid about users spoofing my web app with curl-like tools but I'd rather be safe than sorry. Duplicating the logic is really painful and I would rather not do that. I don't know much about SSL client certificates, can I use them in conjunction with basic HTTP authentication? Will they make my requests take longer to process? What other options do I have?
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
SSL 可以保护您免受中间人攻击,但不能防止源自 SSL 客户端的攻击。客户端 API 中内置的客户端证书将允许您识别数据是由客户端 API 制作的,但无法帮助您确定客户端是否在加密之前手动修改了数据。从技术上讲,精通客户端的用户始终可以通过客户端 API 进行调试来找到修改数据的方法。你能做的最好的事情就是在你的客户端 API 上设置障碍,以使其更难以破译。在服务器端进行验证确实是可行的方法。
考虑重构您的验证代码,以便双方都可以使用。
SSL protects you from the man-in-the-middle attacks, but not from attacks originated on the client side of the SSL. A client certificate built into your client API would allow you to identify that data was crafted by the client side API, but will not help you figuring out if client side manually modified the data just before it got encrypted. Technically ssavy user on the client end can always find a way to modify data by debugging through your client side API. The best you can do is to put roadblocks to your client side API, to make it harder to decipher it. Validation on the server side is indeed the way to go.
Consider refactoring your validation code so that it can be used on both sides.
您必须在服务器端验证数据。如果服务器端验证失败,您可以通过连接抛出令人讨厌的错误 - 没关系,它们不应该这样做被绊倒——但如果你不这样做,你就完全脆弱了。 (这样想:您完全控制的是服务器的逻辑,因此服务器的逻辑必须对通信的有效性做出明确的决定。)
使用客户端证书并不能真正保护您免受用户的侵害首先拥有使用该 API 的权限;如果没有别的事,他们可以分解代码来提取客户端证书(并且它必须对您的客户端代码可读才能使用)。添加额外的加密也不会;它使事情变得更加困难(更多的事情会出错),并且没有比 SSL 连接已经提供的安全性增加太多。 (当通过 HTTPS 发送的消息必须通过不受信任的代理时,添加加密会有所帮助。)
Base-64 不是加密。它只是将字节编码为更易于处理的字符的一种方法。
You must validate the data on the server side. You can throw nasty errors back across the connection if the server-side validation fails — that's OK, they're not supposed to be tripped — but if you don't, you are totally vulnerable. (Think about it this way: it's the server's logic that you totally control, therefore it is the server's logic that has to make the definitive decisions about the validity of communications.)
Using client certificates won't really protect you much additionally from users who have permission to use the API in the first place; if nothing else, they can take apart the code to extract the client certificate (and it has to be readable to your client code to be usable at all). Nor will adding extra encryption; it makes things much more difficult for you (more things to go wrong) without adding much safety over that already provided by that SSL connection. (The scenario where adding encryption helps is when the messages sent over HTTPS have to go via untrusted proxies.)
Base-64 is not encryption. It's just a way of encoding bytes as easier-to-handle characters.
我总体上同意 sinelaw 的评论,即这种验证通常在服务器端更好,以避免您遇到的那种问题(支持多种客户端类型)。也就是说,您可能无法移动逻辑,在这种情况下您需要做一些事情。
对我来说,您的选择是:
客户端证书,正如您所建议的那样 - 您基本上是在验证客户端是您期望的人(或者在您的情况下是什么)。我之前曾使用过这些,并且相互身份验证配置可能会令人困惑。我不会担心性能,因为我认为第一步是获得您想要的行为(正确性第一)。无论如何,一般来说,虽然此选项是可行的,但设置起来可能会很麻烦,具体取决于您的 Web 容器。
桌面应用程序中的自定义 HTTP 标头,检查其在服务器端的存在/值,或者只是利用现有的 User-Agent 标头。由于您正在加密流量,因此人们应该无法轻松看到您发送的 HTTP 标头,因此您可以将其名称和值设置为您想要的任何内容。在服务器端检查这一点类似于确保发送请求的客户端几乎肯定正在使用您的桌面应用程序。
我个人会选择自定义标头路线。它可能不是 100% 完美,但如果您有兴趣做最简单的事情来降低最大的风险,我认为这是最好的路线。如果您不使用 HTTPS,这不是一个很好的选择(因为任何人只要打开嗅探器就可以看到标头),但考虑到您确实使用 HTTPS,它应该可以正常工作。
顺便说一句,我认为您可能会混淆一些事情 - HTTPS 将为您提供加密,但它不一定涉及(客户端)身份验证。这是两个不同的东西,尽管它们经常捆绑在一起。我假设您使用 HTTPS 来对实际用户进行身份验证(基本身份验证或其他身份验证)。
I would agree in general with sinelaw's comment that such validations are usually better on the server side to avoid exactly the kind of issue you're running into (supporting multiple client types). That said, you may just not be in a position to move the logic, in which case you need to do something.
To me, your options are:
Client-side certificates, as you suggest -- you're basically authenticating that the client is who (or what, in your case) you expect it to be. I have worked with these before and mutual authentication configuration can be confusing. I would not worry about the performance, as I think the first step is getting the behavior your want (correctness first). Anyway, in general, while this option is feasible, it can be exasperating to set up, depending on your web container.
Custom HTTP header in your desktop app, checking for its existence/value on the server side, or just leveraging of the existing User-Agent header. Since you're encrypting the traffic, one should not be able to easily see the HTTP header you're sending, so you can set its name and value to whatever you want. Checking for that on the server side is akin to assuring you that the client sending the request is almost certainly using your desktop app.
I would personally go the custom header route. It may not be 100% perfect, but if you're interested in doing the simplest possible thing to mitigate the most risk, it strikes me as the best route. It's not a great option if you don't use HTTPS (because then anyone can see the header if they flip on a sniffer), but given that you do use HTTPS, it should work fine.
BTW, I think you may be confusing a few things -- HTTPS is going to give you encryption, but it doesn't necessarily involve (client) authentication. Those are two different things, although they are often bundled together. I'm assuming you're using HTTPS with authentication of the actual user (basic auth or whatever).