When you're writing sample code to reproduce a security violation, one of the challenges you face is that such code, by definition, incorporates poor practices. As you read the code examples in the main article, you might find yourself making comments that start with, "I wouldn't do..." or "This wouldn't be a problem if...." However, the point of using an example that readers might respond negatively to is to show why some best practices are valuable.

I selected a Web-form-based logon page for the main article's example for a couple of reasons. In part, I chose this example for shock value—it's always good to remind people that although Web-form-based authentication can be as secure as any other form of authentication, it also has vulnerabilities. Alternatively, I could have used a Search input box, which is probably the second most likely point of attack.

A second tactic I chose for this article that might trigger a negative response for readers is that I've embedded in the example page the actual database connection credentials that my Web application's service account uses for portability. Although I mention the impropriety of using the sa account later in the article, you probably noticed that by exposing my connection credentials, I bypassed a layer of security. But hiding connection-string credentials is outside the scope of this article. Obviously, the credentials don't belong in the page, but placing them there makes this example easy to understand.

However, what of the fact that I used a service account instead of the user's credentials for database access? The answer to that question has two parts. First, how—or even whether—I authenticated the user's credentials doesn't matter. The example logon page reminds you that Internet-based applications are inherently insecure unless you take action to make them secure. If you're going to allow anonymous queries against a product database, you're accepting user input. If you're keeping your list of customer or user accounts in SQL Server, as is the case with many Web applications, your application uses a model similar to the one in this example. SQL Server authenticates accounts defined in a SQL Server table only after a service account has already connected to the database.

Second, using a proxy account as part of a Web application is a practice that Microsoft fully supports. A good reference that discusses the use of service accounts is the "Authentication in Data Access Components" section of Chapter 3 in the Microsoft Patterns and Practices reference guide "Application Architecture for .NET: Designing Applications and Services" (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/AppArchCh3.asp). The guide notes that allowing access through service accounts is appropriate in situations in which you might not have a valid set of account credentials for every distinct user or you might want to use connection pooling for scalability. Public-access Internet sites are places where these circumstances might occur. To optimize connection pooling, ADO.NET requires that you use a common connection string for each connection that's part of the pool. The main point to remember is that regardless of what type of authentication you use, an anonymous user is going to query your application database.

Finally, you might wonder whether you should use SQL Server or Windows-based authentication. Using Windows-based authentication has several advantages, but describing them would require another article. The Microsoft Reference Architecture for OpenHack (MRAO) provides a good example of how to effectively use the ASP.NET User account for SQL Server authentication. But even if I followed the best practices that MRAO prescribes, I could still reproduce the example attack in the main article—including the use of a logon page. Vulnerabilities always exist. The main article's example illustrates several bad security practices and lets you easily see the vulnerabilities they create.