18

我们目前正在开发一个非常简单的 Webapp,我们希望“混淆” (正确的术语是什么?)或以某种方式对请求参数进行编码,因此我们可以减少空闲用户发送任意数据的机会。

例如,网址看起来像/webapp?user=Oscar&count=3

我们希望有类似的东西:/webapp?data=EDZhjgzzkjhGZKJHGZIUYZT并在服务器中使用真实的请求信息对该值进行解码。

在我们自己实施这样的事情之前(并且可能做错了),我想知道是否有什么事情可以做到这一点?

我们在服务器上有 Java,在客户端有 JavaScript。

4

6 回答 6

32

不,不要这样做。如果您可以在客户端代码中构建一些东西来混淆传输回服务器的数据,那么一个任性的黑客也可以。无论您的官方客户端做什么,您都无法信任发送到您服务器的数据。坚持转义客户端数据并根据服务器端的白名单对其进行验证。使用 SSL,如果可以的话,将您的请求参数放在 POST 而不是 GET 中。

扩展编辑

您的困惑源于阻止用户篡改请求数据的目标,以及实施标准安全措施的需要。Web 应用程序的标准安全措施涉及使用身份验证、特权和会话管理、审计跟踪、数据验证和安全通信通道的组合。

使用 SSL 并不能防止客户端篡改数据,但可以防止中间人看到或篡改数据。它还指示行为良好的浏览器不要在 URL 历史记录中缓存敏感数据。

似乎您有某种简单的 Web 应用程序,它没有身份验证,并在 GET 中传递控制它的请求参数,因此一些非技术精明的人可能会发现user=WorkerBee可以简单地user=Boss在他们的浏览器栏中更改为,因此他们可以访问他们不应该看到的数据,或者做他们不应该做的事情。您混淆这些参数的愿望(或您的客户的愿望)是幼稚的,因为它只会挫败最不精通技术的人。这是一个半生不熟的措施,您没有找到现有解决方案的原因是它不是一个好方法。您最好花时间实施一个体面的身份验证系统,并带有审计跟踪,以便采取良好措施(如果这确实是您所做的,请标记加里的回答是正确的)。

所以,总结一下:

  1. 混淆的安全性根本不是安全性。
  2. 你不能信任用户数据,即使它是模糊的。 验证您的数据
  3. 使用安全通信通道 (SSL) 有助于阻止其他相关威胁。
  4. 你应该放弃你的方法,做正确的事。在你的情况下,正确的事情可能意味着添加一个具有特权系统的身份验证机制,以防止用户访问他们没有足够特权看到的东西——包括他们可能试图通过篡改 GET 参数来访问的东西。Gary R 的回答,以及 Dave 和 Will 的评论一针见血。
于 2010-10-25T18:54:19.040 回答
13

如果您的目标是“减少空闲用户发送任意数据的机会”,我会尝试另一种更简单的方法。制作一个私有加密密钥并将其存储在您的应用程序服务器端。每当您的应用程序生成 url 时,使用您的私有加密密钥创建 url 的哈希并将该哈希放入查询字符串中。每当用户请求带有 url 中参数的页面时,重新计算哈希并查看它是否匹配。这将使您确定您的应用程序计算了 url。它会让您的查询字符串参数可读。在伪代码中,

SALT = "so9dnfi3i21nwpsodjf";

function computeUrl(url) {
  return url + "&hash=" + md5(url + SALT );
}

function checkUrl(url) {
  hash = /&hash=(.+)/.match(url);
  oldUrl = url.strip(/&hash=.+/);
  return md5(oldUrl + SALT ) == hash;
}
于 2010-10-25T19:03:18.087 回答
7

如果您尝试限制对数据的访问,请使用某种登录机制和提供单点登录身份验证密钥的 cookie。如果客户端发送带有密钥的 cookie,那么他们可以根据与其帐户关联的权限(管理员、公共用户等)来操作数据。只需查看 Spring Security、CAS 等,即可在 Java 中轻松使用此实现。cookie 中提供的令牌通常使用发行服务器的私钥加密,并且通常是防篡改的。

或者,如果您希望您的公共用户(未经身份验证)能够将一些数据发布到您的网站,那么所有的赌注都没有了。您必须在服务器端进行验证。这意味着限制对某些 URI 的访问并确保清除所有输入。

这里的黄金法则是禁止一切,除了你知道是安全的东西。

于 2010-10-25T20:15:18.633 回答
3

如果目标是防止“静态” URL 被操纵,那么您可以简单地加密参数或对其进行签名。在 URL 参数的 MD5 上加上一些盐可能“足够安全”。例如,盐可以是存储在会话中的随机字符串。

然后你可以:

http://example.com/service?x=123&y=Bob&sig=ABCD1324

这种技术暴露了数据(即他们可以“看到”xyz=123),但他们不能改变数据。

“加密”有一个优势(我松散地使用该术语)。这是您加密 URL 的整个参数部分的地方。

在这里,您可以执行以下操作:

http://example.com/service?data=ABC1235ABC

使用加密的好处有两个。

一种是保护数据(例如,他们的用户永远看不到 xyz=123)。

另一个特点是它是可扩展的:

http://example.com/service?data=ABC1235ABC&newparm=123&otherparm=abc

在这里,您可以解码原始有效负载,并与新数据进行(安全)合并。

因此,请求可以将数据添加到请求中,而不是更改现有数据。

您可以通过签名技术做同样的事情,您只需要将整个请求合并到一个“blob”中,并且该 blob 是隐式签名的。那是“有效”加密的,只是一种弱加密。

显然,您不想在客户端上执行任何此操作。毫无意义。如果你能做到,“他们”也能做到,但你无法区分,所以你最好不要这样做——除非你想通过普通的 HTTP 端口“加密”数据(与 TLS 相比,但是人们会明智地想知道“为什么要打扰”)。

对于 Java,所有这些工作都在一个过滤器中进行,我就是这样做的。后端与此隔离。

如果您愿意,您可以使用出站过滤器使后端与此完全隔离,该过滤器在出站时处理 URL 加密/签名。

这也是我所做的。

不利的一面是,要使其正确且高效,需要非常复杂。您需要一个轻量级的 HTML 解析器来提取 URL(我编写了一个流式解析器来即时执行此操作,因此它不会将整个页面复制到 RAM 中)。

好的一面是所有内容方面都“正常工作”,因为他们对此一无所知。

在处理 Javascript 时还有一些特殊处理(因为您的过滤器不会轻易“知道”哪里有要加密的 URL)。我通过要求将 url 签名为特定的“var signedURL='....'”来解决这个问题,因此我可以在输出中轻松找到它们。不像你想象的那样给设计师带来沉重的负担。

过滤器的另一个亮点是您可以禁用它。如果您发生了一些“奇怪的行为”,只需将其关闭即可。如果该行为继续存在,则您发现了与加密相关的错误。它还允许开发人员以纯文本形式工作,并将加密留给集成测试。

做起来很痛苦,但总体来说还是不错的。

于 2010-10-25T19:29:23.337 回答
1

像 jCryption 之类的东西?

http://www.jcryption.org/examples/

于 2010-10-25T19:08:57.003 回答
1

您可以使用 base64 或类似的东西对数据进行编码。我会在 JSON 中对参数本身进行编码以序列化它们。

于 2010-10-25T18:54:44.950 回答