############# DO NOT FORGET TO CHANGE "grav_path" BY YOUR ACTUAL GRAV INSTALLATION FOLDER ############# ############# IF GRAV IS AT THE ROOT OF YOUR WEBSITE, ie http://yoursite.tld POINTS TO ############# ############# GRAV DIRECTLY, THEN JUST REMOVE ANY "/grav_path/" MENTION BELOW. OTHERWISE ############# ############# WE ASSUME YOU RUN AN INSTALLATION SUCH AS http://yoursite.tld/grav_path/ ############# ####################################################################################################### ### GRAV RULES FOR LIGHTTPD ### ### By Mr3ase ### ### Last Rev. 2015/11/20 ### #PREVENTING EXPLOITS $HTTP["querystring"] =~ "base64_encode[^(]*\([^)]*\)" { url.redirect = (".*" => "/grav_path/index.php" ) } $HTTP["querystring"] =~ "(<|%3C)([^s]*s)+cript.*(>|%3E)" { url.redirect = (".*" => "/grav_path/index.php" ) } $HTTP["querystring"] =~ "GLOBALS(=|\[|\%[0-9A-Z])" { url.redirect = (".*" => "/grav_path/index.php" ) } $HTTP["querystring"] =~ "_REQUEST(=|\[|\%[0-9A-Z])" { url.redirect = (".*" => "/grav_path/index.php" ) } #REROUTING TO THE INDEX PAGE # A URL ending in .md goes to Grav whether or not a file of that name exists, so # page routes ending in .md get Grav's Markdown output and Markdown source files # such as README.md and CHANGELOG.md are never served as they are. lighttpd 1.4 # has no condition on whether a file exists, and these rewrites run before the # deny rules below, which then see /grav_path/index.php. url.rewrite-once = ( "(?i)^/grav_path/[^?]*\.md(\?|$)" => "/grav_path/index.php${qsa}" ) url.rewrite-if-not-file = ( "^/grav_path/(.*)$" => "/grav_path/index.php?$1" ) #IMPROVING SECURITY $HTTP["url"] =~ "(?i)^/grav_path/(LICENSE\.txt|composer\.json|composer\.lock|nginx\.conf|web\.config|htaccess\.txt)$" { url.access-deny = ("") } $HTTP["url"] =~ "(?i)^/grav_path/(\.git|cache|bin|logs|backup|tmp|webserver-configs|tests)/" { url.access-deny = ("") } $HTTP["url"] =~ "(?i)^/grav_path/user/(env/[^/]+/)?config/" { url.access-deny = ("") } # Block user/accounts too, but allow avatar images to be served directly, whether # stored at user/accounts/avatars/ (flatfile accounts) or user/accounts/ # / (Flex folder storage). SVG is intentionally excluded as a # stored-XSS vector. $HTTP["url"] =~ "(?i)^/grav_path/user/(env/[^/]+/)?accounts/(?![^/]+/[^/]+\.(jpe?g|png|gif|webp|avif|bmp|ico)$)" { url.access-deny = ("") } # Block user/data too, but allow public media uploads (e.g. Flex Object images) # to be served directly. SVG is intentionally excluded as a stored-XSS vector. $HTTP["url"] =~ "(?i)^/grav_path/user/(env/[^/]+/)?data/(?!.*\.(jpe?g|png|gif|webp|avif|bmp|ico|mp4|webm|ogg|ogv|mov|mp3|wav|m4a|flac|pdf)$)" { url.access-deny = ("") } # Serve page media only through the page route, so plugins can apply the page's # `access` rules to it. DO NOT uncomment without first setting # `pages.media_route_urls: true` in user/config/system.yaml, or every media URL # on the site becomes a 403. #$HTTP["url"] =~ "(?i)^/grav_path/user/pages/" { # url.access-deny = ("") #} $HTTP["url"] =~ "(?i)^/grav_path/(images|assets)/(.*)\.(php|php2|php3|php4|php5|php7|php8|phar|phtml|pht|phtm|phps|pl|py|cgi|sh|bat)$" { url.access-deny = ("") } $HTTP["url"] =~ "(?i)^/grav_path/(system|vendor)/(.*)\.(txt|xml|md|html|htm|shtml|shtm|json|yaml|yml|php|php2|php3|php4|php5|phar|phtml|pl|py|cgi|twig|sh|bat)$" { url.access-deny = ("") } $HTTP["url"] =~ "(?i)^/grav_path/user/(.*)\.(txt|md|html|htm|shtml|shtm|json|yaml|yml|php|php2|php3|php4|php5|phar|phtml|pl|py|cgi|twig|sh|bat)$" { url.access-deny = ("") } # Hidden files and folders at any depth, except /.well-known/ files whose own # names don't start with a dot (ACME challenges, security.txt) $HTTP["url"] =~ "(?i)(^|/)\.(?!well-known(?:/|$))" { url.access-deny = ("") } url.access-deny += ("~",".inc") #PREVENT BROWSING AND SET INDEXES $HTTP["url"] =~ "^/grav_path($|/)" { dir-listing.activate = "disable" index-file.names = ( "index.php", "index.html" , "index.htm" ) }