How to secure phpMyAdmin

PhpMysqlSecurityUbuntuPhpmyadmin

Php Problem Overview


I have noticed that there are strange requests to my website trying to find phpmyadmin, like

/phpmyadmin/
/pma/

etc.

Now I have installed PMA on Ubuntu via apt and would like to access it via webaddress different from /phpmyadmin/. What can I do to change it?

Thanks


Update

For Ubuntu 9.10 and Apache2, the corresponding setting is located in the file /etc/apache2/conf.d/phpmyadmin.conf which is a link to /etc/phpmyadmin/apache.conf. The file contains

Alias /phpmyadmin /usr/share/phpmyadmin

where the first /phpmyadmin should be changed to something different if one wants to avoid the unnecessary activity, e.g.:

Alias /secret /usr/share/phpmyadmin

Php Solutions


Solution 1 - Php

The biggest threat is that an attacker could leverage a vulnerability such as; directory traversal, or using SQL Injection to call load_file() to read the plain text username/password in the configuration file and then Login using phpmyadmin or over tcp port 3306. As a pentester I have used this attack pattern to compromise a system.

Here is a great way to lock down phpmyadmin:

  • PhpMyAdmin lacks strong bruteforce protection, so you must use a long randomly generated password.
  • DO NOT ALLOW REMOTE ROOT LOGINS! Instead phpmyadmin can be configured to use "Cookie Auth" to limit what user can access the system. If you need some root privileges, create a custom account that can add/drop/create but doesn't have grant or file_priv.
  • Remove file_priv permissions from every account. file_priv is one of the most dangerous privileges in MySQL because it allows an attacker to read files or upload a backdoor.
  • Whitelist IP address who have access to the phpmyadmin interface. Here is an example .htaccess reulset:

> Order deny,allow > Deny from all > allow from 199.166.210.1

  • Do not have a predictable file location like: http://127.0.0.1/phpmyadmin. Vulnerability scanners like Nessus/Nikto/Acunetix/w3af will scan for this.

  • Firewall off tcp port 3306 so that it cannot be accessed by an attacker.

  • Use HTTPS, otherwise data and passwords can be leaked to an attacker. If you don't want to fork out the $30 for a cert, then use a self-signed. You'll accept it once, and even if it was changed due to a MITM you'll be notified.

Solution 2 - Php

One of my concerns with phpMyAdmin was that by default, all MySQL users can access the db. If DB's root password is compromised, someone can wreck havoc on the db. I wanted to find a way to avoid that by restricting which MySQL user can login to phpMyAdmin.

I have found using AllowDeny configuration in PhpMyAdmin to be very useful. http://wiki.phpmyadmin.net/pma/Config#AllowDeny_.28rules.29

AllowDeny lets you configure access to phpMyAdmin in a similar way to Apache. If you set the 'order' to explicit, it will only grant access to users defined in 'rules' section. In the rules, section you restrict MySql users who can access use the phpMyAdmin.

$cfg['Servers'][$i]['AllowDeny']['order'] = 'explicit'
$cfg['Servers'][$i]['AllowDeny']['rules'] = array('pma-user from all')

Now you have limited access to the user named pma-user in MySQL, you can grant limited privilege to that user.

grant select on db_name.some_table to 'pma-user'@'app-server'

Solution 3 - Php

Another solution is to use the config file without any settings. The first time you might have to include your mysql root login/password so it can install all its stuff but then remove it.

> $cfg['Servers'][$i]['auth_type'] = 'cookie'; > > $cfg['Servers'][$i]['host'] = 'localhost'; > > $cfg['Servers'][$i]['connect_type'] = 'tcp'; > > $cfg['Servers'][$i]['compress'] = false; > > $cfg['Servers'][$i]['extension'] = 'mysql';

Leaving it like that without any apache/lighhtpd aliases will just present to you a log in screen. enter image description here

You can log in with root but it is advised to create other users and only allow root for local access. Also remember to use string passwords, even if short but with a capital, and number of special character. for example !34sy2rmbr! aka "easy 2 remember"

-EDIT: A good password now a days is actually something like words that make no grammatical sense but you can remember because they funny. Or use keepass to generate strong randoms an have easy access to them

Solution 4 - Php

In newer versions of phpMyAdmin access permissions for user-names + ip-addresses can be set up inside the phpMyAdmin's config.inc.php file. This is a much better and more robust method of restricting access (over hard-coding URLs and IP addresses into Apache's httpd.conf).

Here is a full example of how to switch to white-listing all users (no one outside this list will be allowed access), and also how to restrict user root to the local system and network only.

$cfg['Servers'][$i]['AllowDeny']['order'] = 'deny,allow';
$cfg['Servers'][$i]['AllowDeny']['rules'] = array(
	'deny % from all', // deny everyone by default, then -

	'allow % from 127.0.0.1', // allow all local users
	'allow % from ::1',

	//'allow % from SERVER_ADDRESS', // allow all from server IP

	// allow user:root access from these locations (local network)
	'allow root from localhost',
	'allow root from 127.0.0.1',
	'allow root from 10.0.0.0/8',
	'allow root from 172.16.0.0/12',
	'allow root from 192.168.0.0/16',

	'allow root from ::1',

	// add more usernames and their IP (or IP ranges) here -	
	);

Source: How to Install and Secure phpMyAdmin on localhost for Windows

This gives you much more fine-grained access restrictions than Apache's URL permissions or an .htaccess file can provide, at the MySQL user name level.

Make sure that the user you are login in with, has its MySQL Host: field set to 127.0.0.1 or ::1, as phpMyAdmin and MySQL are on the same system.

Solution 5 - Php

Most likely, somewhere on your webserver will be an Alias directive like this;

Alias /phpmyadmin "c:/wamp/apps/phpmyadmin3.1.3.1/"

In my wampserver / localhost setup, it was in c:/wamp/alias/phpmyadmin.conf.

Just change the alias directive and you should be good to go.

Solution 6 - Php

The best way to secure phpMyAdmin is the combination of all these 4:

1. Change phpMyAdmin URL
2. Restrict access to localhost only.
3. Connect through SSH and tunnel connection to a local port on your computer
4. Setup SSL to already encrypted SSH connection. (x2 security)

Here is how to do these all with: Ubuntu 16.4 + Apache 2 Setup Windows computer + PuTTY to connect and tunnel the SSH connection to a local port:

# Secure Web Serving of phpMyAdmin (change URL of phpMyAdmin):

	sudo nano /etc/apache2/conf-available/phpmyadmin.conf
			/etc/phpmyadmin/apache.conf
		Change: phpmyadmin URL by this line:
			Alias /newphpmyadminname /usr/share/phpmyadmin
		Add: AllowOverride All
			<Directory /usr/share/phpmyadmin>
				Options FollowSymLinks
				DirectoryIndex index.php
				AllowOverride Limit
				...
		sudo systemctl restart apache2
		sudo nano /usr/share/phpmyadmin/.htaccess
			deny from all
			allow from 127.0.0.1
		
		alias phpmyadmin="sudo nano /usr/share/phpmyadmin/.htaccess"
		alias myip="echo ${SSH_CONNECTION%% *}"

# Secure Web Access to phpMyAdmin:
	
		Make sure pma.yourdomain.com is added to Let's Encrypt SSL configuration:
			https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-ubuntu-16-04
			
		PuTTY => Source Port (local): <local_free_port> - Destination: 127.0.0.1:443 (OR localhost:443) - Local, Auto - Add
		
		C:\Windows\System32\drivers\etc
			Notepad - Run As Administrator - open: hosts
				127.0.0.1 pma.yourdomain.com

		https://pma.yourdomain.com:<local_free_port>/newphpmyadminname/ (HTTPS OK, SSL VPN OK)
		https://localhost:<local_free_port>/newphpmyadminname/ (HTTPS ERROR, SSL VPN OK)
		
		# Check to make sure you are on SSH Tunnel
			1. Windows - CMD:
				ping pma.yourdomain.com
				ping www.yourdomain.com
				
				# See PuTTY ports:
				netstat -ano |find /i "listening"
				
			2. Test live:
				https://pma.yourdomain.com:<local_free_port>/newphpmyadminname/
				

If you are able to do these all successfully,

you now have your own url path for phpmyadmin,
you denied all access to phpmyadmin except localhost,
you connected to your server with SSH,
you tunneled that connection to a port locally,
you connected to phpmyadmin as if you are on your server,
you have additional SSL conenction (HTTPS) to phpmyadmin in case something leaks or breaks.

Solution 7 - Php

If you are running a linux server:

  • Using SSH you can forbid the user/password loging and only accept a public key in the authorized_keys file
  • Use putty to connect to your server and open a remote terminal
  • Forward X11 and brings localhost firefox/iceweasel to your desktop (in windows you need Xming software installed)
  • Now you secured your phpMyAdmin throught ssh

This system is quite secure/handy for homeservers -usually with all ports blocked by default-. You only have to forward the SSH port (don't use number 22).

If you like Microsoft Terminal Server you can even set a SSH Tunneling to your computer and connect securely to your web server throught it.

With ssh tunneling you even can forward the 3306 port of your remote server to a local port and connect using local phpMyAdmin or MySQL Workbench.

I understand that this option is an overkill, but is as secure as the access of your private key.

Solution 8 - Php

The simplest approach would be to edit the webserver, most likely an Apache2 installation, configuration and give phpmyadmin a different name.

A second approach would be to limit the IP addresses from where phpmyadmin may be accessed (e.g. only local lan or localhost).

Solution 9 - Php

You can use the following command :

$ grep "phpmyadmin" $path_to_access.log | grep -Po "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" | sort | uniq | xargs -I% sudo iptables -A INPUT -s % -j DROP 

Explanation:

Make sure your IP isn't listed before piping through iptables drop!!

This will first find all lines in $path_to_access.log that have phpmyadmin in them,

then grep out the ip address from the start of the line,

then sort and unique them,

then add a rule to drop them in iptables

Again, just edit in echo % at the end instead of the iptables command to make sure your IP isn't in there. Don't inadvertently ban your access to the server!

Limitations

You may need to change the grep part of the command if you're on mac or any system that doesn't have grep -P. I'm not sure if all systems start with xargs, so that might need to be installed too. It's super useful anyway if you do a lot of bash.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndreiView Question on Stackoverflow
Solution 1 - PhprookView Answer on Stackoverflow
Solution 2 - PhpJae ChoView Answer on Stackoverflow
Solution 3 - PhpPiotr KulaView Answer on Stackoverflow
Solution 4 - PhprightstuffView Answer on Stackoverflow
Solution 5 - PhpMathewView Answer on Stackoverflow
Solution 6 - PhpTarikView Answer on Stackoverflow
Solution 7 - PhpJJFSView Answer on Stackoverflow
Solution 8 - PhplexuView Answer on Stackoverflow
Solution 9 - PhpTechnical BloodView Answer on Stackoverflow