document and improve hash algorithm randomization related build options
authorYves Orton <demerphq@gmail.com>
Tue, 7 May 2013 21:52:16 +0000 (23:52 +0200)
committerYves Orton <demerphq@gmail.com>
Tue, 7 May 2013 22:10:45 +0000 (00:10 +0200)
Install was a copy of other material, made heavy reference to 5.8.x and
and didnt really document what it should have. I reworked it to be more
up to date.

INSTALL
hv.h
hv_func.h
pod/perlrun.pod

diff --git a/INSTALL b/INSTALL
index c547867..4fce90a 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -336,38 +336,62 @@ and the long double support.
 
 =head3 Algorithmic Complexity Attacks on Hashes
 
-In Perls 5.8.0 and earlier it was easy to create degenerate hashes.
-Processing such hashes would consume large amounts of CPU time,
-enabling a "Denial of Service" attack against Perl.  Such hashes may be
-a problem for example for mod_perl sites, sites with Perl CGI scripts
-and web services, that process data originating from external sources.
-
-In Perl 5.8.1 a security feature was introduced to make it harder to
-create such degenerate hashes. A visible side effect of this was that
-the keys(), values(), and each() functions may return the hash elements
-in different order between different runs of Perl even with the same
-data.  It also had unintended binary incompatibility issues with
-certain modules compiled against Perl 5.8.0.
-
-In Perl 5.8.2 an improved scheme was introduced.  Hashes will return
-elements in the same order as Perl 5.8.0 by default.  On a hash by hash
-basis, if pathological data is detected during a hash key insertion,
-then that hash will switch to an alternative random hash seed.  As
-adding keys can always dramatically change returned hash element order,
-existing programs will not be affected by this, unless they
-specifically test for pre-recorded hash return order for contrived
-data. (eg the list of keys generated by C<map {"\0"x$_} 0..15> trigger
-randomisation) In effect the new implementation means that 5.8.1 scheme
-is only being used on hashes which are under attack.
-
-One can still revert to the old guaranteed repeatable order (and be
-vulnerable to attack by wily crackers) by setting the environment
-variable PERL_HASH_SEED, see L<perlrun/PERL_HASH_SEED>.  Another option
-is to add -DUSE_HASH_SEED_EXPLICIT to the compilation flags (for
-example by using C<Configure -Accflags=-DUSE_HASH_SEED_EXPLICIT>), in
-which case one has to explicitly set the PERL_HASH_SEED environment
-variable to enable the security feature, or by adding -DNO_HASH_SEED to
-the compilation flags to completely disable the randomisation feature.
+Perl 5.18 reworked the measures used to secure its hash function
+from algorithmic complexity attacks.  By default it will build with
+all of these measures enabled along with support for controlling and
+disabling them via environment variables.
+
+You can override various aspects of this feature by defining various
+symbols during configure. An example might be:
+
+    Configure -Accflags=-DPERL_HASH_FUNC_SIPHASH
+
+B<Unless stated otherwise these options are considered experimental or
+insecure and are not recommended for production use.>
+
+Perl 5.18 includes support for multiple hash functions, and changed
+the default (to ONE_AT_A_TIME_HARD), you can choose a different
+algorithm by defining one of the following symbols. Note that as of
+Perl 5.18 we can only recommend use of the default or SIPHASH. All
+the others are known to have security issues and are for research
+purposes only.
+
+    PERL_HASH_FUNC_SIPHASH
+    PERL_HASH_FUNC_SDBM
+    PERL_HASH_FUNC_DJB2
+    PERL_HASH_FUNC_SUPERFAST
+    PERL_HASH_FUNC_MURMUR3
+    PERL_HASH_FUNC_ONE_AT_A_TIME
+    PERL_HASH_FUNC_ONE_AT_A_TIME_HARD
+    PERL_HASH_FUNC_ONE_AT_A_TIME_OLD
+
+Perl 5.18 randomizes the order returned by keys(), values(), and each(),
+and allows controlling this behavior by using of the PERL_PERTURB_KEYS
+option. You can disable this option entirely with the define:
+
+    PERL_PERTURB_KEYS_DISABLED
+
+You can disable the environment variable checks and specify the type of
+key traversal randomization to be used by defining one of these:
+
+    PERL_PERTURB_KEYS_RANDOM
+    PERL_PERTURB_KEYS_DETERMINISTIC
+
+In Perl 5.18 the seed used for the hash function is randomly selected
+at process start which can be overriden by specifing a seed by setting
+the PERL_HASH_SEED environment variable.
+
+You can change this behavior by building perl with the
+
+   USE_HASH_SEED_EXPLICIT
+
+define, in which case one has to explicitly set the PERL_HASH_SEED
+environment variable to enable the security feature or by adding
+
+    NO_HASH_SEED
+
+to the compilation flags to completely disable the randomisation feature.
+Note these modes are poorly tested, insecure and not recommended.
 
 B<Perl has never guaranteed any ordering of the hash keys>, and the
 ordering has already changed several times during the lifetime of Perl
@@ -378,6 +402,10 @@ between different runs of Perl, since Data::Dumper by default dumps
 hashes "unordered".  The use of the Data::Dumper C<Sortkeys> option is
 recommended.
 
+See L<perlrun/PERL_HASH_SEED> and L<perlrun/PERL_PERTURB_KEYS> for details on
+the environment variables, and L<perlsec/Algorithmic Complexity Attacks> for
+further security details.
+
 =head3 SOCKS
 
 Perl can be configured to be 'socksified', that is, to use the SOCKS
diff --git a/hv.h b/hv.h
index 0d619f2..2eea477 100644 (file)
--- a/hv.h
+++ b/hv.h
 /* These control hash traversal randomization and the environment variable PERL_PERTURB_KEYS.
  * Currently disabling this functionality will break a few tests, but should otherwise work fine.
  * See perlrun for more details. */
-#define PERL_HASH_RANDOMIZE_KEYS 1
-#define USE_PERL_PERTURB_KEYS 1
 
-
-#ifdef PERL_HASH_RANDOMIZE_KEYS
-#   if defined(DEBUGGING) || defined(USE_PERL_PERTURB_KEYS)
-#       define PL_HASH_RAND_BITS_ENABLED PL_hash_rand_bits_enabled
-#   endif
-#   define PERL_HASH_ITER_BUCKET(iter) (((iter)->xhv_riter) ^ ((iter)->xhv_rand))
+#if defined(PERL_PERTURB_KEYS_DISABLED)
+#   define PL_HASH_RAND_BITS_ENABLED        0
+#   define PERL_HASH_ITER_BUCKET(iter)      ((iter)->xhv_riter)
 #else
-#   define PERL_HASH_ITER_BUCKET(iter) ((iter)->xhv_riter)
+#   define PERL_HASH_RANDOMIZE_KEYS         1
+#   if defined(PERL_PERTURB_KEYS_RANDOM)
+#       define PL_HASH_RAND_BITS_ENABLED    1
+#   elif defined(PERL_PERTURB_KEYS_DETERMINISTIC)
+#       define PL_HASH_RAND_BITS_ENABLED    2
+#   else
+#       define USE_PERL_PERTURB_KEYS        1
+#       define PL_HASH_RAND_BITS_ENABLED    PL_hash_rand_bits_enabled
+#   endif
+#   define PERL_HASH_ITER_BUCKET(iter)      (((iter)->xhv_riter) ^ ((iter)->xhv_rand))
 #endif
 
 /* entry in hash value chain */
index 9dfe158..7678807 100644 (file)
--- a/hv_func.h
+++ b/hv_func.h
@@ -11,9 +11,9 @@
 
 #ifndef PERL_SEEN_HV_FUNC_H /* compile once */
 #define PERL_SEEN_HV_FUNC_H
-#define PERL_HASH_FUNC_ONE_AT_A_TIME_HARD
 
 #if !( 0 \
+        || defined(PERL_HASH_FUNC_SIPHASH) \
         || defined(PERL_HASH_FUNC_SDBM) \
         || defined(PERL_HASH_FUNC_DJB2) \
         || defined(PERL_HASH_FUNC_SUPERFAST) \
         || defined(PERL_HASH_FUNC_ONE_AT_A_TIME_HARD) \
         || defined(PERL_HASH_FUNC_ONE_AT_A_TIME_OLD) \
     )
-#ifdef HAS_QUAD
-#define PERL_HASH_FUNC_SIPHASH
-#else
 #define PERL_HASH_FUNC_ONE_AT_A_TIME_HARD
 #endif
-#endif
 
 #if defined(PERL_HASH_FUNC_SIPHASH)
 #   define PERL_HASH_FUNC "SIPHASH_2_4"
index 9078677..ae2efe1 100644 (file)
@@ -1272,19 +1272,19 @@ L</PERL_HASH_SEED_DEBUG> for more information.
 X<PERL_PERTURB_KEYS>
 
 (Since Perl 5.18.0)  Set to C<"0"> or C<"NO"> then traversing keys
-will be repeatedable from run to run for the same PERL_HASH_SEED.
+will be repeatable from run to run for the same PERL_HASH_SEED.
 Insertion into a hash will not change the order, except to provide
 for more space in the hash. When combined with setting PERL_HASH_SEED
 this mode is as close to pre 5.18 behavior as you can get.
 
 When set to C<"1"> or C<"RANDOM"> then traversing keys will be randomized.
 Every time a hash is inserted into the key order will change in a random
-fashion. The order may not be repeatedable in a following program run
+fashion. The order may not be repeatable in a following program run
 even if the PERL_HASH_SEED has been specified. This is the default
 mode for perl.
 
 When set to C<"2"> or C<"DETERMINISTIC"> then inserting keys into a hash
-will cause the key order to change, but in a way that is repeatedable
+will cause the key order to change, but in a way that is repeatable
 from program run to program run.
 
 B<NOTE:> Use of this option is considered insecure, and is intended only