Open Mobile Menu


Five Things Every Web App Tester Wished Developers Knew

Views: 2853

Written By: Stephen Haywood October 22, 2015

I Am On Your Side

As a developer, you’ve honed your craft through seemingly endless months/years of long hours. Constantly learning new languages, techniques, and frameworks. As an application tester, I’ve done the same thing. Constantly learning new languages, new frameworks, and new techniques. The only real difference is our perspective. I know that you’ve poured your blood, sweat, and tears into this application and I know it feels like I am calling your baby ugly, but the truth is we have the same goal: to provide your users with a safe, usable experience.

In your quest to become a developer, you have learned to see all of the great beauty that is possible. However, my quest has led me to see all of the underlying flaws and potential failings. When we use our strengths together, we can build the Sistine Chapel but when you ignore my strengths, we often end up with the leaning tower of Pisa.


Encryption and Hashing Are Not The Same

Encryption is a two-way function designed to allow plain text to be scrambled and unscrambled using a key. Anyone who holds the key can unscramble the encrypted text to reveal the plain text. Hashing is a one-way function designed to take an arbitrary amount of data and reduce it to a representative value of a fixed size. When passwords are encrypted it means they can be decrypted using the key. Often if a password database is compromised the encryption key is likely compromised as well. When a password is properly hashed it is nearly impossible to reconstruct the password based solely on the hash.

Passwords should always be hashed with a unique salt value using a hashing algorithm designed for passwords. The three major algorithms available right now are bcrypt, scrypt, and PBKDF2. Each one of these algorithms is designed to take a password and a salt value then produce a hash. The true beauty of these algorithms is that they can be configured to make it increasingly harder to produce the original plaintext knowing only the hash. So over time as computing power increases and cracking password hashes becomes easier, the algorithms can be modified to continue protecting the passwords.


Users Can Not be Trusted

People are not rational and they are not perfect, which means you can never trust a user to give you valid input. Even if a user has no malicious intent, mistakes happen and invalid data will eventually be entered into your application. Your application should be designed to handle this. Further, your application should be designed to handle a malicious user who is purposely entering invalid input into your application.

The best form of data validation is white listing acceptable values. If your application is expecting a user to enter a phone number then only allow the user to enter digits, +, ., -, (, and ), all of which are commonly found in phone numbers. There is no reason to allow any other characters. When validating input, it is faster to validate it on the client side but the data must be validated again on the server side because there are many techniques for bypassing client-side validation.

There will be times when you must accept dangerous characters such as <, >, \, “, ‘, and &. These characters should be encoded before being stored in the database and they should be encoded for the appropriate output context. For example in HTML the double quote should be encoded as &quot; but in JSON data it should be encoded as \”. User data should never be stored or reflected back to the user without proper encoding.

In addition to validating and encoding user input, always use parameterized queries to query a database. Database requests should never be constructed directly from user input.


Sessions Should be Managed

This means they should only be created when needed and should be destroyed when not needed. A new session should be created each time a user logs in because if the same session ID is used before and after login, then an attacker may be able to gain authenticated access to the application using only the captured session ID. This is particularly important when sites allow unencrypted connections before login, which makes it easier for an attacker to capture the user’s session ID. In addition, when a user logs out of the application or when their session has been idle for too long, the session should be destroyed on the server side so that an attacker cannot reuse any captured session IDs or access an idle account when the user is no longer around.

All session data should be stored on the server with only a session ID stored on the client side. User credentials and other sensitive data should never be stored in a session ID. If the session ID is compromised, an attacker may be able to use the stored data to compromise the account.

Finally, session IDs should only be sent via headers or via hidden fields in POST requests. They should never be sent as parameters of a GET request because requested URLs are often logged by the web server and if the session ID is sent as a parameter in the GET request, then the session ID will be logged.


Always Use TLS

The Internet is a large network of interconnected computers. Data transmitted from your users will pass through many other networks before it arrives at your server. The owners of those networks can and likely are making copies of the data that flows through their networks. Your users’ data is important and should be protected from eavesdroppers. This is why Transport Layer Security (TLS) is so important. When used properly, TLS encrypts all of the data sent between your user and your server so that eavesdroppers, including government agencies, cannot decrypt the data.

To provide the most protection for your users, configure your web server to only use an HTTPS connection. If a user attempts to make an HTTP connection they should be redirected to the appropriate HTTPS page. In addition, set the Strict-Transport-Security header to tell the browser that your site should only be accessed via HTTPS.

In addition, configure your site to only accept TLS connections, Secure Sockets Layer (SSL) is deprecated and should not be used. You should also configure your server to only use strong TLS algorithms that support Perfect Forward Secrecy. This ensures that even if an attacker is able to decrypt some data in a session they will not be able to decrypt the entire session or previous sessions.

Stephen Haywood

Stephen Haywood, aka AverageSecurityGuy, is a Senior Penetration Tester with AppSec Consulting with 14 years of experience in the Information Technology field working as a programmer, technical trainer, network operations manager, and information security consultant. He holds a Bachelor of Science in Math, the Certified Information Systems Security Professional (CISSP) certification, the Offensive Security Certified Expert (OSCE) certification, and the Offensive Security Certified Professional (OSCP) certification. Over the last eight years, he has helped improve the network security of many small businesses ranging in size from ten employees to hundreds of employees by offering practical, time-tested information security advice.

In his off hours, Stephen created a number of security tools including the Prometheus firewall analysis tool and a set of penetration testing scripts used by testers worldwide. In addition, Stephen has made multiple contributions to the Metasploit exploitation framework including, auxiliary, exploitation, and post exploitation modules. Finally, Stephen created and delivered high-quality security training, spoke at multiple security conferences, and self-published an introduction to penetration testing book.

read more articles by Stephen Haywood