Introduce auth.httpTrustedProxyNetworks for securing HTTP auth When using auth=HTTP or auth=HTTP_LDAP, Gerrit relies on receiving the incoming username from an HTTP header. When misusing this configuration with a remote proxy and having Gerrit listening to an external interface over plain HTTP without firewalls, the security of the incoming username is subject to HTTP header spoofing. Highlight the risk in the documentation and also add a mitigation of the problem with a new auth.httpTrustedProxyNetworks that would restrict the fetching of the username from HTTP to a subset of CIDRs. The solution is similar to the mitigation adopted in other projects with a similar vulnerability. The parsing of the auth.httpTrustedProxyNetworks is expensive because it involves the creation of a SubnetUtils object and the string-based parsing of CIDRs. As a mitigation of the computational costs, parse and store the subnets in the RemoteUserUtil during the singleton instantiation, so that incoming HTTP calls can reuse the SubnetUtils objects and reduce the runtime memory and CPU footprint. Also, with regard to the subnet matching, differentiate between individual IP matching (CIDRs ending with /32) and full networking address matching with SubnetUtils. The individual IP matching is a simple O(1) independently of the number of entries; however, the full CIDRs matching will loop through all the networks and check the netmasks against the IP, with an O(N) complexity. The detection of the proxy-IP is quite complex because it also involves the wrapping of the X-Forwarded* headers management by Jetty, which overwrites the socket remote IP address with the original client IP forwarded by the proxy in between. It is necessary to wrap the concept of the extraction of the address into a generic interface, which can be overridden by actual implementations, with a default fallback to the standard servlet mechanism. The auth path in RemoteUserUtil needs exactly one piece of information that the servlet API does not give it directly: the pre-X-Forwarded-* TCP peer address. - RemoteUserUtil declares a public PROXY_REMOTE_ADDRESS_ATTR constant. Its javadoc documents the contract: any HTTP layer that wants its requests evaluated against auth.httpTrustedProxyNetworks sets this attribute to the pre-rewrite peer address. If unset, RemoteUserUtil falls back to HttpServletRequest.getRemoteAddr(). - JettyServer writes the attribute (one line) before delegating to the parent ForwardedRequestCustomizer, which is where Jetty rewrites getRemoteAddr() with the X-Forwarded-For value. Beyond the smaller surface, this design generalizes to non-Jetty HTTP layers without any new class hierarchy. A Tomcat valve, an embedded Netty pipeline stage, or a plain servlet filter installed before the auth filter can opt into the trusted-proxy check by setting the same attribute on the request. No subclass of ProxyAddressProvider, no module override, no Guice rebinding -- the contract is the constant plus its javadoc. In the case of JettyServer, we need to extend the ForwardedRequestCustomizer to remember what the original IP was before the wrapping and store into a request attribute. The runtime filter then accesses the attribute transparently and, if present, uses the proxy IP instead of the wrapped client IP. This also protects from malicious attackers trying to fake their client IP by spoofing the X-Forwarded* header values. Co-Author: David Ostrovsky <david.ostrovsky@gmail.com> Bug: Issue 520369774 Release-Notes: Introduce auth.httpTrustedProxyNetworks for mitigating the vulnerability of auth=HTTP or auth=HTTP_LDAP on external IPs Change-Id: If9809ff092520aa467fa108b4179b7b75afe0a85
Gerrit is a code review and project management tool for Git based projects.
Gerrit makes reviews easier by showing changes in a side-by-side display, and allowing inline comments to be added by any reviewer.
Gerrit simplifies Git based project maintainership by permitting any authorized user to submit changes to the master Git repository, rather than requiring all approved changes to be merged in by hand by the project maintainer.
For information about how to install and use Gerrit, refer to the documentation.
Our canonical Git repository is located on googlesource.com. There is a mirror of the repository on Github.
Please report bugs on the issue tracker.
Gerrit is the work of hundreds of contributors. We appreciate your help!
Please read the contribution guidelines.
Note that we do not accept Pull Requests via the Github mirror.
The Developer Mailing list is repo-discuss on Google Groups.
Gerrit is provided under the Apache License 2.0.
Install Bazel and run the following:
git clone --recurse-submodules https://gerrit.googlesource.com/gerrit
cd gerrit && bazel build release
The instruction how to configure GerritForge/BinTray repositories is here
On Debian/Ubuntu run:
apt-get update && apt-get install gerrit=<version>-<release>
NOTE: release is a counter that starts with 1 and indicates the number of packages that have been released with the same version of the software.
On CentOS/RedHat run:
yum clean all && yum install gerrit-<version>[-<release>]
On Fedora run:
dnf clean all && dnf install gerrit-<version>[-<release>]
Docker images of Gerrit are available on DockerHub
To run a CentOS 8 based Gerrit image:
docker run -p 8080:8080 gerritcodereview/gerrit[:version]-centos8
To run a Ubuntu 20.04 based Gerrit image:
docker run -p 8080:8080 gerritcodereview/gerrit[:version]-ubuntu20
NOTE: release is optional. Last released package of the version is installed if the release number is omitted.