How to obtain values of all Apache's mod_rewrite environment variables, without PHP? - apache

I have an Apache instance but without PHP (almost all the SO answers I found for this are PHP-specific). In fact it's mostly serving static content.
I'm working on some mod_rewrite redirections and I'd like to know the exact values of all environment variables.
Those pages list Apache's available env variables and example values
http://www.zytrax.com/tech/web/env_var.htm
https://www.cheatography.com/davechild/cheat-sheets/mod-rewrite/
however I'd like to see the exact values coming from my requests, to facilitate working on my rewrite rules.
What would be the easiest way to get all the Apache environment values? (without installing PHP on it).
As a poor man's debugging, I know I can get values one by one by defining some example rewrites like this
RewriteRule ^/test.htm http://localhost/test2.htm?SERVER_NAME=%{SERVER_NAME} [R,L,NC]
and then hitting http://localhost/test.htm and observing the redirect, but this is not a really good solution.
Is there a better way to learn about all the environment, not specific to any particular language like PHP?

You can obtain the values of all Apache environment variables with Perl. The standard Apache distribution still bundles the good old printenv.pl CGI script. Here's what mine (Apache/2.4 on Windows) looks like:
#!D:/programs/perl/bin/perl.exe
#
# To permit this cgi, replace # on the first line above with the
# appropriate #!/path/to/perl shebang, and on Unix / Linux also
# set this script executable with chmod 755.
#
# ***** !!! WARNING !!! *****
# This script echoes the server environment variables and therefore
# leaks information - so NEVER use it in a live server environment!
# It is provided only for testing purpose.
# Also note that it is subject to cross site scripting attacks on
# MS IE and any other browser which fails to honor RFC2616.
##
## printenv -- demo CGI program which just prints its environment
##
use strict;
use warnings;
print "Content-type: text/plain; charset=iso-8859-1\n\n";
foreach my $var (sort(keys(%ENV))) {
my $val = $ENV{$var};
$val =~ s|\n|\\n|g;
$val =~ s|"|\\"|g;
print "${var}=\"${val}\"\n";
}
Of course:
You need Perl installed
Apache administrator will typically not enable the default /cgi-bin directory
Other that using a program, you're out of luck. I'm not aware of any builtin Apache module that reports ENV variables (not even mod_info).

Related

SetEnv or PassEnv Variables for cgi bin perl script

Have an apache project and a perl script in cgi-bin that needs to read from env variables.
Using PassEnv or SetEnv in the apache config the variables don't show up when looping through the env variables in perl
foreach $key (sort keys(%ENV)) {
print "$key = $ENV{$key}<p>";
}
What am I doing wrong?
For security reasons, Apache's suexec wrapper clears all environment variables that don't appear on its whitelist. Generally speaking, this whitelist only includes variables that are part of the CGI interface: DOCUMENT_ROOT, REQUEST_METHOD, SCRIPT_FILENAME, etc, as well as any variable starting with HTTP_ (from HTTP headers).
Unfortunately, this makes SetEnv basically useless when suexec is enabled. This is a known limitation, but is difficult to solve without introducing potential security vulnerabilities.

Accessing PHP Environment variables in php-fpm pool conf file

I am using apache Apache/2.2.22 (Ubuntu)
I am using php5-fpm
I am using PHP version 5.3.10
My issue is the following:
When a request is made to index.php, PHP Environment variables defined in my .htaccess file are being prefixed with "REDIRECT_" due to php-fpm acting as a redirect. For example, the variable _SERVER["HTACCESS_SET_VARIABLE"] is being renamed to _SERVER["REDIRECT_HTACCESS_SET_VARIABLE"]
I need to be able to set _SERVER["HTACCESS_SET_VARIABLE"] in the php-fpm.conf file. Obviously static variables can be set as suck
env[HTACCESS_SET_VARIABLE] = Some static text here
However, I want to be able to dynamically set the value of env[HTACCESS_SET_VARIABLE] to be whatever the value of _SERVER["REDIRECT_HTACCESS_SET_VARIABLE"] is. I have tried using $REDIRECT_HTACCESS_SET_VARIABLE, $_SERVER["REDIRECT_HTACCESS_SET_VARIABLE"] and ever other $ prefixed variable I can think of.
Does anyone know how to access the PHP environment variables in php-fpm.conf?
Thank you for your time.

Executing CGI under apache without a shebang? Or how to execute CGI in a server neutral manner

So I find myself in a strange situation whereby I need to understand old skool CGI (simple CGI) execution under Apache web server. Yes, I know, in a real setup we use an Apache module or FastCGI! But anyway...
As I understand it, an Apache CGI script looks like this (perl in this example, but could be anything):
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "Hello, World.";
This was borrowed from here: http://httpd.apache.org/docs/2.2/howto/cgi.html
You would then use the following apache directives to make sure that perl scripts were executed as CGI:
<Directory ...>
...
Options +ExecCGI
AddHandler cgi-script .pl
</Directory>
That's great it works. Note how Apache relies upon the shebang to decide the interpreter to run the script as.
Under lighttpd though, this works differently. In the server config we state explicitly which interpreter to use on a per file extension basis, e.g.:
cgi.assign = (
".php" => "/usr/local/bin/php",
".pl" => "/usr/bin/perl"
)
If lighttpd comes to execute a script with a shebang, it seems it is ignored. Fine.
My question is, is there a way to do something like this in Apache? Can I specify which interpreter to use in the server configuration so that scripts do not need a shebang. Presumably people did not (back when CGI was the in thing) go adding shebangs to each and every PHP file so that the app could be run in Apache/CGI.
I have been unable to find an answer in the Apache docs. So maybe you can't do this?
EDIT: Also, whose responsibility is it to send the Content-Type header. Did people really manually output that back in the CGI days? I don't recall ever seeing a PHP script that did this.
Cheers

Apache 2.4.x ip blacklist

I'm looking for an easy way to blacklist IP addresses in Apache 2.4.x. My web site logs ip addresses that tried illegal operations into a text file. I would like to use this text file within Apache to deny all access to all vhosts to this ip list. What would be the best way (easiest and least resource consuming way) ?
Found this but this is only for 2.2.. Not sure how this applies to 2.4..
Cheers.
edit: this is a windows x64 box running apache x64
#vastlysuperiorman called it right, csf/lfd is the best at this. Unfortunately, they only run on linux.
This free utility promises to provide the same functionality: dynamically monitor access attempts and auto-block IP addresses. You can unblock with a command, in case of false positives. Certainly worth a short.
An alternative could be to create a VM (if your platform supports virtualization) deploy a very small spec linux box, and use that as a proxy. This should be easy to implement. BTW, why not just use linux? .. :-)
(this should have been a comment on #vastlysuperiorman's post, but I don't have enough SO reps to comment on the post of others)
Edited to suggest a possible apache 2.4 based solution:
To translate ACL directives between the 2.2 and 2.4 in apache
2.2 Syntax
order Deny,Allow
include conf/IPList.conf
Allow from all
2.4 Syntax
DocumentRoot /some/local/dir
<Directory /some/local/dir/>
<RequireAll>
Require all granted
Include conf/IPList.conf
</RequireAll>
</Directory>
#this will also work
<Location />
<RequireAll>
Require all granted
Include conf/IPList.conf
</RequireAll>
</Directory>
# conf/IPLIst.com is actually in /etc/apache2/conf/IPList.conf
# (ie, paths are relative to where apache is installed.
# I guess you can also use the full path to the list.
And inside conf/IPList.conf, you will have individual lines with entries like the following
Require not ip 10.10.1.23
Require not ip 192.168.22.199
Require not ip 10.20.70.100
Using mod-rewrite and a list of IPs for banning
For a redirect-to-another-page to work, you need to keep the RewriteRule outside the base URL you are guarding.
For instance, the redirect would not work under a Directory directive on DocumentRoot or a Location directive on '/', because the ban affects the status page we want to display.
So, best to keep this outside a Directory or Location directive, or link to a status page on another unprotected web server.
#Required set of rewrite rules
RewriteEngine on
RewriteMap hosts-deny txt:/etc/apache/banned-hosts
RewriteCond ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND [OR]
RewriteCond ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND
RewriteRule ^ /why-am-i-banned.html
## inside our banned hosts file, we have:
## /etc/apache2/banned-hosts (maintain the format .. its not just a plain text file)
##
193.102.180.41 -
192.168.111.45 -
www.example.com -
www.sumwia.net -
# inside our status page, could be html as below or a plain text file with '.txt' extension
#/var/www/html/why-am-i-banned.html
#
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Why is my IP banned?</title>
</head>
<body>
<h2>Why is my IP address banned?</h2>
<p>
To manage spammers and for other security needs, our server automatically blocks
suspicious IP address. If however you reckon your IP address has been blocked
wrongfully, please contact us.
</p>
</body>
</html>
And of course, you can parse your log files and populate conf/IPList.conf or /etc/apache2/banned-hosts as appropriate ..
As a short term solution
An alternative that will allow you to use the 2.2 syntax, is to install mod_access_compat module and continue using your deprecated 2.2 style 'Deny,Allow' directives. But this is only advisable as a short-term solution since that module is just there to aid transition, and would probably go away in future versions of apache 2.4
I too have not seen a good alternative for blocking access dynamically from within Apache itself. There are "hacky" ways: you could set an environment variable to contain a list of IPs and then use the module with ${REMOTE_ADDR} and the env function, but that's a stretch. Details on the Expression Parser
However, I have used several light weight modules that are helpful in protecting your Apache server.
ConfigServer Firewall (CSF/LFD) is a great solution for linux systems. It provides a simple method for managing iptables, and can be set up to do brute force detection and blocking. Info here
EDIT:
Add the following line to /etc/csf/csf.deny to include your custom IP block list:
Include /var/www/example.deny
Alternately, update your script to append IP addresses to csf.deny either directly:
echo $badIP >> /etc/csf/csf.deny
or using the CSF command line option (preferred):
csf -d 10.20.30.40
CSF readme here
mod_security is one of my favorite Apache/nginx modules. It detects dangerous GET and POST requests and blocks access accordingly. When set up properly, it will trigger CSF to block the IP addresses that frequently violate rules. Details here

Does Apache's SetEnv directive work if not in CGI mode?

Quoted from here:
Sets an internal environment variable, which is then available to
Apache HTTP Server modules, and passed on to CGI scripts and SSI
pages.
Does it work for mod_php or mod_perl that's embedded into Apache directly?
For perl, use PerlSetEnv.
In the Apache config:
PerlSetEnv VAR1 value
PerlSetEnv VAR2 "value with spaces"
Then, in the perl code, access as usual:
print STDERR $ENV{VAR1}, "\n";