Web App Security Checklist

Cookies

Use secure cookie attributes

The session cookie should have the HttpOnly, Secure, and SameSite flags set. These attributes are set during web development to ensure the session ID created when the user logs in to the application is not transferred into another website. This prevents malicious users from redirecting the valid user to a new site to create illegal transactions. The session id should not be accessible to client- side scripts, should only be transmitted over HTTPS, and should only be sent with requests from the same site (mitigates CSRF).

Securing connections containing cookie data

Websites use cookies to track the movements of a user within the site, help the user resume where they left off and set user preferences. Cookies can be used by attackers to impersonate genuine users and escalate their privileges on the application, enabling them to have access to data that should be available to only the genuine users. Encrypting cookies will help prevent this type of attack.


Access Control

Apply the principle of least privilege

User accounts should be given only the privileges required to perform their prescribed tasks. Privilege can be escalated as increased access is needed.

Don’t use direct object references for access control checks

Do not allow direct references to files or parameters that can be manipulated to grant excessive access. Access control decisions must be based on the authenticated user’s identity and trusted server-side information.

Don’t use unvalidated forwards or redirects

Conduct appropriate checks on the privileges and access a user has to a page before redirecting or forwarding the user to the page. An unvalidated forward can allow an attacker to access private content without authentication.


Error Messages and Logging

Use generic error messages

Application developers should be careful with how much information is provided in error messages. Provide only minimal amount of information to protect sensitive server data (e.g. API keys or database passwords). Providing full-exception details can make complex attacks like SQL injection far easier by telling attackers how data is sanitized or stored. Keep detailed errors in your server logs, and show users only the information they need.

Error messages should not reveal technical details about the application. For example, a file system path should not be exposed to the user through error messages. These error massages should be customized to prevent revealing of sensitive information to the user.

Hide authentication error details

Messages for authentication errors must be clear and, at the same time, be written so that sensitive system information is not disclosed. For example, error messages which reveal that the user id is valid but that the corresponding password is incorrect confirms to an attacker that the account does exist in the system.

Log authentication activity

The application should log all login activity, whether successful or not. These logs help identify attackers who are trying different combinations of usernames and password to log into the application.

Securely store logs

Logs are files that contain all the error messages and process messages of the application and should be stored and maintained appropriately to avoid information loss or tampering by intruders.


Secure Headers and Certificates

Use the Strict Transport-Security header

When a user types in the URL of a website and omits the ‘https’ and types ‘http://websitename.com’ or even just ‘websitename.com’, the user can be redirected to a malicious site. This could allow the user’s data to be transferred in plain text format, which can be easily intercepted by malicious hackers. Implementing the Strict Transport-Security header will ensure that the user’s browser of users always connect to the website only over HTTPS.

Use X-Frame-Options or CSP headers

It is recommended that the X-Frame-Options header or Content-Security-Policy (CSP) header frame-ancestors directive is used to help protect users against clickjacking attacks. The clickjacking attack is when an attacker hijacks the clicks meant for the original server by tricking the user into clicking a button or a link and sending them to another server.

Use Expect-CT

Expect-CT prevents fraudulent SSL certificates from being served to clients. Expect-CT is put as the header in the code telling the browser perform additional background checks to ensure the certificate is genuine. When a server uses the Expect-CT header, it is fundamentally requesting the client to verify that the certificates being used are present in public CT logs.

Websites are issued these certificates to protect sensitive information that’s sent between computers and servers. They encrypt the data and ensure that the unauthorized users are not able to read it. If personal information, such as credit card numbers and passwords, are not encrypted/hashed, the information is open to being accessed by unauthorized users. With the certificate, your information is unreadable to unauthorized users.

Use Valid SSL Certificates

SSL certificates used for web applications should be signed by a reputable certificate authority. The name on the certificate should match the full domain name of the website. The certificate should be maintained so that it remains valid and does not expire.


Form Data Input and Output

Validate form data

Filling out web forms should be easy and secure. When the user enters data, the web application should check to verify that the data is correct, and if it is, the application should allow the data to be submitted to the server and then to the database. If the data is not correct, the application should generate an error message.

Validation protects the user’s account information and prevents user errors like incorrectly entering data or forgetting to input data at a required field. Server-side validation is important to protect against malicious users, who can easily bypass client-side validation by injecting malicious scripts into the server.

Establish strategies against harmful user input

Never assume that user entries are secure. Malicious users can use these assumptions to send harmful information to your application. The following rules can help protect the application from harmful entries:

  • Never display unfiltered user entries. Before displaying unreliable information, encode HTML to convert the potentially harmful script into display random
  • Never store unfiltered user entries in a database.
  • If you want to accept data from a user, filter it In its filter, it explicitly defines the elements to be accepted.

If possible, do not store confidential information in a location accessible from the browser; such as a hidden field or a cookie.

Validate uploaded files

When accepting file uploads from a user, make sure to validate the size of the file, the file type,  and the file contents; and ensure that it is not possible to override the destination path for the file. 

Use the nosniff header for uploaded content

Applications that host content uploaded by the user; either PDFs, docXs; which can be viewed by other users, use the X-Content-Type-Options: nosniff header so that browsers do not try to guess the data type. Browsers can be tricked into displaying the data type incorrectly (e.g., showing a GIF file as HTML). The server or application should determine the data type

Validate the source of input

The input source must be validated. For example, if input is expected from a POST request, input variables from a GET request should not be accepted.

Prefer whitelists over blacklists

Data entered into user input fields should be validated. Whitelisting input is the preferred approach. Only accept data that meet a certain criterion. For input that needs more flexibility, blacklisting can also be applied where known bad input patterns or characters are blocked.

Use parameterized SQL queries

When queries are being made to a database, the user’s content and the query should be passed into a variable. Queries written this way are safe against SQL injection attacks.

Example: ‘select * from orders where order_id = :ord;’ should be used instead of ‘select * from orders where order_id = 1234;’ where the ‘1234’ is stored in ‘ord’.

Conduct contextual output encoding

All data should be encoded before beint sent to the user. Each piece of data should be encoded based on the according of its usage. For example, data placed in the URL context must be encoded differently than data placed in a JavaScript context within the HTML page.


Managing Credentials

Don’t hardcode credentials

Never allow credentials to be stored directly within the application code. This can be convenient to use for testing application code during development, but it significantly increases risk and should be avoided after the code is in production.

Use secure key management processes

When keys/access credentials are stored in your system, they must be secured and only accessible to authorized users.

Securely store user passwords

Storing user passwords in a plain-text format is insecure and can allow passwords to be viewed or collected by unauthorized individuals. To prevent hackers from getting access to passwords, store a representation of the password by converting the password into a unique string of text to be stored in the database by hashing or salting (appending a string of text to the password before hashing).

Disable data caching

Computers store some website data to a temporary memory storage area. This makes it easier and faster to access the data when the user requests in the future. Disabling data caching instructs the browser not to cache sensitive data like user credentials.

Store database credentials securely

Database credentials must be stored in a central location, that is hashed, to prevent attackers from gaining access to it.


Session Management

Ensure that session identifiers are sufficiently random

Session tokens must be generated by secure random functions and must be of sufficient length to withstand analysis and prediction.

Regenerate session tokens

Session tokens should be regenerated when the user authenticates to the application and when the user’s privilege level changes. Additionally, the session token should be regenerated if the encryption status changes.

Implement an absolute session timeout

Inactive or idle users should be automatically logged out of the application after a predetermined amount of time; i.e. 30 min. There is a higher risk of a session being hijacked by when a valid authenticated user remains idle for an extended period of time.

Destroy sessions at any sign of tampering

Unless the application requires multiple simultaneous sessions for a single user, implement features to detect session cloning attempts. When the system detects that two users are using the same session ID’s, the sessions should be destroyed and the users should be logged out of the application forcing reauthentication.

Invalidate the session after logout

When a user logs out of an application, the assigned session ID and any corresponding data communicated based on that session ID must be destroyed. This ensures that the session cannot be accidentally revived.

Place a logout button on every page

The logout button or logout link should be easily accessible to users on every page after they have authenticated.

Implement account lockout against brute force attacks

User accounts should be automatically locked out after several unsuccessful login attempts. Accounts should remain locked until the user completes the prescribed steps for resetting the password or unlocking the account. Unsuccessful login attempts should receive a generic failure message like “Username Incorrect” to prevent the attacker from harvesting usernames.

Use tokens to prevent forged requests

To prevent Cross-Site Request Forgery attacks, embed a random value that is not known to third parties into the HTML form. This CSRF protection token must be unique to each request. This prevents a forged CSRF request from being submitted because the attacker does not know the value of the token.

Return to Web Application Security.