如何保护 .NET WCF 中的 HTTP JSON Web 服务
所以,我想保护 http json Web 服务。
我将拥有一群系统用户,他们都有用户名和密码。 我只想在我的数据库中存储用户密码的随机加盐哈希,以避免在数据库被泄露的情况下发现所有密码,并使用盐(每个密码)来避免预先计算的彩虹表/字典攻击。
我一直在研究摘要身份验证,因为它的优点是通过使用服务器向客户端提供的随机“nonce”来防止重播攻击,如下所示:
A1 = string.hashMD5 (username + ":" + realm + ":" + password)
A2 = string.hashMD5 (paramTable.method + ":" + paramTable.uri)
requestdigest = string.hashMD5 (A1 + ":" + nonce + ":" + A2)
但是,为了让服务器重新计算“requestdigest” ,它必须知道“密码”,但我的服务器只能访问加盐哈希。
如果我没有使用盐,我可以在客户端添加进一步的步骤,如下所示(因为在客户端,密码是已知的) -
HashedPword = string.hashMD5(password)
A1 = string.hashMD5 (username + ":" + realm + ":" + HashedPword)
A2 = string.hashMD5 (paramTable.method + ":" + paramTable.uri)
requestdigest = string.hashMD5 (A1 + ":" + nonce + ":" + A2)
然后在服务器端,我可以从数据库检索哈希密码以执行重新计算。
唉,客户端也需要知道盐才能正确地执行此操作,例如,
HashedSaltedPword = string.hashMD5(password+salt)
A1 = string.hashMD5 (username + ":" + realm + ":" + HashedSaltedPword)
A2 = string.hashMD5 (paramTable.method + ":" + paramTable.uri)
requestdigest = string.hashMD5 (A1 + ":" + nonce + ":" + A2)
这样就可以通过暴露一个在给定用户名的情况下返回盐的 Web 服务函数来将盐传输到客户端而不进行身份验证。 但随后任何人都可以获取这些盐。
但我想知道的是,发放盐是否有问题。 因为,如果没有存储在数据库中的哈希值,盐本身是无用的,如果数据库遭到破坏,那么攻击者无论如何都可以访问哈希值和盐。 接下来,如果我免费赠送盐,那么我也可以使用用户名本身作为盐,因为每个用户都是唯一的 - 因此我什至不需要公开 Web 服务调用首先发现盐。
你们觉得怎么样?暴露盐或具有已知的盐析机制重要吗? 还有其他想法吗?
我并不真正担心消化身份验证的缺点 - 即客户端不知道它是否正在与“真实”服务器通信。因为,使用这种方法不会暴露客户的密码,而且我不会通过此链接要求客户提供任何机密信息,例如信用卡。即我想要保护的内容驻留在我的服务器上,并且服务器不会向客户端询问任何他们的安全信息。
编辑: 嗯,实际上我刚刚读了这个链接Salt,密码和安全,它基本上向我证实了这一点知道盐并不重要。 所以我正在考虑实现某种哈希,例如:
HashedSaltedPword = string.hashMD5(password+username+siteWideSaltExistingOnlyInCode)
添加站点范围的盐是为了防止有人为常见用户名创建彩虹表。 这种方法看起来安全吗?
So, I want to secure a http json web service.
I will have a bunch of users of the system who will all have a username and password.
I only want to store a randomly salted hash of user's passwords in my database so as to avoid all passwords being discovered in the case of the database being compromised, and a salt (per password) to avoid pre-computed rainbow tables / dictionary attacks.
I've been looking at digest authentication as it has the benefit of preventing replay attacks by the use of random 'nonce' provided by the server to the client, like so:
A1 = string.hashMD5 (username + ":" + realm + ":" + password)
A2 = string.hashMD5 (paramTable.method + ":" + paramTable.uri)
requestdigest = string.hashMD5 (A1 + ":" + nonce + ":" + A2)
However, in order for the server to re-compute 'requestdigest', it must know 'password', but my server will only have access to a salted hash.
If I was not using a salt, I could add a further step on the client side like so (because on the client side the password is known) -
HashedPword = string.hashMD5(password)
A1 = string.hashMD5 (username + ":" + realm + ":" + HashedPword)
A2 = string.hashMD5 (paramTable.method + ":" + paramTable.uri)
requestdigest = string.hashMD5 (A1 + ":" + nonce + ":" + A2)
And then on the server side I could retrieve the Hashed password from the db to perform the re-computation.
Alas, the client would need to know the salt as well in order to do it properly which would be e.g.
HashedSaltedPword = string.hashMD5(password+salt)
A1 = string.hashMD5 (username + ":" + realm + ":" + HashedSaltedPword)
A2 = string.hashMD5 (paramTable.method + ":" + paramTable.uri)
requestdigest = string.hashMD5 (A1 + ":" + nonce + ":" + A2)
So that leaves transmitting the salt to the client without authentication by maybe exposing a web service function that returns the salt, given a username.
But then anyone could get access to the salts.
What i'm wondering though is if giving out the salts is a problem or not.
Because, the salt on it's own is useless without the hash stored in the database, and if the database is compromised, then the attacker would have access to both the hashes and salt anyway.
And following on from that, if I give away the salt for free, then I may as well just use the username itself AS the salt, as that would be unique per user - and thus I wouldn't even need to expose a webservice call to discover the salt in the first place.
What do you guys think? Does exposing salts or having a known salting mechanism matter?
Any other thoughts?
I'm not really worried about the downside to digest authentication - i.e. that the client does not know if it is talking to the 'real' server or not. Because, it's not like the client's password is going to be exposed using this method, and i'm not asking the client for anything confidential over this link like a credit card. I.e. stuff i want to secure resides on my server, and the server won't be asking the client for any of THEIR secure information.
Edit:
hmm, actually i just read this link Salt, passwords and security which does basically confirmed to me that knowing the salt does not matter.
So i'm thinking of implementing some sortof hash like:
HashedSaltedPword = string.hashMD5(password+username+siteWideSaltExistingOnlyInCode)
The addition of the site-wide salt is in case someone has created rainbow tables for common username's.
Does this approach seem secure?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您必须选择传输密码的方式。您想仅将哈希值从客户端传输到服务器端吗?在这种情况下,服务器必须存储密码,否则将无法重新计算哈希值。您希望服务器不存储密码吗?在这种情况下,您必须以纯文本形式传输密码,以便服务器可以计算哈希值并将其与存储的哈希值进行比较。
前一种情况需要在数据库中存储密码,如果您想保护它们,您应该使用某种数据库/应用程序级加密。后一种情况需要安全传输(HTTPS、VPN 等),因为密码以可读形式传输。
You must choose how do you want transmit password. Do you want to transmit it only hashed from client side to the server side? In such case server must store passwords otherwise it will not be able to recompute the hash. Do you want server to not store passwords? In such case you must transfer the password in the plain text so that server can compute the hash and compare it with stored one.
The former case requires stored passwords in database and if you want to secure them you should use some database / application level encryption. The later case requires secured transport (HTTPS, VPN, etc.) because passwords are transmitted in readable form.