Author: philip
Date: Thu Aug 10 21:02:20 2017
New Revision: 1804728

URL: http://svn.apache.org/viewvc?rev=1804728&view=rev
Log:
* contrib/hook-scripts/CVE-2017-9800-pre-commit.py: New, a pre-commit
   hook to prevent users committing svn:externals that attempt to
   exploit CVE-2017-9800.

Added:
    subversion/trunk/contrib/hook-scripts/CVE-2017-9800-pre-commit.py   (with 
props)

Added: subversion/trunk/contrib/hook-scripts/CVE-2017-9800-pre-commit.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/contrib/hook-scripts/CVE-2017-9800-pre-commit.py?rev=1804728&view=auto
==============================================================================
--- subversion/trunk/contrib/hook-scripts/CVE-2017-9800-pre-commit.py (added)
+++ subversion/trunk/contrib/hook-scripts/CVE-2017-9800-pre-commit.py Thu Aug 
10 21:02:20 2017
@@ -0,0 +1,74 @@
+#!/usr/bin/env python2
+
+# Licensed under the same terms as Subversion: the Apache License, Version 2.0
+#
+# pre-commit hook script for Subversion CVE-2017-9800
+#
+# This prevents commits that set svn:externals containing suspicions
+# svn+ssh:// URLs.
+#
+# With this script installed a commit like the one below should fail:
+#
+# svnmucc -mm propset svn:externals 'svn+ssh://-localhost/X X' REPOSITORY-URL
+
+import sys, locale, urllib, urlparse, curses.ascii
+from svn import wc, repos, fs
+
+# A simple whitelist to ensure these are not suspicious:
+#    user@server
+#    [::1]:22
+#    server-name
+#    server_name
+#    127.0.0.1
+# with an extra restriction that a leading '-' is suspicious.
+def suspicious_host(host):
+    if host[0] == '-':
+        return True
+    for char in host:
+        if not curses.ascii.isalnum(char) and not char in ':.-_[]@':
+            return True
+    return False
+
+native = locale.getlocale()[1]
+if not native: native = 'ascii'
+repos_handle = repos.open(sys.argv[1].decode(native).encode('utf-8'))
+fs_handle = repos.fs(repos_handle)
+txn_handle = fs.open_txn(fs_handle, sys.argv[2].decode(native).encode('utf-8'))
+txn_root = fs.txn_root(txn_handle)
+rev_root = fs.revision_root(fs_handle, fs.txn_root_base_revision(txn_root))
+
+for path, change in fs.paths_changed2(txn_root).iteritems():
+
+    if change.prop_mod:
+
+        # The new value, if any
+        txn_prop = fs.node_prop(txn_root, path, "svn:externals")
+        if not txn_prop:
+            continue
+
+        # The old value, if any
+        rev_prop = None
+        if change.change_kind == fs.path_change_modify:
+            rev_prop = fs.node_prop(rev_root, path, "svn:externals")
+        elif change.change_kind == fs.path_change_add and change.copyfrom_path:
+            copy_root = fs.revision_root(fs_handle, change.copyfrom_rev)
+            rev_prop = fs.node_prop(copy_root, change.copyfrom_path,
+                                    "svn:externals")
+
+        if txn_prop != rev_prop:
+            error_path = path.decode('utf-8').encode(native, 'replace')
+            externals = []
+            try:
+                externals = wc.parse_externals_description2(path, txn_prop)
+            except:
+                sys.stderr.write("Commit blocked due to parse failure "
+                                 "on svn:externals for %s\n" % error_path)
+                sys.exit(1)
+            for external in externals:
+                parsed = urlparse.urlparse(urllib.unquote(external.url))
+                if (parsed and parsed.scheme[:4] == "svn+"
+                    and suspicious_host(parsed.netloc)):
+                    sys.stderr.write("Commit blocked due to suspicious URL "
+                                     "containing %r in svn:externals "
+                                     "for %s\n" % (parsed.netloc, error_path))
+                    sys.exit(1)

Propchange: subversion/trunk/contrib/hook-scripts/CVE-2017-9800-pre-commit.py
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: subversion/trunk/contrib/hook-scripts/CVE-2017-9800-pre-commit.py
------------------------------------------------------------------------------
    svn:executable = *


Reply via email to