Uploaded image for project: 'Rules Repository'
  1. Rules Repository
  2. RSPEC-5344

Authentication should not rely on insecure "PasswordEncoder"

    Details

    • Message:
      Use secure "PasswordEncoder" implementation.
    • Default Severity:
      Critical
    • Impact:
      High
    • Likelihood:
      Low
    • Default Quality Profiles:
      Sonar way
    • Covered Languages:
      Java
    • Irrelevant for Languages:
      ABAP, APEX, C#, C, C++, Cobol, CSS, Flex, Go, HTML, JavaScript, Kotlin, Objective-C, PHP, PL/I, PL/SQL, Python, RPG, Ruby, Rust, Scala, Solidity, Swift, T-SQL, TypeScript, VB.Net, VB6, XML
    • Remediation Function:
      Constant/Issue
    • Constant Cost:
      30min
    • Analysis Level:
      Semantic Analysis
    • Analysis Scope:
      Main Sources
    • CWE:
      CWE-328, CWE-327
    • OWASP:
      A2, A6
    • SANS Top 25:
      Porous Defenses
    • FindSecBugs:
      WEAK_MESSAGE_DIGEST_MD5, WEAK_MESSAGE_DIGEST_SHA1

      Description

      Storing users' passwords in clear-text in a database is definitely not safe as hackers may have read access to all user accounts stored in the database. It's common then to hash passwords and only store these hashes in the database. When running the authentication process, the hash of the password provided by the user is compared to the hash stored in the database. If both matches, the access is granted.
      This looks like a perfect solution but some algorithms such as MD5 and its successor, SHA-1, are no longer considered secure, because it is too easy to create hash collisions with them.
      That is, it takes too little computational effort to come up with a different input that produces the same MD5 or SHA-1 hash, and using the new, same-hash value gives an attacker the same access as if he had the originally-hashed value. This applies as well to the other Message-Digest algorithms: MD2, MD4, MD6, HAVAL-128, HMAC-MD5, DSA (which uses SHA-1), RIPEMD, RIPEMD-128, RIPEMD-160, HMACRIPEMD160.

      For this reason, when PasswordEncoder is used to authenticate user in a Spring application, it should use a secure algorithm. The following algorithms are considered not safe and should not be used:

      • org.springframework.security.authentication.encoding.ShaPasswordEncoder (Spring Security 4.2.x)
      • org.springframework.security.authentication.encoding.Md5PasswordEncoder (Spring Security 4.2.x)
      • org.springframework.security.crypto.password.LdapShaPasswordEncoder (Spring Security 5.0.x)
      • org.springframework.security.crypto.password.Md4PasswordEncoder (Spring Security 5.0.x)
      • org.springframework.security.crypto.password.MessageDigestPasswordEncoder (Spring Security 5.0.x)
      • org.springframework.security.crypto.password.NoOpPasswordEncoder (Spring Security 5.0.x)
      • org.springframework.security.crypto.password.StandardPasswordEncoder (Spring Security 5.0.x)
      • org.springframework.security.crypto.scrypt.SCryptPasswordEncoder (Spring Security 5.0.x)

      Consider using safer alternatives, such as org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder (preferred) or org.springframework.security.crypto.password.Pbkdf2PasswordEncoder.

      Noncompliant Code Example

          @Autowired
          public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
              auth.jdbcAuthentication()
                      .dataSource(dataSource)
                      .usersByUsernameQuery("SELECT * FROM users WHERE username = ?")
                      .passwordEncoder(new StandardPasswordEncoder()); // Noncompliant
              // OR
              auth.jdbcAuthentication()
                      .dataSource(dataSource)
                      .usersByUsernameQuery("SELECT * FROM users WHERE username = ?"); // Noncompliant; default uses plain-text
              // OR 
              auth.userDetailsService(...); // Noncompliant; default uses plain-text
              // OR 
              auth.userDetailsService(...).passwordEncoder(new StandardPasswordEncoder()); // Noncompliant
          }
      

      Compliant Solution

          @Autowired
          public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
              auth.jdbcAuthentication()
                      .dataSource(dataSource)
                      .usersByUsernameQuery("Select * from users where username=?")
                      .passwordEncoder(new BCryptPasswordEncoder());
              // or 
              auth.userDetailsService(null).passwordEncoder(new BCryptPasswordEncoder());
          }
      

      See

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                Unassigned
                Reporter:
                alexandre.gigleux Alexandre Gigleux
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated: