Bug 43666

Summary: CGI works, but client denied error messages in error.log
Product: Apache httpd-2 Reporter: Georg Sauthoff <bz-apache-org>
Component: CoreAssignee: Apache HTTPD Bugs Mailing List <bugs>
Status: NEW ---    
Severity: normal CC: jerrocks, Martin.vGagern
Priority: P2    
Version: 2.5-HEAD   
Target Milestone: ---   
Hardware: PC   
OS: Linux   

Description Georg Sauthoff 2007-10-20 12:57:12 UTC
Hi,

I have a working Apache 2 setup and Apache calls successfully the
cgi-scripts. The problem is, that for every successfull CGI-call I get a
'client denied by server configuration' error message into the error.log
file.

This message conflicts with the fact, that the CGI-call was executed
successfully and I saw the correct output in the Web browser.

I am basically using a '/ Deny all' policy and a ScriptAlias definition.

A minimal working example which reproduces the error follows at the end of the 
report.

Analysis:
I debugged this issue a bit and it:
- check_dir_access() is called two times for every cgi request
- the 2nd check_dir_access() call actually prints the 'client denied' error 
message
=> the cause is server/util_script.c:ap_add_cgi_vars()
   - to construct PATH_TRANSLATED ap_sub_req_lookup_uri() is called and as a 
result a few frames later check_dir_access() is called

Conclusion:
Well, the problems with this wrong error messages are:
1. it makes no sense, because the cgi-script don't use apaches access control 
mechanism
2. such wrong messages hide real error messages

Minimal working example:
NameVirtualHost *
<VirtualHost *>
  DocumentRoot /var/www/

  <Directory />
    Options -FollowSymLinks -Indexes -Includes -ExecCgi
    AllowOverride None
    Order Deny,Allow
    Deny from all
  </Directory>

  ScriptAlias /project /var/www/project/cgi-bin/test.cgi
  <Directory /var/www/project/cgi-bin>
    SetHandler cgi-script
    Options +ExecCGI
    Order Deny,Allow
    Allow from all
  </Directory>
</VirtualHost>

# cat test.cgi
#!/bin/sh

cat out.min

# cat out.min
Content-Type: text/html; charset=utf-8
Status: 200 OK

<HTML>
<HEAD></HEAD><BODY><H1>HELLO WORLD!</H1></BODY></HTML>

# curl http://127.0.0.1/project/bar
<HTML>
<HEAD></HEAD><BODY><H1>HELLO WORLD!</H1></BODY></HTML>

Error message in error.log:
[error] [client 127.0.0.1] client denied by server configuration: /var/www/bar

Before the debugging the problem with gdb I discussed it two months ago at the 
apache user mailing list:
http://thread.gmane.org/gmane.comp.apache.user/70767/focus=70804
(at that time nobody could identify the cause for this wrong error messages)

Best regards
Georg Sauthoff
Comment 1 Jeremy Prevost 2009-02-09 09:56:11 UTC
I see this issue on Windows 2003, Windows 2008 and Mac 10.5.6 running Apache 2.2.
Comment 2 David Tonhofer 2010-07-13 07:26:39 UTC
Looks like this is alive on 

Red Hat Enterprise Linux Server release 5.5

with 

httpd-2.2.3-43.el5
Comment 3 Ulrich Windl 2013-10-23 13:52:43 UTC
I also see this problem in SLES11 SP2 (Apache 2.2.12):
I wrote a Perl CGI script that uses path info heavily to select the function to dispatch (virtually encoding the function to perform in the URI). In combination with ScriptAlias I call functions like http://vserver.domain.org/topic/session/function/transaction/step where http://vserver.domain.org/topic is a ScriptAlias to /srv/www/cgi-bin/freaky.pl
So freaky.pl processes parameters like "/session/function/transaction/step". I verified (in the browser) that freaky.pl creates hyperlinks like http://vserver.domain.org/topic/session/function2/transaction2/step2, and those hyperlinks _work_ (i.e. the function is performed with the proper URI).

Unfortunately at the same time Apache logs an _error_ like this:
client denied by server configuration: /srv/www/vserver/session, referrer http://vserver.domain.org/topic/session/function/transaction/step

So I guess Apache gets somewhat confused. I'd like to see this problem fixed, or at least to be presented a work-around.
Comment 4 Viktor Ć tujber 2023-04-28 09:56:39 UTC
The issue is caused by server/util_script.c::ap_add_cgi_vars(). At the end, it needs to define the variable "PATH_TRANSLATED", as required by https://www.rfc-editor.org/rfc/rfc3875#section-4.1.6 - by tacking on the cgi subpath to DocumentRoot, even though the result is a nonsensical path that doesn't exist.
To achieve this, it calls server/request.c::ap_sub_req_lookup_uri(), lets it do its thing, and just picks up the computed 'filename' from the result. The fact that this call is actually trying to access the fake path, and is tripping security checks as it does so, makes me suspect it is not the most appropriate tool for the job.

Reproduces on a default httpd install on ubuntu, freebsd, windows. Reproduces with mod_cgi and mod_wsgi. Requires only minimal edits:
1. edit httpd.conf - comment out 'Require all granted' from default DocumentRoot directory.
2. edit httpd.conf - append "ScriptAlias /test /tmp/test.cgi" "<Location /test>Require all granted</Location>".
3. wget http://localhost/test/whatever
4. [authz_core:error] [pid 1861] [client 127.0.0.1:20266] AH01630: client denied by server configuration: /usr/local/www/apache24/test/whatever

The call stack looks like this for httpd 2.4.57:
1. ap_log_rerror_(file="mod_authz_core.c", int line=879, module_index=6, level=3, status=0, r=0x00bc2f00, fmt="AH01630...", ...) in server/log.c(1366)
2. authorize_user_core(r=0x00bc2f00, int after_authn=0) in modules/aaa/mod_authz_core.c(879)
3. authorize_userless(r=0x00bc2f00) in modules/aaa/mod_authz_core.c(916)
4. ap_run_access_checker_ex(r=0x00bc2f00) in server/request.c(92)
5. ap_process_request_internal(r=0x00bc2f00) in server/request.c(339)
6. ap_sub_req_method_uri(method="GET", new_uri="/test", r=0x00bbeaf0, next_filter=NULL) in server/request.c(2289)
7. ap_sub_req_lookup_uri(new_uri="/test", r=0x00bbeaf0, next_filter=NULL) in server/request.c(2301)
8. ap_add_cgi_vars(r=0x00bbeaf0) in server/util_script.c(432)
9. cgi_handler(r=0x00bbeaf0) in modules/generators/mod_cgi.c(805)