Security issues for Visual Basic .NET and Visual C # .NET programmers
Robin Reynolds-Haertle
Visual Studio Team
Microsoft Corporation
January 2002
Summary: This article focuses on the main security issues that Visual Basic .NET and Visual C # .NET developers need to address when starting to use the .NET framework. This overview discusses Windows and Web applications, as well as the implementation, debugging, and deployment phases of the development process.
This article applies to the final versions of Visual Studio .NET and the .NET Framework. If you are using a pre-release version, the application may run slightly differently than discussed in this article.
table of Contents
Introduction
Code access security
complete trust
Partial trust
Development of a partially trusted environment
test
Other resources
Web application
Dynamic discovery
Authentication, impersonation, and delegation
ASPNET process identity
Secure file resources when running under the ASPNET identity
Debugging with ASPNET Identity
Security mechanism in Visual Studio .NET development environment
to sum up
Introduction
Compared to earlier versions of Visual Studio, Microsoft® Visual Studio® .NET provides better security control for the running of applications. The .NET framework provides more control, while also requiring you to assume more programming responsibilities. When creating user-friendly applications for your users, you need to address some security issues.
Security issues often need to be addressed in the following three situations:
The user running your application may deny permissions to the application because the application is running in a location that has been designated to deny the user access to certain system resources. For example, users can deny file permissions for all applications stored on network drives by configuring the common language runtime. You should be aware of this when writing your code, and you should write your code to respond appropriately to this rejection.
You need to prevent users who access your web application from your web server from running malicious code or corrupting data on the server.
The way Visual Studio is set up will more or less expose the server to malicious code attacks.
Code access security
Code access security is a system of the .NET framework that controls access to resources by controlling the execution of code. This security function is independent of the security provided by the operating system and is a complement to the security provided by the operating system. When users run your application, the application is assigned to one of five regions by the .NET common language runtime. The five areas are:
My Computer-an application on the user's computer.
Local intranet-Application on the user's intranet.
Internet-applications from the Internet.
Trusted sites-Applications from Internet Explorer defined as "trusted" sites.
Untrusted sites-Applications from Internet Explorer defined as "restricted" sites.
Each of these areas has specific access rights set by the system administrator. You can set the security level of each zone to Full Trust, Medium Trust, Low Trust, or Untrust. The trust level defines the resources that an application can access. Zones, along with other security credentials, such as publisher, strong name, website, and URL of the code, determine the permissions granted to that code at runtime. You cannot control the security settings on the user's computer, but your application will still be limited by the instant settings while it is running. This means that applications may be denied access to certain specific resources. For example, an application might need to write data to a file, but the user's system will deny write access at runtime by throwing an exception. For more information on security credentials, see Evidence.
Your job is to develop applications to handle this situation. This does not mean that your application writes data in another way, but rather that your application should anticipate that data might not be written and then respond to this possibility. You may need to use more exception handling (Try ... Catch in Visual Basic or try ... catch in C #) or some objects in the System.Security.Permissions namespace to make your application code more reliable . These methods are briefly explained in the "Partial Trust Environment Development" section later in this article.
A zone's security level can be set through the Management Tools installed with the .NET framework. For more information on setting the zone security level on your computer, see Administration Tools.
complete trust
Developers often work in a fully trusted environment. They store the source code on a hard drive and test their applications on a computer used for development. In this fully trusted environment, any code compiled by a developer can run on a local computer. Because the local computer is defined as a fully trusted environment by default, there are no security exceptions.
Partial trust
Partial trust refers to all areas except full trust. When the application is deployed, the application may be moved to a new region, and the new region may not fully trust the application. The two most common scenarios for running code in a partially trusted environment are:
Run code downloaded from the Internet.
Run code that resides on a network share (intranet).
Examples of resources that may be denied access in partially trusted zones include:
File I / O, including reading, writing, creating, deleting, or printing files.
System components such as registry values and environment variables.
Server components, including directory services, the registry, event logs, performance counters, and message queues.
What is not allowed in a partially trusted environment? This is not easy to determine. Each class in the .NET framework and each method in each class has a security attribute that defines the level of trust required to run the method, and it is precisely these security features that may make it inaccessible at runtime The property. The zone level is not just a simple mapping of trust levels to attributes, but a collection of specific permissions granted to specific classes and methods. Your application cannot simply query the trust level and then predict which resources are unavailable. You can determine whether the application is running in a fully trusted environment. In the next section, "Development of a Partially Trusted Environment," we will introduce one approach.
Development of a partially trusted environment
This section briefly describes how security issues may affect the code you write. There is no single solution for the development of a partially trusted environment. Your solution depends on the application you write. In addition, because trust levels can change during the execution of an application, you cannot just test an existing trust level and then continue execution.
The first step in developing a partial trust zone is to write code that can identify imminent security exceptions. Please note the following code:
'Visual Basic Public Sub MakeABitmap () Dim b As Bitmap = New Bitmap (100, 100)' The code here will draw a beautiful picture in bitmap format b.Save ("c: /PrettyPicture.bmp") End Sub // C # public void MakeABitmap () {Bitmap b = new Bitmap (100, 100); // the code here will draw a beautiful picture in bitmap format b.Save ("c: //PrettyPicture.bmp ");}
If the project and project assemblies are stored on your computer's hard drive and you are a member of the computer's Administrators group, this method will not throw an exception at runtime. If you deploy this application to your intranet, a System.Security.SecurityException will be thrown when the application attempts to save a bitmap object (see SecurityException Class [English]). If there is no Try ... Catch (in Visual Basic) or try ... catch (in C #) blocks around this code, the application will terminate with an exception. This can make users unsatisfactory. If you add exception handling code, your application can:
Warn users that the application cannot complete all tasks that need to be completed.
Clear all existing objects so that the code behind the catch block can run successfully.
You can modify the code that saves the bitmap as shown below. The added code will warn users that the file failed to be saved because it was denied security, distinguishing security failures from file I / O failures such as incorrect file names. This method does not create any security holes. Users should modify the security settings to trust your application or the application will not run.
'Visual Basic Public Sub MakeABitmap () Dim b As Bitmap Try b = New Bitmap (100, 100) b.Save ("c: /PrettyPicture.bmp") Catch ex As System.Security.SecurityException' Tell the user that the save failed. MessageBox.Show ("Permission to save this file was denied, & & _" This bitmap was not saved. ") Catch ex As System.Exception 'React to other exceptions here. MessageBox.Show (ex.Message) End Try End Sub // C # public void MakeABitmap () {Bitmap b = null; try {b = new Bitmap (100, 100); b.Save ("c: //PrettyPicture.bmp ");} catch (System.Security.SecurityException ex) {// Tell the user that the save failed. MessageBox.Show ("Permission to save this file was denied," + "This bitmap was not saved.");} Catch (System.Exception ex) {// react to other exceptions here. MessageBox.Show (ex.Message);}}
Use the classes, properties, and enumerations in the System.Security.Permissions namespace to gain more control over security tasks in your application. If you are writing a library that can be called from other applications, you can let the library verify the permissions of the calling code. For example, you just need to add the following assembly-level attributes at the top of the code file. When the assembly is loaded, the runtime verifies permissions. If the requested permission is denied at runtime, the assembly will fail to load and a security exception will be thrown. If you add this property to a stand-alone application, the application may not run. If this property appears in a class library, the library may not be loaded at runtime. You need to add try / catch blocks to the code that calls such libraries.
'Visual Basic // C # [assembly: System.Security.Permissions.FileIOPermissionAttribute (SecurityAction.RequestMinimum, Write = "c: //PrettyPicture.bmp")]
You can also specifically request permissions from the runtime, the Demand method is used in the following example. The runtime may allow or deny the request. Rejecting a request is achieved by raising a security exception. You can rewrite the code as follows to explicitly request permission to write to the bitmap file:
'' Visual Basic Public Sub MakeABitmap ()
Dim filename As String = "c: /PrettyPicture.bmp"
Dim permission As FileIOPermission = _
New FileIOPermission (FileIOPermissionAccess.Write, _
filename)
Dim b As Bitmap = Nothing Try b = New Bitmap (100, 100)
permission.Demand ()
b.Save (filename) Catch ex As System.Security.SecurityException 'Tell the user that the save failed. MessageBox.Show ("Permission to save this file was denied, & & _" This bitmap was not saved. ") Catch ex As System.Exception 'React to other exceptions here. MessageBox.Show (ex.Message) End Try End Sub // C # using System.Security.Permissions; public void MakeABitmap () {
string filename = "c: // PrettyPicture.bmp ";
FileIOPermission permission = new
FileIOPermission (FileIOPermissionAccess.Write,
filename);
Bitmap b = null; try {b = new Bitmap (100, 100);
permission.Demand ();
b.Save (filename);} catch (System.Security.SecurityException ex) {// Tell the user that the save failed. MessageBox.Show ("Permission to save this file was denied," + "This bitmap was not saved.");} Catch (System.Exception ex) {// react to other exceptions here. MessageBox.Show (ex.Message);}}
test
The second step in developing a partial trust zone is to test in multiple environments, especially on your intranet and the Internet. This will force a security exception.
Other resources
In addition to what is described in the overview above, there are many more options to choose from. The following topics discuss code access security in more detail:
Introduction to Code Access Security (English)
Code Access Security (English)
Security Namespaces in Visual Studio (English)
Web application
Addressing web application security issues can protect your server from malicious code and protect your data from corruption. You can use several methods to protect your server.
Prevent users from finding and running your XML Web services by disabling the dynamic discovery of XML Web services.
Before allowing a user to access the server, authenticate the user's identity through authentication.
By using ASPNET process identity, you can better adjust the resources that users can use.
Each method is discussed in detail below.
Dynamic discovery
Dynamic discovery is a feature of the .NET framework that allows Web browsers to find XML Web services running on the server. Once the XML Web service is found, the user can call the methods of the XML Web service. Although dynamic discovery provides users with powerful functions, it also brings potential security risks to the server. In most cases, you do not need to enable dynamic discovery. When the .NET framework is installed, dynamic discovery is disabled by default. This does not mean that XML Web services are unavailable, it only means that the server will not provide a catalog of available services. Clients can still use XML Web services, but you need to provide them with the exact location of the service.
Warning: After disabling dynamic discovery, you need to send the location of the XML Web service to the client.
On the deployment server, there are two items that control the discovery of XML Web services. The first item (the machine.config file) controls the overall discovery capabilities of the server. The machine.config file is an XML file containing settings for the web application on the control server and is located in the /%windows%/Microsoft.NET/Framework/Version/Config folder. This file contains an element that is commented out by default. To enable discovery, you need to delete these comment characters. You also need to use the ASPNET account to run the application, as described in the next section, "ASPNET Process Identity."
The second item is a discovery file. The discovery file can be the default discovery file (default.vsdisco) or an XML Web services-specific discovery file. It is an XML file that contains information about the location of the XML Web services file.
To enable clients to discover specific XML Web services, you need to enable discovery in the machine.config file and create and deploy a discovery file for your application. A discovery file is an XML file that lists only paths that do not contain XML Web services. An example is provided below. For complete instructions on creating and deploying this file, see Deploying XML Web Services in Managed Code.
<? xml version = "1.0" encoding = "utf-8"?>
If your deployment server has Visual Studio .NET installed, the web root folder will contain the default discovery file (default.vsdisco), which was created during the Visual Studio .NET installation process. If this file is included in the server and discovery is enabled in the machine.config file, all XML Web services on the server can be discovered. If you want to prevent the discovery of XML Web services, you need to delete this file.
Warning: If Visual Studio .NET is installed on the deployment server, the default.vsdisco file should be deleted before the server is ready for use.
We recommend that you do not deploy XML Web services on a server that has Visual Studio .NET installed. The Visual Studio .NET installer adds available files and users to your system. You can secure systems that have Visual Studio .NET installed, but if you do not need to install Visual Studio .NET on the deployment server, we recommend that you do not install it.
For more information on enabling dynamic discovery, see Enabling Discovery for an XML Web services (in English) and Fine-Tuning Discovery Mechanisms (in English).
Authentication, impersonation, and delegation
By default, the web application will run in anonymous mode, meaning that the application does not need any information about the user's identity. This works great for sites that contain public information. If you want to control users who access the application or other resources, you need to add authentication to the application. Authentication is the process of identifying the user of an application and verifying that the user has access to the application. ASP.NET supports multiple authentication methods. The most common methods are:
Anonymous No user is required to provide any identifying information. This method is suitable for websites that contain public content. If you need a personalized site, you can use cookies. For more information on using cookies in ASP.NET applications, see Introduction to Web Forms State Management.
Forms The application provides a login form to the user, asking the user to provide login information (such as name and password). The form is sent back to the server, and the server compares this information with the data warehouse.
Basic Basic authentication is configured using Internet Information Services (IIS), and most browsers support basic authentication. If enabled, the browser will prompt the user for a name and password, and then pass the information back to the ASP.NET application using Base64 encoding, which is easy to decrypt. This method requires the user to have a Windows account. If you use Secure Sockets Layer (SSL) in addition to basic authentication, you can ensure the security of this authentication method. For information on SSL support in ASP.NET, see Using Secure Sockets Layer.
Brief Brief authentication is configured using IIS and can be used on servers running Microsoft Windows® 2000 or Windows XP. Brief authentication provides a higher level of password encryption than basic authentication. This method requires the user to have a Windows account stored in Microsoft Active Directory®.
Integrated Windows Integrated Windows authentication is similar to basic and brief authentication, except that the user's name and password are not passed back to the web application. This method is especially suitable for intranet environments. It requires users to have a Windows account, and only Internet Explorer browsers support this method.
Certificate A certificate is a digital key installed in your computer. This key is required when the user tries to access the server. The server then validates the certificate in the domain or Active Directory. This method is suitable for applications that require a high degree of security at the cost of managing certificates.
Passport Microsoft provides this centralized authentication service. Passport authentication works when your Web site is used with other Passport sites so that users can log in to all sites once, or you don't want to maintain a user database.
Authentication allows you to authorize users of your application, but this is not sufficient to enable users to access resources such as files and databases. You can configure resources to make them available to specific users, not the Web application itself. In this case, you can use impersonation to allow users to access these resources. When using impersonation, the server process runs as an authenticated user ID. When an application uses impersonation and queries a database, the database application processes the query as if the query came from the user, not the server. As shown in the following example, impersonation can be enabled by setting the impersonate attribute of the identity element in the application's Web.config file. The Web.config file is created as part of each Web application project.
Going further than impersonation is delegation, which uses the user ID when accessing remote resources (other computers). As shown in the following table, not all authentication methods support delegation.
Supported delegation Not supported
Basic anonymous
Integrated Windows Brief
Certificate Passport
Form
For a detailed discussion of choosing and implementing an authentication method, see Authentication in ASP.NET: .NET Security Guidance. For more information on web application security, see Web Application Security at Run Time.
ASPNET process identity
When a web application starts running on the server, it doesn't run as if you were logged in as the author of the web application. Instead, it runs as if logged in using a Windows user account defined on the server. The account (also known as an identity) can be one of three accounts: an ASPNET identity, a SYSTEM identity, or a custom identity. The ID is specified in the machine.config XML file (located in the server's /%windows%/Microsoft.NET/Framework/Version/Config folder). Shown below are simplified examples of the three configuration methods for this element. Elements in the file have several attributes that are not shown in this example.
ASPNET is the default identity chosen when installing the machine.config file with the .NET framework. The ASPNET account is a member of the Users group, and by default, the Users group has minimal permissions. The ASPNET account also has several other permissions, including full permissions to ASP.NET and Windows temporary directories.
If you change the identity to SYSTEM, the application runs under the SYSTEM identity, which has permissions for the Administrators group. The SYSTEM account can access almost all resources on the server.
Warning: If the server is running under the SYSTEM identity, there is a high risk of malicious code attacks and data corruption.
To use a custom identity, you must create an account and configure its permissions in a specific way. For more information on creating a custom identity, see Authentication in ASP.NET: .NET Security Guidelines.
There are several system resources that are not available to ASPNET accounts by default. The following outlines common limitations and solutions. We recommend that you use an ASPNET account and the solution described instead of running applications under the SYSTEM identity.
File Resources Access Control Lists (ACLs) for individual files and folders can be accessed through Windows Explorer to adjust file and folder permissions granted to the ASPNET account. Changes to ASPNET's ACL are not automatically propagated through deployment. For example, you might allow the ASPNET account to have write permissions to the c: /picture.bmp file on the development computer. When the application is deployed, the application .
The program will run on another computer that also has an ASPNET account. You need to add write permissions to the c: /picture.bmp file on the deployment computer for the ASPNET account on the deployment computer. Fortunately, you can use custom actions to make changes to ACLs in your deployment projects, but you must track the changes you make.
Event logs ASPNET accounts can add entries to existing logs, but they cannot create new event log categories. You can now enable impersonation when using an ASPNET account to create a new event log category. The impersonation ID must have sufficient permissions to create event log categories. If the event logs required by the application can be specified before being put into use, they can be created by the deployment project.
Directory services and Active Directory access to them requires impersonation and delegation, or passes specific security credentials to the DirectoryEntry object. If you choose to pass specific security credentials to the DirectoryEntry object, you need to ensure that this information is stored correctly.
Performance counters ASPNET accounts can only write to, not read performance counters, and cannot create new performance counter categories. You can now enable impersonation when using an ASPNET account to create a new performance counter category. The impersonation ID must have sufficient permissions to create a performance counter category. If the performance counters required by the application can be specified before being put into use, these performance counters can be created by the deployment project.
Secure file resources when running under the ASPNET identity
Note: The instructions in this section apply to systems running the NTFS file system. If your server is running a FAT32 file system, see the file system documentation for information on securing files.
By default, the ASPNET account only has read and execute permissions for the Users group. If your web application needs to write or create new files, you can authorize specific files and folders by modifying access control lists (ACLs). To access the ACL of a file, right-click the file in Windows Explorer, then select the Properties and Security tabs. It's best to modify the ACLs for specific files rather than adding universal permissions to the ASPNET account. The most commonly used permissions include:
Read-Data files and executables require read permissions.
Write-Data files updated by the application require write permissions.
Execute-In a web application, the .asmx file is an executable file.
Create-To create a file, you need to add create permissions to the folder where you want to create the file.
These permissions apply to:
file
folder
Warning: Avoid allowing both execute and write or create permissions on the same file or directory. In this case, the user may try to write malicious code in the file before executing it.
Here are some tips for simplifying the authorization process:
Place files in different directories based on the permissions required for the files in the application. For example, if you only store read / execute files in a directory, you only need to set these permissions for one directory, rather than setting permissions for each file individually. Consider creating separate directories in your application for read / execute, read / write, and read / create permissions.
An application can contain data files that are empty when deployed, and it can also contain the code needed to create the files when the application is first run. This requires adding create permissions to the directory, which is a higher security setting. To avoid adding code to create new empty files, consider providing an empty file to your application when you deploy. This way, you only need to add write permissions to the file instead of adding create permissions to the directory.
When developing an application, you will add permissions to files and directories on the development computer to fine-tune the security level of the application. Unfortunately, ACLs are not passed to the corresponding files on the deployment computer. To plan the delivery of these ACLs, keep in mind the following:
You can use custom actions in the deployment package to change the ACL. For more information, see Custom Actions.
You can use third-party tools to track and find changes.
You may need to confirm each setting with your system administrator. You need to document why you made the change, and why you have to change the settings to achieve it.
Debugging with ASPNET Identity
When debugging an XML Web service, if an ASPNET ID is defined in the machine.config file, it will be used to call this XML Web service. By default, the ASPNET identity is not a member of the Debugger Users group (see the next section "Security in the Visual Studio .NET Development Environment"), so XML Web services code cannot be accessed during debugging. To debug XML Web services, open the code for XML Web services and set a breakpoint.
We recommend that you debug on a test computer instead of a deployment computer. This is discussed in the next section, "Security Mechanisms in the Visual Studio .NET Development Environment."
For more information on configuring process identity, see ASP.NET Process Identity and ASP.NET Impersonation.
Security mechanism in Visual Studio .NET development environment
In addition to protecting the security of your server, you also need to protect your development computer from malicious code and data corruption. You can use multiple mechanisms in your development environment to secure your development server:
VS Developers and Debuggers add these two account groups when installing Visual Studio .NET. The VS Developers group has the necessary file, share, and IIS permissions to create and develop web applications on the server. The Debuggers group can debug processes on a specific computer (local or remote). Both groups are users with significant permissions on the server and can access most resources. For more information, see Web Application Security at Design Time in Visual Studio.
Debugging It is recommended that you debug on a test computer instead of a deployment computer. If you must debug on the deployment server, install only the remote debugging component and uninstall the component after debugging is complete. Please debug the server offline. For more information, see Introduction to Web Application Debugging.
Deployment For most applications, it is sufficient to install the .NET framework on the server. If Visual Studio .NET or Visual Studio .NET server components are installed on the deployment computer, both the VS Developers group and the Debuggers group will appear on the deployment computer. You need to restrict members and Debugger users of VS Developers. In addition, you may need to disable dynamic discovery.
Warning: It is strongly recommended that you do not install Visual Studio on the deployment server.
The Copy Project feature of Visual Studio .NET includes the option to deploy the application using a configuration file (Web.config) that is different from the configuration file used in development. Development files may have debugging enabled, and after deployment, will allow users to check the call stack when an exception is thrown. We recommend that you deploy using a configuration file that does not allow debugging.
to sum up
Protecting resources is a process that involves multiple technologies and the entire development cycle. By carefully designing, implementing, testing, and deploying your applications, you can create very secure applications. Applications can be secured using security technologies provided by ASP.NET, the operating system, and a web browser.