编码/混淆 HTTP 参数

发布于 2024-09-28 23:35:19 字数 343 浏览 10 评论 0原文

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

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

我们希望有这样的内容: /webapp?data=EDZhjgzzkjhGZKJHGZIUYZT 并对该值进行解码在具有真实请求信息的服务器中。

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

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

We are currently working on a very simple Webapp, and we would like to "obfuscate" ( what would be the right term? ) or encode somehow the request parameter, so we can reduce the chance an idle user from sending arbitrarily data.

For instance, the url looks like /webapp?user=Oscar&count=3

We would like to have somthing like: /webapp?data=EDZhjgzzkjhGZKJHGZIUYZT and have that value decoded in the server with the real request info.

Before going into implementing something like this ourselves ( and probably doing it wrong ) I would like to know if there is something to do this already?

We have Java on the server and JavaScript on the client.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

一梦等七年七年为一梦 2024-10-05 23:35:19

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

扩展编辑

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

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

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

所以,总而言之:

  1. 通过混淆实现安全性并不是
    安全根本不存在。
  2. 你不能信任
    用户数据,即使它被掩盖。
    验证您的数据
  3. 使用安全通信通道 (SSL)
    帮助阻止其他相关威胁。

  4. 应该放弃你的方法并做
    正确的事情。正确的事情,在
    你的情况,可能意味着添加一个
    身份验证机制
    权限系统阻止用户
    避免访问它们不属于的东西
    有幸看到 - 包括
    他们可能尝试访问的东西
    篡改 GET 参数。 加里
    R 的回答
    ,以及 Dave 和 Will 的评论很受欢迎
    头上的这个。

No, don't do this. If you can build something in your client code to obfuscate the data being transmitted back to the server, then so can a willful hacker. You simply can't trust data being sent to your server, no matter what your official client does. Stick to escaping client data and validating it against a whitelist on the server side. Use SSL, and if you can, put your request parameters in a POST instead of GET.

Expansion edit

Your confusion stems from the goal to block users from tampering with request data, with the need to implementing standard security measures. Standard security measures for web applications involve using a combination of authentication, privilege and session management, audit trails, data validation, and secure communication channels.

Using SSL doesn't prevent the client from tampering with the data, but it does prevent middle-men from seeing or tampering with it. It also instructs well-behaved browsers not to cache sensitive data in the URL history.

It seems you have some sort of simple web application that has no authentication, and passes around request parameters that control it right in the GET, and thus some non-technically savvy people could probably figure out that user=WorkerBee can simply be changed to user=Boss in their browser bar, and thus they can access data they shouldn't see, or do things they shouldn't do. Your desire (or your customer's desire) to obfuscate those parameters is naïve, as it is only going to foil the least-technically savvy person. It is a half-baked measure and the reason you haven't found an existing solution is that it isn't a good approach. You're better off spending time implementing a decent authentication system with an audit trail for good measure (and if this is indeed what you do, mark Gary's answer as correct).

So, to wrap it up:

  1. Security by obfuscation isn't
    security at all.
  2. You can't trust
    user data, even if it is obscured.
    Validate your data.
  3. Using secure communication channels (SSL)
    helps block other related threats.
  4. You
    should abandon your approach and do
    the right thing. The right thing, in
    your case, probably means adding an
    authentication mechanism with a
    privilege system to prevent users
    from accessing things they aren't
    privileged enough to see - including
    things they might try to access by
    tampering with GET parameters. Gary
    R's answer
    , as well as Dave and Will's comment hit
    this one on the head.
身边 2024-10-05 23:35:19

如果您的目标是“减少空闲用户发送任意数据的机会”,我会尝试另一种更简单的方法。制作一个私有加密密钥并将其存储在您的应用程序服务器端。每当您的应用程序生成 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;
}

If your goal is to "reduce the chance an idle user from sending arbitrarily data," there's another simpler approach I would try. Make a private encryption key and store it in your application server side. Whenever your application generates a url, create a hash of the url using your private encryption key and put that hash in the query string. Whenever a user requests a page with parameters in the url, recompute the hash and see if it matches. This will give you some certainty that your application computed the url. It will leave your query string parameters readable though. In pseudo-code,

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;
}
萌逼全场 2024-10-05 23:35:19

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

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

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

If you're trying to restrict access to data then use some kind of login mechanism with a cookie providing a Single Sign On authentication key. If the client sends the cookie with the key then they can manipulate the data in accordance with the authorities associated with their account (admin, public user etc). Just look at Spring Security, CAS etc for easy to use implementations of this in Java. The tokens provided in the cookie are usually encrypted with the private key of the issuing server and are typically tamper proof.

Alternatively, if you want your public user (unauthenticated) to be able to post some data to your site, then all bets are off. You must validate on the server side. This means restricting access to certain URIs and making sure that all input is cleaned.

The golden rule here is disallow everything, except stuff you know is safe.

萌面超妹 2024-10-05 23:35:19

如果目标是防止“静态”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,所有这些工作都在 Filter 中进行,这就是我所做的。后端与此隔离。

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

我也是这么做的。

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

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

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

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

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

If the goal it to prevent "static" URLs from being manipulated, then you can simply encrypt the parameters, or sign them. It's likely "safe enough" to tack on an MD5 of the URL parameters, along with some salt. The salt can be a random string stored in the session, say.

Then you can just:

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

This technique exposes the data (i.e. they can "see" that xyz=123), but they can not change the data.

There's is an advantage of "encryption" (and I use that term loosely). This is where you encrypt the entire parameter section of the URL.

Here you can do something like:

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

The nice thing about using encryption is two fold.

One it protects the data (they user can never see that xyz=123, for example).

The other feature tho is that it's extensible:

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

Here, you can decode the original payload, and do a (safe) merge with the new data.

So, requests can ADD data to the request, just not change EXISTING data.

You can do the same via the signing technique, you would just need consolidate the entire request in to a single "blob", and that blob is implicitly signed. That's "effectively" encrypted, just a weak encryption.

Obviously you don't want to do ANY of this on the client. There's no point. If you can do it, "they" can do it and you can't tell the difference, so you may as well not do it at all -- unless you want to "encrypt" data over a normal HTTP port (vs TLS, but then folks will wisely wonder "why bother").

For Java, all this work goes in a Filter, that's the way I did it. The back end is isolated from this.

If you wish, you can make the back end completely isolated from this with an outbound filter that handles the URL encryption/signing on the way out.

That's also what I did.

The down side is that it's very involved to get it right and performant. You need a light weight HTML parser to pull out the URLs (I wrote a streaming parser to do it on the fly so it didn't copy the entire page in to RAM).

The bright side is all of the content side "just works", as they don't know anything about it.

There's also some special handling when dealing with Javascript (as your filter won't easily "know" where there's a URL to encrypt). I resolved this by requiring urls to be signed to be specific "var signedURL='....'", so I can find those easily in the output. Not as crushing a burden on designers as you might think.

The other bright side of the filter is that you can disable it. If you have some "odd behavior" happening, simply turn it off. If the behavior continues, you've found a bug related to encryption. It also let developers work in plain text and leave the encryption for integration testing.

Pain to do, but it's nice overall in the end.

悸初 2024-10-05 23:35:19

您可以使用 base64 或类似的方式对数据进行编码。我会将参数本身编码为 JSON 来序列化它们。

You can encode data using base64 or something similar. I would encode the arguments inself in JSON to serialize them.

度的依靠╰つ 2024-10-05 23:35:19

像 jCryption 之类的东西?

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

Something like jCryption ?

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文