Match request data in Apache Httpd.conf - regex

I want to match request parameters in httpd.conf if the request has malicious data i want to return 404 http status code to the client. Request data should have number , words and & = sign .If there is anything apart from this in request we don't have to process the request further
How we can do this Apache 2.2
Invalid URL :
http://ip/index.html?daa=1; rm /tmp/f;mkfifo /tmp/f;cat /tmp/f%7C/bin/sh -i %26
Valid URL
http://ip/index.html?daa=1&data=1
After adding :
<Directory "folder/scripts">
RewriteEngine On
RewriteCond %{QUERY_STRING} !^[a-zA-Z0-9&=?\-]*$
RewriteRule . test.html [R=404,L]
</Directory>
It is not redirecting to my test.html page

If you are trying to filter query strings only, you could add this on top of your rules:
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} !^[a-zA-Z0-9&=#?]*$
RewriteRule . /index.php [R=404,L]
Note: You only have to put allowed characters in character class.

You can use this rule as your top rule to block all requests with characters you don't want to allow:
RewriteEngine On
RewriteCond %{THE_REQUEST} [A-Z]{3,}\s/+\S*[^/\w?&=.#-]\S*\sHTTP [NC]
RewriteRule ^ - [B,F]

Related

How prevent access if the request URL doesn't have string in .htacess

I have an alias domain name which I don't want it to load the website.
I only want my alias domain to access if the request URL has a certain string.
Example: www.myalias.com/pass/whatever/here
The string I'm looking at is the "pass" If the request URL has the "pass" there, then allow to access to the website, if not then return 404 error.
The rule will check if the domain name is equal to "myalias.com" then check to see if the string "pass" is exist in the request URL.
How can I write that to a rule in .htaccess ?
Sounds pretty straight forward: you check the http host, the presence of the pass and react as desired:
This denies requests
RewriteEngine on
RewriteCond %{HTTP_HOST} ^alias\.example\.com$
RewriteCond %{REQUEST_URI} !^/pass/
RewriteRule ^ - [F]
That one sends a custom http status (here 403):
RewriteEngine on
RewriteCond %{HTTP_HOST} ^alias\.example\.com$
RewriteCond %{REQUEST_URI} !^/pass/
RewriteRule ^ - [R=403]
Or you can redirect clients to wherever you want:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^alias\.example\.com$
RewriteCond %{REQUEST_URI} !^/pass/
RewriteRule ^ https://example.com/ [R=301]
You obviously need to have the rewriting module loaded inside your http server. Typically such rules should get implemented in the actual http server's host configuration. If you really want to use a distributed configuration file (".htaccess") you need to enable its interpretation first (see the documentation for the AllowOverride directive).

1 subdomain doesn't support HSTS

My website is hosted on AWS and I am using SEMRush to track any server and programming issues.
And my SEMRush found this error when I run it.
2 subdomains don't support HSTS.
Hence I put below code to solve this issue
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
Now 1 error resolved but still having one more subdomain having the same error.
As you can see rosterelf.com still doesn't support HSTS.
Further, I am redireting non www to www in my htaccess and this is how my .htaccess file looks like.
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
RewriteEngine On
##
## You may need to uncomment the following line for some hosting environments,
## if you have installed to a subdirectory, enter the name here also.
##
# RewriteBase /
##
## Uncomment following lines to force HTTPS.
##
# RewriteCond %{HTTPS} off
# RewriteRule (.*) https://%{SERVER_NAME}/$1 [L,R=301]
# CONDITIONS FOR ONLY LIVE SITE STARTS
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
# CONDITIONS FOR ONLY LIVE SITE ENDS
##
## Allow robots.txt
##
RewriteRule ^robots.txt - [L]
## 301 redirect for old support details page url to new one
## OLD URL https://www.rosterelf.com/support-detail/1903/how-can-employees-clock-inout-of-time-clock-different-slug
## NEW URL https://www.rosterelf.com/support-detail/how-can-employees-clock-inout-of-time-clock-different-slug
RewriteRule ^(support-detail)/\d+/([\w-]+)/?$ /$1/$2 [R=301,NC,L]
RewriteRule ^blog-detail/\d+/([\w-]+)/?$ /blog/$1 [R=301,NC,L]
##
## Black listed folders
##
RewriteRule ^bootstrap/.* index.php [L,NC]
RewriteRule ^config/.* index.php [L,NC]
RewriteRule ^vendor/.* index.php [L,NC]
RewriteRule ^storage/cms/.* index.php [L,NC]
RewriteRule ^storage/logs/.* index.php [L,NC]
RewriteRule ^storage/framework/.* index.php [L,NC]
RewriteRule ^storage/temp/protected/.* index.php [L,NC]
RewriteRule ^storage/app/uploads/protected/.* index.php [L,NC]
##
## White listed folders
##
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} !/.well-known/*
RewriteCond %{REQUEST_FILENAME} !/storage/app/uploads/public/.*
RewriteCond %{REQUEST_FILENAME} !/storage/app/media/.*
RewriteCond %{REQUEST_FILENAME} !/storage/app/resized/.*
RewriteCond %{REQUEST_FILENAME} !/storage/temp/public/.*
RewriteCond %{REQUEST_FILENAME} !/themes/.*/(assets|resources)/.*
RewriteCond %{REQUEST_FILENAME} !/plugins/.*/(assets|resources)/.*
RewriteCond %{REQUEST_FILENAME} !/modules/.*/(assets|resources)/.*
RewriteRule !^index.php index.php [L,NC]
##
## Block all PHP files, except index
##
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} \.php$
RewriteRule !^index.php index.php [L,NC]
##
## Standard routes
##
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Do I need to put below code
<IfModule mod_headers.c>
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header set Strict-Transport-Security "max-age=31536000"
</If>
</IfModule>
Out side of <IfModule mod_rewrite.c> condition ? What should I do to solve this ?
Can someone please guide me ..
Thanks
Pretty sure you need always if you want a header to also be added to redirects so try this:
Header always set Strict-Transport-Security "max-age=31536000"
my SEMRush found this error when I run it.
Just to clarify, that's not strictly an "error", unless you are explicitly trying to implement HSTS. (It doesn't look as if you were?) HSTS is a recommendation.
but still having one more subdomain having the same error.
SEMRush's identification is curious; that's not a subdomain, that's the "domain apex" (ie. no subdomain).
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
When implementing HSTS you need to first redirect from HTTP to HTTPS on the "same hostname", before you canonicalise the hostname, ie. before you redirect from no-www (the domain apex) to www.
This means you can't do what you are doing here... redirecting from HTTP and no-www to HTTPS and www in a single redirect. (The currently commented out HTTP to HTTPS redirect is what you need to be using instead.)
However, your current rule is also incomplete as it fails to canonicalise the hostname when requesting HTTPS. ie. It does not redirect https://example.com/ to https://www.example.com/. The first condition that checks that HTTPS is off ensures the rule is only processed for HTTP requests.
When implementing HSTS your redirects need to be written like this:
# 1. Redirect HTTP to HTTPS on the same host
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# 2. Redirect non-www to www
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
The second redirect to canonicalise the hostname does assume that you have no other subdomains that should be accessible since it redirects anything that is "not www".
Yes, this does (unfortunately) mean that users will experience two redirects when requesting http://example.com/ the very first time. But this is the nature of HSTS. And it is only the very first time that user visits HTTP on the non-canonical hostname.
<If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
Header set Strict-Transport-Security "max-age=31536000"
</If>
This sets the STS header on HTTPS "success" responses. However, it is also a requirement of HSTS that you set this header on the HTTPS canonical redirect from no-www to www. Currently, the above directive is only setting the header on onsuccess (200 Ok) responses (the default). To set the header on the 301 redirect you need the always condition, as #BarryPollard has already pointed out in his answer:
# Set the STS header on redirects as well as 200 OK responses.
Header always set Strict-Transport-Security "max-age=31536000"
Just to add, not only will the always condition set the header on 3xx responses, but also other 4xx responses as well etc.
The <If> expression itself is also a bit dubious. You should only check the X-Forwarded-Proto header if your application server is behind a front-end proxy that manages the secure connection. However, if you are behind a proxy then you don't need to check the REQUEST_SCHEME server variable. (It looks like this expression is intended to be a generic "catch-all".) The issue with the above expression is that if you are not behind a proxy then a malicious request could inject the X-Forwarded-Proto HTTP request header and fool your server into sending the header.
From your HTTP to HTTPS redirect (that checks the HTTPS server variable) it looks like you are not behind a front-end proxy. Although, maybe you are and we'll need to modify the above HTTP to HTTPS redirect?
So, if you are not behind a front-end proxy then the following <If> expression is preferable:
<If "%{REQUEST_SCHEME} == 'https'>
Or,
<If "%{HTTPS} == 'on'>
And if using Apache 2.2 (or Apache 2.4) you could do the following instead of using an <If> expression:
# Set HSTS env var only if HTTPS
RewriteCond %{HTTPS} on
RewriteRule ^ - [E=HSTS:1]
# Set STS header only when the HSTS env var is set (including redirects)
Header always set Strict-Transport-Security "max-age=31536000" env=HSTS
Out side of `<IfModule mod_rewrite.c>` condition ?
Placing the directive inside or outside the <IfModule> containers makes no difference in this instance (since mod_rewrite and mod_headers are presumably installed). In fact, strictly speaking, the <IfModule> wrappers should probably be removed altogether.
See my answer to the following question on the Webmasters stack for more info on this:
https://webmasters.stackexchange.com/questions/112600/is-checking-for-mod-write-really-necessary

Rewriting URL and hiding Subpage Name

I have a rewrite in my .htaccess file that sends people from example.com to example.com/home
RewriteEngine On
RewriteBase /
RewriteRule ^$ home [L,R=301]
How do I do this but then strip the string "home" from the url bar so that it appears to be example.com? I'm not interested in any subdirectories after home as the rest of the site lives in the root.
Full Context
# Perch Runway
<IfModule mod_rewrite.c>
# Turn on RewriteEngine
RewriteEngine On
# When user goes to the home page send to .com/home and strip /home
RewriteBase /
RewriteRule ^$ home [L,R=301]
# Cache Busting
RewriteRule (assets[/])([^.]*).min.+.(css|js)$ $1$2.min.$3
# Perch Runway
RewriteCond %{REQUEST_URI} !^/login
RewriteCond %{REQUEST_URI} !(/sub-directory-one|/sub-directory-two) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /login/core/runway/start.php [L]
</IfModule>
Use below rule,
RewriteEngine On
RewriteBase /
RewriteRule !home /home%{REQUEST_URI} [L]
When you use the R|redirect flag, Apache sends a redirect status to the client. The client then requests the new URL (e.g. http://www.example.com/home) and displays the new URL.
To avoid this behaviour, you do not send a redirect (e.g. R), but silently rewrite internally to the new URL. This way Apache sends the contents of the target without notifying the client.
To just rewrite internally from / to /home, keep the existing rule, but remove the R flag
RewriteRule ^$ /home [L]

Writing some 301 rules for subdomain only

I'm trying to write some 301 rules for some old backlinks, these would be placed in .htaccess within http://subdomain.domain.com (not in root .htaccess of domain.com).
Here are a some types of redirects I'd like to set up, first specific rules followed by a catch-all fallback. I would appreciate some advice on writing correct RewriteCond rules for this kind of logic, all of these have a specific final URL to redirect to:
A) request contains location=uae
= 301 to "http://www.domain.com/subfolder/sub2/sub3" (match pattern, redirect all to a specific final URL, no trailing slash).
B) request contains searchTerms=someterm1= 301 to "http://www.domain.com/subfolder2/program/url" (again match a paticular pattern and redirect all matches to a specific final URL with no trailing slash).
C) request contains reqGK=755381 or reqGK=795971 = 301 to "http://www.domain.com/another/specific/url" ... this RewriteCond would have a part of the regex that looks like reqGK=(755381|795971) i believe but i'm not totally sure.
D) [FALLBACK / CATCHALL for all requests not already matched by A-C above] ANY other request at all = 301 to "http://www.domain.com/specific/url/forfallback" (a final specific URL reference that gets sent all the remaining HTTP requests from subdomain.domain.com).
Thanks so much in advance!
Try this:
RewriteEngine On
RewriteCond %{QUERY_STRING} \blocation=uae\b
RewriteRule ^.*$ http://www.domain.com/subfolder/sub2/sub3 [L,R=301]
RewriteCond %{QUERY_STRING} \bsearchTerms=someterm1\b
RewriteRule ^.*$ http://www.domain.com/subfolder2/program/url [L,R=301]
RewriteCond %{QUERY_STRING} \breqGK=(755381|795971)\b
RewriteRule ^.*$ http://www.domain.com/another/specific/url [L,R=301]
RewriteRule ^.*$ http://www.domain.com/specific/url/forfallback [L,R=301]

SetEnvIfNoCase redirection

Hi all ive been learning wildcard methods using SetEnvIfNoCase User-Agent and wildcards,
But using the example below.only serves a 403 error page if a useragent matches the wildcards.
but what i want is to redirect the "user-agent" to another website such as a black hole or spam page.
using something like RewriteRule ^(.*)$ http://send junk to here/
SetEnvIfNoCase User-agent "(B2|Bac|Bad|Bag|Bai|Bast|Batch|Bing|Bite|Bla|Blex)" bad_bot=yes
#
Order Allow,Deny
Allow from All
Deny from env=bad_bot
what can i replace the Deny from env=bad_bot with to make it redirect to the wanted website instead of serving the 403 error page.
Have your rewrite rule like this in your DOCUMENT_ROOT/.htaccess file:
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} B2|Bac|Bad|Bag|Bai|Bast|Batch|Bing|Bite|Bla|Blex [NC]
RewriteRule !^spam/ http://officeofstrategicinfluence.com/spam/ [L,NC,R=302]
UPDATE:: In response this comment by OP
1- adding a new line of filters do i need to change the [NC] ? and 2- if i wanted to add a single word by itself do i still use RewriteCond %{HTTP_USER_AGENT} ^word [NC]? with the ^
Try this code:
RewriteCond %{HTTP_USER_AGENT} B2|Bac|Bad|Bag|Bai|Bast|Batch|Bing|Bite|Bla|Blex [NC,OR]
RewriteCond %{HTTP_USER_AGENT} foo|bar|etc [NC]
RewriteRule !^spam/ http://officeofstrategicinfluence.com/spam/ [L,NC,R=302]
The RewriteCond directive can filter by server variables, including environment variables like your bad_bot. Syntax is:
%{ENV:variable}, where variable can be any environment variable, is
also available. This is looked-up via internal Apache httpd structures
and (if not found there) via getenv() from the Apache httpd server
process.
But it can also filter by HTTP headers as well so you don't need your env variable:
RewriteCond %{HTTP_USER_AGENT} ^Mozilla
RewriteRule ^/$ /homepage.max.html [L]
RewriteCond %{HTTP_USER_AGENT} ^Lynx
RewriteRule ^/$ /homepage.min.html [L]
RewriteRule ^/$ /homepage.std.html [L]