-*- coding: utf-8 -*-
Changes with Apache 2.5.0
+ *) Introduce request taint checking framework to prevent privilege
+ hijacking through .htaccess. [Nick Kew]
+
*) mod_proxy_wstunnel: Add "upgrade" parameter to allow upgrade to other
protocols. [Jean-Frederic Clere]
* Added ap_scan_vchar_obstext()
* 20161018.2 (2.5.0-dev) add ap_set_conn_count()
* 20161018.3 (2.5.0-dev) add ap_exists_directive()
+ * 20161018.4 (2.5.0-dev) Add taint to request_rec and ap_request_tainted()
*/
#define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20161018
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 3 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 4 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
* TODO: 2 bit signed bitfield when this structure is compacted
*/
int double_reverse;
+ /** Mark the request as potentially tainted. This might become a
+ * bitfield if we identify different taints to be flagged.
+ * Always use ap_request_tainted() to check taint.
+ */
+ int taint;
};
/**
*/
AP_DECLARE(int) ap_request_has_body(request_rec *r);
+/** Request taint flags. Only .htaccess defined. */
+#define AP_TAINT_HTACCESS 0x1
+/**
+ * Check whether a request is tainted by potentially-untrusted sources.
+ *
+ * @param r the request
+ * @param flags Taint flags to check
+ * @return truth value
+ */
+AP_DECLARE(int) ap_request_tainted(request_rec *r, int flags);
+
/**
* Cleanup a string (mainly to be filesystem safe)
* We only allow '_' and alphanumeric chars. Non-printable
return DECLINED;
}
+ /* A request that has passed through .htaccess has no business
+ * landing up here.
+ */
+ if (ap_request_tainted(r, AP_TAINT_HTACCESS)) {
+ return DECLINED;
+ }
+
#ifdef HAVE_TIMES
times_per_thread = getpid() != child_pid;
#endif
if (!r->proxyreq || !r->filename || strncmp(r->filename, "proxy:", 6) != 0)
return DECLINED;
+ /* A request that has passed through .htaccess has no business
+ * serving contents from so far outside its directory.
+ * Since we're going to decline it, don't waste time here.
+ */
+ if (ap_request_tainted(r, AP_TAINT_HTACCESS)) {
+ return DECLINED;
+ }
+
/* XXX: Shouldn't we try this before we run the proxy_walk? */
url = &r->filename[6];
return DECLINED;
}
+ /* A request that has passed through .htaccess has no business
+ * serving contents from so far outside its directory.
+ */
+ if (ap_request_tainted(r, AP_TAINT_HTACCESS)) {
+ return DECLINED;
+ }
+
if (!r->proxyreq) {
/* We may have forced the proxy handler via config or .htaccess */
if (r->handler &&
const char *errmsg;
ap_directive_t *temptree = NULL;
+ /* Mark the request as tainted by .htaccess */
+ r->taint |= AP_TAINT_HTACCESS;
dc = ap_create_per_dir_config(r->pool);
parms.config_file = f;
return has_body;
}
+/**
+ * Check whether a request is tainted by exposure to something
+ * potentially untrusted.
+ *
+ */
+AP_DECLARE(int) ap_request_tainted(request_rec *r, int flags)
+{
+ /** Potential future: a hook or callback here could serve modules
+ * like mod_security and ironbee with more complex needs.
+ */
+ return r && ((r->taint&flags)
+ || ap_request_tainted(r->main, flags)
+ || ap_request_tainted(r->prev, flags));
+}
+
AP_DECLARE_NONSTD(apr_status_t) ap_pool_cleanup_set_null(void *data_)
{
void **ptr = (void **)data_;