git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 16/18] receive-pack: GPG-validate push certificates

From
Junio C Hamano <gitster@pobox.com>
Date
Aug 20, 2014, 19:38 UTC
Message-ID
<xmqqr40bt0i0.fsf@gitster.dls.corp.google.com>
In-Reply-To
<1408557408.1282.5.camel@leckie>
David Turner <dturner@twopensource.com> writes:
Show 29 quoted lines
> On Wed, 2014-08-20 at 10:29 -0700, Junio C Hamano wrote:
>> On Wed, Aug 20, 2014 at 9:56 AM, David Turner <dturner@twopensource.com> wrote:
>> > On Tue, 2014-08-19 at 15:06 -0700, Junio C Hamano wrote:
>> >> Reusing the GPG signature check helpers we already have, verify
>> >> the signature in receive-pack and give the results to the hooks
>> >> via GIT_PUSH_CERT_{SIGNER,KEY,STATUS} environment variables.
>> >>
>> >> Policy decisions, such as accepting or rejecting a good signature by
>> >> a key that is not fully trusted, is left to the hook and kept
>> >> outside of the core.
>> >
>> > If I understand correctly, the hook does not have enough information to
>> > make this decision, because it is missing the date from the signature.
>> 
>> The full certificate is available to the hook so anything we can do the hook
>> has enough information to do ;-)  But of course we should try to make it
>> easier for the hook to validate the request.
>
> Excellent, then motivated hooks can do the right thing.
>
>> > This might allow an old signed push to be replayed, moving the head of a
>> > branch to an older state (say, one lacking the latest security updates).
>> 
>> ... with old-sha1 recorded in the certificate?
>
> That does prevent most replays, but it does not prevent resurrection of
> a deleted branch by a replay of its initial creation (nor an undo of a
> force-push to rollback).  So I think we still need timestamps, but
> parsing them out of the cert is not terrible.

As I aleady mentioned elsewhere, a more problematic thing about the push certificate as presented in 15/18 is that it does not say anything about where the push is going. If you can capture a trial push to some random test repository I do with my signed push certificate, you could replay it to my public repository hosted at a more official site (say, k.org in the far distant future where it does not rely on ssh authentication to protect their services but uses the GPG signature on the push certificate to make sure it is I who is pushing).

We can add a new "pushed-to <repository URL>" header line to the certificate, next to "pushed-by <ident> <time>", and have the receiving end verify that it matches to prevent such a replay. I wonder if we can further extend it to avoid replays to the same repository.

Instead of "pushed-to", we can tweak the capability advertisement sent from the server upon initial contact to advertise not just "push-cert", but "push-cert=<nonce>", add a new "push-nonce <nonce>" header to the certificate and then have the receiving end make sure they are the same. That way, the receiver can make sure it is not being fed a certificate used when a different push was done to it or somebody else and by doing so we do not even need "pushed-to <repository URL>" header, perhaps?

I am still fuzzy how robust such a scheme be against MITM, though. One way I can think of to attack the "nonce-only" scheme would be to create a "you can push anything here" service, convince me to push garbage there, and when I try to push to it, it can turn around and act as a client to some high-value site the attacker does not even control, grab the <nonce>, relay it back to me and advertise the same <nonce>, have me sign the certificate to push garbage, and relay that push session to the high-value target.

I am not sure if that is a valid threat model we would care about, but with "pushed-to <repository URL>" the high-value target site can notice that I am pushing garbage to the joker site and reject the certificate.

Previous: David TurnerNext: David Turner
Message 26 of 59 in “Signed push”
  1. 00/18 Signed pushJunio C Hamano, Aug 19, 2014
  2. 01/18 receive-pack: do not overallocate command structureJunio C Hamano, Aug 19, 2014
  3. 02/18 receive-pack: parse feature request a bit earlierJunio C Hamano, Aug 19, 2014
  4. Junio C HamanoAug 19, 2014
  5. 03/18 receive-pack: do not reuse old_sha1[] to other thingsJunio C Hamano, Aug 19, 2014
  6. Junio C HamanoAug 19, 2014
  7. 04/18 receive-pack: factor out queueing of commandJunio C Hamano, Aug 19, 2014
  8. 05/18 send-pack: move REF_STATUS_REJECT_NODELETE logic a bit higherJunio C Hamano, Aug 19, 2014
  9. 06/18 send-pack: refactor decision to send update per refJunio C Hamano, Aug 19, 2014
  10. 07/18 send-pack: always send capabilitiesJunio C Hamano, Aug 19, 2014
  11. 08/18 send-pack: factor out capability string generationJunio C Hamano, Aug 19, 2014
  12. 09/18 send-pack: rename "new_refs" to "need_pack_data"Junio C Hamano, Aug 19, 2014
  13. 10/18 send-pack: refactor inspecting and resetting status and sending commandsJunio C Hamano, Aug 19, 2014
  14. 11/18 send-pack: clarify that cmds_sent is a booleanJunio C Hamano, Aug 19, 2014
  15. 12/18 gpg-interface: move parse_gpg_output() to where it should beJunio C Hamano, Aug 19, 2014
  16. 13/18 gpg-interface: move parse_signature() to where it should beJunio C Hamano, Aug 19, 2014
  17. 14/18 pack-protocol doc: typofix for PKT-LINEJunio C Hamano, Aug 19, 2014
  18. 15/18 the beginning of the signed pushJunio C Hamano, Aug 19, 2014
  19. brian m. carlsonAug 20, 2014
  20. Bert WesargAug 20, 2014
  21. Junio C HamanoAug 20, 2014
  22. 16/18 receive-pack: GPG-validate push certificatesJunio C Hamano, Aug 19, 2014
  23. David TurnerAug 20, 2014
  24. Junio C HamanoAug 20, 2014
  25. David TurnerAug 20, 2014
  26. Junio C HamanoAug 20, 2014
  27. David TurnerAug 21, 2014
  28. Junio C HamanoAug 22, 2014
  29. 17/18 send-pack: send feature request on push-cert packetJunio C Hamano, Aug 19, 2014
  30. 18/18 signed push: final protocol updateJunio C Hamano, Aug 19, 2014
  31. Shawn PearceAug 21, 2014
  32. Junio C HamanoAug 21, 2014
  33. Kyle J. McKayAug 22, 2014
  34. Junio C HamanoAug 22, 2014
  35. Shawn PearceAug 22, 2014
  36. Junio C HamanoAug 25, 2014
  37. Shawn PearceAug 26, 2014
  38. Junio C HamanoAug 26, 2014
  39. Junio C HamanoAug 26, 2014
  40. Junio C HamanoSep 4, 2014
  41. Shawn PearceSep 5, 2014
  42. Junio C HamanoAug 22, 2014
  43. David TurnerAug 22, 2014
  44. Duy NguyenAug 19, 2014
  45. Junio C HamanoAug 19, 2014
  46. Nico WilliamsAug 20, 2014
  47. Junio C HamanoAug 20, 2014
  48. Junio C HamanoAug 20, 2014
  49. Junio C HamanoAug 20, 2014
  50. Nico WilliamsAug 20, 2014
  51. Stefan BellerAug 22, 2014
  52. Junio C HamanoAug 22, 2014
  53. Stefan BellerAug 22, 2014
  54. Junio C HamanoAug 22, 2014
  55. Stefan BellerAug 22, 2014
  56. Junio C HamanoAug 22, 2014
  57. Stefan BellerAug 22, 2014
  58. Junio C HamanoAug 25, 2014
  59. Jason PyeronAug 25, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.