Hello,

As of 2.6.8, 2.7.3 and 3.2.3, Python supports hash seed randomization. See
http://bugs.python.org/issue13703 for details.

It's off by default, except in 3.3+, and can be enabled via the
PYTHONHASHSEED=random environment variable, the -R command-line flag, or by
flipping the Py_HashRandomizationFlag flag in C before Python is initialized.

Since we cannot alter the os.environ via Apache directives, like SetEnv, I
thought it would make sense to make a mod_wsgi configuration option for this.

Attached is a patch that adds a WSGIHashRandomization configuration directive.

I tested the patch and can confirm that `sys.flags.hash_randomization` reflects
that it is getting properly enabled in my application.

Right now the patch enables this feature by default, if it's available. This
behavior is obviously up for discussion, as it may break code that makes
assumptions about dictionary ordering and such (as seen in some stdlib unit
tests that broke). However, for security purposes, I think everyone will want
this feature turned on by default.

Cheers,

luke
diff -up ./configure.ac.orig ./configure.ac
--- ./configure.ac.orig 2009-11-23 01:49:39.000000000 -0500
+++ ./configure.ac      2012-03-01 16:07:15.211953095 -0500
@@ -92,6 +92,16 @@ else
 CPPFLAGS3=""
 fi
 
+AC_MSG_CHECKING(Python hash randomization support)
+PYTHON_HASH_RANDOMIZATION=`${PYTHON} -c 'from sys import flags, stdout; \
+    stdout.write(str(getattr(flags, "hash_randomization", "")))'`
+if test -n "${PYTHON_HASH_RANDOMIZATION}"; then
+    CPPFLAGS3="${CPPFLAGS3} -DWITH_PYTHON_HASH_RANDOMIZATION"
+    AC_MSG_RESULT(yes)
+else
+    AC_MSG_RESULT(no)
+fi
+
 CPPFLAGS="${CPPFLAGS} ${CPPFLAGS1} ${CPPFLAGS2} ${CPPFLAGS3}"
 
 AC_SUBST(CPPFLAGS)
diff -up ./mod_wsgi.c.orig ./mod_wsgi.c
--- ./mod_wsgi.c.orig   2010-07-25 23:58:37.000000000 -0400
+++ ./mod_wsgi.c        2012-03-01 16:05:33.225451743 -0500
@@ -479,6 +479,10 @@ typedef struct {
     int error_override;
     int chunked_request;
 
+#ifdef WITH_PYTHON_HASH_RANDOMIZATION
+    int hash_randomization;
+#endif
+
 #if AP_SERVER_MAJORVERSION_NUMBER >= 2
     apr_hash_t *handler_scripts;
 #endif
@@ -532,6 +536,10 @@ static WSGIServerConfig *newWSGIServerCo
     object->restrict_stdout = -1;
     object->restrict_signal = -1;
 
+#ifdef WITH_PYTHON_HASH_RANDOMIZATION
+    object->hash_randomization = -1;
+#endif
+
 #if defined(WIN32) || defined(DARWIN)
     object->case_sensitivity = 0;
 #else
@@ -5810,6 +5818,12 @@ static void wsgi_python_init(apr_pool_t
         _wputenv(L"PYTHONIOENCODING=cp1252:backslashreplace");
 #endif
 
+#ifdef WITH_PYTHON_HASH_RANDOMIZATION
+        if (wsgi_server_config->hash_randomization != 0) {
+            Py_HashRandomizationFlag = 1;
+        }
+#endif
+
         /* Initialise Python. */
 
         ap_log_error(APLOG_MARK, WSGI_LOG_INFO(0), wsgi_server,
@@ -7328,6 +7342,30 @@ static const char *wsgi_set_restrict_sig
     return NULL;
 }
 
+#ifdef WITH_PYTHON_HASH_RANDOMIZATION
+static const char *wsgi_set_hash_randomization(cmd_parms *cmd, void *mconfig,
+                                               const char *f)
+{
+    const char *error = NULL;
+    WSGIServerConfig *sconfig = NULL;
+
+    error = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+    if (error != NULL)
+        return error;
+
+    sconfig = ap_get_module_config(cmd->server->module_config, &wsgi_module);
+
+    if (strcasecmp(f, "Off") == 0)
+        sconfig->hash_randomization = 0;
+    else if (strcasecmp(f, "On") == 0)
+        sconfig->hash_randomization = 1;
+    else
+        return "WSGIHashRandomization must be one of: Off | On";
+
+    return NULL;
+}
+#endif
+
 static const char *wsgi_set_case_sensitivity(cmd_parms *cmd, void *mconfig,
                                            const char *f)
 {
@@ -9232,6 +9270,11 @@ static const command_rec wsgi_commands[]
     { "WSGIChunkedRequest", wsgi_set_chunked_request, NULL,
         OR_FILEINFO, TAKE1, "Enable/Disable support for chunked request." },
 
+#ifdef WITH_PYTHON_HASH_RANDOMIZATION
+    { "WSGIHashRandomization", wsgi_set_hash_randomization, NULL,
+        RSRC_CONF, TAKE1, "Enable/Disable hash randomization" },
+#endif
+
     { NULL }
 };
 
@@ -14951,6 +14994,11 @@ static const command_rec wsgi_commands[]
     AP_INIT_RAW_ARGS("WSGIHandlerScript", wsgi_add_handler_script,
         NULL, ACCESS_CONF|RSRC_CONF, "Location of WSGI handler script file."),
 
+#ifdef WITH_PYTHON_HASH_RANDOMIZATION
+    AP_INIT_RAW_ARGS("WSGIHashRandomization", wsgi_set_hash_randomization,
+        NULL, RSRC_CONF, "Enable/Disable hash randomization."),
+#endif
+
     { NULL }
 };
 

Attachment: pgpVdtVodOqPs.pgp
Description: PGP signature

Reply via email to