Anatomy of a Web Application Compromise - Part 6: Lessons Learned

Aug 01 2011

One of the most important parts of a penetration test is to take a step back afterwards and look at the big picture. What were the root causes that allowed the compromise to take place? How can the system be better protected against such attacks in the future? In closing this series, we will show you how to address the specific security issues that allowed our attack to succeed, divided into three main categories: initial exploit, escalation, and data security.

This is the last entry in a series of six blog posts; the previous post was Part 5: Data Exfiltration.

Initial Exploit

A combination of factors came together to allow for the initial exploit to take place. If any one of these had not been in place, the compromise would have been either significantly harder or next to impossible.

  • Disable web server directory indexes (file listings), and don't disclose version information.
  • Audit your systems against published vulnerabilities and update as soon as new versions are available.
  • Remove sample code from the web server root, especially third-party code.
  • Don't allow debug level control via URL parameters (this is what allowed us to see the command output that normally would not have been shown).
  • When calling external software on the server, use standard APIs whenever possible rather than building command-line strings that can be vulnerable to command injection. For example, PHP provides an ImageMagick library that allows direct API calls to be made.
  • Never store your logs inside the web server root, especially at an easily-guessed URL like /logs. All logs should be stored in their standard location outside the web server root (such as /var/log) and have the proper permissions set to prevent unauthorized viewing or tampering.
  • Log and frequently audit all system commands executed by your web applications (assuming that no API is available and you must use system commands). If you know that your application should only be calling certain commands, then seeing a lot of unexpected commands (see Part 4: Expanding Access) would immediately be suspicious.

Escalation

While the initial compromise was significant, the damage was contained to the web server. There were a few key factors that allowed us to very quickly expand our limited access to full system administrator access.

  • Don’t use the administrator (root) database account. Instead, have multiple application-specific accounts with limited privileges to only one database (or even at the individual table level).
  • Don’t reuse passwords across systems. Database passwords are particularly insecure since they often need to be stored unencrypted in a configuration file. In these cases, generate a random, unique password that is only used for this application's database account.
  • Don’t enable root logins directly via SSH; instead require an unprivileged user login followed by sudo to perform administrative functions. This has the additional benefit of logging all administrative commands performed via sudo.
  • Set up comprehensive system logging and perform regular audits of the logs. This will help detect any rogue logins, use of backdoor accounts, suspicious web server requests, etc.

Data Security

Once we had gained complete system and database access, there was still one additional protection in place for the passwords stored in the database: they were hashed using the MD5 algorithm. Unfortunately, this protection proved to be ineffective since the hashes were easily reversible using rainbow tables. If the guidelines below had been followed, cracking passwords would have been significantly harder.

  • Encrypt sensitive data in the database with a unique key for each user. One way of implementing this is to link the encryption and decryption of a user’s data to his account password. This way, even if a user gets full access to the back-end database, he will not automatically have all of the data unless he can crack the users’ passwords too.
  • Don’t use simple MD5 hashes for passwords, which can be cracked quickly in bulk using rainbow tables. Instead, use salted hashes and key stretching to slow down bulk hash cracking efforts.
    • Salting adds a random value to each hash, making it unique and exponentially multiplying the resources required for cracking.
    • Key stretching refers to the practice of running the data through the same hash algorithm multiple times (for example, the MD5-Crypt algorithm used by most Linux systems uses 1,000 iterations of MD5), which also requires an attacker to perform the same number of iterations for each hash being calculated, slowing him down significantly.
    • The following Wikipedia article explains both practices in more detail: http://en.wikipedia.org/wiki/Rainbow_table#Defense_against_rainbow_tables
  • Enforce password length and complexity standards when users set and change their passwords. Increasingly, password length is becoming the key factor, and anything under eight characters should be considered very insecure. If rainbow tables are available for a particular hash type (and it’s not salted correctly), password complexity does not matter at all since all possible combinations (up to a certain number of characters) are reflected in the tables.

Conclusion

This series has been an introduction to the mindset and toolkit of the malicious attackers who may be out to break into your applications and data. We hope you’ve enjoyed learning about the process of penetration testing and the technical details of this specific attack. More importantly, we hope that the lessons learned in this last post will help you improve your organization’s security posture, both through general awareness and specific technical best practices.

Disclaimer: The work described in this series was performed with the full knowledge and consent of the target organization. Unauthorized access to computer and network systems is illegal in most jurisdictions, so don't try this at home without the proper consent!

About the Author

Daniel is a business and technical systems analyst with a background in IT security and software development. He has six years experience in the IT security field, including published academic research. His main areas of expertise include software assurance, network security, and authentication. In addition to security, Daniel has a software development background in languages such as Java, Perl, SQL, and PHP. He also has 14 years experience working with and administering various versions of Linux and related open-source software.

 

Disclaimer

The words and opinions expressed here are those of each article's respective author, and do not necessarily represent the views of CapTech Ventures.