Secure Code Auditing is a structured approach to identifying, evaluating and mitigating programming and database security risks to web applications, databases and general network security. The majority of programmers are not security-minded, let alone security experts. Applications and infrastructure are typically designed with security vulnerabilities that can lead to security exploitations and potentially catastrophic results for your servers, network, and your business overall. When the programming team lacks security expertise and experience, and where security vulnerabilities may be an important issue for your business, a subsequent secure code audit is required. Different security consulting companies approach secure code audits differently, but essentially have the same goals in mind. This article is my description of what a secure code audit is, how we approach code inspection, and how to balance the factors that influence secure code audits.
The types and degree of security vulnerabilities to your network and applications depends on what your applications are designed to do and how good the programmers were. Threat modeling is required to develop a methodology for the approach to secur auditing, leading to the actual code inspection. Subsequentt to the process of modeling, a triage list of inspection points and points of perspective may be defined. A structured, logical and methodical approach to secure auditing is mandatory, unless the volume of code is rather small. The intensity and aggressiveness of a secure code audit depends on the risks involved, the scope of the audit based on the cost allowed, and the time allotted for completion. Obviously, a project in excess of 100,000 lines of code is radically different from a 2,000 line project. These and other factors affect the approach to code auditing and the audit timeline.
Secure Code Audit discoveries and feedback may be categorized simply:
- Security Flaws – The primary purpose of a secure code audit is to discover flaws in the programming that may be lead to security exploitations. Security flaws are introduced by programmers who do not understand security, are not educated or experienced with security programming, do not care about security, or wrote the flaws into the programming intentionally. Flaws may include the lack of data cleansing and data validation, lacking encryption, and anything that lets a hacker manipulate the web application or network in an insecure or unexpected fashion. Security flaws may be insidious, in that they may lay dormant and unrecognized in applications and networks awaiting the correct attack, even though the application is intact and fully functional.
- Security Bugs – Code-level problems such as pathway dead-ends, buffer overflows, global variable access, and missing variable handlers constitute security bugs. Bugs are introduced by programmers as a result of insufficient debugging, inept programming capabilities, poor programming and pathway definitions prior to programming, and poor team communication. Programming errors require language-specific mediation with clear understanding of the process being corrected as well as the Big Picture of the entire application.
- Programming Flaws & Bugs – Flaws and bugs that do not constitute a possible security vulnerability, but do negatively affect user interactivity, messaging, and overall application performance are important too.
- Good Programming – Especially in team environments, it is important to note areas of good programming that can be associated with particular programmers. Noting areas of good programming allows the programming team to inspect and evaluate what constitutes “secure” and “quality” programming that should be applied throughout the application.
- Bad Programming – Not so much to pass blame, as to identify the weak programmers and areas requiring attention, bad programming must be mediated for both security flaws as well as bugs. Weak programmers should be educated and some level of oversight should be instated. Areas of bad programming help define a model of what not to do for the programming team.
- Recommendations – Applications may be programmed many different ways, with the same general results. However, there are ideal methods for some processes that may increase performance, provide superior extensibility, and minimize security vulnerabilities during application expansion. “Best Practices” is a relative term, yet all programmers should aspire to improve their programming skills and spectrum of knowledge to produce better code. Recommendations range greatly from design pathway requirements to memory allocation and performance, to error handling and messaging.
Before launching a secure code audit on a large application with significant volumes of programming, a code base should be compiled and prepared for the auditing team. Auditing code is not typically performed from the user-side, but from the server-side, so every process may be inspected as closely as required. Bugs an flaws may not become apparent from the outside, requiring significant iteration before stumbling upon them. Direct code inspection of a fully operation project allows identification of bugs and flaws and defining what conditions would trigger the flaw or bug.
Code may be evaluated at different levels for categories of issues. The logical approach to methodically reviewing the code provides a structured and controlled approach, so the auditing team does not become overwhelmed or miss issues. Vulnerabilities may be categorized into the overview list below:
Configuration Management: Programming languages utilize a server-side parsing system that handles the code prior to release to the user, and the data submitted by the user to the server. During startup, the server typically reads a configuration file declaring variables, pathways, conditions, and restrictions on the parser. Configuration files can easily create conditions for security vulnerabilities and must be inspected carefully before launching the server and any applications. Default database passwords, session management and storage, and other variables can greatly affect server security. The configuration file controls how errors are handled and what responses are sent out. Debuggging may be disabled for production systems, while kpet enabled for development systems, since debugging messaging may disseminate proprietary or private information about the operating system, the parser conditions, and the application.
Cryptography and Encryption: Protecting data in-transit and between servers is often important, sometimes critical. Credit card information is a well-known issue for the banking and eCommerce communities. Encryption, such as SSL, comes in various flavors and should be defined prior to publication. Defending the privacy of the server’s private certificate is important. Enforcing SSL and encryption on public systems may be desired, if un-encrypted connections are a security risk. Served pages contianing both encrypted and un-encrypted objects may defeat the purpose the encryption as a whole, and requires content handling considerations. Encrypting data goes beyond simple SSL transactions, such as encrypting user passwords and other inforamtion before storing them in a database. Database encryption and decryption methods must be carefully considered and instated prior to publication.
Authentication: Hackers may attack an application using standard web forms and other poits of entry to the server and parser. There are multiple ways to authenticate a user, ranging from very insecure to very secure. Realm protection may generate a nice looking login box that looks secure to general users, but uses simple base64 encryption that any beginner hacker could decrypt in their sleep. Authentication should go beyond the minimum requirements and include session storage of critical data instea dof cookie storage, track IP Addresses and the user fingerprint to prevent attacks such as session hijacking, prevent multiple logins by the same user, limit the duration of the login, etc. Enforcing password updates periodically is healthy. Mandating quality passwords (sometimes user names also) helps minimize attacks such as Brute Force Attacks, such as dictionary or iteration attacks on logins. Note that Brute Force and Iteration Attacks can be somewhat mediated with fingerprinting and throttling restrictions. Blacklisting and IP Filtering may help mediate Denial of Service attacks and other attack methods.
Authorization: Controlling access to restricted and tracked application areas is important and critical. Tracking is important for operations that rely on statistical analysis of traffic to determine future efforts and current goals, etc. Preventing unauthorized access to restricted content is critical, especially for financial applications. eCommerce applications rely on privacy and authorization controls, else face potential dissolution. Most people do not want their credit card information made public or to be abused. Administration access to inventory management systems, site administration, and user profile management are just a few common aras that require valid authentication mechanisms. Maintinaing authorization control is one of the most critical application issues demanding attention and inspection.
Session Management: TMost websites today use sessions and cookies to track users, traffic, and general data objectives. Session Hijacking is a common security exploitation that renders accounts and profiles vulnerable to the whim of whoever takes control. Restricting session access to the intended admin or user can be critical for protecting proprietary information and user profiles. Especially for the financial communities, losing ctornoll of an acocunt and the funds it manages can be catstrophic not only for the individual, but devastating for the reputation of the business. Session management includes how and where the session is stored, the quality of the session ID generated, maintenance and cleanup mechanisms, and restricting session acces sby tracking IP Addresses and user fingerprints, amongst other unique identifiable user factors.
Data Validation & Data Cleansing: This is a subject any security programmer will revisit over and over… and over and over. Preventing the vast majority of code-level attacks is achieved by validating the data received by the server and cleansing it as needed. Cross Site Scripting, Code and SQL Injection, and other attacks stop dead in their tracks when the programmer has instatedd quality cleansing and validation of ALL data objects received by users and hackers alike. Everything from character substitution to plain raw code submittedd to the server should be inspected rigorusly with protective measures, error messaging, and administration alerts combined to increase the level of application security and realtime response potential. Identifying SQL Injections as opposed to Buffer Overflows may be a nuance desired by the network administrator, amongst many other filterable attack types. Don’t expect your IDS to do all the work, especially if it resides outside the layer of encryption/decryption!
Exception Management & Error Messaging: There will undoubtedly be a user or attacker who submits garbage to your server, and the response should be handled or meddiated appropriately no matter what was sent. For the general user or site member, error messagin indicates what was wrong with the submitted data, direct them to where the change should be made, and make their navigation and data entry as easy as possible. For the hacker, a friendly and uninformative message that their submission (attack) was rejected increases the chances they will move on and consider other applications more worth their time. The quality and quantity of application programming are directly proportional to the quality and ease of site use for the user. Users who see a blank page when an eror occurs are likely to become frustrated and the application may lose traffic and therefore cash flow.
On the other hand, too much messaging can be a security vulnerability in itself. Server and parser configurations may turn on debugging messaging that reveals far too much arhcitectural information, including code fragments, database query strings, variable names, and other juicy stuff that hackers accumulate during an attack to profile the server and application. Debugging messaging may be turned on at thsw script level, which creates the same vulnerabilities and information disclosure. There is little excuse for sloppiness when taking a development project to a global launch. Differentiating between messaging for programers and that used by visitors is clear and easy to distinguish.
Auditing and Logging: Tracking and logging application use, database connections and queries, errors and exceptions, and attacks can all be performed by even small amounts of code. Attacks can occur in just moments, but after the fact there will be ample time to complain that there was no record of the attack. Without valid logging systems and log analysis systems, applications are often left out in the wind with hope and faith by your side. Unauthorized access and straight forward hacking attacks must be identifiable, traceable, and repeatable in order that they may be remediated and prevented in the future. Although logging is a critical measure to securing your applicatons and network, it must be done logically and with expectation for later analysis. Cluttered logs may be slow to process, but this can be prevented. Logs may be separated into different categories, such as Access, Denial, Error, Attack, Database, or whatever flavor is ideal for your application. Although this is not mandatory for logging systems, it can speed your discovery rate and reduce your headaches. Ample literature on logging system architecture is available Online.
Secure Code Audits may be perrformed by inspecting code for each category above, which is usually slower and less accurate. The other method is to inspect code for each category independently, as this tends to allow a greater focus and has a higher accuracy rate. Audomated code auditing software exists, but few have truly refinde the process performed by the individual expert security programmer. All the same, automated code audits can produce fast results for spot-checking follow-ups by the aditor. There is no reason to reject any single tool, when they may all be combined to perform faster audits, especially on volumous applications. Auditing every line of code is typically not feasible, and in many cases simply ridculous.
The conclusive result of a secure code audit includes a list of what was wrong, where the errors were found, what they imply, and a rating list for the remediators to follow. How to remediate errors is usually a combined effort of the network security consultants performing the security audit, and the application programmers who are intimate with the code. Clever “fixes” and temporary “patches” are not a substitute for solid, viable programming, unless your project is for Microsoft. Security Policies and Programming Policies may be developed during the auditing and remediation efforst, setting a new pace for more secure and quality programming. Educating and managing the programming team may be a valid direction to take, depending on the audit results. As useful and powerful as a secure code audit may be, the steps taken subsequently should not defunct the efforts of the audit by introducing new insecure code! Whatever the results and future requirements, the single goal for all involve must be the greater benefit of the application, to increase code and network security and protect the business.
A secure code audit by an experienced security programming expert is the only thorough and effective way to discover security issues in an application. Auditing should be scheduled as part of the whole development process, including smaller audits on sections of code with more changes than others, or written by less security-minded programmers. Code inspection constitutes the most viable security measure for preventing and remedating flaws prior to launch and during development.
Simply answered, “Do I need a secure code audit” is a decision you make based on the quality of your programming team’s knowledge of security, and how important it is that your applications and network not be successfully attacked.
If you have questions about secure code audits and improving your programing team’s understanding of programming security, contact me with your questions and concerns. andrewlandsman at emagined dot com