Securing DirectAdmin
Secure DirectAdmin panel port 2222 with SSL
SSL is designed to keep an internet connection secure by safeguarding any sensitive data that is being sent between two systems, thereby preventing a third party from reading and modifying any information transferred, including protected personal information (PPI).
It's important to to use a secure connection for services and for the DirectAdmin panel itself: Secure DirectAdmin panel port 2222 with SSL
Creating a Login Key
Multiple Levels of security are mandatory these days. A single password is only 1 level, and if lost or stolen, an attacker would be able to login if there are no other levels of security. If you need to give out your DirectAdmin password for any reason, either for an API script, or even to a remote tech, it's best not to hand out your true password.
DirectAdmin has a feature called Login Keys which allows you to have multiple other passwords for your DirectAdmin account, and these other passwords can be set with heavy restrictions. These include:
- Number of CMD_ requests can be limited to a specific number, or unlimited.
- Login Key can be set to expire at a certain time
- Key can be deleted after expiry or after all requests are used.
- Key can be set to not allow HTM_, IMG_ or CSS_ requests, making it very difficult to use DA with a browser.
- Ability to restrict the key to a limited number of commands (CMD_*) or Level groupings.
- Key can be set to only allow specific IPs or simple ranges (1.2.3.4-5)
To create your own Login Key, first log in to DirectAdmin as the user the key is for, e.g., "admin".
- Browse to the Login Keys page User Level -> Login Keys . If you don't yet have any domains created, then you can manually access the page via this URL:
/CMD_LOGIN_KEYS
Click "Create new Login Key" to get started with a new key.
Enter all fields as needed.
- You'll need to specify a Key Name. Note that this is only for your own tracking purposes, it will not be the username for the login. Your current DirectAdmin username will still be used, along with the key as the password.
- Specify a Key Value, or use the random button for a longer value. The text will be shown to your when the key is created.
- Expiry can be set if you only want this key to be temporary.
- You can specify the Number of Uses if you only want the given key to be valid for a certain number of requests. For long-term APIs, you'd use 0 for unlimited.
- The Clear Key option will typically only be used with temporary keys, and is handy for temporary tech logins and such so that you don't need to worry about forgetting to disable the key after its expiry is passed (or all "uses" are consumed).
- The Allow HTM option is only used if this key is going to be used for a person to log in with a browser. API keys should not have this option enabled.
- Commands will let you specify which CMD_ or CMD_API_ calls are allowed to be used with this key. This will depend on what your key needs. If you are creating this key for an API/script, then you'd want to limit it to the smallest set of CMD_API commands you can. Contact the author of the script to find out which commands the script needs. Restricting the commands allowed will make the key significantly more secure by vastly limiting the damage an attacker could cause since their privileges are limited to only those commands listed.
- Remember that the commands ALL_USER, CMD_LOGIN_KEYS, or CMD_API_LOGIN_KEYS all allow access to the Login Keys for this, meaning that with this access, they can change the keys, which defeats the purpose, so make sure that you select your list of commands carefully.
- The Allowed IPs options lets you limit which IPs can connect with this key, one entry per line. You can specify a simple IP range such as 1.2.3.4-6.
- When testing your Login Key, it's often useful to run DA in debug mode, level 2000, which will have DA tell you why a login is being rejected.
Login Key Examples
A) Power Reseller
Although this has not be tested, in theory, you can create a 2nd Admin account, and only allow them these commands:
All_RESELLER
ALL_USER
CMD_ACCOUNT_RESELLER
CMD_RESELLER_SHOW
and deny these commands:
CMD_LOGIN_KEYS
CMD_API_LOGIN_KEYS
CMD_PASSWD
Also, set the key with these attributes enabled: Never expires, unlimited uses, clear key disabled, and allow HTM. This will give someone a Reseller Account, plus some Admin privileges. Note that this is not fool-proof. There are overlapping commands that would still allow them to delete an Admin account or change their true password (via non-obvious means), so you would still need a certain degree of trust of this account. However, it would be useful to help prevent accidents/errors by that account.
B) User Level API to create/manage email accounts
As this is a script, it will never expire, will have unlimited uses, we don't need "clear key", and "allow htm" is not required. The list of commands should only need to be:
CMD_API_POP
CMD_API_EMAIL_VACATION
and lastly, the IP field should contain just 1 IP, which is the IP that will connect to DA from the script. If the script is local, you'd specify 127.0.0.1. If your connecting from a remote server, you'd enter the main IP of the remote server.
C) DNS Clustering with the Multi Server Setup
DA only needs a small set of commands to control the DNS on a remote box. The "allow" list would be as follows:
CMD_API_DNS_ADMIN
CMD_API_LOGIN_TEST
CMD_API_USER_EXISTS
and you can set the IP of the remote box that needs to connect to this slave, as nobody else should be connecting with this key other than the master.
D) Key for Technical Support
If access to your server is requested, instead of providing the true admin password, you could provide a full-access Login Key instead. For this, use any key name (e.g., "support"), a random password (use the generator button), set an Expiry to say 5 days in the future (however long you thing it will be needed), Uses=0, Clear Key = yes, Allow HTM = yes, and enter the current admin password at the bottom. It can be restricted to an IP, but if different techs may be logging in, it's simplest to allow any.
Security Questions or Two-Factor authentication after DirectAdmin login for an additional layer of security
To help increase the level of security with a DirectAdmin server, a feature was added which allows you to add questions or enable two-factor authentication after the login is already successful. These questions can be User specified, and any incorrect answer can then notify the User.
To enable the questions, or to add/modify the questions, log in as the user and go to:
Dashboard -> Change your Password -> Manage Security Questions
To enable two-factor authentication, log in as the user and go to:
Dashboard -> Change your Password -> Two-Step Authentication
The page also allows you to disable API access to the account using the same password used to login. Session Keys and Login Keys do not apply to this setting, as they're always allowed.
NOTE: Each failed 2FA/security question is counted in the 'failed_logins' file (where wrong passwords are counted). This means you must get a valid password and valid 2FA/Security Question within the "brutecount" limit, else you'll be put on the ip_blacklist (/usr/local/directadmin/data/admin/ip_blacklist), which is where IPs bruteforcing the DA login are blocked. To remove yourself from the blacklist, edit /usr/local/directadmin/data/admin/ip_blacklist
and remove your IP from the list. You can also ensure you never become blocked by adding your IP to the file /usr/local/directadmin/data/admin/ip_whitelist
.
Login Trigger changes regarding Two-step Authentication and Security Questions
Login triggers only trigger after both the user/pass login and 2FA are answered correctly. Previously, the trigger would happen after the valid login, before the 2FA answered.
Triggers include:
- checking to ensure the
task.queue
is being processed (random) - check for old
custombuild/versions.txt
(random) - clear the
data/admin/ip_access/1.2.3.4
folder - add to "login history"
Two-Step Authentication
The feature allows any DirectAdmin account to require the Two-Step Authentication using a time-based code from a smart-phone app (e.g., Google Authenticator, FreeOTP, Authy, etc.)
Access this feature from: Password Icon -> Two-Step Authentication
Once you have a "Secret" created, scan the barcode into your Authenticator App in your smart phone. Enable the feature, and future logins will require the temporary code generated from the App, entered on a 2nd page after a successful user/password login.
You can also optionally create one-time use "Scratch Codes", which can be printed and kept somewhere safe.
These scratch codes are used as a backup, in case your phone is not available to generate the code. A scratch code is only valid for one use, then is removed from the list of codes. The scratch code can be entered into the same "Code" field when logging into DA.
Information on the importance of Two-Factor Authentication can be found here: http://comparitech.net/2fa
Applicable directadmin.conf
settings include the following:
twostep_auth=0|1 default 1
twostep_auth_discrepancy=1
twostep_auth_trust_days=30
Where twostep_auth=1
enables two-step authentication.
The twostep_auth_discrepancy value should be a positive integer representing the number of 30 second time slices you can be off by (before or after). So the default of 1 allows a code to be valid before 30 seconds before, and 30 second after the phone's timer is done counting down.
DA's "Test Code" button may show you a message about the code being valid, but for a different time. If, for example, you see the time discrepancy as "-4", that means your code expired 2 minutes ago.
If you can't fix your server's time, then change this setting to be "4" (positive 4), and DA will allow a wider range of -4 to +4 for logins. Also useful if someone's phone time isn't accurate.
The twostep_auth_trust_days=30 value represents the duration that a trusted cookie is allowed to live in the client's browser. A trusted device can be un-trusted on the CMD_TWOSTEP_AUTH page. This may make your phone sad, as the server would no longer be its friend.
Applicable DA User files:/usr/local/directadmin/data/users/username/twostep_auth_secret.txt
/usr/local/directadmin/data/users/username/twostep_auth_scratch_codes.list
Applicable DA User user.conf
settings:
twostep_auth=no
twostep_auth_description=user@host.domain.com
notify_on_all_twostep_auth_failures=yes
NOTE: Each failed 2FA/security question is counted in the 'failed_logins' file (where wrong passwords are counted). This means you must get a valid password and valid 2FA/Security Question within the "brutecount" limit, else you'll be put on the ip_blacklist (/usr/local/directadmin/data/admin/ip_blacklist
), which is where IPs bruteforcing the DA login are blocked. To remove yourself from the blacklist, edit /usr/local/directadmin/data/admin/ip_blacklist
to remove your IP from the list. You can also ensure you never become blocked by adding your IP to the file /usr/local/directadmin/data/admin/ip_whitelist
.
Detecting and preventing brute-force attacks
A common method of gaining access over a server is to use a technique called a brute force attack, or dictionary attack. What the attacker will do, is use a script to try and log in to an account with every possible password combination. This tends to require tens of thousands of login attempts, but eventually, the right combination will be found, and they can log in normally.
To prevent this, we can use a brute force login detection system. DirectAdmin has 2 such systems for these attacks.
- The original feature was created in DA 1.25.5, and will detect and block login attempts on DA itself (port 2222):
http://www.directadmin.com/features.php?id=573
This feature only applies to port 2222. It only blocks IPs on this port. It does not block IPs from other ports.
To enable this feature, go to Admin Level -> Admin Settings -> Blacklist IPs for excessive login attempts use a value around 10-20.
- The newer system works in tandem with the previous, and will scan the logs for the other services (Apache, Dovecot, Exim, ProFTPd, SSHd).
When an attack is detected, DA will notify the Admins on the box that the attack is in progress.
DA will not block the IPs since that would require a firewall, and DA doesn't manage firewalls (see block_ip.sh
below).
To enable the detection reporting, go to:
Admin Level -> Admin Settings -> Parse service logs for brute force attacks
The brute force monitor (BFM) page can be viewed at Admin Level -> Brute Force Monitor.
Hide brute-force notifications
As brute force attacks are fairly common, and the tools to prevent those attacks are fairly reliable, some admins do not wish to be told about every case of attacks.
Since the trigger of the brute_force_notice_ip.sh
only happens with notices, I've added an option to prevent the sending of the notices, but still call the scripts normally to block the IP.
The directadmin.conf option will be:
hide_brute_force_notifications=0
which is the internal default (option disabled, notifications shown).
If you wish to prevent notices from being sent out, but still have the IPs blocked, then set this in your directadmin.conf:
hide_brute_force_notifications=1
All servers should be running some sort of firewall to prevent them, e.g., </operation-system-level/securing/firewall#i-need-a-firewall-what-are-my-options>
The purpose of this guide is to hide those Message System messages once you've established that your blocking system is working correctly. There are several options and levels to suppress the messages.
If you want to hide the messages from the "Message System", but continue to be notified via E-Mail:
http://www.directadmin.com/features.php?id=1441If you want to send the high-volume attack E-Mails to some different address, like attacks@domain.com, you can add a user.conf variable:
http://www.directadmin.com/features.php?id=1558
E.g.,
alternate_email=attacks@domain.com
Brute-force monitor page generates a timeout
If you get a timeout message similar to the one below when accessing the Brute Force Monitor (BMF) page CMD_BRUTE_FORCE_MONITOR:
Your connection has timed out.
Either your request was invalid or the program hasn't completed your request.
Please notify the server admin.
This is usually caused by an over-sized file /usr/local/directadmin/data/admin/brute_log_entries.list
. Check this file to see if it's large. If it is, you can shrink it down, but only keep the entries at the end of the file (the end of the file has the newest entries).
cd /usr/local/directadmin/data/admin
mv brute_log_entries.list brute_log_entries.list.backup
tail -n 1000 brute_log_entries.list.backup > brute_log_entries.list
chown diradmin:diradmin brute_log_entries.list
Where you can increase or decrease the 1000 lines as needed.
Other possible affected file are the brute_user.data
and brute_ip.data
. Of these 2 files, it's more likely the brute_user.data
is causing the slowdown, because attacks typically happen on many Users from 1 IP address. If you need to empty the brute_user.data
file, type:
cd /usr/local/directadmin/data/admin
mv brute_user.data brute_user.data.backup
touch brute_user.data
chown diradmin:diradmin brute_user.data
We wouldn't recommend emptying the brute_ip.data
because this is what counts the attacks per IP, and is what is used to determine if an IP should be blocked.
Prevent BFM from reporting specific email
If you're using the Brute Force Monitor (BFM) and 1) have an email address that is repeatedly checking your server, but that account is invalid (either a wrong password, or a non-existent account), and 2) you know that the person doing it is not malicious, but only stubborn for not updating their settings, then you can tell the BFM to skip that email address from being checked.
To do this, create the /usr/local/directadmin/scripts/custom/brute_force_notify_pre.sh
script and add the following code:
#!/bin/sh
if [ "$type" = "User" ]; then
if [ "$value" = "your@email.com" ]; then
echo "exempt your@email.com";
exit 1;
fi
fi
exit 0;
Make it executable:
chmod 755 /usr/local/directadmin/scripts/custom/brute_force_notify_pre.sh
Note that this will only prevent reports for users/emails being logged. It will not prevent the blocking of the IPs, as the IP could be "attacking" some other account as well.
Found an XSS or CSRF hole in DirectAdmin?
People who think they've found one often are testing with a form in the DA skin, on port 2222 on the same IP. This means the form is in the skin, which is exactly where it lives usually for its intended purpose. So of course, the form submission passes, as one would expect. So this test is only possible if they've got access to editing the skins, which means they've already got root access on your server, so the XSS test doesn't mean anything.
Please, before submitting your security report, please check to ensure that you're not actually testing your form in 2222, since that's where it's going to be valid. Test with your form on any different port or IP.
I wish to have a block_ip.sh so I can block IPs through DirectAdmin
Starting from DirectAdmin version 1.61.0, the CSF integration is done directly. New installs will have CSF automatically installed and BFM autoblock covered if installation isn't customized to disable them.
Existing installations after updating to 1.61.0 could have direct CSF integration upon deleting previously installed plugin files.
To activate, remove the following files:
/usr/local/directadmin/scripts/custom/block_ip.sh
/usr/local/directadmin/scripts/custom/brute_force_notice_ip.sh
/usr/local/directadmin/scripts/custom/show_blocked_ips.sh
/usr/local/directadmin/scripts/custom/unblock_ip.sh
Brute Force Monitoring for xmlrpc.php
DirectAdmin v1.590
The xmlrpc.php
, a file included with WordPress, is an API file used for data transfers or actions between various things.
A stand-alone setup often does not need web access to this file, but any external connections, like iPhone apps that routinely do POSTs to it generating a 200 return code would require it.
This is also one of the major attack points for WordPress, used in attempts to determine the website's WordPress password.
As a result, our Brute Force Monitor (BFM), when "Scan for WordPress attacks" is enabled in the Admin Settings, will scan for POSTs to this file with a valid 200 return code (wordpress2 brute_filter.list
).
This change is to increase the match count, which would have been the same as the Brute Force Monitor's count limit (set in Admin Settings), to now be 8x that value, to allow for possible valid usage, while still blocking attacks.
For example, if you set your ip_brutecount=100, aka:
"Notify Admins after an IP has: [100] login failures on any account"
This would mean that any User would be allowed 800 POST with a 200 response code to the xmlrpc.php file, based on the BFM's rules.
Note that the BFM's time window is sliding and is entirely based on a period of time where there are no attacks counted in order to reset the count to 0.
So if you have the following set in your Admin Settings,
"Reset count of IP/User failed attempts: [4] hours after last attempt"
A period of 4 hours must pass where there are 0 failed attempts from this IP address in order for the count up to 800 to reset to 0.
If even 1 POST to xmlrpc+200 is done per hour, then the count will never reset, and the 800 limit WILL eventually be hit.
There are plugins for WordPress, which can monitor for such attacks, saving the need for DA to do it, such as WordFence.
It's ultimately up to a website to be protecting itself, as the "Scan for WordPress attacks" is simply there to be a fall-back in case the website owner failed to secure WordPress.
The /usr/local/directadmin/data/templates/brute_filter.list
contains options:
wordpress3=ip_after=&ip_until= -&text=] "POST /&text2=/wp-login.php&text3=" 302%20&count_multiplier=4
What this does, is after all log parsing is done, the Brute Force Monitor will count how many entries were triggered for that item (e.g., wordpress3) for that given IP.
Say there were 20 triggers. The multiplier means that instead of having a limit of 100, that item needs 400.
The actual logic in DA is actually backwards, as the total count uses other items, so we actually divide the number of wordpress3 counts by 4.
So instead of 20 hits, the count only see 5 towards the total. This also means that if there are only 3 hits, then 3/4 = 0, so no count would be triggered for that IP.
The entries will still show up in the log list, but count for that given IP (top table) would be lower.
The whole purpose for this is that the entry:
POST /wp-login.php HTTP/1.1" 302
could represent an attack, but could also just be a normal redirection. So we do want to count it, but it should be of lower significance.
Custom blacklisted IP page
An optional custom template file exists here:/usr/local/directadmin/data/templates/custom/blacklisted_ip.html
If that file exists and the client IP is blacklisted, this content type text/html page will be sent to the client, instead of the hard-coded: "Your IP is blacklisted".
Read more.