21 Jun, 2017

Securing GitHub Commits With GPG Signing

by John Poulin

At nVisium we use Git, and more specifically, GitHub, quite frequently. A lot of our clients also manage their application source code via Git. As such, it is important to us that we protect both our source code as well as our client’s source code.

One issue we have been talking a lot about recently is Git commit attribution. For instance, when a user pushes a commit up to a repository, part of that commit includes the user’s email address. On Git-based SCM systems, such as GitHub or Bitbucket, these email addresses link the commit to a specific user account. From a security perspective, it is a bit concerning to utilize a known value (such as email address) as a form of attribution. Our CTO Ken Johnson has talked about this issue several times, but we’ll be digging in a bit deeper.

Quick Walkthrough

To give you a quick example of the issue that may arise, consider the following example:

I created a new repository, and pushed up an initial commit.

Initial Commit

The commit is attributed to my email address, as expected. But, what happens if we change the email address and make a new commit?

.gitconfig File Changed

Our goal here is to try to commit some code that appears to be either malicious, or contains a security vulnerability. Being the CTO of a security company, committing vulnerable code would be a cardinal sin. So, we create a Rails controller that is vulnerable to dynamic render, and push it on his behalf.

Vulnerable file uploaded

What’s interesting, though, is that GitHub suggests that we may want to “claim email address” – we’ll come back to that later.

Claim email?

For a more illustrative example, take a look at Ken’s repository, within which he appears to have Linus Torvalds contributing as a committer.

Torvalds Committing

The problem with this situation is that it is easy to masquerade commits on behalf of other, trusted users. For instance, Ken may be more trusted amongst the company than other employees. As such, we would be more likely to accept Pull Requests from him than we would from newer employees. These PR’s would likely have a less rigorous review than if they were submitted by a junior developer.

Another Case: Hijacking GitHub Commits

Another situation we discovered, is that on GitHub, in certain conditions you can claim ownership of an old email address. If an account is deactivated, for instance, any user can claim ownership of the commits tied to the particular account. For instance, we saw this behavior earlier when we made a commit to an old account belonging to our CTO.

Upon browsing to one of our repositories, I saw a commit from Ken’s account. When I opened it via GitHub it asked me if I wanted to claim the email address. Obviously, this piqued my interest, so I did.

Email Claim

Upon claiming it, I noticed that it was now listed in my account settings as “unverified.”

Unverified Email

Upon claiming his account, I noticed that all of his commits were now attributed to me. In fact, my account now showed commits that were older than the account!

Commits Before Account Inception

In this situation, I was able to claim commits that never belonged to me. If my company used the number or frequency of Git commits as some form of performance metric, it would be easy to trick them.

The Solution: GPG-Signing

GitHub is fully aware of these situations, and considers them “an intentional design decision [which] is working as expected.” Essentially, it is a fundamental problem with the Git protocol, which offers no real authentication of commits. And to be clear, these situations do not allow you to interact with repositories of which you do not have access. For instance, I could not utilize these issues to hijack commits belonging to a private repository.

From my discussions with several folks at GitHub, the best solution is to utilize GPG signing of commits. Instead of just accepting the commits at a whim, the GPG signing feature of Git will match the email address of your Git account with a GPG key, and sign them before pushing them to the server. GitHub handles signed commits by comparing the signature with your known public key, displaying a “Verified” flag next to the commit as long as it passes verification.

Verified Commit

I highly recommend enabling GPG signing for your account. It is very easy to do by following Github’s guide.

Additionally, if you manage projects or are responsible for your organizations security, I recommend enforcing a rule that all commits must be signed and verified. This will help ensure that the commits actually belong to the user that they claim to, and are not an attempt to masquerade the ownership of malicious code.