客户端编码:如何防止恶意使用?


60

在过去的几年中,客户端(浏览器)应用程序的趋势确实起飞了。

对于我的最新项目,我决定尝试与时俱进,并编写一个客户端应用程序。

此应用程序的一部分涉及向用户发送交易电子邮件(例如,验证注册,密码重置电子邮件等)。我正在使用第三方API发送电子邮件。

通常,我会让我的应用程序在服务器上运行。我会从服务器上的代码中调用第三方API。

运行客户端应用程序意味着这现在需要在用户的浏览器上进行。第三方API提供了实现此目的所需的JavaScript文件。

我看到的第一个明显问题是我需要使用API​​密钥。通常,这通常可以安全地存储在我的服务器上,但是现在大概需要将这个密钥提供给客户端浏览器。

假设我可以解决这个问题,那么下一个问题就是阻止精通技术的用户在浏览器上加载JavaScript开发人员工具并以他们喜欢的方式使用电子邮件API,而不是坚持我在应用程序中设置的任何规则。

我想我的一般问题是-我们如何防止恶意使用客户端应用程序?


24
您是否没有此应用程序与您自己的服务器通信,然后服务器将这些请求转发到您需要使用的任何外部服务的任何原因?(许多这样的服务无论如何都禁止以这种方式使用它们)
thorstenmüller2014年

11
这就是API密钥最终毫无意义的原因。服务器不应试图信任正在发送命令的应用程序;它应该只信任用户。
凯文·潘科2014年

42
我还没有看到任何理智的人将“客户端应用程序”定义为“在任何情况下都不会与服务器通信” –似乎更像是一个稻草人,而不是一个合理的论点。显然,有一些事情你必须处理在服务器端,但绝大多数的操作可以在本地没有问题来完成,这将反过来大大提高响应能力和可扩展性..
VOO

4
您在哪里看到向“仅限浏览器应用程序”的推动?我从未见过像您所描述的那样的东西,以疯狂的坏主意将客户端代码保密,即使我认识的最顽固的前端人员也绝不会这样做。
Wheeyls 2014年

2
保护客户端安全资源的任何尝试都是注定的,因为它违反了一些不变的安全法则。#2/3-如果您的软件在对手计算机上运行,​​那么从定义上来说它不是您的计算机,并且您已经迷路了。#7尝试通过加密保护资源的做法注定要失败,因为您还必须向客户端提供解密密钥。#10没有任何技术可以解决上述问题。 blogs.technet.com/b/rhalbheer/archive/2011/06/16/...
丹·尼利

Answers:


200

您做不到,而且人们了解的越多,他们了解的越深,对世界越好。

无法控制在用户控制下在设备上运行的代码。智能手机可能越狱了。机顶盒可能会破裂。普通浏览器甚至没有尝试阻止对JavaScript代码的访问。如果您有值得窃取或滥用的东西,那么除非您验证您珍视服务器端的所有内容,否则坚定的攻击者能够做到这一点。

混淆几乎没有什么帮助。一旦涉及到任何涉及财务方面的问题,您就会吸引那种对手,它会读取汇编语言(如分类广告)。加密无法帮助您,因为可以保护密钥的设备与您必须假定的设备相同。出于类似原因,还有许多其他似乎无效的对策无效。

不幸的是,这是一个非常不便的事实。世界上到处都是小型和大型运营商,他们认为他们可以以某种方式摆脱远程信任的根本破坏,仅仅是因为如果我们可以假设我们的代码将按照我们假设的方式运行,那就太好了。是的,它将使一切变得如此简单,甚至变得不那么有趣。但是,希望并非如此,而寄希望于您是能避免这种不愉快的唯一智能cookie只会烧伤您和您的客户。因此,进入互联网是敌人领土的想法,将增加的成本包括在您的估算中,您会没事的。

就是说,当然有诸如纵深防御的事情。对JavaScript进行模糊处理并不能阻止坚定的攻击者,但可能会阻止一些不确定性强的攻击者。如果您的资产足以保护您的资产,但又不惜一切代价,那么任何这些措施都可以为您的系统增加业务价值;只是不完美。只要您充分意识到自己正在做出的取舍,那可能就是一个合理的策略。


6
但是从一个角度来看:无论是操作系统还是交易软件,每种软件都是如此。最后,如果没有立即的经济诱因来入侵您的软件,那么会有一些非常好的代码混淆器,您可以将门槛提高到足够高的水平!
Falco 2014年

5
如今,公司已经威胁要对在处理(例如通过广告拦截器)之前从他们那里收到的内容进行黑客攻击的人采取法律行动。那只能说明技术行动是多么不可能。
Kilian Foth 2014年

62
如果我能详细说明前两个句子,那么人们经常会错过的精妙之处在于,客户端浏览器应用程序的重点在于减轻繁重的工作量。您的服务器仍然负责受信任的操作,例如发送电子邮件或访问数据。但是,让客户端根据该数据绘制图形,可以节省CPU时间(和金钱),而无需更改安全模型。
ssube 2014年

11
@Gaz_Edge重要的是要注意,这里的问题不是客户端应用程序本身是不安全的。问题在于编写这些客户端应用程序的方式要求您将不希望公开的信息信任客户端。完全有可能编写一个像客户端一样重的应用程序,该应用程序与大多数处理在服务器上进行的应用程序一样安全。(有关更多信息,请参阅jhocking的回答
Ajedi32

7
@ Ajedi32客户端应用程序不安全的。如果未在服务器端检查任何逻辑,则无法设计安全的应用程序。到那时,客户端逻辑就变成了UI精巧或减轻基本检查负担的一种方法,但是必须始终在服务器上检查所有内容!

69

这里的规则是:

如果用户篡改,请在客户端进行所有不影响其他人的操作。特别是,这意味着图形效果。

在服务器端执行所有需要确保安全的操作,并仅从客户端发送UI事件(例如,当服务器实际执行交易时,客户端只说“用户点击了“购买”按钮)。特别是,这意味着金融交易。


28

这也正是情况下使其成为一个完全客户端应用程序是恰当的。

您可以对客户端表单进行逻辑验证和基本验证(您仍必须在服务器上进行验证,因为有人可能会伪造该请求)以提高响应速度,您可以通过JavaScript进行HTTP请求,然后在那儿传递数据并以JSON形式返回给避免重新发送页面修饰等,但是如果事务本身需要进行身份验证和授权,则它仍应在服务器上进行。


11
注意:虽然验证表单客户端非常有用,但永远不要忘记同时验证它们在服务器端!当您将客户代码发送到浏览器时,它不再是您的代码!您必须验证它再次发送的每一位!
约瑟夫

17

您的中间段落是问题的核心:

运行客户端应用程序意味着这现在需要在用户浏览器上进行。第三方API提供了实现此目的所需的js文件。

为什么客户端应用程序意味着您无法进行服务器端工作?向客户端编程的推动力不是消除服务器,而是利用浏览器最终支持的新技术来创建更好的用户界面。

至于.js收到的文件,确定要用于浏览器吗?可以是一个node.js库吗?


4
+1表示该JS文件适用于NodeJS服务器
Machinarius 2014年

11

让我们从此退后一步,进行更高级的了解..我们是否应该。Eudora或Outlook(客户端应用程序,甚至不需要浏览器)是否会给任何公司造成财务损失?否。任何人都可以写POP / SMTP API并成为客户端。但是对服务器没有任何损失。服务器并没有限制客户端的动作,计算,存储,温度,磁盘大小,内存大小,监视器DPI,GPU,FPU yada yada yada yada,但没有具体说明它会回答什么。您是否听说过加快或MS-Money被用来破产的问题?

您的浏览器(即客户端)应用程序可以使用相同的体系结构。

  1. 您使用API​​构建服务器(顺便说一句,BTW总是归结为GET POST HEAD等的派生类)。
  2. 在服务器上,请确保对于每个调用,API仅与经过身份验证和身份验证的客户端通信。
  3. 然后,您不必在意客户是谁。
  4. 然后,您不必在意是浏览器,越狱设备,Google Glass,DOS 3.1还是在高科技恐惧症患者手中的全新Nexus,他曾旅行到2014年并错过了所有机会在过去的15年里,一直充斥着我们生活的技术。
  5. 现在,您可以开始将其他所有内容卸载到客户端。

SoapBoxBegin

@KilianFoth为幼稚和鲁ck的人们提供了一个重要的认识点,主要是那些经常阅读头条新闻但从不认为应用程序,代码,雇主,客户,自己的银行帐户会发生这种情况的人。他们的雇主(尤其是CTO)更加鲁ck,他们允许应用程序退出,使任何系统都受到不受管/不受控制的暴露。但是,我总是对看起来“我们永远不会学”的东西感到困惑。

SoapBoxEnd

总结一下。制作一个坚实而紧密的服务器端API。根据客户端可以处理的一切,将其他所有内容卸载到客户端。


6

我认为你真的不能。如果您愿意将数据发送给客户端,则必须期望它将被滥用-可能的话。您关于API密钥的示例说明了这一点,我不会在您的客户端JS中包括它-它会被盗用。

您绝对仍然需要一定数量的服务器代码来确保事物的安全。甚至只是检索与已登录用户有关的数据之类的简单操作。身份验证不能全部在客户端完成,否则您将被利用,并且您的数据不安全。

我总是将JS客户端体验视为服务器代码的补充。在客户端上进行验证可提供良好的用户体验,但是如果您也未验证接收服务器上的POST数据,则可能会遭受攻击。客户的任何东西都应视为可疑物品。


4

确实很简单。假定客户端计算机及其上运行的所有软件都在一个聪明的恶意黑客的完全控制之下。

这意味着恶意软件将知道您从服务器发送到客户端的任何信息,因此您必须确保不向客户端发送任何可用于攻击服务器或企业的信息。

这也意味着从客户端发送到服务器的所有内容都是由恶意黑客产生的,因此您的服务器代码必须确保客户端无法发送的任何内容都能够成功攻击您的服务器。

诚然,实现是一个问题,但是重要的是心态,即您认为服务器正在与之交谈的“客户端”不是客户端而是活跃的攻击者。

(您还需要假设用户是一个聪明的骗子,将尝试攻击您的业务方法,但这与客户端编程无关)。


0

在我看来,客户端应用程序主要是关于UI的。例如,您的所有UI系统将一次发送给客户端,然后客户端将对其执行任何操作。

通常,我会让我的应用程序在服务器上运行。我会从服务器上的代码中调用第三方API。

运行客户端应用程序意味着这现在需要在用户的浏览器上进行。第三方API提供了实现此目的所需的JavaScript文件。

如果您具有API密钥,则该密钥不适合在客户端使用。如果您在客户端提供API密钥,那么任何人都可以访问它,然后可以将其用于自己的目的。存储它并在客户端需要它时在服务器端使用它,然后使用Ajax / WebSockets发送结果。

就像您的银行在说:“好吧,我要输入主数据库客户端的密码,以便客户端可以自己请求它,而他不会再打扰我们的服务器了。”

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.