• Welcome to Valhalla Legends Archive.
 

Securely passing responsibility between trusted entities

Started by Arta, July 19, 2005, 09:46 AM

Previous topic - Next topic

Arta

Ok, I wanted to bounce this off people to see if I've missed anything important.

A job I'm working on at the moment requires that I pass a user from a non-secure server (A) to a secure server (B) for the purpose of registration and payment. After they've registered and paid, they need to be passed back to the non-secure server to continue their visit.

I need to make sure that users can't just skip the secure server and proceed directly to 'continuing their visit'. I don't want to do something hackish like adding a field to the database to use as a flag (eugh). I've come up with the following:

When A is sending a user to B, A hashes a prearranged secret with a salt value. It then sends the hash and the salt to B. B hashes the salt with its copy of the secret, and checks that the hashes match before allowing the user to continue. When B sends the user back to A, it does the exact same thing (with a different salt). Thus, the user cannot skip B, because the final stage of A will require a correct hash before the user can continue. Avoiding reuse of the salt prevents a replay attack.

Thoughts?

Newby

Sounds good. I would have recommended that you pass some sort of value from A -> B, so that B can give it back to A (changed or not) when the user returns from B to A, to prove he was there.
- Newby

Quote[17:32:45] * xar sets mode: -oooooooooo algorithm ban chris cipher newby stdio TehUser tnarongi|away vursed warz
[17:32:54] * xar sets mode: +o newby
[17:32:58] <xar> new rule
[17:33:02] <xar> me and newby rule all

Quote<TehUser> Man, I can't get Xorg to work properly.  This sucks.
<torque> you should probably kill yourself
<TehUser> I think I will.  Thanks, torque.

dxoigmn

I assume you are using different secrets for each direction?

Newby

- Newby

Quote[17:32:45] * xar sets mode: -oooooooooo algorithm ban chris cipher newby stdio TehUser tnarongi|away vursed warz
[17:32:54] * xar sets mode: +o newby
[17:32:58] <xar> new rule
[17:33:02] <xar> me and newby rule all

Quote<TehUser> Man, I can't get Xorg to work properly.  This sucks.
<torque> you should probably kill yourself
<TehUser> I think I will.  Thanks, torque.

Arta

Quote from: Newby on July 19, 2005, 06:09 PM
Perhaps base the value off of the current time.

That would be a terrible idea - a predictable secret would make the scheme much less secure.

Quote from: dxoigmn on July 19, 2005, 04:19 PM
I assume you are using different secrets for each direction?

I'm not sure that's necessary. Would that really be more secure, or would it just be paranoia?

Quote from: Newby on July 19, 2005, 01:56 PM
Sounds good. I would have recommended that you pass some sort of value from A -> B, so that B can give it back to A (changed or not) when the user returns from B to A, to prove he was there.

hmm, why?

Kp

Basing it off the current time isn't necessarily predictable.  Consider if the necessary value is determined as pub = (time() * X) % Y, where X and Y are 64bit (or larger) integers known only to your servers.  Then pub will automatically change over time, but also be difficult to predict without knowing X and Y.  To compensate for clock drift, you could round time down to the nearest Nth time unit, e.g. nearest minute.  Even if someone does figure out X and Y, you can change them easily, thus rendering moot the work done by the attacker.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

R.a.B.B.i.T

I thought about it a bit and that sounds like a way to double confirm (IE: "A - im giving you bob; B - okay, got bob, now im done and giving him back; A - got him; B - you sure?; A - yep!").  B would confirm A sent Bob to B from A (grr I hate that sentence), do what B needs to do, then send Bob back with a note proving it was Bob and not John who was actually there.  iago and his paranoid ways would probably be able to explain it better with one of his flow charts, but eh.

Arta

Quote from: Kp on July 19, 2005, 08:51 PM
Basing it off the current time isn't necessarily predictable.  Consider if the necessary value is determined as pub = (time() * X) % Y, where X and Y are 64bit (or larger) integers known only to your servers.  Then pub will automatically change over time, but also be difficult to predict without knowing X and Y.  To compensate for clock drift, you could round time down to the nearest Nth time unit, e.g. nearest minute.  Even if someone does figure out X and Y, you can change them easily, thus rendering moot the work done by the attacker.

If the secret isn't prearranged, then it would have to be transferred securely between A and B. That introduces a host of other problems that I don't want to deal with. I think it'll be fine to prearrange a secret and change it occasionally.

Rabbit: not sure what you're getting at. Why is a double-confirm beneficial? Doesn't it just add complexity?

R.a.B.B.i.T

I was just goin off what Newby said :\

If you want max security, a double-check isn't a bad idea.

Arta

It could easily be a bad idea. It could introduce unnecessary complexity, and thereby increase the attack surface of the system. The more complicated it is, the more can go wrong.

Adron

Making sure salts aren't reused is important. A should know what it's going to get back from B already when it sends the user off to get it. That way, there's no risk of the user finding a way to reuse a payment confirmation. If B generates a salt in some random way and A just accepts it, I don't see how you could prevent that.

Arta

A just accepts it because of the hash. A rehashes the secret and the salt, compares the hashes, and can thus be sure that B knows the secret. The security lies in the secret, not the salt - the salt is only there to prevent sending a hash of the secret by itself, which would allow a replay attack. And yes, the salt should be different every time, for the same reason.

Adron

Quote from: Arta[vL] on July 20, 2005, 09:40 AM
A just accepts it because of the hash. A rehashes the secret and the salt, compares the hashes, and can thus be sure that B knows the secret. The security lies in the secret, not the salt - the salt is only there to prevent sending a hash of the secret by itself, which would allow a replay attack. And yes, the salt should be different every time, for the same reason.


What I meant was that after user X has gotten salt1 hashed from B and sends it to A, you need to be really sure that user Y can't get the salt1+hash from user X and use that as proof that user Y has paid as well. Or that user X can't reuse his salt1 tomorrow when he's buying something else. Or that user X can't reuse his salt1 after A has been rebooted, or after the database has crashed or ....

Arta

hmm, I see what you mean. As it turns out, this is no longer a problem. Nonetheless, it's interesting :)

How would you solve that?

Adron

Quote from: Arta[vL] on July 21, 2005, 12:05 PM
hmm, I see what you mean. As it turns out, this is no longer a problem. Nonetheless, it's interesting :)

How would you solve that?

You might include current date/time and transaction id. You might include the user id. Lots of things that ensure that this particular hash is only valid for what you want it to be valid for.