Guide For QA Engineers and Testers: What To Know About Passwords

Konstantin Sakhchinskiy
8 min readJul 23, 2024

--

I would like to discuss different stuff regarding passwords that are used in an app and mechanisms that have to be considered, implemented, and properly tested in the app’s features where user passwords are involved. You can use it as a checklist and source of advice for further consideration of some features and policies.

It’s important to remember that sometimes implemented security features are overkill for a particular app, which can negatively impact the user experience, and frustrate and annoy users. It’s important to keep in mind that maximum security isn’t always necessary and that security mechanisms should be easy to understand and use, as they are also features for users. However, security has never should be sacrificed for the sake of UX, you just need to use a reasonable approach and evaluate all potential security risks.

I’m writing this as a QA Engineer for QA Engineers and Testers not as a cybersecurity consultant so these are my recommendations that have to be discussed with a cybersec professional and your team to understand if they are valid for your particular situation.

Policies

  • The application should enforce the minimum length of passwords — shorter than 8 characters are considered to be weak.
  • Password has to be valid for a particular period (e.g. 3, 6, 12 months) and then have to be asked to change for a new one (this is quite a strict requirement so maybe not all products need this).
  • The login and password values shouldn’t be the same.
  • Maximum password length should not be set too low. A common maximum length is 64 characters. Set a maximum password length to prevent long password Denial of Service attacks.
  • Most special characters shouldn’t be forbidden in passwords. If users want to use secure strong passwords even if there is no need for such a level of security they have to be able to do so.
  • Enforce/encourage usage of difficult passwords (numbers, upper and lower case letters, special symbols). Have a tip and have strict validation for this, and show error messages if needed (this is also quite a strict requirement, and for some products usage of any special characters shouldn’t be forbidden but shouldn’t be mandatory).
  • As far as I know, it’s typically not recommended to support non-lating alphabet letters but so far I don’t have any strong security reasons not to do so. So maybe think about your particular implementation and decide if you need it or not.
  • Forbide using previous passwords — when users change their password for some reason they shouldn’t be able to use the old previous password. Also, the validation may check that the diff level (new vs old pass) is bigger than just 1 (or more) symbol (it’s strict and complicated and not applicable and beneficial for many products, so consider using maybe the only 1st part of this recommendation).
  • If your system has temporary passwords, after password reset users have to be forced/encouraged (depending on the needed security level) to change their temporary password (which they got via email). Make it valid for a particular short period or immediately ask the user to change it, for example, by restricting full access to the app without doing so (if needed).
  • You can add a password strength meter to help and encourage users to create more complex passwords and block common and previously breached passwords (for instance zxcvbn-ts library can be used for this purpose or Pwned Passwords is a service where passwords can be checked against previously breached passwords).

Features

  • Require re-authentication for sensitive features.
  • All validations, policies, and restrictions have to be implemented not only on the client but on the backed side.
  • Use cooldowns and rate limits for attempts with incorrect passwords for all features with passwords — login, change password, reset the password, and confirmation for sensitive operations with a password. Prevent brute force attacks when it’s possible, through many attempts it’s possible to find the right password. The same should be implemented for features where logins can be enumerated.
  • Do not show in any way (in UI or API responses) if the email is already registered (but I assume for some apps it might be considered as a bad UX and in some circumstances such errors can be shown, but consider this carefully). In this case, you can send the appropriate email with instructions. The goal is to prevent email enumeration.
  • Never shows what is incorrect login/email or password on the login screen — the error has to be general, which means it shows that the credentials are invalid (remember to check that the system doesn’t return this info in BE responses).
  • Check that there is no technical info in BE responses or significant differences in response time that may help to understand whether the email/login or password was incorrect. For example, responses may contain different errors for different cases, even if they are technical messages, because by doing a couple of tests we can find out that one error message is for an incorrect email and another one is for a valid email but invalid password.
  • Never transmit passwords as plain text over the network. Use HTTPS to protect the data in transit.
  • Avoid using GET requests to send passwords, URL query parameters can be logged in server logs or browser history. Use POST requests with the body of the request encrypted via HTTPS.
  • Do not store passwords or their hashes on the client side, such as in local storage, session storage, or cookies. If needed, consider using secure, HTTP-only cookies that are not accessible via JS, and always transmit these over HTTPS to store some auth tokens on the client side.
  • Use modern, secure hashing algorithms like Argon2, bcrypt, or PBKDF2. These algorithms are designed to be to resist brute-force attacks. Store the hash, along with a unique salt for each password, in the DB. Salts should be random and at least as long as the hash function’s output. Optionally add a secret value added to the password before hashing. The values are not stored in the DB but kept securely on the server - an additional layer of security (if needed).

NOTE: encryption and hashing algorithms are not easy stuff to understand for QA and testers (personally, I don’t know the details) and it might be a challenge to test but it’s important to understand the basics and have a checkbox to ask questions and discuss the implementation with devs/security testers. It’ll help the team to avoid some mistakes and notice that something is off. You can check many mentioned things by yourself, and by dealing with hashes and encrypted values and knowing the approach you can try to find a simple way to get the password values. This won’t guarantee that the approach is fully secure but at least you can try to eliminate the most obvious flaws. No one expects that as a tester you will be able to brake or asses properly encryption and hashing algorithms.

  • Integration of external services — if using 3rd party authentication services like OAuth, OpenID Connect, or SAML for authentication, usually ensure thorough testing of these integrations. However, it’s important to check for any vulnerabilities introduced by these external services, especially in how tokens and credentials are handled and stored. Thoroughly check the integration with such services so that there are no breaches on your side.

Additional Security Features

  • For higher security implementation of 2FA with OTP codes (on email/phone or by using authenticator apps) might be considered. It might be optional but if you have it in your app and it’s optional then it’s better to encourage users to use it. Test them thoroughly for all mentioned issues such as brute force and login enumerations.
  • Biometric authentication can also enhance security and user experience by providing a seamless yet secure login process.
  • Timely notifications about upcoming password expirations, changing and/or resetting passwords, turning off any additional/second authentification factors, attempting too many times to log in with invalid credentials, using old passwords, getting login attempts cooldowns, accessing data/account from new/unknown device/location, etc.
  • You can use security questions as an additional secure authentication factor. If security questions are used, test for the strength and privacy of these questions. The same principles as for password storing, transmitting, checking, and verifying, cooldowns, rate limits, and notifications have to be implemented for security questions. Avoid common questions whose answers may be easily guessed or found through social media. Consider allowing users to create their own questions.
    Personally, I’m not a fan of this mechanism (as a user, from the UX standpoint). It’s not commonly seen nowadays and seems less user-friendly and secure compared to 2FA OTP codes. However, I also can’t say that this mechanism shouldn’t be used at all as an additional or optional layer of account protection.

Rate limits testing

If your application has basic features like login, registration, password reset/recovery, resending confirmation links, and other specific functionalities requiring server requests, it’s crucial to implement mechanisms against brute force attacks. Without such mechanisms, your application may be vulnerable to various threats, including sending an excessive number of emails/OTPs to users, potentially leading to harmful consequences for a business.

Many web apps lack adequate rate-limiting measures, relying solely on the limitations imposed by their business logic, such as restricting the number of requests. Some apps have rate limits only for some actions like login attempts, registration, and maybe some other critical features (not only features where passwords are involved). These implementations often depend on the IP address tracking (e.g. using an X-Forwarded-For header) that can be implemented in a not-very-secure manner which will lead to possible brute-force attacks.

You can read the detailed guide on testing for this issue here: https://hackernoon.com/defending-your-web-app-a-guide-to-rate-limiting-and-brute-force-attack-prevention

NOTE: When implementing such a defense mechanism, perform thorough testing. This approach might be subsequently applied to the entire cluster and affect certain functions and microservices where it is unnecessary. In a nutshell, while fixing a security breach, be cautious, as it could potentially impact the entire application negatively and break some features. Analyze which part of your system might be affected negatively and test everything before shipping changes to the prod env.

You can find more details and examples on this topic in the eBook: https://huddle.eurostarsoftwaretesting.com/resources/test-management/the-ultimate-web-security-testing-handbook-for-qa-and-testers/. There are lots of other useful for QA professionals and Testers stuff, so check this out if you want to learn more about vulnerabilities. Also, you can find lots of useful guides and info in the QA field on my website: https://softwareqa.io/publications

Remember, always conduct penetration testing with explicit permission (notification) and/or within a controlled environment. This approach ensures that your tests align with responsible testing procedures, preventing inadvertent compromises to systems (or users) and upholding the integrity of both the testing process, and overarching cybersecurity strategy, triggering any IPS/IDS, alerting system, and spamming live monitoring with anomaly entries.

--

--

Konstantin Sakhchinskiy

I'm a product-minded Software QA Team Lead, Engineer, and Analyst with a Master's Degree in Math (IT) and 10+ years of experience with all sorts of web apps