Created
June 8, 2017 08:52
-
-
Save phlbnks/94773378dce06336d05f35a88d88d9dd to your computer and use it in GitHub Desktop.
Revisions
-
phlbnks created this gist
Jun 8, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,339 @@ #!/bin/bash -e # # Description: # This will deploy WordPress in the current directory. # Without modification it: # - will configure basic security: # - remove initial user created # - deploy 6G firewall in .htaccess # - attempt to prevent user enumeration in .htaccess # - protect sensitive files and disallow executables in /wp-uploads # - presumes a htpasswd file called wp-login is located in /etc/apache2/ # - disallows theme/plugin editor in wp-admin # - only allows core/plugin/theme updates in wp-admin when using a cookie set using &key=xxx # - presumes it is a staging environment so sets 'discourage search engines' # - deletes akismet and hello_dolly plugins # - deletes the default page and post # - creates a blank page called Home and sets it as the frontpage # - sets permalinks to /%postaname%/ # - optionally it: # - bootstraps an _S theme # - installs some plugins - advanced-custom-fields autoptimize better-wp-security breadcrumb-navxt broken-link-checker cms-tree-page-view custom-post-type-ui ewww-image-optimizer google-analytics-dashboard-for-wp google-captcha google-sitemap-generator gravity-forms-custom-post-types plugincheck query-monitor redirection re generate-thumbnails simple-local-avatars theme-check wp-fail2ban wp-pagenavi wp-super-cache # - finally it will delete itself after it finishes. clear echo "============================================" echo "WordPress Install Script" echo "============================================" echo "Do you need to setup new MySQL database? (y/n)" read -e setupmysql if [ "$setupmysql" == y ] ; then echo "MySQL Admin User: " read -e mysqluser echo "MySQL Admin Password: " read -s mysqlpass echo "MySQL Host (Enter for default 'localhost'): " read -e mysqlhost mysqlhost=${mysqlhost:-localhost} fi echo "WP Database Name: " read -e dbname echo "WP Database User: " read -e dbuser echo "WP Database Password: " read -s dbpass echo "WP Database Table Prefix [numbers, letters, and underscores only] (Enter for default 'wp_'): " read -e dbtable dbtable=${dbtable:-wp_} echo "Key for updating in wp-admin: " read -e hardenkey echo "Last chance - sure you want to run the install? (y/n)" read -e run if [ "$run" == y ] ; then if [ "$setupmysql" == y ] ; then echo "============================================" echo "Setting up the database." echo "============================================" #login to MySQL, add database, add user and grant permissions dbsetup="create database $dbname;GRANT ALL PRIVILEGES ON $dbname.* TO $dbuser@$mysqlhost IDENTIFIED BY '$dbpass';FLUSH PRIVILEGES;" mysql -u $mysqluser -p$mysqlpass -e "$dbsetup" if [ $? != "0" ]; then echo "============================================" echo "[Error]: Database creation failed. Aborting." echo "============================================" exit 1 fi fi # configure wp cli to allow htaccess modification / re-write flushing. cat > wp-cli.local.yml <<'EOL' apache_modules: - mod_rewrite EOL echo "============================================" echo "Downloading WordPress for you." echo "============================================" #download wordpress wp core download --locale=en_GB echo "+++ Configuring..." wp core config --dbname=$dbname --dbprefix=$dbtable --dbuser=$dbuser --dbpass=$dbpass --extra-php <<PHP /** WP_DEBUG setup **/ define( 'WP_DEBUG', false ); if ( WP_DEBUG ) { define( 'WP_DEBUG_LOG', true ); define( 'SCRIPT_DEBUG', true ); define( 'WP_DEBUG_DISPLAY', false ); @ini_set( 'display_errors', 0 ); } /** Disallow theme and plugin editor in admin. Updates only with query var **/ define( 'DISALLOW_FILE_EDIT', true ); if ( $_REQUEST['key'] == "$hardenkey" ) { setcookie( 'updatebypass', 1 ); } elseif ( ! $_COOKIE['updatebypass'] ) { define( 'DISALLOW_FILE_MODS', true ); } PHP #create uploads folder and set permissions mkdir -p wp-content/uploads chmod 775 wp-content/uploads #remove readme.html rm readme.html #create root .htaccess with some useful starters cat > .htaccess <<'EOL' # Protect this file <Files ~ "^\.ht"> Order allow,deny Deny from all </Files> # Prevent directory listing Options -Indexes ## BEGIN 6G Firewall from https://perishablepress.com/6g/ # 6G:[QUERY STRINGS] <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{QUERY_STRING} (eval\() [NC,OR] RewriteCond %{QUERY_STRING} (127\.0\.0\.1) [NC,OR] RewriteCond %{QUERY_STRING} ([a-z0-9]{2000}) [NC,OR] RewriteCond %{QUERY_STRING} (javascript:)(.*)(;) [NC,OR] RewriteCond %{QUERY_STRING} (base64_encode)(.*)(\() [NC,OR] RewriteCond %{QUERY_STRING} (GLOBALS|REQUEST)(=|\[|%) [NC,OR] RewriteCond %{QUERY_STRING} (<|%3C)(.*)script(.*)(>|%3) [NC,OR] RewriteCond %{QUERY_STRING} (\\|\.\.\.|\.\./|~|`|<|>|\|) [NC,OR] RewriteCond %{QUERY_STRING} (boot\.ini|etc/passwd|self/environ) [NC,OR] RewriteCond %{QUERY_STRING} (thumbs?(_editor|open)?|tim(thumb)?)\.php [NC,OR] RewriteCond %{QUERY_STRING} (\'|\")(.*)(drop|insert|md5|select|union) [NC] RewriteRule .* - [F] </IfModule> # 6G:[REQUEST METHOD] <IfModule mod_rewrite.c> RewriteCond %{REQUEST_METHOD} ^(connect|debug|delete|move|put|trace|track) [NC] RewriteRule .* - [F] </IfModule> # 6G:[REFERRERS] <IfModule mod_rewrite.c> RewriteCond %{HTTP_REFERER} ([a-z0-9]{2000}) [NC,OR] RewriteCond %{HTTP_REFERER} (semalt.com|todaperfeita) [NC] RewriteRule .* - [F] </IfModule> # 6G:[REQUEST STRINGS] <IfModule mod_alias.c> RedirectMatch 403 (?i)([a-z0-9]{2000}) RedirectMatch 403 (?i)(https?|ftp|php):/ RedirectMatch 403 (?i)(base64_encode)(.*)(\() RedirectMatch 403 (?i)(=\\\'|=\\%27|/\\\'/?)\. RedirectMatch 403 (?i)/(\$(\&)?|\*|\"|\.|,|&|&?)/?$ RedirectMatch 403 (?i)(\{0\}|\(/\(|\.\.\.|\+\+\+|\\\"\\\") RedirectMatch 403 (?i)(~|`|<|>|:|;|,|%|\\|\s|\{|\}|\[|\]|\|) RedirectMatch 403 (?i)/(=|\$&|_mm|cgi-|etc/passwd|muieblack) RedirectMatch 403 (?i)(&pws=0|_vti_|\(null\)|\{\$itemURL\}|echo(.*)kae|etc/passwd|eval\(|self/environ) RedirectMatch 403 (?i)\.(aspx?|bash|bak?|cfg|cgi|dll|exe|git|hg|ini|jsp|log|mdb|out|sql|svn|swp|tar|rar|rdf)$ RedirectMatch 403 (?i)/(^$|(wp-)?config|mobiquo|phpinfo|shell|sqlpatch|thumb|thumb_editor|thumbopen|timthumb|webshell)\.php </IfModule> # 6G:[USER AGENTS] <IfModule mod_setenvif.c> SetEnvIfNoCase User-Agent ([a-z0-9]{2000}) bad_bot SetEnvIfNoCase User-Agent (archive.org|binlar|casper|checkpriv|choppy|clshttp|cmsworld|diavol|dotbot|extract|feedfinder|flicky|g00g1e|harvest|heritrix|httrack|kmccrew|loader|miner|nikto|nutch|planetwork|postrank|purebot|pycurl|python|seekerspider|siclab|skygrid|sqlmap|sucker|turnit|vikspider|winhttp|xxxyy|youda|zmeu|zune) bad_bot <limit GET POST PUT> Order Allow,Deny Allow from All Deny from env=bad_bot </limit> </IfModule> # 6G:[BAD IPS] <Limit GET HEAD OPTIONS POST PUT> Order Allow,Deny Allow from All # uncomment/edit/repeat next line to block IPs # Deny from 123.456.789 </Limit> ## END 6G Firewall ## BEGIN htauth basic authentication # STAGING Require all denied AuthType Basic AuthUserFile /etc/apache2/wp-login AuthName "Please Authenticate" Require valid-user # LIVE - prevent wp-login brute force attacks from causing load #<FilesMatch "^(wp-login|xmlrpc)\.php$"> # AuthType Basic # AuthUserFile /etc/apache2/wp-login # AuthName "Please Authenticate" # Require valid-user #</FilesMatch> # Exclude the file upload and WP CRON scripts from authentication <FilesMatch "(async-upload\.php|wp-cron\.php)$"> Satisfy Any Order allow,deny Allow from all Deny from none </FilesMatch> ## END htauth ## BEGIN WP file protection <Files wp-config.php> order allow,deny deny from all </Files> # WP includes directories <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^wp-admin/includes/ - [F,L] RewriteRule !^wp-includes/ - [S=3] # note - comment out next line on multisite RewriteRule ^wp-includes/[^/]+\.php$ - [F,L] RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L] RewriteRule ^wp-includes/theme-compat/ - [F,L] </IfModule> ## END WP file protection # Prevent author enumeration RewriteCond %{REQUEST_URI} !^/wp-admin [NC] RewriteCond %{QUERY_STRING} author=\d RewriteRule ^ /? [L,R=301] EOL #create .htaccess to protect uploads directory cat > wp-content/uploads/.htaccess <<'EOL' # Protect this file <Files .htaccess> Order Deny,Allow Deny from All </Files> # whitelist file extensions to prevent executables being # accessed if they get uploaded order deny,allow deny from all <Files ~ "(?i)\.(docx?|xlsx?|pptx?|txt|pdf|xml|css|jpe?g|png|gif)$"> allow from all </Files> EOL echo "Setup WordPress to a 'standard install'? (y/n)" read -e setupwp if [ "$setupwp" == y ] ; then echo "=========================" echo "Configuring WordPress." echo "=========================" # useful ref: https://indigotree.co.uk/automated-wordpress-installation-with-bash-wp-cli/ echo "Site URL (no trailing slash): " read -e siteurl echo "Site name: " read -e sitename wp core install --url="${siteurl}/" --title="$sitename" --admin_user=admin --admin_password=admin [email protected] --skip-email echo "Is this a sub-directory install? (y/n)" read -e issubdir if [ "$issubdir" == y ] ; then read -e subdir wp option update "${siteurl}/$issubdir" fi echo "+++ Setting up users..." echo "Admin user name: " read -e adminname echo "Admin user email: " read -e adminemail wp user create $adminname $adminemail --role=administrator --send-email echo "+++ Deleting dummy admin user..." wp user delete admin echo "+++ Discouraging search engines..." wp option update blog_public 0 echo "+++ Setting permalinks to /%postaname%/..." wp rewrite structure '/%postname%/' --hard wp rewrite flush --hard echo "+++ Sample page and post deleted when users cleaned; now create empty 'Home' page..." #echo "+++ Deleting sample page and post; create empty 'Home' page..." #wp post delete $(wp post list --post_type=page,post --field=ID --format=ids) wp post create --post_type=page --post_title=Home --post_status=publish echo "+++ Set frontpage setting to show a page..." wp option update show_on_front 'page' echo "+++ Set 'Home' to be the frontpage..." wp option update page_on_front $(wp post list --post_type=page --pagename=home --field=ID --format=ids) echo "Install _s theme? (y/n)" read -e underscores if [ "$underscores" == y ] ; then echo "Theme slug: " read -e themeslug echo "Theme name: " read -e themename echo "Author: " read -s themeauthor echo "Author URI: " read -s themeuri wp scaffold _s $themeslug --theme_name="$themename" --author="$author" --author_uri="$themeuri" --activate --sassify fi echo "Install default plugins? (y/n)" read -e plugins if [ "$plugins" == y ] ; then echo "+++ Deleting Akismet and Hello Dolly..." wp plugin delete akismet hello echo "+++ Installing standard plugins..." wp plugin install advanced-custom-fields autoptimize better-wp-security breadcrumb-navxt broken-link-checker cms-tree-page-view custom-post-type-ui ewww-image-optimizer google-analytics-dashboard-for-wp google-captcha google-sitemap-generator gravity-forms-custom-post-types plugincheck query-monitor redirection regenerate-thumbnails simple-local-avatars theme-check wp-fail2ban wp-pagenavi wp-super-cache fi fi echo "Cleaning..." #remove bash script if it exists in this dir [[ -f "wp_cli.sh" ]] && rm "wp_cli.sh" echo "=========================" echo "[Success]: Installation is complete." echo "=========================" else exit fi