UPDATE: This post is outdated. Please see 301 Moved Permanently below for its updated version.
Here is another example of securing your Piwik installation, based on Joomla .htaccess example under htaccess examples (security) - Joomla! Documentation, modified and adapted to Piwik. Please refer to that for additional information, if needed. The file is being used on a free shared web hoster (i.e. php.ini, etc., is not modifiable).
It does not use user or IP authentication (which could be done additionally as shown in posts above, if desired).
The assumed Piwik installation address is www.test.example.com/piwik/, with the www.test.example.com domain used exclusively for the only one Piwik installation, and the below .htaccess file placed into its main directory (i.e. above the /piwik/ directory).
###############################################################################
## .htaccess example implementation, last tested with Piwik 1.6
##
## Based on version 2.5 (proposed) of May 16th, 2011 (proposed 2.5.5 wiki doc
## history verstion by G1smd of May 17th, 2011) Joomla .haccess file
## example under http://docs.joomla.org/Htaccess_examples_%28security%29
##
###############################################################################
########## Begin - RewriteEngine enabled
RewriteEngine On
########## End - RewriteEngine enabled
########## Begin - RewriteBase
# Uncomment following line if your webserver's URL
# is not directly related to physical file paths.
# Update Your Joomla! Directory (just / for root)
#RewriteBase /
########## End - RewriteBase
########## Begin - No directory listings
## Note: +FollowSymlinks may cause problems and you might have to remove it
IndexIgnore *
Options +FollowSymLinks All -Indexes
########## End - No directory listings
########## Begin - File execution order, by Komra.de
DirectoryIndex index.php index.html
########## End - File execution order
########## Begin - ETag Optimization
## This rule will create an ETag for files based only on the modification
## timestamp and their size. This works wonders if you are using rsync'ed
## servers, where the inode number of identical files differs.
## Note: It may cause problems on your server and you may need to remove it
FileETag MTime Size
########## End - ETag Optimization
#####################################################
# Beginning of additional settings by jawsmith (from the
# "htaccess.txt" provided with Joomla, and Joomla
# security forums)
#####################################################
# Code taken from "Other useful settings" of http://docs.joomla.org/Htaccess_examples_(security)
ServerSignature Off
# Disable all methods except GET and POST, as only those are needed
# (Note: TRACE does not seem to be possible to disable in .htaccess, only in server config by the host)
RewriteCond %{REQUEST_METHOD} !^(GET|POST) [NC]
# Return 405 Method Not Allowed
RewriteRule .* - [R=405,L]
RewriteCond %{THE_REQUEST} (\\r|\\n|%0A|%0D) [NC,OR]
RewriteCond %{HTTP_REFERER} (<|>|’|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
RewriteCond %{HTTP_COOKIE} (<|>|’|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
RewriteCond %{REQUEST_URI} ^/(,|;|:|<|>|”>|”<|/|\\\.\.\\).{0,9999} [NC,OR]
# Note: User agents blocking not taken over, as agent names could easily be changed, and e.g. Nikto is used by me as well on http://www.hackertarget.com/website-scan
#Block mySQL injects
RewriteCond %{QUERY_STRING} (;|<|>|’|”|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|cast|set|declare|drop|update|md5|benchmark) [NC,OR]
RewriteCond %{QUERY_STRING} \.\./\.\. [OR]
RewriteCond %{QUERY_STRING} (localhost|loopback|127\.0\.0\.1) [NC,OR]
# Comment by jawsmith: commented following out, as otherwise error by the world map widget (flash)
#RewriteCond %{QUERY_STRING} \.[a-z0-9] [NC,OR]
RewriteCond %{QUERY_STRING} (<|>|’|%0A|%0D|%27|%3C|%3E|%00) [NC]
# Note: The final RewriteCond must NOT use the [OR] flag.
# Return 403 Forbidden
RewriteRule .* - [F]
########## Begin - Rewrite rules to block out some common exploits
## If you experience problems on your site block out the operations listed below
## This attempts to block the most common type of exploit `attempts` to Joomla!
# Protect .htaccess (Note: other file extensions will be
# protected implicitly by rewrite rules (folder access, etc.) below.)
<FilesMatch "\.htaccess$">
Order allow,deny
Deny from all
</FilesMatch>
#####################################################
# End of additional settings by jawsmith
#####################################################
########## Begin - Rewrite rules to block out some common exploits
## If you experience problems on your site block out the operations listed below
## This attempts to block the most common type of exploit `attempts` to Joomla!
#
# If the request query string contains /proc/self/environ (by SigSiu.net)
RewriteCond %{QUERY_STRING} proc/self/environ [OR]
# Block out any script trying to set a mosConfig value through the URL
# (these attacks wouldn't work w/out Joomla! 1.5's Legacy Mode plugin)
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR]
# Block out any script trying to base64_encode or base64_decode data within the URL
RewriteCond %{QUERY_STRING} base64_(en|de)code[^(]*\([^)]*\) [OR]
## IMPORTANT: If the above line throws an HTTP 500 error, replace it with these 2 lines:
# RewriteCond %{QUERY_STRING} base64_encode\(.*\) [OR]
# RewriteCond %{QUERY_STRING} base64_decode\(.*\) [OR]
# Block out any script that includes a <script> tag in URL
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
# Block out any script trying to set a PHP GLOBALS variable via URL
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
# Block out any script trying to modify a _REQUEST variable via URL
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
# Return 403 Forbidden
RewriteRule .* - [F]
#
########## End - Rewrite rules to block out some common exploits
########## Begin - File injection protection, by SigSiu.net
RewriteCond %{REQUEST_METHOD} GET
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=http:// [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=(\.\.//?)+ [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=/([a-z0-9_.]//?)+ [NC]
RewriteRule .* - [F]
########## End - File injection protection
########## Begin - Advanced server protection - query strings, referrer and config
# Advanced server protection, version 3.2 - May 2011
# by Nicholas K. Dionysopoulos
## Disallow PHP Easter Eggs (can be used in fingerprinting attacks to determine
## your PHP version). See http://www.0php.com/php_easter_egg.php and
## http://osvdb.org/12184 for more information
RewriteCond %{QUERY_STRING} \=PHP[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [NC]
RewriteRule .* - [F]
## SQLi first line of defense, thanks to Radek Suski (SigSiu.net) @
## http://www.sigsiu.net/presentations/fortifying_your_joomla_website.html
## May cause problems on legitimate requests
RewriteCond %{QUERY_STRING} concat[^\(]*\( [NC,OR]
RewriteCond %{QUERY_STRING} union([^s]*s)+elect [NC,OR]
RewriteCond %{QUERY_STRING} union([^a]*a)+ll([^s]*s)+elect [NC]
RewriteRule .* - [F]
########## End - Advanced server protection - query strings, referrer and config
########################################################################
# Added by jawsmith: sub-domain prevention and www requirement (redirect with code 301 ("moved permanently")
# in the same rule
# Notes: 1. If you want to do it separately, or use https, refer to Joomla reference htaccess implementation
# 2. This needs to be done before the below file protection exceptions,
# so that the redirect occurs before the exceptions are accessed. And no F or L flag,
# so that execution proceeds.
# 3. Replace test.example.com with your own domain
########################################################################
RewriteCond %{HTTP_HOST} !^www\.test\.example\.com$
RewriteRule ^(.*)$ http://www.test.example.com/$1 [R=301]
########## Begin - Advanced server protection rules exceptions ####
##
## These are sample exceptions to the Advanced Server Protection 3.1
## rule set further down this file.
##
## Allow Piwik API files
RewriteRule ^piwik/(index\.php|piwik\.(php|js))$ - [L]
RewriteRule ^piwik/js/(index\.php|piwik\.js)$ - [L]
########## End - Advanced server protection rules exceptions ####
########## Begin - Advanced server protection - paths and files
# Advanced server protection, version 3.2 - May 2011
# by Nicholas K. Dionysopoulos
## Disallow front-end access for certain Piwik system directories
# (Note: "js" directory deliberately not disallowed, as contains scripts accessible by browser)
RewriteRule ^piwik/(config|core|lang|misc|tests|tmp)/ - [F]
## Allow limited access for certain Piwik system directories with client-accessible content
RewriteRule ^piwik/(libs|plugins|themes)/([^/]+/)*([^/.]+\.)+(jp(e?g|2)?|png|gif|bmp|css|js|swf|html?|pdf|svg|ico)$ - [L]
RewriteRule ^piwik/(libs|plugins|themes)/ - [F]
## Disallow access to rogue PHP files throughout the site, unless they are explicitly allowed
# (Note: This is not needed, as no SEO is used - all access through files excepted above, and no SEO pseudo directories are used)
#RewriteCond %{REQUEST_FILENAME} \.php$
#RewriteCond %{REQUEST_FILENAME} !/(index|piwik)\.php$
#RewriteCond %{REQUEST_FILENAME} -f
#RewriteRule ^([^/]+/)*([^/.]+\.)+php$ - [F]
########## End - Advanced server protection - paths and files
As an additional tweak, following files were removed from the Piwik installation, to limit “fingerprinting”, and to prevent the need in the above .htaccess to disable access to them if they were kept:
\piwik\LEGALNOTICE
\piwik\README
\piwik\js\LICENSE.txt
\piwik\js\README
Note that those are in the only directories accessible by the client - the Piwik installation directory and the “js” directory. Access to other similar files will be implicitly prevented by the above .htaccess file - via directory access prevention.
Additional hint: As with any other web application, unless you use https AND your TLS is super up-to-date AND your client is up-to-date and secure, try to log-in to your Piwik installation with administrator rights as little as possible. Simply create an additional account restricted to “viewing” and use it when no administration work is required. And: same applies if the above “unless” condition is met, as we all know that a piece of software stays secure forever.