Re: [RFC] tag-ref and tag object binding
On Tue, Jan 26, 2016 at 01:13:16PM -0800, Junio C Hamano wrote: > Jeff Kingwrites: > > > On Tue, Jan 26, 2016 at 10:29:42AM -0500, Santiago Torres wrote: > > > >> > If you cannot trust those with write access to a repo that you are > >> > pulling and installing from you might want to re-check where you are > >> > pulling or installing from ;) > >> > >> Yeah, I see your point, but mechanisms to ensure the server's origin can > >> be bypassed (e.g., a MITM). I don't think it would hurt to ensure the > >> source pointed to is the source itself. The tag signature can help us do > >> this. > > > > Right. I think the more interesting use case here is "I trust the > > upstream repository owner, but I do not trust their hosting site of > > choice." > > Yup, and push-certificate is there to help with that issue. Yes, I agree, but wouldn't this provide an in-band solution to this very particular scenario. In order to provide the spureous tag, you have to provide the tagname it should be pointing to (or tamper with the tag object). Push certificates can address many other sorts of attacks, but are not in-band in this sense are they? Thanks! -Santiago. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
Hello, sorry for being MIA yesterday among all this movement... On Wed, Jan 27, 2016 at 08:53:08AM +0100, Michael J Gruber wrote: > Jeff King venit, vidit, dixit 27.01.2016 08:33: > > On Wed, Jan 27, 2016 at 08:23:02AM +0100, Michael J Gruber wrote: > > > >>> Tag objects already have a "tag" header, which is part of the signed > >>> content. If you use "git verify-tag -v", you can check both that the > >>> signature is valid and that the tag is the one you are expecting. > >> > >> Yes, that's what I described in my last paragraph, using the term > >> (embedded) tag "name" which is technically wrong (it's not the tag > >> object's name, which would be a sha1) but the natural term for users. > > > > Indeed. I should have read further back in the quoting. :) > > > >>> Git pretty much punts on all of these issues and assumes either a human > >>> or a smarter tool is looking at the verification output. But I don't > >>> think it would hurt to build in some features to let git automatically > >>> check some things, if only to avoid callers duplicating work to > >>> implement the checks themselves. > >> > >> That is really a can of worms for several reasons: > >> [...] > >> So, for those who shy away from for-each-ref and such, we may add the > >> header check to verify-tag, with a big warning about the marginal gain > >> in security (or the requirements for an actual gain). > > > > Yeah, definitely. My thinking was that `verify-tag` could learn a series > > of optional consistency checks, enabled by command line options, and > > verifying programs (or humans) could turn them on to avoid having to > > replicate them manually. So something like: > > > > git verify-tag \ > > --verify-tagger-matches-key \ > > --verify-tag-matches-ref \ # or --verify-tag-matches=v2.0.0 > > v2.0.0 > > > > or to implement more specific policy, maybe an option to check for a > > _specific_ tagger, either by email (as provided by gpg) or even key-id. > > > > Those are all things that are not _too_ hard to do if you're willing to > > parse gpg or git output, but we could make life easier for our callers. > > And hopefully by asking for specific, concrete checks, it doesn't > > introduce a false sense of security. I.e., we're not making a foolproof > > tool; we're making building blocks that one could use for a more > > foolproof tool. > > OK, let's make a tool that helps fooling as well as proofing :) > > I'll look into the tag header check. Maybe "--check-tagname"? "check" > seems to imply less than "verify". This seems like exactly what I was thinking of. What I believe would be helpful is to provide upstream tools the means to automatically verify tags (--check-tagname could return non-0 if the tagname doesn't match), could this possibly be the default behavior (--no-check-tagname instead)? What worries me is something like this experiment with pip: (git-tag2) santiago@LykOS:~$ pip install -e git+https://github.com/santiagotorres/django/@1.8.3#egg=django Obtaining django from git+https://github.com/santiagotorres/django/@1.8.3#egg=django Cloning https://github.com/santiagotorres/django/ (to 1.8.3) to ./.virtualenvs/git-tag2/src/django Installing collected packages: django Running setup.py develop for django Successfully installed django (git-tag2) santiago@LykOS:~$ django-admin.py --version 1.4.10 I only had to swap the tag refs and push for this simulation. Needless to say, this deprectated django version (1.4.10) is vulnerable to a wide range known exploits that include session hijacking, DoS, "MySQL typecasting" and XSS. And the person who served this tampered tag could exploit the webserver right away (knows who got this vulnerable package). Of course, this could also trick a CI system and have people package the wrong version of django. I agree that nothing beats manual inspection of a paranoid developer, but these tools are widely used today and could avoid these edge cases. > > As for the gpg related stuff: We provide the full diagnostic output from > gpg on request. But I think a mismatch between the signing key's uid and > the taggers' name/email is more common than not, and on the other hand a > signature by a key identified by its uid is meaningless unless you keep > your keyring tidy... We could punt on that and let users identify the > key by any means that gpg allows, of course, and check that the > signature comes from whatever "gpg --list-key " gives as > long as it's unique. > > But maybe I'm biased by my zoo of uids/emails addresses/full name > spellings... and general paranoia regarding the term "verify" ;) Yeah, I believe the gpg related stuff might be a little out of scope. I think, for the sake of this RFC, that we could assume that tools/people have acess to the right key and could perform verification. As it was already pointed out, key distribution and a project-specific gpg keychain could be integrated. The problem I see is that, even with the right key and a
Re: [RFC] tag-ref and tag object binding
On Wed, Jan 27, 2016 at 08:53:08AM +0100, Michael J Gruber wrote: > > Yeah, definitely. My thinking was that `verify-tag` could learn a series > > of optional consistency checks, enabled by command line options, and > > verifying programs (or humans) could turn them on to avoid having to > > replicate them manually. So something like: > > > > git verify-tag \ > > --verify-tagger-matches-key \ > > --verify-tag-matches-ref \ # or --verify-tag-matches=v2.0.0 > > v2.0.0 > > > > or to implement more specific policy, maybe an option to check for a > > _specific_ tagger, either by email (as provided by gpg) or even key-id. > > > > Those are all things that are not _too_ hard to do if you're willing to > > parse gpg or git output, but we could make life easier for our callers. > > And hopefully by asking for specific, concrete checks, it doesn't > > introduce a false sense of security. I.e., we're not making a foolproof > > tool; we're making building blocks that one could use for a more > > foolproof tool. > > OK, let's make a tool that helps fooling as well as proofing :) > > I'll look into the tag header check. Maybe "--check-tagname"? "check" > seems to imply less than "verify". Yeah, I think that is fine (I actually wrote --check originally; I'm not quite sure why I decided to change it). > As for the gpg related stuff: We provide the full diagnostic output from > gpg on request. But I think a mismatch between the signing key's uid and > the taggers' name/email is more common than not, Is it? I'd think if you are using that name with a signed tag, you would bother to issue (and get people to sign) the matching uid. Certainly it is the case for git and linux signatures, but I admit that it a pretty small sampling size. The bigger issue is that gpg seems to give us only _one_ uid, when there may be several. E.g., Junio's v2.7.0 is signed by 96AFE6CB, which is a sub-key that has several uids associated with it. The one that "git verify-tag --raw" shows from gpg is gits...@pobox.com, which is good, but I think that's just because it happens to be the first uid. Or maybe there is some gpg arcana going on that I don't know about. > and on the other hand a > signature by a key identified by its uid is meaningless unless you keep > your keyring tidy... We could punt on that and let users identify the > key by any means that gpg allows, of course, and check that the > signature comes from whatever "gpg --list-key " gives as > long as it's unique. Right, I think it's an open question whether people actually participate in the web of trust. I don't have a good signature path to Junio's key, but I happen to know what it is based on past interaction. But then, I also do not really verify tags. Why would I? I routinely fetch and run "make" on the result, and there is no cryptographic protection there at all. Verifying tag signatures after a release seems all but pointless. :) I think for any of this to be useful, it has to be part of some tool that is very opinionated on policy. E.g., imagine a post-fetch hook that validated that each incoming commit was signed, and that the signer was part of a whitelisted group of keys that you "somehow" got hold of out-of-band for your project. That is not that useful for an open-source project, but I could see the appeal for a proprietary development environment. -Peff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
Michael J Gruberwrites: > Jeff King venit, vidit, dixit 27.01.2016 09:09: > >> The bigger issue is that gpg seems to give us only _one_ uid, when there >> may be several. E.g., Junio's v2.7.0 is signed by 96AFE6CB, which is a >> sub-key that has several uids associated with it. The one that "git >> verify-tag --raw" shows from gpg is gits...@pobox.com, which is good, >> but I think that's just because it happens to be the first uid. Or maybe >> there is some gpg arcana going on that I don't know about. > > You do not sign with a uid, you sign with a (sub)key, and the tag is > signed with Junio's primary key. His subkey is encryption only. Hmm, actually I meant to sign my tags with signing subkey, not the primary one, but I may have made a mistake. > You do sign a uid. > > So, if you want to be sure that a tag is signed "with a specific uid" by > relying on signatures from a set of signers, you would really need to > check that the key that signed the tag has a signature on the correct > uid. Having a signed key with the right uid in it doesn't mean much > unlss the right uid is signed. > > E.g., I have a key with many signatures, and I could have Junio's uid on > it in a minute without invalidating any of those signatures. I have signatures on my primary key from others, and my signing key is signed by my primary key and by no other keys. Here is an abbreviated output from running "gpg --list-sigs 96AFE6CB": pub 4096R/713660A7 2011-10-01 uid Junio C Hamano sig 3713660A7 2011-10-01 Junio C Hamano sig 3713660A7 2011-10-01 Junio C Hamano sig F3119B9A 2011-10-01 Junio C Hamano sig 493BACE4 2011-10-04 H. Peter Anvin (hpa) sig 93674C40 2011-10-04 Theodore Y. Ts'o sig 00411886 2012-07-20 Linus Torvalds sig C11804F0 2011-10-04 Theodore Ts'o sig 02A80207 2011-10-05 Andrew Morton (akpm) uid Junio C Hamano sig 3713660A7 2011-10-01 Junio C Hamano sig F3119B9A 2011-10-01 Junio C Hamano sig 493BACE4 2011-10-04 H. Peter Anvin (hpa) sig 00411886 2012-07-20 Linus Torvalds sig C11804F0 2011-10-04 Theodore Ts'o uid Junio C Hamano sig 3713660A7 2011-10-01 Junio C Hamano sig F3119B9A 2011-10-01 Junio C Hamano sig 493BACE4 2011-10-04 H. Peter Anvin (hpa) sig 00411886 2012-07-20 Linus Torvalds sub 4096R/833262C4 2011-10-01 sig 713660A7 2011-10-01 Junio C Hamano sub 4096R/96AFE6CB 2011-10-03 [expires: 2017-09-20] sig 713660A7 2015-09-21 Junio C Hamano sub 4096R/B3F7CAC9 2014-09-20 [expires: 2017-09-19] sig 713660A7 2014-09-20 Junio C Hamano So I understand that the way you trust 96AFE6CB has to be indirect. You may have somebody's key you know belongs to that somebody you trust (say, Linus) in the list of signers of 713660A7 (my primary), and you know 96AFE6CB is a key I use because it is signed by my primary key. You can add a subkey to your keyring a uid that says "Junio", but the signature on that subkey would not have a signature by me you can verify by following the web of trust. You are correct to point out that "this key claims to be by somebody, and it has some signature" is not a sufficient reason for you to trust it. > That one is easy already by setting "GNUPGHOME" to a special dir with a > small keyring and tight trust settings (or having a dedicated account on > the incoming side in the first place). Yes, I understand that the above is how automated services per project should be set up, with a dedicated verification keyring that holds keys the project trusts. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
Junio C Hamano venit, vidit, dixit 27.01.2016 19:10: > Michael J Gruberwrites: > >> Jeff King venit, vidit, dixit 27.01.2016 09:09: >> >>> The bigger issue is that gpg seems to give us only _one_ uid, when there >>> may be several. E.g., Junio's v2.7.0 is signed by 96AFE6CB, which is a >>> sub-key that has several uids associated with it. The one that "git >>> verify-tag --raw" shows from gpg is gits...@pobox.com, which is good, >>> but I think that's just because it happens to be the first uid. Or maybe >>> there is some gpg arcana going on that I don't know about. >> >> You do not sign with a uid, you sign with a (sub)key, and the tag is >> signed with Junio's primary key. His subkey is encryption only. > > Hmm, actually I meant to sign my tags with signing subkey, not the > primary one, but I may have made a mistake. Oops, I needed to refresh my copy of your key, sorry. You did sign 2.7.0 with the subkey 0xB0B5E88696AFE6CB >> You do sign a uid. >> >> So, if you want to be sure that a tag is signed "with a specific uid" by >> relying on signatures from a set of signers, you would really need to >> check that the key that signed the tag has a signature on the correct >> uid. Having a signed key with the right uid in it doesn't mean much >> unlss the right uid is signed. >> >> E.g., I have a key with many signatures, and I could have Junio's uid on >> it in a minute without invalidating any of those signatures. > > I have signatures on my primary key from others, and my signing key > is signed by my primary key and by no other keys. Here is an > abbreviated output from running "gpg --list-sigs 96AFE6CB": > > pub 4096R/713660A7 2011-10-01 > uid Junio C Hamano > sig 3713660A7 2011-10-01 Junio C Hamano > sig 3713660A7 2011-10-01 Junio C Hamano > sig F3119B9A 2011-10-01 Junio C Hamano > sig 493BACE4 2011-10-04 H. Peter Anvin (hpa) > sig 93674C40 2011-10-04 Theodore Y. Ts'o > sig 00411886 2012-07-20 Linus Torvalds > > sig C11804F0 2011-10-04 Theodore Ts'o > sig 02A80207 2011-10-05 Andrew Morton (akpm) > > uid Junio C Hamano > sig 3713660A7 2011-10-01 Junio C Hamano > sig F3119B9A 2011-10-01 Junio C Hamano > sig 493BACE4 2011-10-04 H. Peter Anvin (hpa) > sig 00411886 2012-07-20 Linus Torvalds > > sig C11804F0 2011-10-04 Theodore Ts'o > uid Junio C Hamano > sig 3713660A7 2011-10-01 Junio C Hamano > sig F3119B9A 2011-10-01 Junio C Hamano > sig 493BACE4 2011-10-04 H. Peter Anvin (hpa) > sig 00411886 2012-07-20 Linus Torvalds > > sub 4096R/833262C4 2011-10-01 > sig 713660A7 2011-10-01 Junio C Hamano > sub 4096R/96AFE6CB 2011-10-03 [expires: 2017-09-20] > sig 713660A7 2015-09-21 Junio C Hamano > sub 4096R/B3F7CAC9 2014-09-20 [expires: 2017-09-19] > sig 713660A7 2014-09-20 Junio C Hamano > > So I understand that the way you trust 96AFE6CB has to be indirect. > You may have somebody's key you know belongs to that somebody you > trust (say, Linus) in the list of signers of 713660A7 (my primary), > and you know 96AFE6CB is a key I use because it is signed by my > primary key. > > You can add a subkey to your keyring a uid that says "Junio", but > the signature on that subkey would not have a signature by me you > can verify by following the web of trust. You are correct to point > out that "this key claims to be by somebody, and it has some > signature" is not a sufficient reason for you to trust it. "subkey" and "uid" are different things. You bind a subkey to your primary key with that self-signature. subkeys don't carry any other signatures. A primary key "carries" the uids, and whenever someone "signs your key" they in fact sign a specific uid - usually all, resulting in multiple signatures, one for each uid of the (primary) key. A key is usually considered trusted if it carries "a" signature from a trusted key. So, assuming my key carries a signature from a trusted key to at least one uid, it would be trusted no matter what (fake) uids I add to it later. >> That one is easy already by setting "GNUPGHOME" to a special dir with a >> small keyring and tight trust settings (or having a dedicated account on >> the incoming side in the first place). > > Yes, I understand that the above is how automated services per > project should be set up, with a
Re: [RFC] tag-ref and tag object binding
On Wed, Jan 27, 2016 at 09:09:31PM +0100, Michael J Gruber wrote: > "subkey" and "uid" are different things. You bind a subkey to your > primary key with that self-signature. subkeys don't carry any other > signatures. > > A primary key "carries" the uids, and whenever someone "signs your key" > they in fact sign a specific uid - usually all, resulting in multiple > signatures, one for each uid of the (primary) key. > > A key is usually considered trusted if it carries "a" signature from a > trusted key. > > So, assuming my key carries a signature from a trusted key to at least > one uid, it would be trusted no matter what (fake) uids I add to it later. Right. I think I didn't do a good job of explaining myself earlier, so let me try to rephrase. When we look at the v2.7 tag, GPG sees that we are signed by Junio's subkey, 96AFE6CB. It then knows that belongs to the main public key 713660A7, because the main key signed the subkey. And then it sees that there are several uids for that main key, each with their own signatures by other people. So of the three uids that I have for that key: pub 4096R/713660A7 2011-10-01 uid Junio C Hamanouid Junio C Hamano uid Junio C Hamano it reports back to git only one (the pobox.com), which we relay to the user via --raw. If we wanted to check that the key matches the "tagger" header, that works. But why did gpg return that first uid, and not any of the others? We would ideally see all of them, and consider it OK if it matches any uid (assuming that uid is sufficiently signed for gpg to consider it valid). Weirder, if you _don't_ use "--raw", the human-readable output gives us all of the uids as "aka" lines: $ git verify-tag v2.7.0 $ git verify-tag v2.7.0 gpg: Signature made Mon 04 Jan 2016 05:08:12 PM EST using RSA key ID 96AFE6CB gpg: Good signature from "Junio C Hamano " gpg: aka "Junio C Hamano " gpg: aka "Junio C Hamano " $ git verify-tag --raw v2.7.0 [GNUPG:] SIG_ID xFANmHj+QJ1gwIcoRuT5BF/y8H4 2016-01-04 1451945292 [GNUPG:] GOODSIG B0B5E88696AFE6CB Junio C Hamano [GNUPG:] VALIDSIG E1F036B1FEE7221FC778ECEFB0B5E88696AFE6CB 2016-01-04 1451945292 0 4 0 1 2 00 96E07AF25771955980DAD10020D04E5A713660A7 [GNUPG:] TRUST_FULLY It seems like we should be able to get the raw-output to tell us all of those uids. I guess it is not the end of the world to go back to gpg and say "give me all of the valid uids that match this signing key", but it seems silly to have to do so. -Peff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
Jeff King venit, vidit, dixit 27.01.2016 09:09: > On Wed, Jan 27, 2016 at 08:53:08AM +0100, Michael J Gruber wrote: > >>> Yeah, definitely. My thinking was that `verify-tag` could learn a series >>> of optional consistency checks, enabled by command line options, and >>> verifying programs (or humans) could turn them on to avoid having to >>> replicate them manually. So something like: >>> >>> git verify-tag \ >>> --verify-tagger-matches-key \ >>> --verify-tag-matches-ref \ # or --verify-tag-matches=v2.0.0 >>> v2.0.0 >>> >>> or to implement more specific policy, maybe an option to check for a >>> _specific_ tagger, either by email (as provided by gpg) or even key-id. >>> >>> Those are all things that are not _too_ hard to do if you're willing to >>> parse gpg or git output, but we could make life easier for our callers. >>> And hopefully by asking for specific, concrete checks, it doesn't >>> introduce a false sense of security. I.e., we're not making a foolproof >>> tool; we're making building blocks that one could use for a more >>> foolproof tool. >> >> OK, let's make a tool that helps fooling as well as proofing :) >> >> I'll look into the tag header check. Maybe "--check-tagname"? "check" >> seems to imply less than "verify". > > Yeah, I think that is fine (I actually wrote --check originally; I'm not > quite sure why I decided to change it). > >> As for the gpg related stuff: We provide the full diagnostic output from >> gpg on request. But I think a mismatch between the signing key's uid and >> the taggers' name/email is more common than not, > > Is it? I'd think if you are using that name with a signed tag, you would > bother to issue (and get people to sign) the matching uid. Certainly it > is the case for git and linux signatures, but I admit that it a pretty > small sampling size. > > The bigger issue is that gpg seems to give us only _one_ uid, when there > may be several. E.g., Junio's v2.7.0 is signed by 96AFE6CB, which is a > sub-key that has several uids associated with it. The one that "git > verify-tag --raw" shows from gpg is gits...@pobox.com, which is good, > but I think that's just because it happens to be the first uid. Or maybe > there is some gpg arcana going on that I don't know about. You do not sign with a uid, you sign with a (sub)key, and the tag is signed with Junio's primary key. His subkey is encryption only. uids do not identify keys, you can add and delete them at will without changing the primary key id. To help recognize ("identify") a key, gpg displays the uid with the most recent self-signature, which is usually the most "recent uid". You do sign a uid. So, if you want to be sure that a tag is signed "with a specific uid" by relying on signatures from a set of signers, you would really need to check that the key that signed the tag has a signature on the correct uid. Having a signed key with the right uid in it doesn't mean much unlss the right uid is signed. E.g., I have a key with many signatures, and I could have Junio's uid on it in a minute without invalidating any of those signatures. >> and on the other hand a >> signature by a key identified by its uid is meaningless unless you keep >> your keyring tidy... We could punt on that and let users identify the >> key by any means that gpg allows, of course, and check that the >> signature comes from whatever "gpg --list-key " gives as >> long as it's unique. > > Right, I think it's an open question whether people actually participate > in the web of trust. I don't have a good signature path to Junio's key, > but I happen to know what it is based on past interaction. > > But then, I also do not really verify tags. Why would I? I routinely > fetch and run "make" on the result, and there is no cryptographic > protection there at all. Verifying tag signatures after a release seems > all but pointless. :) No signature protects us from our own dogfood :) > I think for any of this to be useful, it has to be part of some tool > that is very opinionated on policy. E.g., imagine a post-fetch hook that > validated that each incoming commit was signed, and that the signer was > part of a whitelisted group of keys that you "somehow" got hold of > out-of-band for your project. That is not that useful for an open-source > project, but I could see the appeal for a proprietary development > environment. That one is easy already by setting "GNUPGHOME" to a special dir with a small keyring and tight trust settings (or having a dedicated account on the incoming side in the first place). Michael -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
Santiago Torres venit, vidit, dixit 25.01.2016 22:22: > Hello everyone. > > I've done some further research on the security properties of git > metadata and I think I've identified something that might be worth > discussing. In this case, The issue is related to the refs that point to > git tag objects. Specifically, the "loose" nature of tag refs might > possibly trick people into installing the wrong revision (version?) of a > file. > > To elaborate, the ref of a tag object can be moved around in the same > way a branch can be moved around (either manually or by using git > commands). If someone with write access can modify where this ref points > to, and points it to another valid tag (e.g., an older, vulnerable > version), then many tools that work under the assumption of static tags > might mistakenly install/pull the wrong reivision of source code. I've > verified that this is possible to pull off in package managers such as > PIP, rubygems, gradle(maven), as well as git submodules tracking tags. > > In order to stay loyal to the way files in the .git directory are > ordered, I don't think that making the ref file (or packed refs) files > differently is an option. However, I think that it could be possible to > store the "origin ref" in the git tag object, so tools can verify that > they are looking at the appropriate tag. There might also be a simpler > solution to this, and I would appreciate any feedback. > > What do you guys think? > > Thanks! > Santiago. If you cannot trust those with write access to a repo that you are pulling and installing from you might want to re-check where you are pulling or installing from ;) In fact, just like you shouldn't blindly download and install a tarball (but check its signature) you shouldn't blindly pull and install from a repo. Your best bet is checking the signature of signed tags. Now, if you're worried about someone maliciously pointing you to the wrong, correctly signed tag then you should verify that the tag object contains the tag "name" that you expect (for example by using "git verify-tag -v" or "git cat-file -p"), since that is part of the signed content. Michael -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
On Wed, Jan 27, 2016 at 08:23:02AM +0100, Michael J Gruber wrote: > > Tag objects already have a "tag" header, which is part of the signed > > content. If you use "git verify-tag -v", you can check both that the > > signature is valid and that the tag is the one you are expecting. > > Yes, that's what I described in my last paragraph, using the term > (embedded) tag "name" which is technically wrong (it's not the tag > object's name, which would be a sha1) but the natural term for users. Indeed. I should have read further back in the quoting. :) > > Git pretty much punts on all of these issues and assumes either a human > > or a smarter tool is looking at the verification output. But I don't > > think it would hurt to build in some features to let git automatically > > check some things, if only to avoid callers duplicating work to > > implement the checks themselves. > > That is really a can of worms for several reasons: > [...] > So, for those who shy away from for-each-ref and such, we may add the > header check to verify-tag, with a big warning about the marginal gain > in security (or the requirements for an actual gain). Yeah, definitely. My thinking was that `verify-tag` could learn a series of optional consistency checks, enabled by command line options, and verifying programs (or humans) could turn them on to avoid having to replicate them manually. So something like: git verify-tag \ --verify-tagger-matches-key \ --verify-tag-matches-ref \ # or --verify-tag-matches=v2.0.0 v2.0.0 or to implement more specific policy, maybe an option to check for a _specific_ tagger, either by email (as provided by gpg) or even key-id. Those are all things that are not _too_ hard to do if you're willing to parse gpg or git output, but we could make life easier for our callers. And hopefully by asking for specific, concrete checks, it doesn't introduce a false sense of security. I.e., we're not making a foolproof tool; we're making building blocks that one could use for a more foolproof tool. -Peff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
Jeff King venit, vidit, dixit 26.01.2016 21:26: > On Tue, Jan 26, 2016 at 10:29:42AM -0500, Santiago Torres wrote: > >>> If you cannot trust those with write access to a repo that you are >>> pulling and installing from you might want to re-check where you are >>> pulling or installing from ;) >> >> Yeah, I see your point, but mechanisms to ensure the server's origin can >> be bypassed (e.g., a MITM). I don't think it would hurt to ensure the >> source pointed to is the source itself. The tag signature can help us do >> this. > > Right. I think the more interesting use case here is "I trust the > upstream repository owner, but I do not trust their hosting site of > choice." > >>> Your best bet is checking the signature of signed tags. Now, if you're >>> worried about someone maliciously pointing you to the wrong, correctly >>> signed tag then you should verify that the tag object contains the tag >>> "name" that you expect (for example by using "git verify-tag -v" or "git >>> cat-file -p"), since that is part of the signed content. >> >> Yep, this is my intuition behind my proposal. While someone can manually >> inspect a tag (git tag -v [ref]) to ensure he's getting the correct one, >> there's no mechanism to ensure that the ref is pointing to the intended >> tag. I do believe that package managers and git submodules could check >> whether the ref is pointing to the right tag with a small change in the >> tag header. Although it would be up to each tool to implement this >> check. >> >> I don't think that an addition like this would get in the way of any >> existing git workflow, and should be backwards-compatible right? > > Doesn't this already exist? > > $ git cat-file tag v2.0.0 > object e156455ea49124c140a67623f22a393db62d5d98 > type commit > tag v2.0.0 > tagger Junio C Hamano1401300269 -0700 > > Git 2.0 > -BEGIN PGP SIGNATURE- > [...] > -END PGP SIGNATURE- > > Tag objects already have a "tag" header, which is part of the signed > content. If you use "git verify-tag -v", you can check both that the > signature is valid and that the tag is the one you are expecting. Yes, that's what I described in my last paragraph, using the term (embedded) tag "name" which is technically wrong (it's not the tag object's name, which would be a sha1) but the natural term for users. > Of course, "verify-tag" could do this for you if you give it a refname, > too, but I think that may be the tip of the iceberg in terms of > automatic verification. In particular, verify-tag knows it was signed by > _somebody_, but it doesn't know what the signing policy is. As a human, > _I_ know that Junio is the right person to be signing the release tag, > but no tool does. > > Git pretty much punts on all of these issues and assumes either a human > or a smarter tool is looking at the verification output. But I don't > think it would hurt to build in some features to let git automatically > check some things, if only to avoid callers duplicating work to > implement the checks themselves. That is really a can of worms for several reasons: - Do you fetch tags into refs/tags/ or refs/tags/upstream/ or wherever, and which part of the tag refname should we check for? We can DWIM that to the last part after / and allow "--tagname" to override, of course. - By all means, we need to avoid a false sense of security. "GOOD SIGNATURE" in gpg terms is bad enough with the usual trust model when users don't check who actually made that signature. If you don't *really* check the signature then anyone can shove a signed tag object under your nose with the *expected tag header* (tag "name") so that there is no gain at all, unless you envison a scenario where Man I. T. Middle can mess with refs but not objects. So, for those who shy away from for-each-ref and such, we may add the header check to verify-tag, with a big warning about the marginal gain in security (or the requirements for an actual gain). Michael -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
Jeff King venit, vidit, dixit 27.01.2016 08:33: > On Wed, Jan 27, 2016 at 08:23:02AM +0100, Michael J Gruber wrote: > >>> Tag objects already have a "tag" header, which is part of the signed >>> content. If you use "git verify-tag -v", you can check both that the >>> signature is valid and that the tag is the one you are expecting. >> >> Yes, that's what I described in my last paragraph, using the term >> (embedded) tag "name" which is technically wrong (it's not the tag >> object's name, which would be a sha1) but the natural term for users. > > Indeed. I should have read further back in the quoting. :) > >>> Git pretty much punts on all of these issues and assumes either a human >>> or a smarter tool is looking at the verification output. But I don't >>> think it would hurt to build in some features to let git automatically >>> check some things, if only to avoid callers duplicating work to >>> implement the checks themselves. >> >> That is really a can of worms for several reasons: >> [...] >> So, for those who shy away from for-each-ref and such, we may add the >> header check to verify-tag, with a big warning about the marginal gain >> in security (or the requirements for an actual gain). > > Yeah, definitely. My thinking was that `verify-tag` could learn a series > of optional consistency checks, enabled by command line options, and > verifying programs (or humans) could turn them on to avoid having to > replicate them manually. So something like: > > git verify-tag \ > --verify-tagger-matches-key \ > --verify-tag-matches-ref \ # or --verify-tag-matches=v2.0.0 > v2.0.0 > > or to implement more specific policy, maybe an option to check for a > _specific_ tagger, either by email (as provided by gpg) or even key-id. > > Those are all things that are not _too_ hard to do if you're willing to > parse gpg or git output, but we could make life easier for our callers. > And hopefully by asking for specific, concrete checks, it doesn't > introduce a false sense of security. I.e., we're not making a foolproof > tool; we're making building blocks that one could use for a more > foolproof tool. OK, let's make a tool that helps fooling as well as proofing :) I'll look into the tag header check. Maybe "--check-tagname"? "check" seems to imply less than "verify". As for the gpg related stuff: We provide the full diagnostic output from gpg on request. But I think a mismatch between the signing key's uid and the taggers' name/email is more common than not, and on the other hand a signature by a key identified by its uid is meaningless unless you keep your keyring tidy... We could punt on that and let users identify the key by any means that gpg allows, of course, and check that the signature comes from whatever "gpg --list-key " gives as long as it's unique. But maybe I'm biased by my zoo of uids/emails addresses/full name spellings... and general paranoia regarding the term "verify" ;) Michael -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
On Tue, Jan 26, 2016 at 10:35:34AM +0100, Michael J Gruber wrote: > Santiago Torres venit, vidit, dixit 25.01.2016 22:22: > > Hello everyone. > > > > I've done some further research on the security properties of git > > metadata and I think I've identified something that might be worth > > discussing. In this case, The issue is related to the refs that point to > > git tag objects. Specifically, the "loose" nature of tag refs might > > possibly trick people into installing the wrong revision (version?) of a > > file. > > > > To elaborate, the ref of a tag object can be moved around in the same > > way a branch can be moved around (either manually or by using git > > commands). If someone with write access can modify where this ref points > > to, and points it to another valid tag (e.g., an older, vulnerable > > version), then many tools that work under the assumption of static tags > > might mistakenly install/pull the wrong reivision of source code. I've > > verified that this is possible to pull off in package managers such as > > PIP, rubygems, gradle(maven), as well as git submodules tracking tags. > > > > In order to stay loyal to the way files in the .git directory are > > ordered, I don't think that making the ref file (or packed refs) files > > differently is an option. However, I think that it could be possible to > > store the "origin ref" in the git tag object, so tools can verify that > > they are looking at the appropriate tag. There might also be a simpler > > solution to this, and I would appreciate any feedback. > > > > What do you guys think? > > > > Thanks! > > Santiago. > > If you cannot trust those with write access to a repo that you are > pulling and installing from you might want to re-check where you are > pulling or installing from ;) Yeah, I see your point, but mechanisms to ensure the server's origin can be bypassed (e.g., a MITM). I don't think it would hurt to ensure the source pointed to is the source itself. The tag signature can help us do this. > > In fact, just like you shouldn't blindly download and install a tarball > (but check its signature) you shouldn't blindly pull and install from a > repo. Yep. As a matter of fact, many of these package managers can install from a specific commit, which should be safer. However, I do think that pointing to a tag is more "usable" given that they are human-readable. Also, tags are usually meant to point to releases, so it follows its design pattern doesn't it?. I think it wouldn't be a bad idea to provide a hard-binding between tag-refs and tags themselves. > > Your best bet is checking the signature of signed tags. Now, if you're > worried about someone maliciously pointing you to the wrong, correctly > signed tag then you should verify that the tag object contains the tag > "name" that you expect (for example by using "git verify-tag -v" or "git > cat-file -p"), since that is part of the signed content. Yep, this is my intuition behind my proposal. While someone can manually inspect a tag (git tag -v [ref]) to ensure he's getting the correct one, there's no mechanism to ensure that the ref is pointing to the intended tag. I do believe that package managers and git submodules could check whether the ref is pointing to the right tag with a small change in the tag header. Although it would be up to each tool to implement this check. I don't think that an addition like this would get in the way of any existing git workflow, and should be backwards-compatible right? Thanks, -Santiago. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
On Tue, Jan 26, 2016 at 10:29:42AM -0500, Santiago Torres wrote: > > If you cannot trust those with write access to a repo that you are > > pulling and installing from you might want to re-check where you are > > pulling or installing from ;) > > Yeah, I see your point, but mechanisms to ensure the server's origin can > be bypassed (e.g., a MITM). I don't think it would hurt to ensure the > source pointed to is the source itself. The tag signature can help us do > this. Right. I think the more interesting use case here is "I trust the upstream repository owner, but I do not trust their hosting site of choice." > > Your best bet is checking the signature of signed tags. Now, if you're > > worried about someone maliciously pointing you to the wrong, correctly > > signed tag then you should verify that the tag object contains the tag > > "name" that you expect (for example by using "git verify-tag -v" or "git > > cat-file -p"), since that is part of the signed content. > > Yep, this is my intuition behind my proposal. While someone can manually > inspect a tag (git tag -v [ref]) to ensure he's getting the correct one, > there's no mechanism to ensure that the ref is pointing to the intended > tag. I do believe that package managers and git submodules could check > whether the ref is pointing to the right tag with a small change in the > tag header. Although it would be up to each tool to implement this > check. > > I don't think that an addition like this would get in the way of any > existing git workflow, and should be backwards-compatible right? Doesn't this already exist? $ git cat-file tag v2.0.0 object e156455ea49124c140a67623f22a393db62d5d98 type commit tag v2.0.0 tagger Junio C Hamano1401300269 -0700 Git 2.0 -BEGIN PGP SIGNATURE- [...] -END PGP SIGNATURE- Tag objects already have a "tag" header, which is part of the signed content. If you use "git verify-tag -v", you can check both that the signature is valid and that the tag is the one you are expecting. Of course, "verify-tag" could do this for you if you give it a refname, too, but I think that may be the tip of the iceberg in terms of automatic verification. In particular, verify-tag knows it was signed by _somebody_, but it doesn't know what the signing policy is. As a human, _I_ know that Junio is the right person to be signing the release tag, but no tool does. Git pretty much punts on all of these issues and assumes either a human or a smarter tool is looking at the verification output. But I don't think it would hurt to build in some features to let git automatically check some things, if only to avoid callers duplicating work to implement the checks themselves. -Peff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
Jeff Kingwrites: > On Tue, Jan 26, 2016 at 10:29:42AM -0500, Santiago Torres wrote: > >> > If you cannot trust those with write access to a repo that you are >> > pulling and installing from you might want to re-check where you are >> > pulling or installing from ;) >> >> Yeah, I see your point, but mechanisms to ensure the server's origin can >> be bypassed (e.g., a MITM). I don't think it would hurt to ensure the >> source pointed to is the source itself. The tag signature can help us do >> this. > > Right. I think the more interesting use case here is "I trust the > upstream repository owner, but I do not trust their hosting site of > choice." Yup, and push-certificate is there to help with that issue. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
On Tue, Jan 26, 2016 at 03:26:51PM -0500, Jeff King wrote: > On Tue, Jan 26, 2016 at 10:29:42AM -0500, Santiago Torres wrote: > > > > If you cannot trust those with write access to a repo that you are > > > pulling and installing from you might want to re-check where you are > > > pulling or installing from ;) > > > > Yeah, I see your point, but mechanisms to ensure the server's origin can > > be bypassed (e.g., a MITM). I don't think it would hurt to ensure the > > source pointed to is the source itself. The tag signature can help us do > > this. > > Right. I think the more interesting use case here is "I trust the > upstream repository owner, but I do not trust their hosting site of > choice." Yes, I think this is another possible scenario. Thanks for pointing it out. > > > > Your best bet is checking the signature of signed tags. Now, if you're > > > worried about someone maliciously pointing you to the wrong, correctly > > > signed tag then you should verify that the tag object contains the tag > > > "name" that you expect (for example by using "git verify-tag -v" or "git > > > cat-file -p"), since that is part of the signed content. > > > > Yep, this is my intuition behind my proposal. While someone can manually > > inspect a tag (git tag -v [ref]) to ensure he's getting the correct one, > > there's no mechanism to ensure that the ref is pointing to the intended > > tag. I do believe that package managers and git submodules could check > > whether the ref is pointing to the right tag with a small change in the > > tag header. Although it would be up to each tool to implement this > > check. > > > > I don't think that an addition like this would get in the way of any > > existing git workflow, and should be backwards-compatible right? > > Doesn't this already exist? > > $ git cat-file tag v2.0.0 > object e156455ea49124c140a67623f22a393db62d5d98 > type commit > tag v2.0.0 > tagger Junio C Hamano1401300269 -0700 > > Git 2.0 > -BEGIN PGP SIGNATURE- > [...] > -END PGP SIGNATURE- > > Tag objects already have a "tag" header, which is part of the signed > content. If you use "git verify-tag -v", you can check both that the > signature is valid and that the tag is the one you are expecting. Oh, I inspected the tag object with cat-file, but I assumed this was being inserted by the command itself (by "pretty printing"). This is exactly what I was thinking. > > Of course, "verify-tag" could do this for you if you give it a refname, > too, but I think that may be the tip of the iceberg in terms of > automatic verification. Yes, I think it could be a good first step though (maybe returning non-0 if the tag header could help in this case). If this header exists, I think that package managers (and git submodules) should use it to verify this metadata attacks don't take place; it sounds rather simple. > In particular, verify-tag knows it was signed by > _somebody_, but it doesn't know what the signing policy is. As a human, > _I_ know that Junio is the right person to be signing the release tag, > but no tool does. Yes, shipping a keychain might be helpful, I know the folks at I2P[1] do that in their monotone repository. Maybe something similar could be an extension to git? (using hooks, possibly?) > > Git pretty much punts on all of these issues and assumes either a human > or a smarter tool is looking at the verification output. Yeah, I agree. This works pretty well in some workflows (e.g., the one in this very ML), but I have the feeling this is not the trend that newer users of the tool are adopting. > But I don't think it would hurt to build in some features to let git > automatically check some things, if only to avoid callers duplicating > work to implement the checks themselves. Yeah, I think this check (and maybe others) could be quite simple to integrate and lessen the workload on the git user. Inspecting each git tag after recursively cloning might mitigate an attack like this, but it sounds burdensome. Thanks! -Santiago. [1] https://geti2p.net/en/get-involved/guides/monotone#setting-up-trust-evaluation-hooks -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] tag-ref and tag object binding
Jeff Kingwrites: >> I don't think that an addition like this would get in the way of any >> existing git workflow, and should be backwards-compatible right? > > Doesn't this already exist? > > $ git cat-file tag v2.0.0 > object e156455ea49124c140a67623f22a393db62d5d98 > type commit > tag v2.0.0 > tagger Junio C Hamano 1401300269 -0700 > > Git 2.0 > -BEGIN PGP SIGNATURE- > [...] > -END PGP SIGNATURE- > > Tag objects already have a "tag" header, which is part of the signed > content. If you use "git verify-tag -v", you can check both that the > signature is valid and that the tag is the one you are expecting. Another thing worth mentioning is that "fsck" does not insist that refs/tags/$NAME must have a "tag" line that says "tag $NAME", and that is a very deliberate design decision. A project may want to allow multiple people tag the same commit with the same tagname and publish all of them in the same ref hierarchy. For example, while I am away, Peff may make an emergency maintenance release and tag it like so: $ git tag -s -m 'Git v2.7.1' v2.7.1 master $ git push $there tags/v2.7.1:tags/peff/v2.7.1 master and announce to the list that he has cut a release, and published his signed tag as peff/v2.7.1 in the public repository. While everybody in the project trusts Peff as much as they trust me, I would still want to sign the same commit myself, endorsing what Peff did for the project, when I come back, by doing something like: $ git tag -s -m 'Git v2.7.1' v2.7.1 peff/v2.7.1^0 $ git push $there v2.7.1 In fact, I think "git describe" uses the name recorded in the closest tag, not the refname such a tag is found at, when giveing a name to the commit. E.g. $ git tag foo v2.7.0 $ git tag -d v2.7.0 $ git describe master warning: tag 'v2.7.0' is really 'foo' here v2.7.0-170-ge572fef -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC] tag-ref and tag object binding
Hello everyone. I've done some further research on the security properties of git metadata and I think I've identified something that might be worth discussing. In this case, The issue is related to the refs that point to git tag objects. Specifically, the "loose" nature of tag refs might possibly trick people into installing the wrong revision (version?) of a file. To elaborate, the ref of a tag object can be moved around in the same way a branch can be moved around (either manually or by using git commands). If someone with write access can modify where this ref points to, and points it to another valid tag (e.g., an older, vulnerable version), then many tools that work under the assumption of static tags might mistakenly install/pull the wrong reivision of source code. I've verified that this is possible to pull off in package managers such as PIP, rubygems, gradle(maven), as well as git submodules tracking tags. In order to stay loyal to the way files in the .git directory are ordered, I don't think that making the ref file (or packed refs) files differently is an option. However, I think that it could be possible to store the "origin ref" in the git tag object, so tools can verify that they are looking at the appropriate tag. There might also be a simpler solution to this, and I would appreciate any feedback. What do you guys think? Thanks! Santiago. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html