On Thu, 7 May 2026, Stormy-SDLU wrote:
> What is best practice to disallow all access to the cgi-bin
> except for the local web form.
> I have a vague memory of 127.0.0.1 being usable by apache 2.4.x
Sanity check first: by "local web form", did you mean:
A. HTML form located on the same website.
B. Browser accessing such form is running right on the server;
but the attackers came from the Internet. (Unlikely)
C. Browser accessing such form is running on same Intranet as the server
(Intranet, not Internet); but the attackers came from the Internet.
D. A and B combined.
E. A and C combined.
F. A, B, and C combined.
If what you meant was just A., then `.htaccess` alone would not help you
that much other than papering up a bit over the issue. [1]
Attacker could bypass such measure in a relatively-easy way
once he wised up to what you were trying to do.
A more proper way to prevent such kind of abuse, is to implement
the same measure that's used for preventing cross-site request forgery (CSRF).
This is not really doable in `.htaccess`, and require you to switch the form
from static HTML to CGI, as well as modifying the CGI application itself
to add such protection. [2][4]
But if your answer was not A. however, then we could continue to discuss
about using `.htaccess` to ward against such access.
Regards,
Nutchanon Wetchasit
(Just another Apache user)
[1] By checking the `Referer:` header value on the requests to the affected
CGI application, against the expected URL of HTML form that was supposed
to be invoking it. If it matches, let the request through;
otherwise deny the request.
The most straightforward way to do it would be via mod_rewrite's
`RewriteCond`/`RewriteRule` directives:
RewriteCond %{HTTP_REFERER} !=http://example.com/preciousform/
RewriteRule cgi-bin/precious/program.cgi - [R=403,L]
Other ways (with more side effect) are location-confined version
of new-style mod_authz_core's `Require`:
<Files cgi-bin/precious/program.cgi>
SetEnvIf Referer "^http://example\.com/preciousform/$"
preciousform_referrer
Require env preciousform_referrer
</Files>
And location-confined version of classic HTTPd 2.2-style
mod_access_compat's `Allow from`/`Deny from`:
<Files cgi-bin/precious/program.cgi>
Order Allow,Deny
SetEnvIf Referer "^http://example\.com/preciousform/$"
preciousform_referrer
Allow from env=preciousform_referrer
</Files>
Note that:
- These assume you're doing it in `.htaccess` at the root directory
of the virtual host (or inside `<VirtualHost>` configuration itself).
- The placeholder HTML form URL used my example is
"http://example.com/preciousform/" (beware that some place
in the examples required a regular expression from).
- The placeholder on-site location of the CGI application
in my example being "cgi-bin/precious/program.cgi"
(note the absence of slash prefix).
- The "preciousform_referrer" part is a variable that would become exist
when the request satisfies condition (having a specified
HTTP Referer value). You may change the variable name, but make sure
to change all of them in the example code to use the same changed name.
But if you have more than one CGI programs which you're adding
protection to in such way, make sure that code for each of them
use different variable name from another CGI program.
- Don't forget to substitute the placeholders I mentioned
if you decide to use these.
[2] Usual method is when user accessed the form, in the form CGI script,
you'd assign user a session cookie; then generate one random number,
associate it with that session identifier, save that association
on some kind of server-side database [3], and display the usual
HTML form page, with the usual form, but with one additional hidden field
(`<input type="hidden" ...>`) that has the value of aforementioned
random number.
And once user pressed submit on the form, and POST request arrived
at the application's CGI script, check the session cookie,
look up in the server-side database to find the correct random number,
then check that it must match against the hidden field submitted
from client. If any step failed, fail the request, say "Form expired"
and direct user back to the original CGI form CGI.
(Thus, when attacker blindly flung unsolicited POST requests
to your CGI application, he would have neither valid session cookie,
nor correct random number that your CGI application recognize;
and your application would reject such requests)
But this method is quite involved, and you also need to have both
your CGI form and CGI application automatically weed out the
"used"/"expired" random number associations in the database too.
So in Perl CGI, I will not recommend this "usual" method;
I would recommend TOTP method instead. [4]
[3] PHP for example, uses flat-file database for this kind of session data;
and it has built-in ways of automatic data removal of expired sessions.
[4] The TOTP method of (limited) CSRF protection works by having
a hidden field in the CGI form which contains an OTP number generated
by using on-server TOTP key file, against the timeframe-number
(Unix timestamp divided by 30) of the request for the form.
Then the CGI application that services the POST request, would generate
multiple OTP numbers, using the same on-server TOTP key file--
against timeframe-number of the POST request's access time,
as well as multiple timeframe-numbers prior to it
for the period you deem the form to still be valid.
(Generate 20 OTP numbers backward to compare,
if you would like the form to stay valid for 10 minutes, for example)
Then the CGI application would have to check that the hidden
field was submitted in the POST request, and then try to match it
to the OTP numbers it generated just now. If the submitted hidden value
matched just one of these OTP number, the request was valid and
you could proceed. Otherwise, reject it, say "Form expired" or whatever,
then direct user back to the original CGI form CGI.
(Thus, when attacker blindly flung unsolicited POST requests
to your CGI application, he would not have the correct
cryptographically-generated OTP number to provide;
meaning your application could reject such requests)
This method needs neither cookie nor server-side database;
only a RFC 6238 TOTP library (which CPAN has several, I believe),
and a key file-- which you guard with the same consideration
as password file, but less critical.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]