On a Codeigniter application I want to limit http post request size (in bytes) with limitRequestBody htaccess directive. Since all requests are written to index.php this setting affects to all form submissions. That is problematic. What I really want is limit post size to certain urls. For example, if I have two urls, like below
mysite.com/member/login
mysite.com/contact
I only want to apply this setting only to the mysite.com/member/login. Not for mysite.com/contact
I tried with apache's LocationMatch and IF Directives to specifically target the url but unfortunately none of it worked. Instead server went into a redirect loop.
<LocationMatch "^/member/login">
limitRequestBody 128
</LocationMatch>
<If "%{REQUEST_URI} ^/member/login">
limitRequestBody 128
</If>
Is there anything wrong with the above approach? Syntax? or any other way to get this done?
Related
I want to block direct access to PHP file, for example when someone enters it manually in the address bar (https://example.com/php/submit.php). I used this code:
<Files "submit.php">
Order Allow,Deny
Deny from all
</Files>
But if I block it this way, the form can't be submitted (it doesn't send mails).
Is there another way to block direct access but to be able to submit form?
<form id="form" action="php/submit.php" method="post">
Your form is making a POST request, whereas "when someone enters it manually in the address bar" they are making a GET request. So, you could block anything but POST requests..
Using <LimitExcept>
For example, surround your existing directives in a <LimitExcept> container:
<LimitExcept POST>
<Files "submit.php">
Require all denied
</Files>
</LimitExcept>
Note that this blocks non-POST requests to any submit.php file on your system.
NB: Order, Allow and Deny are Apache 2.2 directives and formerly deprecated on Apache 2.4 (which you are more likely to be using, unless you are on LiteSpeed). Require all denied is the Apache 2.4 equivalent. However, you should not mix authentication directives from both modules.
Using mod_rewrite
Alternatively, using mod_rewrite near the top of the root .htaccess file you can target the /php/submit.php URL-path directly. For example:
RewriteEngine On
RewriteCond %{REQUEST_METHOD} !=POST [NC]
RewriteRule ^php/submit\.php$ - [F]
The above will serve a 403 Forbidden for any request to /php/submit.php that is not a POST request (eg. when a user types the URL directly in the browser's address bar).
Alternatively, check that the request is a GET request. ie. =GET
HOWEVER, you should already be performing this check as part of your standard form validation in your PHP code, so this additional check in .htaccess should be redundant. (After all, how are you checking that the form has been (successfully) submitted?)
I'm going mad over Apache .htaccess
I'm trying to setting as protected my subfolders using relative address, but it seems impossible.
The path of Apache folder is structured like this:
/var/www/apachedir
now I want to protect
/var/www/apachedir/subfolder/*
What I tryied is putting in /var/www/apachedir/ an .htaccess file like this
<FilesMatch "subfolder\/.*">
Order Allow,Deny
Deny from all
</FilesMatch>
but it seems not woking good.
I don't want to use ModRewrite and I want to make this .htaccess reusable.
So, listen, if I put the site over an other server that has a direcory structure like /var/www/zzz it has to protect files in /var/www/zzz/subfolder/*.
Also the file .htaccess has to stay in the root folder /var/www/apachedir.
There's a way to do it?
Edit:
I don't want to use ModRewrite but also I don't want to use Redirectmatch.
I want to know if there's a way to set it up with FilesMatch without ModRewrite or Redirectmatch.
I don't want to use ModRewrite.
You can use RedirectMatch to block access to a known path:
Redirectmatch 403 ^/subfolder/
I want to know if there's a way to set it up with FilesMatch
No, because the FilesMatch (and the non-regex Files) directive(s) literally match against files only, not directories. eg. <Files "*.jpg"> matches all .jpg files in any subdirectory.
There are various methods to block access to that subdirectory...
Use a <Directory> section in the server config
If you have access to the server (virtual host) config then you can use the <Directory> (and <DirectoryMatch>) directive(s) to target specific directories. But this is not permitted in .htaccess. For example:
<Directory "/var/www/apachedir/subfolder">
Require all denied
</Directory>
Create an additional .htaccess file in that subdirectory
The equivalent userland .htaccess way of doing this is to create an additional .htaccess file in that subdirectory (ie. at /subfolder/.htaccess) with a single Require all denied directive. The .htaccess file itself is equivalent to the <Directory> directive in the server config.
Aside: Order, Deny and Allow are Apache 2.2 directives and formerly deprecated on Apache 2.4 (which you are far more likely to be using). You should be using the equivalent Require (mod_authz_core) directives instead, as used above.
Use Redirect 403 (mod_alias) - not a "redirect"
I don't want to use ModRewrite but also I don't want to use Redirectmatch
RedirectMatch (and Redirect) are part of mod_alias - this is a base module and compiled into Apache by default (unlike mod_rewrite), so using the prefix-matching Redirect directive (no need for the regex variant RedirectMatch) is a reasonable solution as #anubhava suggests in his answer, depending on the scenario and existing directives. For example:
Redirect 403 /subfolder/
Despite the use of the Redirect directive, this is not an external (HTTP) redirect. The 403 response is served via an internal subrequest.
Set an environment variable and check with mod_authz_....
Alternatively, you can set an environment variable when the /subfolder is requested (using SetEnvIf) and check for this using the Require directive. This allows you to keep the condition separate from the directives that actually permit access. For example (using Apache 2.4 mod_authz_core):
SetEnvIf Request_URI "^/subfolder/" BLOCK_ACCESS
<RequireAll>
Require all granted
Require not env BLOCK_ACCESS
</RequireAll>
NB: If you are doing any URL-rewriting with mod_rewrite then you might need to check for REDIRECT_BLOCK_ACCESS instead in the above Require directive.
<If> expression (Apache 2.4)
On Apache 2.4 you can also use an <If> expression to target that specific subfolder with a containing mod_authz_core directive. For example:
<If "%{REQUEST_URI} =~ m#^/subfolder/#">
Require all denied
</If>
Although, strictly speaking, these methods target the URL-path, not the file-path.
I keep reading that, where possible, I should not be using mod_rewrite. As such, I am trying to do a http to https rewrite with RedirectMatch.
Question: How can I use RedirectMatch and use Apache server variables (such as %{HTTP_HOST}) in the URL parameter?
This code fails to return a response to the client (Chrome):
RedirectMatch ^(.*) https://%{HTTP_HOST}/$1
I recently asked a similar question to this, but it may have been too wordy and lacks direction for an answer: Redirecting http traffic to https in Apache without using mod_rewrite
If you're using 2.4.19 or later, the Redirect directive has a somewhat obscure feature: putting it inside a Location or LocationMatch will enable expression syntax.
So your example can be written as
<LocationMatch ^(?<PATH>.*)>
Redirect "https://%{HTTP_HOST}%{env:MATCH_PATH}"
</LocationMatch>
(Here, the ?<PATH> notation means that the match capture will be saved to an environment variable with the name MATCH_PATH. That's how we can use it later in the Redirect.)
It's even easier if you always redirect using the entire request path, because you can replace the capture group entirely with the REQUEST_URI variable:
<Location "/">
Redirect "https://%{HTTP_HOST}%{REQUEST_URI}"
</Location>
Now, is this easier to maintain/understand than just using mod_rewrite for this one case? Maybe not. But it's an option.
No, You can't use variables of that type with Redirect/RedirectMatch. If you need variables, such as %{HTTP_HOST}, use mod_rewrite.
Note: I commend you for not trying to use mod_rewrite right away, because most people will go for mod_rewrite even for the simplest of redirections, which is clearly overkill and most times it is just looking to complicate things unnecessarily.
Writing for users who might face the same in future.
Not sure how you are adding vhost entries.
I guess this vhost entries are added automatically with help of some programming script.
Do you use VhostDirective with ServerName?
<VirtualHost *:8080>
ServerName example.domain.com
</VirutalHost>
If so, then you can use the same domain value for populating RedirectMatch field.
If you are manually adding vhost entries just write that domain URL value explicitly instead of HTTP_HOST.
Or let me know if its a different scenario.
So I am able to block specific subdomains like this:
SetEnvIfNoCase Referer knownsub\.sorryspammer\.com sorryspammer
<Location />
Order Allow,Deny
Allow from all
Deny from env=sorryspammer
</Location>
which does successfully block visits to any site on my server that come from the referrer, knownsub.sorryspammer.com
So now, I am getting visits from referrers like 1.sorryspammer.com, 2.sorryspammer.com, 8.sorryspammer.com, 22.sorryspammer.com, etc., and I need to set an environment variable to block any subdomain coming from the referrer domain sorryspammer.com.
I know I need to set the same basic rule for the environment variable but with a wildcard for the subdomain part. I've tried a couple of things, most recently this:
SetEnvIfNoCase Referer (.*)\.sorryspammer\.com sorryspammer
but I am still getting visits from referrers from subdomains on sorryspammer.com. I know I'm missing something real simple. Any help is appreciated. Not sure if it matters, but keep in mind that this is not going in an .htaccess file but is going in the httpd.conf file to apply the rules server wide.
I want exampleapp.com/clientapp/ to execute the index.php in /usr/local/apache/htdocs/clientapp.
This stackoverflow question outlines something similar to what I want to do: https://stackoverflow.com/a/8454/173630
I'm having some trouble getting this working. Here's the start of my VirtualHost setup:
<VirtualHost exampleapp.com:80>
DocumentRoot /home/platform/src/serverapp/public
RewriteEngine On
Alias /clientapp/ "/usr/local/apache/htdocs/clientapp"
<Directory "/usr/local/apache/htdocs/clientapp">
FallbackResource index.php
<IfModule mod_suphp.c>
suPHP_UserGroup nobody nobody
</IfModule>
</Directory>
RewriteRule ^/clientapp/(.*)$ /clientapp/$1 [PT]
I'm using Apache 2.2.22. I know this is kind of a confusing setup -- the reason I'm doing this is to avoid cross-domain AJAX requests from clientapp to serverapp.
With this configuration I'm not getting any errors, it's just falling through to the server app.
Update
The problem was that I had a BasicAuth set up on /usr/local/apache/htdocs/clientapp, and the password wasn't being prompted for when visiting exampleapp.com/clientapp/ and it was just silently failing. I took off the BasicAuth for now, which gets it to work.
After trying a few things out, it looks like this is just mod_alias being retarded and either blindly mashing together file-path and URI-path or mistaking the file-path (/usr/local/apache/htdocs/clientapp) for a URI-path (not sure how). Either way, you can do one of two things, it looks like.
Add a trailing slash to your file-path:
Alias /clientapp/ "/usr/local/apache/htdocs/clientapp/"
Remove the trailing slash from your URI-path:
Alias /clientapp "/usr/local/apache/htdocs/clientapp"
Both seems to do the trick, but I would suggest doing the second option, as it would match requests for exampleapp.com/clientapp (no trailing slash), and mod_dir will properly recognize it as a directory and redirect you to exampleapp.com/clientapp/. Whereas if you go with first option, going to exampleapp.com/clientapp would just give you a 404 (or something in the document root ends up handling it).
Change <Directory ...>...</Directory> to <Location /clientapp>...</Location> and keep everything inside it.