Security for Microsoft Visual Basic .NET

Plan of Attack—The Test Plan

On projects in which there is a clear division of labor between a development team and test team, the test team should come up with a test plan for the project, and the development team should review it. If your project is made up entirely of developers with no test team, the development team should create a test plan in conjunction with the specifications and other design documents. If you’re in the midst of development and don’t have a test plan, drop everything—although you should finish this chapter first—and go through the exercise of creating a test plan. You might be inclined to reconsider all those great features you’ve planned, especially when you see how much effort will be required to adequately test them and how much risk a certain feature represents to your application. The plan should include the following:

A critical part of the test plan—this should be no surprise—will be to include tests for security. The plan should treat security as a distinct feature that requires specific tests. Emphasizing security in a test plan has these benefits:

To create security-focused tests (as part of your test plan), you first need to identify ways an attacker might be able to compromise the application. In other words, you need to come up with various scenarios based on what an attacker might do.

Brainstorm—Generate Security-Related Scenarios

Forget about deadlines, money, or any other practical concerns for a moment, and let your imagination run wild to generate usage, or more accurately, “abusage” scenarios that could be used to compromise your application. When it comes to testing for security, you’ll want to think about all the devious things a person could do with your application.

Take the Attacker’s View

A technique that will help generate useful scenarios is to take an attacker’s view of your application. To an attacker, your application is not a nifty UI, it’s all the stuff behind your UI that gives her an exclusive, backstage pass to wreak havoc. One of the first things an attacker will do when she installs your application— namely a Windows Forms application or component—is to take an inventory of all the components installed by your application. She will look at where components are installed on the hard disk, the registry entries associated with those components, the public functions exposed by the components, and all data files installed by your application. As discussed in Chapter 6 and Chapter 7, all these things represent input to your application that can potentially be manipulated to do bad things.

The attacker will run tools to scan through your application’s binaries— EXEs and DLLs—looking for stored secrets such as passwords or pass-phrases contained within your built application (which shouldn’t be there if the application was designed securely).

In the case of Web applications, the attacker will run tools that crawl the Web site generated by your ASP.NET application and create a mirror image of that site. She will look through all the HTML files for comments that reveal information about your application or the server where it runs—information such as IP addresses or names of other servers that might be exposed. She will look at all input fields, including hidden fields, as a potential in-road for launching a SQL or cross-site scripting attack. She will also look at all embedded script, such as VBScript, and will disable the execution of it—which can be done by toggling a setting within her Internet browser—in an attempt to bypass your client-side input validation.

The attacker techniques described herein are commonly referred to as decomposing, profiling, or footprinting your application. This is equivalent to a burglar getting the blueprints to your house or office building to determine the easiest points of entry. Figure 9-1 lays out a sample blueprint of an application.

Figure 9-1: An attacker’s blueprint of your application

Create a Blueprint of Your Application

You should take the same approach that a hacker would and create your own blueprint of the application to assess vulnerable points of attack. You can create your blueprint by reviewing your source code and the file list that you include in your setup application. Your blueprint should include:

Note

Having access to your source code is a convenience you have when creating a blueprint for your application, but having this access really gives you little advantage over an attacker. Never count on your source code or any complex logic contained within your application to hide secrets. There are a number of tools and techniques to help an attacker reverse-engineer your code. Your safest bet is to assume the attacker has access to your code. For example, a Visual Basic .NET assembly—application EXE or component DLL—is quite easy to reverse-engineer by using a tool such as the Intermediate Language Disassembler (ILDasm.Exe). In fact, you can run ILDasm.Exe provided by the .NET Framework to open any compiled .NET application or component. ILDasm.EXE gives you a view of all the classes and .NET executable instructions (known as MSIL) that make up your application or component. Although ILDasm does not give you a view of the original source code (or comments), you can easily tell by the MSIL instructions what the application or component does. In addition, any stored secrets, such as passwords stored in constants, will be plainly visible when viewed using ILDasm. If C# is easier for you to read than MSIL, you can use tools such as Anakrino, which is available on the Web, to reverse-engineer a compiled .NET assembly to C#.

The items in this list generally serve as input to an attacker. As you learned in Chapter 6 and Chapter 7, attacks are usually launched by means of input. Think of ways that input—items such as those given in the previous list—can be manipulated or deprived to make your application either:

Create Scenarios Based on Inroads for Attack

You should create scenarios focused on attacking (by various means, such as supplying malformed input) elements of your blueprint in an attempt to force any of the undesirable results listed previously. Following are examples of scenarios you should include in your test plan, which is based on your application’s blueprint and what a hacker would do with it:

Get Focused—Prioritize Scenarios

Unless you want to dedicate the rest of your life and the lives of your team to preparing to ship your application, you must face the practical matter that you cannot do everything when it comes to testing. However, you must satisfy your goal of shipping a quality and secure application. The best way to strike a balance between shipping your application in a reasonable amount of time and performing enough testing to ensure quality and security is to keep yourself and your team focused on the most important scenarios—so you need to prioritize.

Not all test scenarios are created equal; some are more important than others. The importance of scenarios depends on your application. For example, if you’re creating a Web-based shopping application, testing to make sure all input fields are resilient against bad input is far more important than verifying that all input fields are displayed in the exact intended position on the screen. If the application crashes because of a character such as X being entered instead of a number, this far outweighs the problem of your text boxes being off-center by 1 pixel. However, if you’re creating a Windows Forms game application, which requires no free-form text input, testing that focuses on pixel- level accuracy is more important than verifying text input.

An effective way of prioritizing the important scenarios is to take a break from writing code and meet with the members of your team—including members from all disciplines, such as development, testing, documentation, and product support (especially since those guys are usually more fun to hang out with anyway). Having members of the documentation team involved helps to defend against proposals that call for documenting security problems as a cheap (and ineffective) substitute for making the necessary fix. Get their input to help you rank the scenarios by importance. An effective ranking strategy is to assign each scenario a priority number, such as 1 to 4 (where 1 is the highest priority). You could create application ship criteria that states the product cannot ship until the application performs as expected for priority 1 and 2 scenarios. For example, the prioritization of scenarios could determine ship criteria by using the scale shown in Table 9-1.

Table 9-1: Security Test-Scenario Priority Scale

Scenario Priority

Description

1

Priority 1 scenarios focus on threats having a high impact on application security. An example of a priority 1 scenario test is to make sure that in your data-entry application you cannot enter into any input fields SQL statements that manipulate the underlying database. The application cannot ship with any bugs relating to a priority 1 scenario. It is crucial that you create (and run) tests for all priority 1 scenarios.

2

Priority 2 scenarios deal with threats having a moderate impact on application security, or cases where the application doesn’t work as expected in the secure environment where it is meant to run. The scenario presented in Chapter 2 of not being able to run your application from a network share because of a code-access security violation is an example of a priority 2 scenario. Forcing the user to run the application from his local machine is an inconvenience to the user. The application should be fixed to run in all security zones in which it is intended to run. You should create tests for all priority 2 scenarios.

3

Priority 3 scenarios focus on issues that don’t seriously impede application security but would improve the aesthetics of the application from a security standpoint. For example, if the scenario involves a user attempting to log on to your application and the application shows a logon failed error—ostensibly because of an invalid user name and password—when in fact the server the application is on is down for maintenance, the application should instead show an error message warning the user the server is down for maintenance. This might annoy the user who retries logging on several times thinking he mistyped his password.

4

Priority 4 scenarios have no noticeable impact on security. You explicitly call out these scenarios as ones you will not test. For example, a scenario involving a security-related error message where the error message text contains trailing blanks (not visible to the user) does not rank high enough to test.

Note

You need to include all scenarios in the test plan, no matter how trivial they seem. When it comes to testing, it’s often just as important to see the scenarios you consciously decide not to test as it is to see those that you’ve decided are critical to test. You should continually review the test plan throughout the product-development cycle and question the priority ranking of all scenarios. If a new feature is added that makes a lower-priority scenario more critical or a serious bug related to a priority 4 scenario is found that causes you to elevate the scenario’s priority, you have a chance to redirect your testing effort midstream.

Prioritize Security-Related Scenarios Based on Threats

For the purpose of prioritizing security-related scenarios, evaluate how much of a threat each scenario is to your application. For example, if your application does not use a back-end database to store or retrieve information—and your application doesn’t call components that use a back-end database—SQL-injection attacks are most likely not a threat. However, if your Visual Basic .NET Web application takes user input and uses it as part of the resulting output, cross-site scripting attacks are a definite threat. You can use the STRIDE—an acronym representing general types of attacks such as spoofing, tampering with data, repudiation, information disclosure, denial of service, and elevation of privilege—threat-modeling process discussed in Chapter 15 to help rank security- related test scenarios.

Generate Tests

Once you’ve completed the process of brainstorming and prioritizing test scenarios, you need tests to evaluate how your application responds to the scenarios you have identified. When creating tests to match each scenario in your test plan, put practical considerations—such as how the tests will be implemented or the amount of time they will take—on hold. As in the case of generating scenarios, you want to freely brainstorm what tests will be needed. The important part of this exercise is to generate a complete list of tests, which you can then prioritize. For example, assume you have a priority 1 scenario listed in your test plan that states: “Ensure that only valid user names can be entered in the user name input field.” You’ll need to create an exhaustive list of the tests needed to validate the scenario. In this case, if a valid user name is defined as a name that is limited to 16 characters and can contain only alphabetic names, the following tests could be used to test the scenario:

As you can see, you can create quite a number of tests to validate a given scenario. The list could continue on ad infinitum. Stop at the point you feel comfortable that you have covered all the important cases.

Filter and Prioritize Tests for Each Scenario

To maintain focus and not get sucked into a testing black hole of having to implement a seemingly infinite number of tests, you should prioritize the tests identified for each scenario based on the following criteria:

In the process of creating a blueprint, brainstorming scenarios, and brainstorming the tests that go along with the scenarios, you might uncover flaws in the design of your application. If you decide to redesign to help reduce risk and make your application more secure, retrace the steps of creating the application blueprint and scenarios based on the updated design. Testing is a process, and the test plan is a living document. You should plan to iterate through your tests and test plan several times throughout the development cycle as changes are made to the product or other important test scenarios are discovered.

Категории