CVE-2012-4506 (published 2012-10-22T23:55Z)

Directory traversal vulnerability in gitolite 3.x before 3.1, when wild card repositories and a pattern matching "../" are enabled, allows remote authenticated users to create arbitrary repositories and possibly perform other actions via a .. (dot dot) in a repository name.

Severity: MEDIUM
CVSS v2 base score: 4.6 (AV:N/AC:H/Au:S/C:P/I:P/A:P)

Weakness information:
cwe_id: CWE-22
cwe_name: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
description: The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
extended_description: 
            Many file operations are intended to take place within a restricted directory. By using special elements such as ".." and "/" separators, attackers can escape outside of the restricted location to access files or directories that are elsewhere on the system. One of the most common special elements is the "../" sequence, which in most modern operating systems is interpreted as the parent directory of the current location. This is referred to as relative path traversal. Path traversal also covers the use of absolute pathnames such as "/usr/local/bin" to access unexpected files. This is referred to as absolute path traversal.
         
         

Fix information:
repo_url: https://github.com/sitaramc/gitolite
commit_details: repo_url: https://github.com/sitaramc/gitolite
author: Sitaram Chamarty
author_date: 2012-10-05 07:19:59+05:30
msg: (security) fix bug in pattern to detect path traversal

while we're about it, add the same check to some of the internal
routines, so that commands can also be protected.

finally, just to make sure we don't lose it again in some other fashion,
add a few tests for path traversal...
repository: repo_url: https://github.com/sitaramc/gitolite
repo_name: sitaramc/gitolite
description: Hosting git repositories -- Gitolite allows you to setup git hosting on a central server, with very fine-grained access control and many (many!) more powerful features.
repo_language: Perl
owner: sitaramc
file_changes: filename: gitolite-shell
change_type: ModificationType.MODIFY
diff: @@ -168,7 +168,7 @@ sub sanity {
     my $repo = shift;
     _die "'$repo' contains bad characters" if $repo !~ $REPONAME_PATT;
     _die "'$repo' ends with a '/'"         if $repo =~ m(/$);
-    _die "'$repo' contains '..'"           if $repo =~ m(\.\.$);
+    _die "'$repo' contains '..'"           if $repo =~ m(\.\.);
 }
 
 # ----------------------------------------------------------------------

programming_language: Perl
filename: Load.pm
change_type: ModificationType.MODIFY
diff: @@ -67,8 +67,9 @@ my $last_repo = '';
 
 sub access {
     my ( $repo, $user, $aa, $ref ) = @_;
-    _die "invalid repo '$repo'" if not( $repo and $repo =~ $REPOPATT_PATT );
     _die "invalid user '$user'" if not( $user and $user =~ $USERNAME_PATT );
+    sanity($repo);
+
     my $deny_rules = option( $repo, 'deny-rules' );
     load($repo);
 
@@ -175,8 +176,18 @@ sub option {
     return $ret->{$option};
 }
 
+sub sanity {
+    my $repo = shift;
+
+    _die "invalid repo '$repo'" if not( $repo and $repo =~ $REPOPATT_PATT );
+    _die "'$repo' ends with a '/'" if $repo =~ m(/$);
+    _die "'$repo' contains '..'" if $repo =~ $REPONAME_PATT and $repo =~ m(\.\.);
+}
+
 sub repo_missing {
     my $repo = shift;
+    sanity($repo);
+
     return not -d "$rc{GL_REPO_BASE}/$repo.git";
 }
 
@@ -400,6 +411,8 @@ sub generic_name {
 
 sub creator {
     my $repo = shift;
+    sanity($repo);
+
     return ( $ENV{GL_USER} || '' ) if repo_missing($repo);
     my $f       = "$rc{GL_REPO_BASE}/$repo.git/gl-creator";
     my $creator = '';

programming_language: Perl
filename: 0-me-first.t
change_type: ModificationType.MODIFY
diff: @@ -6,10 +6,12 @@ use warnings;
 use lib "src/lib";
 use Gitolite::Test;
 
+my $rb = `gitolite query-rc -n GL_REPO_BASE`;
+
 # initial smoke tests
 # ----------------------------------------------------------------------
 
-try "plan 65";
+try "plan 73";
 
 # basic push admin repo
 confreset;confadd '
@@ -75,4 +77,19 @@ try "
     glt ls-remote u5 file:///cc/1;  ok;     perl s/TRACE.*//g; !/\\S/
     glt ls-remote u5 file:///cc/2;  !ok;    /DENIED by fallthru/
     glt ls-remote u6 file:///cc/2;  !ok;    /DENIED by fallthru/
+
+    # command
+    glt perms u4 -c cc/bar/baz/frob + READERS u2;
+                                    ok;     /Initialized empty .*cc/bar/baz/frob.git/
+
+    # path traversal
+    glt ls-remote u4 file:///cc/dd/../ee
+                                    !ok;    /FATAL: 'cc/dd/\\.\\./ee' contains '\\.\\.'/
+    glt ls-remote u5 file:///cc/../../../../../..$rb/gitolite-admin
+                                    !ok;    /FATAL: 'cc/../../../../../..$rb/gitolite-admin' contains '\\.\\.'/
+
+    glt perms u4 -c cc/bar/baz/../frob + READERS u2
+                                    !ok;    /FATAL: 'cc/bar/baz/\\.\\./frob' contains '\\.\\.'/
+
+
 ";

programming_language: Shell