mod_dav_svn is vulnerable to a remotely triggerable segfault DoS vulnerability for requests with no existant virtual transaction names. Summary: ======== Subversion's mod_dav_svn Apache HTTPD server module will crash when it receives a request for some invalid formatted special URIs. This can lead to a DoS. There are no known instances of this problem being exploited in the wild. Known vulnerable: ================= Subversion HTTPD servers 1.7.0 through 1.7.18 (inclusive) Subversion HTTPD servers 1.8.0 through 1.8.10 (inclusive) Known fixed: ============ Subversion 1.7.19 Subversion 1.8.11 Details: ======== Subversion 1.7.0 and newer added new protocol variant to the HTTP support. One of the changes in this new protocol was that the client no longer had to generate the UUID by which transactions would be referred to. However, there were circumstances where clients needed to provide their own names for transactions and so it has support for virtual transaction names. These transaction names are then mapped to the servers internal transaction id much as was done in the old protocol. New special URIs were provided to allow the client to access the transactions by these virtual transaction names. Making a request for a URI that refers to a non-existant virtual transaction name results in the lookup for the internal transaction id to be NULL. Subsequent uses of the transaction id do not properly validate that the id is valid and result in a SEGFAULT. Severity: ========= CVSSv2 Base Score: 5.0 CVSSv2 Base Vector: AV:N/AC:L/Au:N/C:N/I:N/A:P We consider this to be a medium risk vulnerability. Repositories which allow for anonymous reads will be vulnerable without authentication. Unfortunately, no special configuration is required and all mod_dav_svn servers that support the new protocol variant are vulnerable. A remote attacker may be able to crash a Subversion server. Many Apache servers will respawn the listener processes, but a determined attacker will be able to crash these processes as they appear, denying service to legitimate users. Servers using threaded MPMs will close the connection on other clients being served by the same process that services the request from the attacker. In either case there is an increased processing impact of restarting a process and the cost of per process caches being lost. Recommendations: ================ We recommend all users to upgrade to Subversion 1.8.11. Users of Subversion 1.7.x or 1.8.x who are unable to upgrade may apply the included patch. New Subversion packages can be found at: http://subversion.apache.org/packages.html No known workarounds are available. References: =========== CVE-2014-8108 (Subversion) Reported by: ============ Evgeny Kotkov, VisualSVN Patches: ======== Patch against 1.7.18: [[[ Index: subversion/mod_dav_svn/repos.c =================================================================== --- subversion/mod_dav_svn/repos.c (revision 1624477) +++ subversion/mod_dav_svn/repos.c (working copy) @@ -506,6 +506,9 @@ parse_vtxnstub_uri(dav_resource_combined *comb, if (parse_txnstub_uri(comb, path, label, use_checked_in)) return TRUE; + if (!comb->priv.root.txn_name) + return TRUE; + comb->priv.root.vtxn_name = comb->priv.root.txn_name; comb->priv.root.txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.vtxn_name); @@ -574,6 +577,9 @@ parse_vtxnroot_uri(dav_resource_combined *comb, if (parse_txnroot_uri(comb, path, label, use_checked_in)) return TRUE; + if (!comb->priv.root.txn_name) + return TRUE; + comb->priv.root.vtxn_name = comb->priv.root.txn_name; comb->priv.root.txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.vtxn_name); @@ -919,6 +925,10 @@ prep_working(dav_resource_combined *comb) point. */ if (txn_name == NULL) { + if (!comb->priv.root.activity_id) + return dav_svn__new_error(comb->res.pool, HTTP_BAD_REQUEST, 0, + "The request did not specify an activity ID"); + txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.activity_id); if (txn_name == NULL) @@ -1029,9 +1039,14 @@ prep_working(dav_resource_combined *comb) static dav_error * prep_activity(dav_resource_combined *comb) { - const char *txn_name = dav_svn__get_txn(comb->priv.repos, - comb->priv.root.activity_id); + const char *txn_name; + if (!comb->priv.root.activity_id) + return dav_svn__new_error(comb->res.pool, HTTP_BAD_REQUEST, 0, + "The request did not specify an activity ID"); + + txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.activity_id); + comb->priv.root.txn_name = txn_name; comb->res.exists = txn_name != NULL; ]]] Patch against 1.8.10: [[[ Index: subversion/mod_dav_svn/repos.c =================================================================== --- subversion/mod_dav_svn/repos.c (revision 1624477) +++ subversion/mod_dav_svn/repos.c (working copy) @@ -508,6 +508,9 @@ parse_vtxnstub_uri(dav_resource_combined *comb, if (parse_txnstub_uri(comb, path, label, use_checked_in)) return TRUE; + if (!comb->priv.root.txn_name) + return TRUE; + comb->priv.root.vtxn_name = comb->priv.root.txn_name; comb->priv.root.txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.vtxn_name); @@ -576,6 +579,9 @@ parse_vtxnroot_uri(dav_resource_combined *comb, if (parse_txnroot_uri(comb, path, label, use_checked_in)) return TRUE; + if (!comb->priv.root.txn_name) + return TRUE; + comb->priv.root.vtxn_name = comb->priv.root.txn_name; comb->priv.root.txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.vtxn_name); @@ -921,6 +927,10 @@ prep_working(dav_resource_combined *comb) point. */ if (txn_name == NULL) { + if (!comb->priv.root.activity_id) + return dav_svn__new_error(comb->res.pool, HTTP_BAD_REQUEST, 0, + "The request did not specify an activity ID"); + txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.activity_id); if (txn_name == NULL) @@ -1031,9 +1041,14 @@ prep_working(dav_resource_combined *comb) static dav_error * prep_activity(dav_resource_combined *comb) { - const char *txn_name = dav_svn__get_txn(comb->priv.repos, - comb->priv.root.activity_id); + const char *txn_name; + if (!comb->priv.root.activity_id) + return dav_svn__new_error(comb->res.pool, HTTP_BAD_REQUEST, 0, + "The request did not specify an activity ID"); + + txn_name = dav_svn__get_txn(comb->priv.repos, comb->priv.root.activity_id); + comb->priv.root.txn_name = txn_name; comb->res.exists = txn_name != NULL; ]]]