ASP.NET Code Access Security
One of the major benefits of using ASP.NET to host multiple Web sites is the common language runtime's support for code access security to help protect server applications. Code is assigned to a security zone classification based on evidence about the code's origin (evidence such as a strongly named assembly or the URL of origin, for example). Without the ability to configure security for individual, unrelated applications installed on a common server, code in an ASP.NET page belonging to one application would be able to read the files, for example, the Web.config file, in another application. Applications that run with full trust are constrained only by the operating system account under which they are executing.
Code access security can be easily handled for an individual assembly by strongly naming it and adding policy for that assembly. However, many ASP.NET assemblies are dynamically generated as a result of dynamic page compilation and therefore are not strongly named, so an additional facility is required.
ASP.NET lets you assign to an application a configurable level of trust that corresponds to a predefined set of permissions. By default (unless you explicitly alter the configuration), applications receive a level of trust commensurate to the evidence they present. For example, local applications must run in the MyComputer zone with the Full trust permission set, and applications located on a Universal Naming Convention (UNC) share must run in the Intranet zone with the LocalIntranet restricted permission set. If you want to run a Web application with less than Full trust, you must use one of the predefined trust levels defined in ASP.NET Trust Levels and Policy Files to enforce a partial trust policy.
You can use the following configuration settings to override the default behavior and associate an application with a given security policy.
<location path="MyApp" allowOverride="false">
<trust level="High"
originUrl="https://www.contoso.com"/>
</location>
The <trust> configuration tag can apply to the machine level or to any application root directory in the hierarchy.
If you want to set policy for the entire site, you can do so by specifying the root of the site as the path location, as follows.
<location path="ContosoSite" allowOverride="false">
<trust level="High"
originUrl="https://www.contoso.com"/>
</location>
You should take care to specify the <location> directive using the allowOverride attribute if you do not want applications to be able to specify their own trust level (this is the case in most shared server installations).
The following table lists the default supported attributes for the <trust> element.
Attribute | Description | Default supported values |
---|---|---|
level | Specifies the security zone under which the application will run. | Full, High, Medium, Low, and Minimal. |
originUrl | Allows an administrator to set the application's URL of origin.
This allows the permissions that rely on the notion of host to function correctly |
Well-formed HTTP URLs. |
By default, the policies associated with the various security levels are granted the permissions shown in the following table.
Level | |||||
---|---|---|---|---|---|
Permission | Full | High | Medium | Low | Minimal |
AspNetHostingPermission | Full | High | Medium | Low | Minimal |
Environment | Un | Un | Read: TEMP, TMP, OS, USERNAME, COMPUTERNAME | ||
FileIO | Un | Un | Read,Write,Append,PathDiscovery:Application Directory | Read,Path Discovery: Application Directory | |
IsolatedStorage | Un | Un | AssemblyIsolationByUser, Unrestricted UserQuota | 1 MB quota (can be varied for individual sites), AssemblyIsolationByUser | |
Reflection | Un | ReflectionEmit | |||
Registry | Un | ||||
Security | Un | Execution, Assertion, ControlPrincipal, ControlThread, RemotingConfiguration | Execution, Assertion, ControlPrincipal, ControlThread, RemotingConfiguration | Execution | Execution |
Socket | Un | Un | |||
WebPermission | Un | Un | Connect to origin host (if configured) | ||
DNS | Un | Un | Un | ||
Printing | Un | Default Printing | Default Printing | ||
OleDBPermission | Un | ||||
SqlClientPermission | Un | Un | AllowBlankPassword=false | ||
EventLog | Un | ||||
Message Queue | Un | ||||
Service Controller | Un | ||||
Performance Counters | Un | ||||
Directory Service | Un |
Un = Unrestricted
Blank = No Permission
When a permission level is available but is not explicitly mentioned in security policy, applications running with the Full level of trust can use it (since they have the Full trust permission set). Applications running with lower trust levels will not be able to use resources protected by nonexplicit permissions unless you specifically alter policy to allow it.
As the table shows, High trust applications have read/write permission for files in their application directories, and Low trust applications have read-only permission for files in their application directories. Because FileIO permission relies on a physical path (for example, c:\MyAppPath
), ASP.NET uses a tokenized statement in the policy files that is replaced at run time with relevant path information for the application.
Note that WebPermission allows the application to connect to the origin host. This mechanism works from ASP.NET by providing an optional OriginUrl attribute on the <trust> section for a given application. The OriginUrl attribute is used to replace the
$OriginHost$ variable in policy files, as demonstrated in the following code from Web_hightrust.config.
<IPermission class="WebPermission" version="1">
<ConnectAccess>
<URI uri="$OriginHost$"/>
</ConnectAccess>
</IPermission>
SocketPermission takes a host name or a dotted IP string (possibly with wildcard characters) and WebPermission takes a regular expression that includes the protocol (for example, http://backendmachine/.*)
. If you want to change this, you can alter the policy files (or create new ones by copying the defaults) with the desired permissions. For example, you can alter the SocketPermission section from the ASP.NET named permission set to grant TCP socket connectivity to "backend1" and "backend2" on port 8080, as follows.
<IPermission class="SocketPermission" version="1">
<ConnectAccess>
<ENDPOINT host="backend1" transport="Tcp" port="8080"/>
<ENDPOINT host="backend2" transport="Tcp" port="8080"/>
</ConnectAccess>
</IPermission>