There are many ways to enhance Asp.Net Web Application security, either on the web, back-end or database level, in this post, I will list some useful tips and tricks that will help you make your web application more secure.
Although the article discusses the concerns in asp.net context, it is applicable to any other framework
Web Level
Connection String
There are 2 ways to configure the security for your database connection in connection string. The first one is windows authentication, your application connect to the database server using the Application Pool Identity, and this is the recommended way as it doesn’t include writing any User Passwords in your connection string, not to mention the need to edit web.config with the new password if it has expired, which will cause a restart in the IIS application pool.
The second way is to connect through SQL authentication, in this case, you should not have the password added as a plain text, you must secure your connection string by encrypting it, .Net already support this by running the following command
aspnet_regiis -pe “connectionStrings” -app “/MyCustomApplication”
The aspnet_regiis exe can be found in your Microsoft.net folder under C:\Windows\Microsoft.net, you should find a folder with the version of your framework, ex: v2.0.*
the -pe parameter specifies which section of your web.config you want to encrypt and the -app parameter specifies which IIS web site you want to use.
The algorithm used to encrypt is RSA, for more information about how does this work, please refer to https://msdn.microsoft.com/en-us/library/dtkwfdky.aspx?f=255&MSPPError=-2147217396
Service Accounts Privillages
The service account is used to run the application pool which in turn run the web application, and it is the account that you web application uses as identity when it needs to connect to the database if you specified Integrated Security=True or if you need to have an access to file system, for ex: Logging.
This account must have the least privilege, on the file system, only give it a read access to a specific folder if this is all what you need, on the database, don’t just get lazy and give it db_owner, only grant it the permissions it needs, if it only needs read or write on certain tables, then let it be and don’t give it access to everything.
Why is that? because simply, if someone succeeded to get to this service account, they could harm your servers, I have seen many cases where people uses a domain admin as a service account, imaging what a hacker could do with such account.
Cross Site Scripting (XSS)
Imagine you have a web application, and there is the page with the URL: http://somesite/dashboard/pay?amount=1000.
This page is requested using GET and it needs the user to be authenticated, now the user can only access if he is logged in, but think of the following scenario:
You access a site named: http://someothersite, and in this site, there is an image with a src =http://somesite/dashboard/pay?amount=1000&toAccount=123-123-123.
What will happen is that your browser will automatically try to fetch the source of the image and make a get request to the URL, and by design, the browser will automatically send the cookies for somesite domain including the authentication cookie, and the result will be the execution of the URL and pay the amount of 1000 because the request seems legitimate.
To prevent this issue, you must implement something called Anti-Forgery tokens, this simply means that with each request, the site will put a hidden field in the page and store its value in the user session or cookie, and when the user posts the page to the server, the server will validate that the value in the hidden field is equal to the value stored in the session or cookie, then it will clear the value in the session, this way, if the user tried to submit the page again or in our example, another site request the URL on behalf of the user, the server will deny the request because the request will not include the correct value for the anti-forgery token.
MVC has an excellent support for this by calling the @Html.AntiForgeryToken() in the view and annotating the action method by [ValidateAntriForgery] attribute
to read more about it, follow these links Anti-Forgery in asp.net , Anti-Forgery in web API
SQL Injection
Although this is a very old issue and nearly most of the existing ORM solutions handle it, still some people fall into this problem, the danger of this issue, is that the hacker can get to your database, your database server and from there, he can get to all your other servers, so always validate the user input, always use parameterized queries and skip the user strings if you are building a dynamic SQL.
Web.Config Encryption
Same issue as the connection string, but applies also to keys stored in app.config, you can also call the same command and encrypt the appsettings section, you don’t need to worry about the decryption cause .Net makes it automatically for you
HTTPS
If your application has sensitive data and you want to prevent any chance of the network between the user and the web server being spoofed, then enable HTTPS, it works by encrypting the traffic between the browser and the server by a public/private key using certificate.
Cookies
If your site is using cookies for authentication or maintaining client state, then make sure no sensitive data is there, also if you don’t need to access the cookie inside your client browser, then mark the cookie as Http Only, if the cookie has httponly enabled then it will not be accessible through JavaScript and the document.cookie JavaScript object will not contain this cookie.
Another trick is to mark your cookie as secure only, this will make it accessible and the client will send it to the server only if HTTPS was enabled on the web site, this will ensure that your cookie is safe
Files under virtual directory
Don’t leave any backups in your virtual directory, sometimes we make a backup from web.config in the shape of web.bak or some other format, these files may be served to the client and a hacker can use the info inside it to hack your application.
Session Hijacking
If you are using session variables, which is mainly some variables stored on server session or a state server, depending on your configuration, the web server has to has a key for your session in order to be able to retrieve the data for your session, this key is called Session ID, and by default it is stored in a cookie named ASP.NET_SessionId, if someone gets to this cookie value, they will be able to log in to the site, use any cookie editor extension and update the session ID to your ID and from there they will be logged in as you, so if your site has an edit profile page or a page that allows the user to add credit card info, this data will be stolen.
To prevent session hijacking, you have to do the following:
- Use SSL, this way no one will be able to capture the traffic between your users and the web application, consequently, they won’t capture the session ID cookie value
- Make the session ID value harder to guess, the worst thing to do is to make the session ID as incremental value, if I logged in and found my session ID as 12345, then I can easily edit it to another number and it will be easy to obtain the session for another user
- Set the session ID cookie to be always Http Only, this will prevent any JavaScript from reading its value and will make it harder for any XSS
- Regenerate the session ID, this will make it harder for the attacker, even if he got the session ID, it won’t be valid for long time
- Prevent concurrent sessions, if you have your user logged in from one session, and he tried to login from another session, there is a probability that he is not the same person, you can be more certain by validating the IP and time used, ex: if the user IP is from USA, and at the same time the user is trying to connect from Europe, then most probably this is an attack
Eliminate unneeded headers
Some headers are not necessary in your web page response, such as Server, Asp-Net version and so on, these headers not only add a performance headache, but make the attacker job easier as he already knows what framework, servers and environment he will be attacking, so always edit your web.config or IIS Console and remove these unneeded headers
Database Level
Data Encryption
A very simple case for encrypting the data is the user passwords, never store it in plain text, you have to use a strong algorithm to encrypt the important data in your database, but note that this will affect the performance of the application because the web application will have to do some calculations to encrypt the data before persistence and decrypt it after retrieval, also you will not be able to write queries that include any of the encrypted columns.
SQL Server 2016 has a great feature called Dynamic Data Masking, it allows you to mask the data stored in a column in some predefined formats, ex: Credit Card, Social Security Number or an email address, permissions can be granted for some users and only those users will be able to see the data unmasked.
To read more about the topic, please follow this link
IPSec
This feature blocks all incoming connections to a specific server on all ports and allows you to allow certain IP and certain port, so in this case, the database server will not allow any connections but from the web servers for your application
SQL Server Transparent Data Encryption (TDE)
In case all the above precautions failed to protect your database, at least you can protect the data on rest, TDE allows you to encrypt the database’s data file itself so that no one can open it on another computer without a secret key, to encrypt your database file, you need a master key, certificate protected by this master key, a database encryption key which is protected by the certificate and finally set the database to use encryption.
To read more about it, following this link https://msdn.microsoft.com/en-us/library/bb934049.aspx