Link to home
Start Free TrialLog in
Avatar of Torquil Beavis
Torquil BeavisFlag for Canada

asked on

403 error with phpMyAdmin after making httpd.conf changes

I'm using AWS linux, apache 2.4.25, PHP 7.0.27, phpMyAdmin 4.7.7, FireFox 68.

For security, I kept/changed/added the following lines in httpd.conf to prevent browser access to .php and .inc.php but full browser access to .menu.php and index.php ..

I kept ..
<Directory "/var/www">
    AllowOverride None
    # Allow open access:
    Require all granted
</Directory>

Open in new window

I changed from None to All ..
# Further relax access to the default document root:
<Directory "/var/www/html">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

Open in new window

And added ..
<Files *.php>
    Require all denied
    Require local
</Files>

# Browser & linux allowed access to .php files
<Files index.php>
    Require all granted
</Files>

 # Browser denied access to .inc.php files
 # linux allowed access to .inc.php files
<Files *.inc.php>
    Require all denied
    Require local
</Files>

# All menu files have this added name before the extn
# Browser & linux allowed access to .menu.php files
<Files *.menu.php>
    Require all granted
</Files>

Open in new window

My website app works perfectly. However, phpMyAdmin fails with 403 errors since I changed the above.

The directory structures ..
For the website: /html/appdirectory/index.php
For PMA: /html/phpMyAdmin/index.php

Since both index.php are allowed browser access through the above index.php granting, I don't understand why it should 403.
When I refer to Page Source in FF, it shows the HTML, yet doesn't render.

Chrome responded identically, and shows in dev tools, console ..
Failed to load resource: the server responded with a status of 403 ()
get_scripts.js.php:1 
Failed to load resource: the server responded with a status of 403 ()
phpmyadmin.css.php:1 
Failed to load resource: the server responded with a status of 403 ()
get_scripts.js.php:1 
Failed to load resource: the server responded with a status of 403 ()
get_image.js.php:1 
Failed to load resource: the server responded with a status of 403 ()
get_scripts.js.php:1 
Failed to load resource: the server responded with a status of 403 ()
messages.php:1 
Failed to load resource: the server responded with a status of 403 ()
get_scripts.js.php:1 
Failed to load resource: the server responded with a status of 403 ()
get_scripts.js.php:1 
Failed to load resource: the server responded with a status of 403 ()
get_scripts.js.php:1 
Failed to load resource: the server responded with a status of 403 ()
get_scripts.js.php:1 
Failed to load resource: the server responded with a status of 403 ()
whitelist.php:1 
Failed to load resource: the server responded with a status of 403 ()
messages.php:1 
Failed to load resource: the server responded with a status of 403 ()
get_image.js.php:1 

Failed to load resource: the server responded with a status of 403 ()
index.php:2 

Uncaught ReferenceError: PMA_commonParams is not defined
    at index.php:2
URL =>		https://www.website.com/phpMyAdmin/index.php

Failed to load resource: the server responded with a status of 403 ()
phpmyadmin.css.php:1 	
URL =>		https://www.website.com/phpMyAdmin/phpmyadmin.css.php?nocache=4546712335ltr&server=1

Open in new window

Any ideas how to resolve this?
Avatar of noci
noci

try to reorder the entries....
- First mention the most narrow settings (index)
then the less specific (.menu.php)
then the more broad classes: *.inc.php
then the most broad class: *.php
...
First thing when I make changes I try to see what the purpose for those changes are.

Based on
<Files *.php>
    Require all denied
    Require local
</Files>

only http://localhost/phpmyadmin will work.

try the following presumably you ssh

ssh -x -L 4567:lolcahost:80 user@webserver
once you establish the ssh session
use the local browser on the workstation
http://localhost:4567/phpmyadmin
and see if you get the same issue,.

The -L sets up a local tunnel through the ssh connection mapping a workstation local  port 4567 to the server''s port 80 and will appear to the web server as a localhost (local) access.
Likely you'll require adding many more files to your PHP file exception list for phpMyAdmin to ever run.

Easy way to do this will be to allow all PHP files in the phpMyAdmin directory to execute, as each different phpMyAdmin action you perform can hit many different files, so whitelisting one file at a time... will take a very long time...

Whitelisting will also fail when you update phpMyAdmin when new files are added or file names change.
You can also try adminer to manage databases.  https://en.wikipedia.org/wiki/Adminer
Then you only have ONE .php file.
Seems like noci's suggestion might be best.

This way you only have one file to white list, so your Apache config remains manageable + secure.
Avatar of Torquil Beavis

ASKER

I've tried combinations of requires in ..
<Directory "/var/www/html/phpMyAdmin/">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all denied
    Require local
    Require ip nn.nn.nn.nn                                                                                                         
</Directory>

Open in new window

.. and each failed to allow access from the browser.

So I'll research and test Adminer and get back.
Noci's suggestion of using admirer will likely be easier to get working.
I installed Adminer - I like it :)

Here is what I tried ..
<Files *.php>
    Require all denied
    Require local
    Require ip nn.nn.nn.nn  nn.nn.nn.nn
</Files>

<Files index.php>
    Require all granted
</Files>

<Files *.inc.php>
    Require all denied
    Require local
</Files>

<Files *.menu.php>
    Require all granted
</Files>

Open in new window

And this is the response ..
"Forbidden
You don't have permission to access /Adminer/adminer-4.7.3-mysql.php on this server."

Did I misunderstand how to implement your advice?
No, Now you need to whitelist the use of THIS ONE specific file: /Adminer/adminer-4.7.3-mysql.php
(before the entry of blocking *.php).
Can you give me a hint as to what whitelisting this file looks like in httpd.conf? I've been all over the web looking for how to do this with a file - there seems plenty on whitelisting IPs but not files :|
Note on line of your posted statement you block all .php files.

Point Noci is making, you should first list the php files you grant access to before you block all php th the exception of local access.

I..e you are locking the door

Reverse the order,
Grant
Grant
Gran
Block
Take the items from line 1 through line 5 and put it at the end versus at the begining.
Try: (reverse order, first mentioning allows!... then block the remainder.)

<Files adminer-*-mysql.php>
  require all granted
</Files>

<Files index.php>
    Require all granted
</Files>

<Files *.menu.php>
    Require all granted
</Files>


<Files *.inc.php>
    Require all denied
    Require local
</Files>

<Files *.php>
    Require all denied
    Require local
    Require ip nn.nn.nn.nn  nn.nn.nn.nn
</Files>

Open in new window

I did as you suggested. I got the message ..
"Amazon Linux AMI Test Page
This page is used to test the proper operation of the Apache HTTP server after it has been installed. If you can read this page, it means that the web server installed at this site is working properly, but has not yet been configured."

So I removed the IP line to test whether the IP address is being rejected, but got the same message.

Since I use CloudFront, I'm thinking it may take propagation time.
Or could it mean that the config is failing?
The document root for the apache is /var/www/html
where did you place the phpmyadmin directory in relation to the above?
What changes if any did you make to get a different result?

commonly the configuration files are in /etc/apache2 /etc/httpd /etc/httpd2 /etc/apache

commonly each has a subdirectory conf.d where one can drop individual conf files that are processed within httpd.conf these files provide for a way to add directory references, add sites ,etc.
/var/www/html/Adminer/adminer-4.7.3-mysql.php

 I removed the IP line to test whether the IP address was being rejected. It made no difference.

/etc/httpd/conf/httpd.conf

Before applying adminer and my IP address, I was able to access the app fully - just not PMA. When I made the changes, the message appeared. This indicates to me that the .conf file is the one being used to configure the changes. I stand to be corrected here ;)
By the way, if the Inbound IP on AWS Security is nn.nn.nn.nn/32, should I be adding the /32 to the IP address in .conf? I tried it and it made no difference, but I'm wondering if the protocol means it should be there.
You are making changes and asking for input on impact those changes have.
I do not have a baseline of what your system had before the changes were made nor how it was functioning when these changes were made.

It is impossible to suggest a corrective action to restore the functionality to what it might have been.
All I can do is look at what you posted and what the consequence of those rules are to try to guesstimate what you are trying to achieve.

in your case http://localhost/Adminer will get you access into the folder. Depending on your document search, default documents the adminer-4.7.3-mysql.php will usually not fit the pattern that is common to have index.htm index.html index.php home.html home .php etc.

when you go to http://localhost or http://IP you will end up at the root which is commonly the data within /var/www/html

Comment out all the restrictictions you implemented by adding a # in front of them.
then run apachectl configtest to make sure you did not introduce errors,
and start from the begining with a map to what it s you are trying to do and what it is you want to achieve.

What guide are you using, what was the question to which the guide you are following applies?
you do not need to explicitly bind apache to the IP.
you can tell it to listen on all interfaces.
a /32 means it is a single IP versus an IP from a group to which you have access.
Deals with whether you can have
<virtualHost IP1:443>
</virtualhost>
<virtualHost IP2:443>
</virtualHost>

with each being a unique site.

Having a single IP means, you are using Host based differentiatiation
i.e. all the virtualhost entries look the same with the differnetiation within
ServerName mydomain.com
ServerAlias www.mydomain.com


when apache gets the reqests it looks through its list of ServerName/ServerAlias to determine which DocumetnRoot is the correct for the request with the first virtualHost seen as the default meaning if the request does not match any, the first site will be displayed.

if you did not setup a "default site" that advises the visitor that they may have mistyped to end up here....
Thank you for the info.

Following your suggestion .. in order to check for any errors in the .conf file that I may have made, I used my original .conf which had none of the below restrictions, copied the .conf file to /etc/httpd/conf/, stopped the EC2 instance then restarted it.

Then tested my app. There was no delay due to any propagation. My app worked perfectly, I was able to access phpMyAdmin, and also adminer, and through the latter two, accessed my DB.

In case it is meaningful, I did not change ..
<Directory "/var/www">
    AllowOverride None
    Require all granted
</Directory>

Open in new window

Then I changed the following directory AllowOverride None to AllowOverride All ..
<Directory "/var/www/html">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

Open in new window

And added ..
<Files adminer-*-mysql.php>
    Require all granted
</Files>

<Files index.php>
    Require all granted
</Files>

<Files *.menu.php>
    Require all granted
</Files>

<Files *.inc.php>
    Require all denied
    Require local
</Files>

<Files *.php>
    Require all denied
    Require local
    Require ip nn.nn.nn.nn
</Files>

Open in new window

.. then copied the .conf file to /etc/httpd/conf/, stopped the EC2 instance then restarted it.

When I tried to start my app it gave the message ..
"This page is used to test the proper operation of the Apache HTTP server after it has been installed. If you can read this page, it means that the web server installed at this site is working properly, but has not yet been configured."

The message for a mistyped URL on my browser is ..
"Hmm. We’re having trouble finding that site.
We can’t connect to the server at (site name) .."

Note that I have a simple script that is called from /var/www/html/index.php. This then outputs a choice of the app, phpMyAdmin, or adminer. The choice is directed to ..

App:		/var/www/html/app_directory/index.php
or
phpMyAdmin:	/var/www/html/phpMyAdmin/index.php
or
Adminer:		/var/www/html/Adminer/adminer-4.7.3-mysql.php

Open in new window

I'm not sure what you mean by 'guide'. I have been following advice on my previous E-E questions on this subject.
I am still at a loss on what the end goal of your pursuits.

You start from a working process and then implement a change at a time to achieve one goal. Then move to the next whilevalidating the changes you make are not impacting existing functionality.

The nn.nn.nn.nn ip is where the site is or from where you are connecting?
The rule to deny will apply to all with two exception, a connection local and connections from nn.nn.nn.nn.
Ah! What you need to know is ..

My intent is to make my app more secure. In order to do this I want only the app index file and menu files (.menu.php) to be accessible by browsers, while my include files (.inc.php) and .php files should not be accessible by browsers either directly or covertly, but should clearly be accessible by PHP.

Since I develop at one location and use AWS EC2 & MySQL at the AWS location, I need to have browser access to my DB while preventing others from having access to the DB. This is the nn.nn.nn.nn location. I use SSH to transfer files to AWS and SUDO to make file adjustments as needed.

Since phpMyAdmin access was causing issues in the .conf file, I took the recommendation to use Adminer instead, and will remove phpMyAdmin after testing Adminer's data integrity  against phpMyAdmin.

I hope this puts my quest in context.
As long as your folders are not browseable the includes are revealed only when misconfigured.

You should implement your "security" one at the time while making sure it does not break your site.

Commonly breaches occur through vulnerabilities in the code such as SQL injection.

If not mistaken, include files if landed in a browser will gave a 1; as content post processing.


It is clear from your own reporting that your approach is breaking your app.

If you do it want phpmyadmin accessible
Add a .htaccess with a deny, allow rule

You are going way too granular barring access to php pages.

Instead of adding use sub cobf.d cobf files to implement narrower rules specific and applicable to one sire, folder.


You are relying the accessing index.php externally, is not

Test a rule at a time while validating your apps continual

There are other tools like fail2ban that you can use to look through error logs for 493 type access to identify a cracking ip and .....
Apologies for the delay. I've been back and forth with AWS Dev Support regarding CloudFront which seemed to be part of the issue but turned out not to be.

The issue turned out to be this:
Each time I changed httpd.conf and SSH'd it to the conf directory, it failed due to the owner:group being ec2-user:ec2-user instead of the original.

And this:
Here is the final solution to the issue using noci's and David Favor's direction and many tests ;)

# For all files in this directory or its sub-directories (including a browser database manager such as phpMyAdmin or adminer) not to be accessible through the browser except by IP
<Directory "/var/www/html/thisname">
    AllowOverride None

    <Files "*.*">				
        Require all denied
        Require ip nn.nn.nn.nn
    </Files>

</Directory>


# For browser-accessible index and all menu files
<Directory "/var/www/html/thatname">
    AllowOverride None

    <Files "*.php">
        Require all denied
        Require ip nn.nn.nn.nn
    </Files>

    <Files index.php>
        Require all granted
    </Files>

    <Files *.menu.php>
        Require all granted
    </Files>

    <Files *.inc.php>
        Require all denied
        Require ip nn.nn.nn.nn
    </Files>

</Directory>

Open in new window


Thanks guys :)
Glad you got this working!
This question needs an answer!
Become an EE member today
7 DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform.
View membership options
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.