Webserver Version
This is simple but very effective - Make sure to keep your webserver up-to-date.
Exploits are being released on a daily basis and there is a chance you will become a victim of somebody who randomly scans IP ranges for certain vulnerabilities to exploit them.
Also keep an eye on addons and plugins you are using, PHP, OpenSSL, etc.
Webserver Version Disclosure
If you read the paragraph above, you'll know how important it may be to hide the server version.
An attacker can search for specific security vulnerabilities for the version of Apache identified within the SERVER header.
Obviously, a terrible person could still try to run an exploit against your server, but it definitely lessens the chances somebody would do so without knowing what webserver you are using and what version you are on.
A common scenario is where a user runs into an error and receives an error like:
There is no reason to let anybody know what webserver and/or what version you are running on.
Hiding Error Messages
Obviously, displaying errors that should not be available to the public can cause critical information disclosure as well. This is something you'll want to take care of at the end of the development phase. At least that's how I handle it.
This would be an example of a terrible mistake. There is literally zero reason to display errors to this extent to your users under any circumstances.
But it can get worse.
...or even worse. IIS delivering whole stack traces;
Errors are something your user should never see. Spend some time on proper error handling.
Add proper error messages if necessary.
SessionID as Cookie
Tomcat is a great example for that, it deliver sessions as get parameter.
Although you can still modify cookies, it certainly increases the needed effort to highjack sessions manually.
Bad:
Cookies httponly
If you do not need to access cookies through JavaScript, you have the option (and you should definitely do so) to set them to httponly.
And if you are on a secure connection (https), you can also add a secure flag!
Directory Listing
Something very usual on frameworks such as XAMPP that are based on Apache.
If you do not specifically want to list files in a directory, you should certainly disable the directory listing.
I've seen extreme cases where the file-structure was as weird as this:
Admin Interfaces
Admin interfaces should obviously only be accessible for administrators.
Although you have many options to set up privileges through programming, there are several options to set up privileges through your webserver.
Htaccess for Apache and authentication rules for IIS - to name some for the most famous webservers.
Error Message for Username/Email/Passwords
Make sure not to disclose too much information.
Example:
User tries to login with the username "Admin
" and password "password
".
User Admin does exist.
Error message: "The password does not match for the user Admin"
We now know that there is indeed a user called Admin and can now start bruteforcing it. If the message was something like "The username and/or password does not match." we would not know if the username or password or even both are wrong.
Passwords
Best case: Do not allow your users to set up an own password - as annoying as it may be.
We all know how lazy people are. They end up with passwords like "asdf1234" and wonder how they got hacked.
If you do allow them to create their own password, go for something like:
- Must be 8 at least characters long
- At least 1 number
- At least 1 special character
- Mixture of upper- and lowercase
Saving Passwords Clientside
You might want to consider disallowing the saving of passwords for clients on loginforms. You can do so with the attribute autocomplete=off
.
Swapping HTTP Methods
Changing the methods should certainly not be possible. POST
parameters should not be accepted as GET
and vice versa.
In a mixture with a CSRF attack (with the help of Ajax on other pages) could lead to critical vulnerabilities for your users.
Basic Authentification
Basic authentification is something you do not want to rely on. If you have the option to go for https - do so!
Changing the Password
Something everybody should know by now. If you give the option to change the password, make them enter the old one too, just in case somebody somehow got access to the computer.
Logging In
If a user fails to log in for more than 5 times, block his IP for a certain amount of time and increase the time for multiple attempts. Add a captcha.
SQL Injections
In modern development, it's very usual to have an abstraction layer between your application and your database in which case it is already a lot harder to SQL inject.
But in some cases, there is none - Make sure to escape your SQL statements or even better go for prepared statements in which case you do not need to escape the parameters.
(Distributed) Denial of Service Attacks
Denial of service attacks are very old school and easy to "fix" with iptables for example.
The more annoying ones are Distributed Denial of service attacks where the traffic does not come from a single source but in a worst case scenario from multiple 10000s.
If you do not have the infrastructure, definitely go for something like forguard or if your server provider offers features to protect you, use them if you need to.
Your users will thank you.
Cross-site Scripting (XSS/RXSS/PXSS)
(Reflected/Persistend) Cross site scripting attacks are possible if the programmer did a sloppy job and did not escape the user input properly.
If your programming language does not offer functions to escape the input, escape <,>,",' manually.
User input should be escaped on the frontend AND the backend.
Remote/Local File Inclusion
Something very common in the PHP world is to accept filenames as a get parameter.
Example: http://www.digitahlen.de/?action=summary
In this case, the PHP file summary.php will be included at page load.
Now, if the parameter won't be validated, a user can execute/include files from the outside and the inside of your server.
Saving Passwords
This is 2014. Stop saving passwords in plain md5 or even worse plain text. Use salts.
Cross-site Request Forgery(CSRF)
Add a CSRF token to every form. You do not want your users to get hurt that easy.
Tokens have to be generated on every new page call.
For GET
request, you add them to the parameter list. For POST
requests, you add them to a hidden field.
Sessions
If you do not explicitly want to allow a user to login multiple times - deny it.
Add a transaction token to a cookie.
If a user logs in without having the token in the cookie - he gets logged off.
That's All For Now
This is my personal check list on what I look out for when I develop a website. I am open to any criticism as this is my first article. This article is not supposed to give you a step my step guide on how to fix certain vulnerabilities, it's more of a guideline, things you want to remember.
I hope I helped somebody with this and thank you so much for reading!
You can find the German version of it here:
http://baberich.de/eine-sichere-webseite-entwickeln-checkliste-2014/