How to endanger an apache/php app by mixing basic and cookie authentication
This simple docker application contains :
_ an Apache http server, responsible for the authentication of the user
_ a PHP backend page, that uses the authentication info
The configuration of the Apache server requires an authentication through a form and a cookie mechanism. But if an Authorization header is present, like it would be in a basic authentication scheme, it may pollute the PHP variables used to identify the connected user, possibly permitting identity fraud, if used incorrectly.
The poc has been setup on an Ubuntu VM. Correct for any other platform (eg remove the sudo)
Docker
cd to the base directory of the repository.
sudo docker build -t poc .
sudo docker run -d -p 80:80 -v ${PWD}/htdocs:/var/www/html/ -v ${PWD}/htpasswd:/htpasswd/ --name poc poc
Open a browser and open http://localhost. The authenticaton form will be displayed :
Two user/pwd are already set : toto/totopwd and titi/titipwd
In case of error, the form is displayed again.
In case of success, a "hello" page is displayed, and indicates the identity of the user as of two different PHP variables :
_ $_SERVER['REMOTE_USER']
_ $_SERVER['PHP_AUTH_USER']

Both variables contain the id of the authenticated user.
Once authenticated, add to the request a basic authentication header, like :
Authorization: Basic RG9uYWxkVHJ1bXA6c3Ryb25ncHdk
(Use a proxy of some sort, eg Burp, or the Developer Tools of the browser)

RG9uYWxkVHJ1bXA6c3Ryb25ncHdk is the base64 encoded string for DonaldTrump:strongpwd, which would represent the user DonaldTrump with the password strongpwd.
The response to the request clearly shows the problem :
<li>$_SERVER['REMOTE_USER'] : toto</li>
<li>$_SERVER['PHP_AUTH_USER'] : DonaldTrump</li>
The $_SERVER['PHP_AUTH_USER'] variable contains the identity present in the Authorization header, without any test of its credentials, even though an other user is currently authenticated (eg toto).
Any code relying on it can then be fooled.
Php documentation indicates some subtleties on those two variables :
- 'REMOTE_USER' : The authenticated user.
- 'PHP_AUTH_USER' : When doing HTTP authentication this variable is set to the username provided by the user.
We can notice that the latter one does not state that the username is actually authenticated... subtle. Not quite sure why this variable is set when no Authorization header is provided, nor why the basic authorization header supersedes the session user.
The Authorization header can also be forcibly removed by the Apache http server configuration
RequestHeader unset Authorization
This requires mod_headers