-
Notifications
You must be signed in to change notification settings - Fork 0
guide security quick S2 Basic Authentication Security
Authentication answers the question, weather "user is who he claims to be". Focus of this solution is the implementation
All pages, functions and resources that require authentication - enforce authentication.
Purpose: Misconfiguration around authentication controls may result in confidential data being exposed to anonymous users.
Solution (Java-based): Create a configuration class that inherits from WebSecurityConfigurerAdapter
and overrides the configure(HttpSecurity) method. Following example is taken from the devonfw sample application (class io.oasp.application.mtsj.general.service.impl.config.BaseWebSecurityConfig:
String[] unsecuredResources = new String[] { "/login", "/security/*", "/services/rest/login",
"/services/rest/logout", "/services/rest/dishmanagement/*", "/services/rest/imagemanagement/*",
"/services/rest/ordermanagement/v1/order", "/services/rest/bookingmanagement/v1/booking",
"/services/rest/bookingmanagement/v1/booking/cancel/*",
"/services/rest/bookingmanagement/v1/invitedguest/accept/*",
"/services/rest/bookingmanagement/v1/invitedguest/decline/*",
"/services/rest/ordermanagement/v1/order/cancelorder/*"};
http.antMatchers(unsecuredResources).permitAll().anyRequest().authenticated();
This approach is a nice example how to implement authentication to be secure by default. Every new functionality will be automatically protected unless an explicit exception is added to unsecuredResources variable.
of secure authentication functions.
Solution (xml based): In Java applications relying on the Spring Security framework (like devonfw does) the need for authentication can be configured in the file beans-security.xml. Following example is taken from the devonfw sample application.
<bean id="FilterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="AuthenticationManager"/>
<property name="accessDecisionManager" ref="FilterAccessDecisionManager"/>
<property name="securityMetadataSource">
<security:filter-security-metadata-source use-expressions="true">
<security:intercept-url pattern="/" access="isAnonymous()"/>
<security:intercept-url pattern="/index.jsp" access="isAnonymous()"/>
<security:intercept-url pattern="/security/login" access="isAnonymous()"/>
<security:intercept-url pattern="/j_spring_security_login" access="isAnonymous()"/>
<security:intercept-url pattern="/j_spring_security_logout" access="isAnonymous()"/>
<security:intercept-url pattern="/services/rest/security/v1/currentuser/" access="isAnonymous() or isAuthenticated()"/>
<security:intercept-url pattern="/" access="isAuthenticated()"/>
</security:filter-security-metadata-source>
</property>
</bean>
In the example we use expression language use-expressions="true" like isAuthenticated() or isAnonymous() to decide, weather the resource identified by the given pattern requires authentication or not.
The last line of the filter configuration defines a pattern / catching all remaining resources and enforcing authentication. This secure default ensures all new pages and resources created by the developers are protected, and all exceptions to this rule must be explicitly added to the configuration.
All user passwords are protected with a strong one way hashing function which incorporates salt and a properly configured work factor.
Purpose: Holding passwords for user accounts in plaintext creates many problems with trust (to e.g. system administrators, developers), backups (data can leak), and raises the criticality of every possible data breach. Passwords need to be hashed with a strong key derivation function like bcrypt, scrypt or PBKDF2 which automatically will include salt. A work factor needs to be calculated and properly set as well, as it mitigates some threat of brute force attacks.
Solution: Spring Security offers its own bcrypt implementation to deal with password hashing issues. An example configuration (which uses in-memory authentication in this case) can look like this:
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder(10))
.withUser("waiter").password("$2a$10$n5UZipMzWmYB18AWbyZES.t9FDJP/9OFp8hKI1rzol6gn/2hVZYE2").roles("Waiter")
and().withUser("user0").password("$2a$10$atp6JC.anPKGhNwc1dEK0OQFzPr3/5moIm7bF1i2yBHXFKpA7YMb2").roles("Customer");
NOTE:
-
The work factor (passed as a parameter to
BCryptPasswordEncoder, which equals 10 in our example) defines the amount of work (as result time) needed to calculate the digest. Incrementing the value by one means multiplication of the work amount by two. -
Work factor = 10 means calculation of the hash lasting about 80ms on a Lenovo P50 machine (which should be good enough for the purpose of online user authentication). Work factor = 11 would result in the calculation lasting about 170ms on same machine.
-
To high work factors will raise the threat of DOS attacks on the authentication functionality. Too low work factor will not offer enough protection.
-
For the purpose of storing hashes in the system they need to be calculated first. Following code can help to do that:
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(10); String digest = encoder.encode("put the password here"); System.out.println(digest); -
Although the passwords are hashed with a one-way function, it’s still not allowed to expose them in logs, APIs or forms. Digests will only slow down an attack to crack the hashes, not prevent it.
All authentication controls are enforced on the server side.
Purpose: An attacker has the ability to bypass any security control on the client side. Because of this it is crucial to implement authentication controls on the server side.
Solution: Secure by design. In the devonfw architecture it is always the server side which is responsible for the authentication. The developers must not bypass the authentication functions in any way.
All authentication controls fail securely.
Purpose: There are many things that can go wrong around authentication from the business or technical perspective. It is crucial that authentications never fail open (which is the opposite from fail secure - users get access to the application despite authentication failure). It is also necessary to prevent any exposure of stack traces (reveals internal system information to the attacker; → TODO) or username enumeration (→ S2-7) possibilities.
Solution: Spring Security handles the technical security aspects of this solution well (prevents timing attacks to enumerate usernames, prevents SQLi, and other). The developer must just handle the displaying of the error message properly.
Credentials, and all other identity information handled by the application(s), do not traverse unencrypted or weakly encrypted links.
Purpose: TCP/IP networks are insecure by default. Any kind of information that travels over insecure channel (HTTP instead of HTTPS) may be revealed to local or (sometimes) remote attackers without the user notice.
Solution: The application on the integration and production environments must always protect the connection with TLS (→ TODO). Ideally the unencrypted HTTP protocol is turned off. If for some reason the unsafe HTTP connection is needed, the server must enforce the authentication dialog and all pages within the session to be served only via TLS. This can be achieved by setting the attribute requires-channel="https" of the element security:intercept-url. In the Java-based Spring Security configuration the relevant part of code looks like this: http.requiresChannel().antMatchers("/*").requiresSecure() For more information see this tutorial.
All sensitive information (including credentials) must only be passed in the HTTP message body, never in the URL. This prevents the sensitive information from being stored in browsers history or in logs on the web server.
The forgotten password function and other recovery paths do not reveal the current password and the new password is not sent in clear text to the user.
Purpose: Passwords are very sensitive. If the user can recover his password from the system, the attacker will be able to recover users password as well.
Solution: Passwords need to be protected using a one-way hashing function (→ S2-2). This way, once they are set, they can not be revealed any more.
Username enumeration is not possible via login, password reset, or forgot account functionality.
Purpose: If the the system is protected by username and passwords, the attacker must know both to gain access. Although username is not sensitive data, it still should not be revealed over the app functionality, as this would unnecessarily support the attacker.
Solution: Prevention of username enumeration can be a tricky thing to do. Not only must the application respond to login attempts in a manner that does not reveal the information, whether the user exists or not. It must also prevent timing attacks that can reveal the information in an indirect way (see this). Note following:
-
User authentication in the devonfw applications is handled by Spring Security. We expect Spring to do it right.
-
Functionality like password reset or password change needs still to be implemented by the developers in a correct manner that does not leak information to the attacker.
-
It can be a challenge to implement the functionality of creating a new user account in a way that does not allow username enumeration (the app usually asks for the username in the very first dialogue window and then automatically reports whether this name is free or taken). One of the ways to tackle this problem is to:
-
Ask for username (usually a mail).
-
Send a mail to the user with the link to a page to continue the registration process OR send a mail stating that the account already exists.
-
There are no default passwords in use for the application framework or any components used by the application.
Purpose: The attacker can try to access the system by brute forcing user account credentials. But he can also try to access the database (or other services) directly by brute-forcing the DB user credentials.
Solution: This is not an issue one can solve with technology or frameworks. Treat is as a non-functional requirement in the development and deployment process not to use passwords like admin, password, 12345 or any password from e.g. Adobe top 100 passwords list.
Password entry fields allow, or encourage, the use of passphrases, and do not prevent password managers, long passphrases or highly complex passwords being entered.
Purpose: For some reason sometimes systems prevent users from entering passwords longer than 8 characters. This weakens the systems protection and opens door to brute force attacks. Other reasons for allowing long passphrases document this xkcd cartoon below: ! XKCD passwords
Solution: Spring Security will not prevent the usage of password managers or long passphrases. This is a nice secure default.
Account identity authentication functions (such as update profile, forgot password, disabled / lost token, help desk or IVR) that might regain access to the account are at least as resistant to attack as the primary authentication mechanism.
Purpose: Rather obvious: The chain is as strong as the weakest link. The attacker will choose the easiest path to gain access to the system.
Solution: Requirement not supported by the devonfw platform, as it addresses topics of business processes and functionality of the system. Treat this as a non-functional requirement to be included in the applications design phase.
The changing password functionality includes the old password, the new password, and a password confirmation.
Purpose: Some critical system functionality may re-authenticate the user before performing the task. This is done to prevent that someone changes the users password by gaining physical access to his machine in the short moment the user is away or distracted.
Asking the user for the password twice is done to prevent the user from losing access to the system because of a misspelled password or passphrase.
Solution: Spring Security does not support this functionality. It needs to be implemented by the developer this way.
Anti-automation is in place to prevent breached credential testing, brute forcing, and account lockout attacks.
Purpose: Even without any knowledge of the system, attackers may try to brute force the users credentials. On the other side, even without knowing the users credentials, the attacker can try to lock out valid users from accessing the system by triggering account lockouts due to brute forcing.
Solution: Protection from brute force and DOS attacks is one of the hardest problems in Application Security. There is a big gap between how easy it is for the attacker to run such attacks, and how hard it is for a developer to implement proper security controls.
This issue can be handled in many different ways. One of the common approaches is to use a Web Application Firewall (WAF) and configure it properly. But some security controls can also be implement by using Spring Security features.
Forgotten password and other recovery paths use a TOTP or other soft token, mobile push, or other offline recovery mechanism. Use of a random value in an e-mail or SMS should be a last resort and is known weak.
Purpose: If your password recovery mechanism is weaker then your authentication, then the attacker will use this way to gain access to your system.
Solution: Requirement not supported by the devonfw platform, as it addresses topics of business processes and functionality of the system. Treat this as a non-functional requirement to be included in the applications design phase.
If shared knowledge based questions (also known as "secret questions") are required, the questions do not violate privacy laws and are sufficiently strong to protect accounts from malicious recovery.
Purpose: If your password recovery mechanism is weaker then your authentication, then the attacker will use this way to gain access to your system.
Solution: Requirement not supported by the devonfw platform, as it addresses topics of business processes and functionality of the system. Treat this as a non-functional requirement to be included in the applications design phase.
Verify that measures are in place to block the use of commonly chosen passwords and weak passphrases.
Purpose: If you allow the users of your application to choose any password they want, you will end up with ~2% of all system accounts protected by passwords like password, 12345 or abc123. (Read more)
Solution: There are many solutions how to tackle this problem. This article offers one of them.
This documentation is licensed under TODO License (CC-ND?, proprietäre Lizenz?)