Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!

Bug 482166 (CVE-2013-4277)

Summary: <dev-vcs/subversion-1.7.13: Possible information loss due to insecure pid file handling (CVE-2013-4277)
Product: Gentoo Security Reporter: Sergey Popov <pinkbyte>
Component: VulnerabilitiesAssignee: Gentoo Security <security>
Status: RESOLVED FIXED    
Severity: minor CC: tommy
Priority: Normal    
Version: unspecified   
Hardware: All   
OS: Linux   
Whiteboard: B3 [glsa]
Package list:
Runtime testing required: ---

Description Sergey Popov gentoo-dev 2013-08-23 06:12:39 UTC
Posting here, because of mail, that was sent to security@gentoo.org:

This email is a confidential pre-notification for security issues with 
Subversion:
 * CVE-2013-4246
 * CVE-2013-4262
 * CVE-2013-4277

Please *do not forward* any part of this mail to anyone.  The public
announcement is not until 29 August 2013 17:00 UTC, and we'd like
to keep the information embargoed until the announcement.

You are receiving this mail because (we think) you distribute software
that uses the Subversion libraries or that you host a Subversion installation
used by a large number of users.  We believe that you might want to have your
software patched by the time these security holes are made public on 29 August.

If you no longer maintain Subversion-related packages or hosting, please reply
to this mail indicating who the appropriate contact would be for your
organization.

Here are the full advisories:
{{{
  Subversion FSFS repositories can be corrupted by editing packed
  revision properties

Summary:
========

  When one or more revision properties of a packed revision are set to new,
  larger values, a "pack file" in the repository may get split.  In the
  process the wrong pack file may be deleted.

  This can lead to data loss of revision property data.

Known vulnerable:
=================

  Subversion servers through 1.8.0 and 1.8.1.

  Only FSFS repositories created with Subversion 1.8 or upgraded to
  1.8 format (using 'svnadmin upgrade') are affected.

Known fixed:
============

  Subversion 1.8.2 and newer.

  BDB repositories (any version) are not vulnerable.

  Subversion 1.7.x and earlier is not vulnerable.

Details:
========

  The FSFS repository stores additional information such as the log
  message for each revision in a revision property (revprop) file.

  In the latest FSFS format introduced with Apache Subversion 1.8.0,
  'svnadmin pack' will aggregate those revprop files into fewer
  pack files plus a manifest acting as an index.  Subversion limits
  the size of those pack files and will create multiple packs as
  necessary.  The limit is configurable in the repository's fsfs.conf.

  Because revprops may be modified for existing revisions, the contents
  of the respective pack files must change in the process.  If the new
  data is larger, Subversion may need to split the pack file to keep
  within the specified limit.

  Due to a simple programming oversight, the revision-to-file mapping
  information in the manifest file is used wrongly, if there is more
  than one pack file and we modify one that pertains to higher
  revisions:

  1) Apache Subversion will most likely remove the first pack file
     instead of the one pertaining to the touched revision.  This
     results in a loss of information for earlier revisions.

  2) The updated manifest file will link the wrong revision(s) to the
     updated pack file.  This causes the wrong data to be returned
     to the user in later queries.

  Part of the revprops are the commit time stamps used by Apache
  Subversion to assign time stamps to each node during export or
  checkout operations.  Thus, those operations are likely to fail
  when the versioned data they would work on includes data from the
  the corrupted revision range.  (Checkout of a later revision may
  fail too if one of the files in the later revision was last changed
  in a revision of the corrupted revision range.)

  'svn log' might succeed but report the log messages and other revprops
  in the wrong revisions.  Confidential information contained in
  those revprops may thus bypass authz filtering.

Severity:
=========

  CVSSv2 Base Score: 6.5
  CVSSv2 Base Vector: AV:N/AC:L/Au:S/C:P/I:P/A:P

  We consider this to be a medium risk vulnerability.  Write access
  to revision properties is opt-in and must be activated by the
  administrator on a per-repository basis.  Packing is opt-in too and
  is never run automatically by Subversion.

  A remote authenticated attacker with commit access may be able to
  corrupt repositories on a Subversion server, gain access to
  confidential information in the same repository and cause
  disruption for other users.
  
Recommendations:
================

  We recommend all 1.8.x users to upgrade to Subversion 1.8.3.
  Users who are unable to upgrade may apply the included patch.
  
  New Subversion packages can be found at:
  http://subversion.apache.org/packages.html

  Until the fix is in effect,

  1) refrain from packing 1.8-format FSFS repositories that have not been
     packed in the past, and
  2) disable the pre-revprop-change hook (to disable revprop
     changes) for 1.8-format repositories that have already been
     packed in the past

  Already corrupted repositories can be brought back into working
  state by the following procedure:

  1) use 'svnadmin verify' to identify corrupted revision ranges
  2) replace shards ($repos/db/revprops) containing corrupted
     revisions with their latest backups
  3) repeat until corrupted revprops have been restored

Patches:
========

Patch for Subversion 1.8:

[[[
Index: subversion/libsvn_fs_fs/fs_fs.c
===================================================================
--- subversion/libsvn_fs_fs/fs_fs.c	(revision 1513879)
+++ subversion/libsvn_fs_fs/fs_fs.c	(revision 1513880)
@@ -3596,7 +3596,7 @@
   /* sum of values in SIZES */
   apr_size_t total_size;
 
-  /* first revision in the pack */
+  /* first revision in the pack (>= MANIFEST_START) */
   svn_revnum_t start_revision;
 
   /* size of the revprops in PACKED_REVPROPS */
@@ -3610,8 +3610,12 @@
    * in the pack, i.e. the pack content without header and compression */
   svn_stringbuf_t *packed_revprops;
 
+  /* First revision covered by MANIFEST.
+   * Will equal the shard start revision or 1, for the 1st shard. */
+  svn_revnum_t manifest_start;
+
   /* content of the manifest.
-   * Maps long(rev - START_REVISION) to const char* pack file name */
+   * Maps long(rev - MANIFEST_START) to const char* pack file name */
   apr_array_header_t *manifest;
 } packed_revprops_t;
 
@@ -3730,9 +3734,11 @@
     }
 
   /* Index for our revision. Rev 0 is excluded from the first shard. */
-  idx = (int)(revprops->revision % ffd->max_files_per_dir);
-  if (revprops->revision < ffd->max_files_per_dir)
-    --idx;
+  revprops->manifest_start = revprops->revision
+                           - (revprops->revision % ffd->max_files_per_dir);
+  if (revprops->manifest_start == 0)
+    ++revprops->manifest_start;
+  idx = (int)(revprops->revision - revprops->manifest_start);
 
   if (revprops->manifest->nelts <= idx)
     return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
@@ -4198,10 +4204,13 @@
   svn_string_t *new_filename;
   int i;
   apr_file_t *file;
+  int manifest_offset
+    = (int)(revprops->start_revision - revprops->manifest_start);
 
   /* get the old (= current) file name and enlist it for later deletion */
-  const char *old_filename
-    = APR_ARRAY_IDX(revprops->manifest, start, const char*);
+  const char *old_filename = APR_ARRAY_IDX(revprops->manifest,
+                                           start + manifest_offset,
+                                           const char*);
 
   if (*files_to_delete == NULL)
     *files_to_delete = apr_array_make(pool, 3, sizeof(const char*));
@@ -4223,7 +4232,8 @@
 
   /* update the manifest to point to the new file */
   for (i = start; i < end; ++i)
-    APR_ARRAY_IDX(revprops->manifest, i, const char*) = new_filename->data;
+    APR_ARRAY_IDX(revprops->manifest, i + manifest_offset, const char*)
+      = new_filename->data;
 
   /* create a file stream for the new file */
   SVN_ERR(svn_io_file_open(&file, svn_dirent_join(revprops->folder,
]]]
}}}

{{{
  The admin-side optional utility daemons svnwcsub.py and irkerbridge.py are
  vulnerable to a local privilege escalation vulnerability via symlink attack.




Restricting this for now, as advised
Comment 1 Thomas Sachau gentoo-dev 2013-08-23 15:08:31 UTC
It mentions 3 security issues, while the following text only mentions 1 issue. Is the text cut and the description of the following 2 missing?

The mentioned one only affects subversion-1.8. Since we only have the 1.7 tree packaged, it does not affect our main tree version (currently 1.7.11).
Comment 2 Sergey Popov gentoo-dev 2013-08-24 05:28:06 UTC
Sorry, it was not pasted, probably it is too big:

{{{
  The admin-side optional utility daemons svnwcsub.py and irkerbridge.py are
  vulnerable to a local privilege escalation vulnerability via symlink attack.

Summary:
========

  svnwcsub.py and irkerbridge.py take a --pidfile option which creates
  a file containing the process id they are running as.  Both of them
  do not take steps to ensure that the file they have been directed at
  is not a symlink.  If the pid file is in a directory writeable by
  unprivileged users, the destination could be replaced by a symlink
  allowing for privilege escalation.  Both are optional extra tools
  that are not installed by default and do not create a pid file by
  default.

Known vulnerable:
=================

  svnwcsub.py and irkerbridge.py included with Subversion 1.8.0 - 1.8.1, when
  --pidfile is passed, due to an underlying problem in daemonize.py.

  svnwcsub.py included with Subversion 1.8.0 - 1.8.2 when run in
  foreground mode (as opposed to daemon mode) when --pidfile is 
  passed.

Known fixed:
============

  daemonize.py included with Subversion 1.8.2 or newer.

  svnwcsub.py included with Subversion 1.8.3.

  Subversion 1.7.x and earlier do not include these files and are not
  vulnerable.

Details:
========

  The pid file is often used by scripts to be able to determine if a specific
  service is running and to determine which process to kill to stop a service.
  If the pid file is created in a directory writable by unprivileged
  directories, they could replace it with a symlink.

  If that is done while the service is stopped, the service may overwrite the
  target of the symlink with a one line containing its pid when it starts.
  This may lead to privilege escalation, depending on the target of the
  symlink.
 
  If that is done while the service is running, the stop script may
  kill the wrong process.  In effect the unprivileged user would be able to
  kill a process they do not have permissions to kill when a privileged script
  depends on the pid file.

  Both svnwcsub.py and irkerbridge.py use the daemonize.py module to help
  implement the pidfile feature.  This module does not properly ensure that
  the pid file is being created new every time and as such are vulnerable.
  The daemonize.py script has been fixed to resolve this issue and the fixed
  version is included in Subversion 1.8.2.

  svnwcsub.py also supports the --pidfile option when running in the
  foreground and does not depend upon the daemonize.py module to support that
  functionality.  The foreground implementation of --pidfile is also
  vulnerable.

Severity:
=========

  CVSSv2 Base Score: 2.4
  CVSSv2 Base Vector: AV:L/AC:H/Au:S/C:N/I:P/A:P

  We consider this to be a low risk vulnerability.

  The tools are not installed by default so most installations are not likely
  to be vulnerable.

  Unless the pid file is created in a directory with permissions for
  unprivileged users the vulnerability cannot be exploited.  The init scripts
  provided with Subversion places the pid file in /var/run or a subdirectory
  under /var/run, which is not typically writable by unprivileged users.

  The svnwcsub and irkerbridge services do not run as root by default and so
  the potential privilege escalation is limited.  In svnwcsub, a file in one
  of the managed working copies or in their metadata (.svn) areas may be
  truncated and replaced with single line containing a pid number.

  The attacker would need to have local access to the machine that the tools
  were running on in order to exploit the vulnerability.
  
Recommendations:
================

  We recommend that users using svnwcsub.py and irkerbridge.py upgrade their
  installations with the files (including daemonize.py) as included in
  Subversion 1.8.3 or newer.
  
  Administrators can mitigate the vulnerability without upgrading by refraining
  from pointing the pid file at a directory where unprivileged users have write
  access (e.g. /tmp).  Instead the pidfile should be placed in a directory
  where only the daemon has access to create, modify, and delete files.

  Alternatively, the pid file may be disabled altogether by removing the
  --pidfile option from the invocation.

References:
===========

  CVE-2013-4262  (Subversion)

Reported by:
============

  Daniel Shahaf, Apache Infrastructure

Patches:
========

Patch for Subversion 1.8:

[[[
Index: tools/server-side/svnpubsub/daemonize.py
===================================================================
--- tools/server-side/svnpubsub/daemonize.py	(revision 1516272)
+++ tools/server-side/svnpubsub/daemonize.py	(working copy)
@@ -143,7 +143,14 @@ class Daemon(object):
       if daemon_accepting.signalled:
         # the daemon is up and running, so save the pid and return success.
         if self.pidfile:
-          open(self.pidfile, 'w').write('%d\n' % pid)
+          # Be wary of symlink attacks
+          try:
+            os.remove(self.pidfile)
+          except OSError:
+            pass
+          fd = os.open(self.pidfile, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0444)
+          os.write(fd, '%d\n' % pid)
+          os.close(fd)
         return DAEMON_STARTED
 
       # some other signal popped us out of the pause. the daemon might not
Index: tools/server-side/svnpubsub/svnwcsub.py
===================================================================
--- tools/server-side/svnpubsub/svnwcsub.py	(revision 1516272)
+++ tools/server-side/svnpubsub/svnwcsub.py	(working copy)
@@ -465,7 +465,15 @@ def handle_options(options):
     # Otherwise, we should write this (foreground) PID into the file.
     if options.pidfile and not options.daemon:
         pid = os.getpid()
-        open(options.pidfile, 'w').write('%s\n' % pid)
+        # Be wary of symlink attacks
+        try:
+            os.remove(options.pidfile)
+        except OSError:
+            pass
+        fd = os.open(options.pidfile, os.O_WRONLY | os.O_CREAT | os.O_EXCL,
+                     0444)
+        os.write(fd, '%d\n' % pid)
+        os.close(fd)
         logging.info('pid %d written to %s', pid, options.pidfile)
 
     if options.gid:
]]]
}}}

{{{
  svnserve is vulnerable to a local privilege escalation vulnerability via
  symlink attack.

Summary:
========

  svnserve takes a --pid-file option which creates a file containing the process
  id it is running as.  It does not take steps to ensure that the file it has
  been directed at is not a symlink.  If the pid file is in a directory
  writeable by unprivileged users, the destination could be replaced by a
  symlink allowing for privilege escalation.  svnserve does not create a pid
  file by default.

Known vulnerable:
=================

  svnserve 1.4.0 through 1.7.12
  svnserve 1.8.0 through 1.8.1
  svnserve 1.8.2 (not publicly released)

  All versions are only vulnerable when the --pid-file=ARG option is used.

Known fixed:
============

  svnserve 1.7.13
  svnserve 1.8.3

  Workaround: do not pass the --pid-file=ARG option.

Details:
========

  The pid file is often used by scripts to be able to determine if a specific
  service is running and to determine which process to kill to stop a service.
  If the pid file is created in a directory writable by unprivileged
  directories, they could replace it with a symlink.

  If that is done while the service is stopped, the service may overwrite the
  target of the symlink with a one line containing its pid when it starts.
  This may lead to privilege escalation, depending on the target of the
  symlink.
 
  If that is done while the service is running, the stop script may
  kill the wrong process.  In effect the unprivileged user would be able to
  kill a process they do not have permissions to kill when a privileged script
  depends on the pid file.

  svnserve did not properly ensure that the pid file is being created new
  every time and as such is vulnerable.

Severity:
=========

  CVSSv2 Base Score: 3.2
  CVSSv2 Base Vector: AV:L/AC:L/Au:S/C:N/I:P/A:P

  ### danielsh: A:P since truncating db/format makes one repository unusable
  ###           (ditto for the authz file, but that's not svnserve-writable)
  ### danielsh: C:N?  Is there a way to use this vulnerability to read
  ###           something you shouldn't be able to read?

  ### Common failure mode:
  ### If you pid-truncate db/current, then db/revs/$((pid + 1)) would be
  ### overwritten.  (What about rep-cache.db?  Would false references to it be
  ### made in r$((pid+2)), or will a sanity check in the post-commit fs
  ### processing trigger?)

  We consider this to be a medium risk vulnerability.

  The pid file is not created by default.

  Unless the pid file is created in a directory with permissions for
  unprivileged users the vulnerability cannot be exploited.  pid files
  are typically placed in /var/run or a subdirectory under /var/run, which
  is not typically writable by unprivileged users.

  The attacker would need to have local access to the machine that svnserve
  is running on in order to exploit the vulnerability.

  However, if the pid file is created in a vulnerable directory, any file
  writable by svnserve can be truncated.  This includes mutable files in the
  repository data directory ("filesystem directory") so may result in deleting
  of a portion of history.

  Note that the user svnserve runs as should not (under good practice
  ### TODO should we doc that in the book?) have write access to the
  hooks and config files (e.g., $REPOSDIR/conf/* and $REPOSDIR/hooks/*).  If
  it does, or if svnserve runs as root, the implications of the vulnerability
  would be more severe.

Recommendations:
================

  We recommend that users of svnserve upgrade to Subversion 1.7.12 or 1.8.3.
  
  Administrators can mitigate the vulnerability without upgrading by refraining
  from pointing the pid file at a directory where unprivileged users have write
  access (e.g. /tmp).  Instead the pidfile should be placed in a directory
  where only the daemon has access to create, modify, and delete files.
  Alternatively, the pid file may be disabled altogether by removing the
  --pid-file option from svnserve's invocation.  Subversion does not release
  system startup scripts for svnserve, so check your local installation for
  details.

  Alternatively, apply the patch below.

References:
===========

  CVE-2013-4277  (Subversion)

Reported by:
============

  Daniel Shahaf, elego Software Solutions GmbH

Patches:
========

Patch for Subversion 1.7:

[[[
Index: subversion/svnserve/main.c
===================================================================
--- subversion/svnserve/main.c  (revision 1516311)
+++ subversion/svnserve/main.c  (working copy)
@@ -403,8 +403,9 @@ static svn_error_t *write_pid_file(const char *fil
   const char *contents = apr_psprintf(pool, "%" APR_PID_T_FMT "\n",
                                              getpid());

+  SVN_ERR(svn_io_remove_file2(filename, TRUE, pool));
   SVN_ERR(svn_io_file_open(&file, filename,
-                           APR_WRITE | APR_CREATE | APR_TRUNCATE,
+                           APR_WRITE | APR_CREATE | APR_EXCL,
                            APR_OS_DEFAULT, pool));
   SVN_ERR(svn_io_file_write_full(file, contents, strlen(contents), NULL,
                                  pool));
]]]

Patch for Subversion 1.8:

[[[
Index: subversion/svnserve/svnserve.c
===================================================================
--- subversion/svnserve/svnserve.c      (revision 1516305)
+++ subversion/svnserve/svnserve.c      (working copy)
@@ -439,8 +439,9 @@ static svn_error_t *write_pid_file(const char *fil
   const char *contents = apr_psprintf(pool, "%" APR_PID_T_FMT "\n",
                                              getpid());

+  SVN_ERR(svn_io_remove_file2(filename, TRUE, pool));
   SVN_ERR(svn_io_file_open(&file, filename,
-                           APR_WRITE | APR_CREATE | APR_TRUNCATE,
+                           APR_WRITE | APR_CREATE | APR_EXCL,
                            APR_OS_DEFAULT, pool));
   SVN_ERR(svn_io_file_write_full(file, contents, strlen(contents), NULL,
                                  pool));
]]]
}}}
Comment 3 Thomas Sachau gentoo-dev 2013-08-24 11:44:50 UTC
so the first 2 dont affect us.

The third does affect us (assuming, that "--pid-file" from the text is the same as "--pidfile" used in our init.d script.

So this will require a bump to subversion-1.7.12, when it got published.
Comment 4 Sergey Popov gentoo-dev 2013-08-24 19:35:21 UTC
Thanks for clarification. Changing bug title accordingly, waiting for upstream release...
Comment 5 Sergey Popov gentoo-dev 2013-09-02 08:48:36 UTC
This issue is now public

From subversion mailling list:

Please note that Subversion 1.7.13 is the next release after Subversion 1.7.11.
The 1.7.12 release was not published publicly, due to issues found
during testing.

@maintainers: please bump it in tree and say when it will be ready to stabilize, thanks
Comment 6 Thomas Sachau gentoo-dev 2013-09-02 21:09:37 UTC
subversion-1.7.13 added
Comment 7 Sergey Popov gentoo-dev 2013-09-03 15:13:40 UTC
(In reply to Thomas Sachau from comment #6)
> subversion-1.7.13 added

Good. Is it ready for stabilization?
Comment 8 Thomas Sachau gentoo-dev 2013-09-03 19:17:51 UTC
tests have passed for me, no new issues reported since addition, so lets go for stabilization.

Arches, please stabilize:

=dev-vcs/subversion-1.7.13

target keywords: "alpha amd64 arm hppa ia64 ~mips ppc ppc64 s390 sh sparc x86 ~ppc-aix ~amd64-fbsd ~x86-fbsd ~x86-freebsd ~hppa-hpux ~ia64-hpux ~x86-interix ~amd64-linux ~arm-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos ~m68k-mint ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris"
Comment 9 Agostino Sarubbo gentoo-dev 2013-09-04 07:27:15 UTC
ppc stable
Comment 10 Agostino Sarubbo gentoo-dev 2013-09-04 12:47:34 UTC
amd64 stable
Comment 11 Jeroen Roovers (RETIRED) gentoo-dev 2013-09-04 15:57:12 UTC
Stable for HPPA.
Comment 12 Agostino Sarubbo gentoo-dev 2013-09-05 10:43:46 UTC
ppc64 stable
Comment 13 Agostino Sarubbo gentoo-dev 2013-09-06 10:24:01 UTC
sparc stable
Comment 14 Markus Meier gentoo-dev 2013-09-09 22:12:25 UTC
arm stable
Comment 15 Agostino Sarubbo gentoo-dev 2013-09-14 07:41:51 UTC
ia64 stable
Comment 16 Agostino Sarubbo gentoo-dev 2013-09-14 10:14:20 UTC
x86 stable
Comment 17 Agostino Sarubbo gentoo-dev 2013-09-14 10:36:34 UTC
alpha stable
Comment 18 Agostino Sarubbo gentoo-dev 2013-09-14 10:38:25 UTC
s390 stable
Comment 19 Agostino Sarubbo gentoo-dev 2013-09-14 10:38:56 UTC
sh stable
Comment 20 Sean Amoss (RETIRED) gentoo-dev Security 2013-09-14 15:27:53 UTC
Already on an existing GLSA draft.

Maintainers, please drop vulnerable versions.
Comment 21 Thomas Sachau gentoo-dev 2013-09-15 09:43:37 UTC
(In reply to Sean Amoss from comment #20)
> Already on an existing GLSA draft.
> 
> Maintainers, please drop vulnerable versions.

done
Comment 22 GLSAMaker/CVETool Bot gentoo-dev 2013-09-17 22:40:28 UTC
CVE-2013-4277 (http://nvd.nist.gov/nvd.cfm?cvename=CVE-2013-4277):
  Svnserve in Apache Subversion 1.4.0 through 1.7.12 and 1.8.0 through 1.8.1
  allows local users to overwrite arbitrary files or kill arbitrary processes
  via a symlink attack on the file specified by the --pid-file option.
Comment 23 GLSAMaker/CVETool Bot gentoo-dev 2013-09-23 23:15:42 UTC
This issue was resolved and addressed in
 GLSA 201309-11 at http://security.gentoo.org/glsa/glsa-201309-11.xml
by GLSA coordinator Sean Amoss (ackle).