WP Salts - How long can they be?

Hi WPMUDev,

Hope your day is going well!

I have a Q about the authentication salts used in wp-config.php

I seem to remember reading about making the salts longer than they are made by the the WP salt api.

For instance, using the WP salt api to generate several sets of salts and then adding bits of them together to make a salts which are twice as long as default.

Is this a) possible b) advisable (for the security motivated)?

Regards,
Max

  • wp.network

    a few minutes searching didn't give yield a clear answer, but I did find these nice articles on salts and WPsec generally.

    http://codeseekah.com/2012/04/09/why-wordpress-authentication-unique-keys-and-salts-are-important/

    http://techatftc.wordpress.com/2013/03/21/storing-passwords-or-the-risk-of-a-no-salt-diet/

    also, thinking for another minute I'm pretty sure that it was actually in a WPMUDev thread in which

    I seem to remember reading about making the salts longer than they are made by the the WP salt api.

    but I can't seem to find it again.

    Cheers, Max

  • aristath

    Hello there @Max, I hope you're well today!

    Security issues can sometimes be a little... weird.
    I don't think that using a longer string for your salts will be useful.
    However, you could simply change them on a daily basis (which of course would mean that people would have to re-login daily).
    Salts can be generated from https://api.wordpress.org/secret-key/1.1/salt/ and you can even automate changing these salts!
    I haven't tested this, it's just an idea that I had 3 minutes ago... but you could do the following:
    1. Create a new file and call it something random like ljhsdf87WERBJSD86.php
    2. create a cronjob on your server that will use wget to grab https://api.wordpress.org/secret-key/1.1/salt/ and save it on that file
    3. delete the salts from your wp-config.php file and instead include the file that has the randomized salts.

    That should be security enough! :wink:

    I hope that helps!

    Cheers,
    Ari.

  • wp.network

    @aristath thats a really good idea! (and I agree that it seems to add much more practical sec than a longer salt that doesn't change often could, even if long salts were a thing)

    I could use some help figuring out how to try this out though :slight_smile:

    1) Ok, this one I'm pretty sure I can do
    2) I'm not a strong command line presence, could this be setup via the Cron UI in cpanel?
    2a) if yes, then by what commands?
    3) I think I get the idea here... I get that I need to tell WP where to find the jhkh43h4hjhdf.php (or whtevr) file, but I need help with this code also.

    I love the idea and would like to test it out if you can help with the code for wp-config and for setting the Cron jobs (though I can get help from my host on that too I imagine).

    Many Kind Regards,
    Max

    4) would it possible to have the wget cron job action discard the first set of Salts loaded from the API? As in only using the second or third set of results? I read about that somewhere too; not sure how much its worth.

  • aristath

    ok, this is completely experimental, but here it goes.
    Step 1: in the root folder of your WordPress installation (right next to your wp-config.php file) create a new file called "get-new-salts.php". In that file paste the following:

    <?php
    
    // Define the name of the salts file
    $salts_file = 'salts.php'
    // Define the address of the Salts
    $salts_api = 'https://api.wordpress.org/secret-key/1.1/salt/'
    
    // Get a new set of salts
    $new_salts = file_get_contents( $salts_api );
    // Open the salts file
    $sf = fopen( $salts_file, 'w' );
    // Write the new salts to the salts file
    fwrite( $sf, $new_salts );
    // Close the file
    fclose( $sf );

    randomize the name of the salts file on this line: $salts_file = 'salts.php'.
    You can use an MD5 generator to create that: http://www.miraclesalad.com/webtools/md5.php

    Step 2: create the file with that randomized name and make sure it is writable by your webserver.

    Step 3: In your wp-config.php file delete the salts lines and replace them with this line:
    require( dirname( __FILE__ ) . '/salts.php' ); again replacing salts.php with the randomized filename that you have.

    Step 4: Create a new cronjob that will simply get the get-new-salts.php file. You can do that from your cPanel by adding the following command:
    wget -qO /dev/null http://domain.com/get-new-salts.php

    Let me know if that works! If it does I'll publish a blog post with detailed instructions for others too. :slight_smile:

    Cheers,
    Ari.

  • wp.network

    @aristath most excellent! I will give it a go and report :slight_smile:

    one clarification:

    randomize the name of the salts file on this line:
    $salts_file = 'salts.php'
    .
    You can use an MD5 generator to create that: http://www.miraclesalad.com/webtools/md5.php

    Lets call this Step 1.2

    Am I correct in understanding that I should
    a) imagine an arbitrary file name, such as
    salty-rainbow-box.php
    and then
    b) enter that name (in this case, 'salty-rainbow-box') into the md5 tool and then
    c) use the randomized output as the actual replacement as the filename value for 'salts.php' in the code?
    such as, in this case, 352d59d6c8f88924f667e51a8b2b0d70.php

    Cheers,
    Max

  • wp.network

    ... ok, seems to be setup... I am using:
    'secret-salty-fetcher.php' in public_html

    <?php
    
    // Define the name of the salts file
    $salts_file = 'md5#s.php'
    // Define the address of the Salts
    $salts_api = 'https://api.wordpress.org/secret-key/1.1/salt/'
    
    // Get a new set of salts
    $new_salts = file_get_contents( $salts_api );
    // Open the salts file
    $sf = fopen( $salts_file, 'w' );
    // Write the new salts to the salts file
    fwrite( $sf, $new_salts );
    // Close the file
    fclose( $sf );

    In my wp-config.php file, I have replaced the salts with the following line:

    require( dirname( __FILE__ ) . '/md5#s.php' );

    I have created an empty file named md5#s.php
    in public_html.

    Currently, the file permissions for all three of these files is set to 660.

    The command I await entering via the cpanel Cron Job interface is:
    wget -qO /dev/null http://www.example.com/secret-salty-fetcher.php

    (yes, md5#s and example.com and secret-salty-fetcher are placeholders for my real values)

    ...however, when I tried navigating directly to the salty-fetcher file via my browser (using 664) I get a 500 server error page.

    Idk if this is expected for a browser visit. I have held off on scheduling the cron job until I hear back from my host with their impressions.

    Regards,
    Max

  • wp.network

    Hi @aristath

    I do have access, and I'm not seeing anything that seems to relate.

    I may have cleared the log in the interim, I can't be positive...

    However, while I love the sound of this trickiness, I have a plateful of high-priority issues to work through at the moment... so, I'm gonna have to back-burner this one. I'd love to know if you end up playing around with this approach. It might be nice to try again in the future.

    I totally appreciate the inventiveness you showed here! Thanks :slight_smile:

    Regards,
    Max

  • aristath

    Hello again!

    Here's another implementation.. similar concept, just different code:

    <?php
    /*
    Plugin Name: Salts Randomizer
    Plugin URI: http://aristeides.com
    Description: Change salts daily
    Author: Aristeides Stathopoulos
    Version: 0.1
    Author URI: http://aristeides.com
    */
    
    /**
     * This plugin provides a simple way to automatically change the salts on a daily basis.
     * It requires you make the following changes in your wp-config.php file:
     *
     * 1. 	Delete the salts from your wp-config.php file.
     * 		Your salts should look something like this:
    define('AUTH_KEY',         'neHTup]h7?v3@#M+%YTs5nl[=1?]6QR5_0l7&$f+4V)ulg5+R@{U__+{a,COu*L');
    define('SECURE_AUTH_KEY',  '1fl${fk@:m>:Kg6WP3aB O.kQb(t[(@[JT&tpF^XC>]VaZ>nwelFT<Y%Rum8Kc:');
    define('LOGGED_IN_KEY',    'V^191EJW$yAtt)(b{;:F)eVvJEtRzC%Pe&YF--0_{x1I<mt*S0JM.t:7J-UwyYrR');
    define('NONCE_KEY',        '^I*|^DHOtr4>~|Iri-[^up{i_%o.Lm6|cdO%-$rjQ#AmBDGOaap0^>JxYMkSt+%');
    define('AUTH_SALT',        'Pfwp{RHMT>%_ozq+}Na|UYjEO8%q1#x-YP!FbxCu P,Ro[Ym0<{KII10L*V*~I}');
    define('SECURE_AUTH_SALT', '22xRGl[{ iFcE*hN8BwH+dh/SCuS!NOlL{BZVbi,^a:>Jg=cjR|t#nfT^fIq-1s');
    define('LOGGED_IN_SALT',   '$+Q(uMl^q[5&uh@|~E#7b]uyGpNcx|FrFP,A!B7NJ.+6[[s9F$EHyl<C:+:M<Or');
    define('NONCE_SALT',       '4qW<NzJWY$sJa^InQa[:BI+9?p<T/u(167:B!Es2<Hjk(o4q.=33Ax>l^gPl=+z');
     *
     * 2.	After you delete the salts, add this line in their place:
    require_once(ABSPATH . 'salts-random-filename.php');
     * Of course you can change that to your own, completely random filename.
     *
     * For the first time this runs, you should copy the salts you deleted from your wp-config.php file in that file like this:
    <?php
    define('AUTH_KEY',         'neHTup]h7?v3@#M+%YTs5nl[=1?]6QR5_0l7&$f+4V)ulg5+R@{U__+{a,COu*L');
    define('SECURE_AUTH_KEY',  '1fl${fk@:m>:Kg6WP3aB O.kQb(t[(@[JT&tpF^XC>]VaZ>nwelFT<Y%Rum8Kc:');
    define('LOGGED_IN_KEY',    'V^191EJW$yAtt)(b{;:F)eVvJEtRzC%Pe&YF--0_{x1I<mt*S0JM.t:7J-UwyYrR');
    define('NONCE_KEY',        '^I*|^DHOtr4>~|Iri-[^up{i_%o.Lm6|cdO%-$rjQ#AmBDGOaap0^>JxYMkSt+%');
    define('AUTH_SALT',        'Pfwp{RHMT>%_ozq+}Na|UYjEO8%q1#x-YP!FbxCu P,Ro[Ym0<{KII10L*V*~I}');
    define('SECURE_AUTH_SALT', '22xRGl[{ iFcE*hN8BwH+dh/SCuS!NOlL{BZVbi,^a:>Jg=cjR|t#nfT^fIq-1s');
    define('LOGGED_IN_SALT',   '$+Q(uMl^q[5&uh@|~E#7b]uyGpNcx|FrFP,A!B7NJ.+6[[s9F$EHyl<C:+:M<Or');
    define('NONCE_SALT',       '4qW<NzJWY$sJa^InQa[:BI+9?p<T/u(167:B!Es2<Hjk(o4q.=33Ax>l^gPl=+z');
     *
     * In other words, DO NOT FORGET TO ADD THE <?php in from of the define lines.
     */
    
    /**
     * The main plugin class
     */
    class Salts_Randomizer {
    
    	/**
    	 * Class constructor
    	 */
    	function __construct() {
    
    		// If the current transients are valid, do not proceed.
    		if ( ! $this->check_transients() ) {
    
    			add_action( 'get_footer', array( $this, 'update' ) );
    
    		}
    	}
    
    	/**
    	 * Update the salts with new values
    	 */
    	function update() {
    
    		$filename = ABSPATH . 'salts-random-filename.php';
    
    		// Write new salts to disk
    		$this->write_to_file( $filename, $this->get_new_salts() );
    
    		// Save the transients
    		$this->save_transients( $this->get_new_salts() );
    	}
    
    	/**
    	 * Check if the existing salts are valid or expired
    	 */
    	function check_transients() {
    
    		$salts = get_transient( 'salts_rand' );
    
    		if ( ! $salts ) {
    			return false;
    		} else {
    			return true;
    		}
    
    	}
    
    	/**
    	 * Save salts in the db
    	 */
    	function save_transients( $salts = null, $expiration = 86400  ) {
    
    		// On mulrisites use set_site_transient() instead of set_transient()
    		if ( is_multisite() ) {
    			set_site_transient( 'salts_rand', $salts, $expiration );
    		} else {
    			set_transient( 'salts_rand', $salts, $expiration );
    		}
    	}
    
    	/**
    	 * Get new transients from the WordPress API.
    	 */
    	function get_new_salts() {
    
    		$new_keys = wp_remote_get( 'https://api.wordpress.org/secret-key/1.1/salt/' );
    
    		return $new_keys;
    
    	}
    
    	/**
    	 * Write the new salts to disk
    	 */
    	function write_to_file( $file, $content ) {
    
    		global $wp_filesystem;
    
    		$wp_filesystem->put_contents( $file, '<?php ' . $content, FS_CHMOD_FILE );
    
    	}
    
    }
    
    $salts_randomizer = new Salts_Randomizer();

    I'm also posting this code on https://gist.github.com/aristath/f115855ab13d7422bf75 just for better readability.

    You should put this code in a new php file in your wp-content/mu-plugins.php file.

    I have included some basic documentation inline in there too...
    I tested this and there were no fatal errors, but I couldn't see if the salts were actually regenerated, I'd have to wait 24 hours to determine that. :slight_smile:

    Cheers,
    Ari.

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.