View Issue Details

IDProjectCategoryView StatusLast Update
0004743Talerwallet (WebExtension)public2016-10-20 17:03
ReporterMarcello Stanisci Assigned ToFlorian Dold  
PrioritynormalSeverityminorReproducibilityhave not tried
Status closedResolutionno change required 
Summary0004743: Merchant signature needed by fulfillment URL
DescriptionThe fulfillment URL gets a set of parameters needed to reconstruct a contract, but there is no link to the
contract that was generated in the first place.

That way, a wallet can tune contract fields (the timestamp, for example), get it reconstructed, and pay for it.

The solution is to include the merchant signature along the fulfillment URL parameters, so that the frontend can then match this signature with the one it gets from the reconstruction.

Note that:

1 is not possible to include the merchant signature into the fulfillment URL because it is inside the contract.
2 the backend never stores contracts it generates the first time; it does so only when handling a /pay.
TagsNo tags attached.

Activities

Florian Dold

2016-10-19 13:55

manager   ~0011348

Right now the fulfillment URL can contain the ${H_contract} parameter, which is expanded by the wallet to be the contract hash. Would a ${merchant_pay_sig} with similar semantics be sufficient for your purpose?

Could you elaborate what we need this for?

Marcello Stanisci

2016-10-19 14:15

reporter   ~0011349

Rigth now, the payment is accomplished by:

1 Get a contract
2 Visit fulfillment URL (which contains ${H_contract} and parameter to reconstruct the contract)
3 Pay for ${H_contract} which is only checked against the contract reconstructed in 2.

Now, step 3 totally ignores the contract generated in 1. So a malicious wallet can forge/modify a contract, hash it, set ${H_contract} to this hash, and start the payment from step 2.
That can be prevented by including the merchant signature of the original contract (the one gotten in step 1) along the fulfillment URL's parameters.

So to answer to your question, a ${merchant_sig} placeholder would fix it.

Florian Dold

2016-10-19 14:44

manager   ~0011350

Last edited: 2016-10-19 14:48

Your analysis is not correct. In step (2) we set a cookie (signed, can't be forged by the client). In step (3), we only mark an article as read when the right cookie was set in step (2), see [1].

You're right that we shouldn't accept the payment before we check the cookie, but that is a much simpler change. I've just fixed that.

I'm against including the merchant's signature in the fulfillment URL by default, since then sharing the URL will also share the payment. For non-technical users, it's much less trivial to share cookies than it is to share a URL.

[1] https://www.git.taler.net/?p=merchant-frontends.git;a=blob;f=talerfrontends/blog/blog.py;h=3402f29ccada042441e5f714fce186caa67f879a;hb=816cccea794195bdd1bcc559ca5eeab4f0d38fd4#l224

Marcello Stanisci

2016-10-19 15:50

reporter   ~0011351

That is the point: we set the cookie in step (2) to the hash of the _restored_ contract. And the
restored contract is derived 100% from the parameters given in fulfillment URL, which don't contain any merchant's autorship right now. Thus the wallet can forge them and continue the payment from step (2) with a restored contract which differs from the contract of step (1).

Florian Dold

2016-10-19 15:54

manager   ~0011352

That's okay though. When restoring contracts, the merchant only allows contracts that are acceptable to the merchant.

If the merchant wants to make sure that it's really a contract from step (1), they'll have to include more information in the fulfillment URL or even store something about the transaction ID in a database.

That's not necessary for the blog though.

But it's a good point to raise anyway, we have to make sure that we document this properly!

Marcello Stanisci

2016-10-19 16:04

reporter   ~0011353

Ok. But as long as the fulfillment URL is used for the restoration, it must contain some proof of merchant authorship, which ${H_contract} cannot provide.

Leaving it open in case you want to reply.

Florian Dold

2016-10-19 16:06

manager   ~0011354

Yeah, the point is that the merchant can look up "authorship" in their database if there's really no other way to confirm that the restored contract is "acceptable" to the merchant.

I'm not completely opposed to having a ${merchant_pay_sig} in the fulfillment URL (that will be filled out with some dummy value when the contract isn't payed for yet).

But it's not necessary for any of the merchants we have so far!

Marcello Stanisci

2016-10-19 16:10

reporter   ~0011355

I thought the ${merchant_pay_sig} would just be the merchant's signature over the contract from step (1) (so the wallet can't forge stuff), which is never dummy ...

Florian Dold

2016-10-19 16:12

manager   ~0011356

Oops, you're right, of course.

We could also introduce a variable for the signature we get from /pay for cookie-less payments, but that's another issue I suppose!

Florian Dold

2016-10-19 16:22

manager   ~0011357

Erm ... I just re-checked what we send in /pay, and we do actually send the merchant's signature there. So I don't really see why it would also be required in the fulfillment URL ...

Marcello Stanisci

2016-10-19 18:48

reporter   ~0011358

It's true, deposit permission contains the signature, but contains H_contract as well. At this point, replacing ${H_contract} with ${merchant_pay_sig} in the fulfillment URL can be considered an optimization: we don't wait an extra round trip until /pay gets called in order to detect a fraudulent contract reconstruction.

Marcello Stanisci

2016-10-20 14:30

reporter   ~0011363

It costs two actions more: (1) /fulfillment handler
needs to store merchant_sig in the state and (2) the /pay
handler in frontend needs to check if the signature it got
in deposit permission equals the one stored in the state.

Florian Dold

2016-10-20 15:47

manager   ~0011366

That's wrong. The wallet sends the merchants signature when posting coins to /pay...

Seems like we really need to document this better ;)

Marcello Stanisci

2016-10-20 16:28

reporter   ~0011367

Yes, but the signature sent by the wallet to /pay must be compared with the one we got from the backend at reconstruction time (= when the wallet visits fulfillment URL). And we have store that signature in the state at reconstruction time, otherwise we lose it (the /pay handler does not reconstruct the contract anymore, and the backend just checks if H_contract is well signed, without reconstructing H_contract -- it cannot detect if H_contract is malicious).

Just to make clear: the goal is to verify that the wallet doesn't gives malicious parameters at fulfillment URL.

Florian Dold

2016-10-20 16:39

manager   ~0011368

Nope, the signature is checked by the backend on /pay. The contract is already restored/validated when we go to the fulfillment URL, which sets session state that /pay will check (namely the contract hash)

Could you please provide a concrete example how you could tamper with the contract in any way for the blog merchant?

Marcello Stanisci

2016-10-20 17:03

reporter   ~0011369

Sorry, I was ignoring that h_contract in deposit permission is used to access the state.

Issue History

Date Modified Username Field Change
2016-10-19 13:46 Marcello Stanisci New Issue
2016-10-19 13:46 Marcello Stanisci Status new => assigned
2016-10-19 13:46 Marcello Stanisci Assigned To => Florian Dold
2016-10-19 13:55 Florian Dold Note Added: 0011348
2016-10-19 14:15 Marcello Stanisci Note Added: 0011349
2016-10-19 14:44 Florian Dold Note Added: 0011350
2016-10-19 14:48 Florian Dold Note Edited: 0011350
2016-10-19 15:50 Marcello Stanisci Note Added: 0011351
2016-10-19 15:54 Florian Dold Note Added: 0011352
2016-10-19 16:04 Marcello Stanisci Note Added: 0011353
2016-10-19 16:06 Florian Dold Note Added: 0011354
2016-10-19 16:10 Marcello Stanisci Note Added: 0011355
2016-10-19 16:12 Florian Dold Note Added: 0011356
2016-10-19 16:22 Florian Dold Note Added: 0011357
2016-10-19 16:23 Florian Dold Status assigned => closed
2016-10-19 16:23 Florian Dold Resolution open => no change required
2016-10-19 18:48 Marcello Stanisci Note Added: 0011358
2016-10-20 14:30 Marcello Stanisci Note Added: 0011363
2016-10-20 15:47 Florian Dold Note Added: 0011366
2016-10-20 16:28 Marcello Stanisci Note Added: 0011367
2016-10-20 16:31 Marcello Stanisci Status closed => feedback
2016-10-20 16:39 Florian Dold Note Added: 0011368
2016-10-20 17:03 Marcello Stanisci Note Added: 0011369
2016-10-20 17:03 Marcello Stanisci Status feedback => assigned
2016-10-20 17:03 Marcello Stanisci Status assigned => closed
2023-04-13 20:37 Florian Dold Category wallet (WebExtensions) => wallet (WebExtension)