内容来自公司的security training.没想到东西还不少。这些安全的东西平时不太注意,有一个安全学习也是好的。
Run-time Host is responsible to local CLR into a process, which will use JIT to compile assembly(IL) to machine code.
Users and Groups
Everything that can be authenticated by the System, such as Users, Computers, and Groups, is referred to as a Security Principal. Each security principal can be a member of many different groups, each with specific permissions allowing or denying access to each resource on the system or network. When created, every security principal is assigned a security identifier (SID) that is used when resolving access rights to a resource. Note that in Vista and later, Services also get a SID. A security group is a collection of accounts or other groups that can be managed as a single unit from a security perspective. It is common to create a security group for each unique combination of security requirements that applies to multiple users in your organization.
a security identifier (SID): A unique alphanumeric value that is issued when a user account, computer account, or group is created and is used to identify an object. SID values remain constant across multiple operating systems(unique).
Objects
Windows Objects are used to represent pieces of data such as a file on disk, data in memory, running processes, and users on the system. Most objects allow you to define a security descriptor that associates security information with that object.
security descriptor: A data structure that contains security information about an object, including SID and ACL information.
ACLs and ACEs
ACLs are lists of access control entries (ACEs) that identify the Security Principal (user or group) and the specific permissions that apply in accessing system objects. An ACL can contain many ACE entries to accurately describe the permission set. When a request for access is made, the access resolution process considers the entire ACL list in determining whether to grant access or not, including the possibility of conflicting permissions.
Access Tokens
When a user logs into the system, the logon service generates an Access Token which is attached to every process created in the user’s session. The access token contains a security descriptor that is built up from the rights described in the user’s ACL and it is used to determine the permissions for every process that executes in the user’s session. For each operation on an object, if the user has the appropriate permissions, the process is allowed to proceed; and if not, the process is denied access.
In order to simplify security permissions and policies, the .NET Framework version 4 eliminated machine-wide security policy. Security permissions and evidence remain in place in order to support CAS, but security policies are obsolete. Security Transparency has become the new security enforcement mechanism simplifying the process by which the CLR controls how code accesses its environment and external resources. The changes impact both the security transparency model from .NET 2.0 and how sandboxed code runs.
Transparency(code or assembly’s attribute)
Transparency separates code that is part of the infrastructure and can execute privileged operations from code that is part of the application and cannot directly execute privileged operations. The latter is referred to as transparent code and it may only execute within the bounds of the permissions it is allowed. The conditions governing the permissions are called annotations and they are enforced at run-time, not when the assembly is loaded. They remain in effect during the entire time the assembly executes and they apply even to fully trusted assemblies. Level 2 transparency does not apply to non-annotated code, such as unmanaged code.
Level 2 transparency replaces and extends level 1 transparency in .NET version 2, as well as the CAS security policies. The obsolete request permissions (RequestMinimum, RequestOptional, and RequestRefuse) receive compiler warnings and do not work in the .NET Framework 4, but they do not cause an exception to be thrown. Deny requests and requests to security policy APIs cause a NotSupportedException to be thrown at run time.
Removal of Security Policies
In the .NET Framework 4, machine-wide security policy does not apply by default. Applications that are not hosted now run as full trust. This includes all applications that reside on shares on the local network. Hosted or sandboxed applications continue to run with trust policies that are decided by their hosts (for example, by Internet Explorer, ClickOnce, or ASP.NET). Applications or controls that run in sandboxes are considered partially trusted. To simplify the security policy, the level 2 transparency model has been applied to the .NET framework.
AllowPartiallyTrustedCallersAttribute (APTCA) attribute: https://msdn.microsoft.com/en-us/data/ms182297(v=vs.85)
Transparency features for .Net 2.0 have the following characteristics:
- They are used primarily to improve code validation efficiency.
- Errors manifest themselves as permission demands, so the transparency rules can be broken by full trust code.
- They cannot satisfy a LinkDemand. Instead, any LinkDemands on APIs called by the transparent assembly will be automatically converted into full demands.
- Calls to P/Invoke methods that have be{j decorated with the SuppressllnmanagedCodeAttribute will cause a full demand for UnmanagedCode.
- Any method that contains unverifiable code will have a demand for UnmanagedCode permission injected into it.
Transparency features for .NET 4 are:
- Transparent code cannot Assert for permissions to stop the stack walk from continuing.
- Transparent code cannot satisfy LinkDemands or call critical code directly.
- Transparent code cannot automatically use unverifiable code, even if it has SkipVerification permission.
- Transparent code cannot call native code.
- Transparent code the effect of running within the same security context as its callers.
Transparency Model Classifications
- Transparent Code(Security Transparent assembly annotation)–ban only call other transparent or security-safe-critical-code. If partially trusted, the code can only perform actions allowed by the domain’s permission set.
- Security-Safe-Critical Code(Security Safe Critical Member annotation)—is fully trusted(full trust permission) but can be called by transparent code. This code can be used as a bridge between transparent and full trust security-critical code while performing proper security checks prior to exposing the required functionality to the transparent code.
- Security-Critical Code(Security-Critical member annotation)—is fully trusted(full trust permission, unhosted, unmanaged code) and cannot be called by transparent code.
The CLR uses objects called permissions to restrict actions that can be executed by code.
- No permissions are given to code automatically.
- Permissions include actions such as file system access(IsolatedStorageFilePermission), database access, printing(PrintingPermission), network access, registry access, and even access to the Ul(UIPermission). They can be very fine-grained; for example, network access can be broken down into DNS, Web, and socket permissions.
There are two types of permissions, each implemented by classes and subclasses.
- Code access permissions – are permission objects that represent the right to access a protected resource or perform a protected operation. (ReflectionPermission)
- Role-Based Permissions – allow you to discover if a user is a member of a specified role.(PrincipalPermission)
Permissions can be used in the context of a permission class (imperative security, –command in code) or as an attribute that represents a permission class (declarative security). Imperative security means that the permission is calculated at run-time, while declarative security means the permission is declared at compile-time. Imperative security is most useful when you need to use business logic in order to determine the permission required by the running code. Use declarative security if you know ahead of time what permissions will be required.
Imperative:
Declarative:
Permission Sets & Permission Set Classes(Permission is value assigned to user/user group)
Permissions can be grouped into sets, to avoid working with lots of individual permissions.
- Permission sets can also be named and described in order to uniquely identify and work with permission sets.
- All the same operations that apply to permissions can be done with permission sets.
The NET framework provides six built-in permission sets: (1) Nothing, (2) Execution. (3) Internet, (4) Local lntranet. (5) Everything(skip verification, can access everything, and (6) Full Trust(NO CAS, can access everything).
Evaluating Permissions at Run-time
Permissions are assigned to assemblies based on their AppDomain’s permission grant sets. These permissions are evaluated at run-time every time system resources are being accessed. During program execution, CAS inspects the call stack (The Stack Walk) to ensure that every piece of code, up to the original caller, has the appropriate permission to perform the specified actions(Permission Demand). If any caller in the call chain fails to have sufficient access rights, the request is denied. This check prevents an assembly from elevating its privilege level by calling higher privileged code.
CAS also provides means for privileged code to demand that any calling code, including each parent caller, has a specific permission set.
Calls to unmanaged code are inherently less secure. The .NET framework cannot make any guarantees or demands regarding such code. When doing the stack walk the CLR will alert you that you have touched an unmanaged frame, and from that point on it’s up to you. You can either ignore it and alert the user or you can write your own unmanaged stack walker The CLR will let you know when it finds the next managed frame.
Intermediate language is transformed into native code by the JIT compiler, so it is not actually executed as IL. When unmanaged code is included in the managed code call stack, the unmanaged code can use direct memory access into the JIT-compiled native code to subvert application domain protection. It can also use pointer arithmetic to read or overwrite private fields of its superclass and to form valid IL constructs that undermine type-safety by allowing access to private members. IL that allows these actions is called “type unsafe”.
Verification checks are built into the JIT compiler and work to prevent the unsafe use of pointers including assignment and arithmetic. Verification checks prevent the execution of type-unsafe code that interferes with its ability to provide predictable and controllable type behavior. To run unverifiable code, assemblies must be granted a SecurityPermission that allows them to skip verification. Because this is a powerful permission, it should be granted only to highly trusted code.
Code that can be proven to be type-safe is called Verifiable Code. The CLR also supports Pure Code and Mixed Code. Pure Code has only managed code. However, native data types and Mixed Code can have both managed and unmanaged code components. These latter two types cannot be verified as safe.
When to Demand Permissions
All .NET Framework classes that perform restricted operations and access restricted resources, such as the file system, demand permissions automatically. As a result, when you use the .NET Framework classes you must not duplicate the permission demands.
However, there are some situations where you will need to manually force a security demand.
For example:
- When code accesses a resource without using the .NET Framework classes, such as when authoring a safe critical function in a custom library. — UnVerifiable Code (non-type-safe code)
- If you want to avoid performing a time-consuming operation that may fail due to a security check, you can perform the test and make a decision to proceed or not.
When to Override Permissions
Normally, a security check examines every caller in the call stack to ensure that each caller has been granted the specified permission.
You can override the outcome of security checks by using the Assert override on a permission object. Using these calls, you can cause the security check to succeed even though the permissions of all callers on the stack might not have been checked. For example, you may want to do this if you need permission for your code that is potentially dangerous, such as disk access, but you are constraining your code to a safe operation, such as writing to a temp file. In this situation, you may want to use Assert to disable the stack walk and avoid any possible security exceptions.
using System;
using System.IO;
using System.Security.Permissions;
public class HandleTemp
{
public HandleTemp() { }
[FilelOPermission(SecurityAction.Assert, All = @”C:\Temp\tempfile”)]
public void OpenTemp()
{
StreamWriter TextStream = new StreamWriter(@”C:\Temp\tempfile”);
…
TextStream.Close();
}
}
}
Process Identity
The main ASP.NET application process, aspnet_wp.exe, runs in the web server using a custom account, ASPNET. Following the Principle of Least Privilege, this account should be configured with less privileges than accounts such as administrative accounts or the Local System account. By doing so, an intruder will have limited power in case security is breached.
The account used to run aspnet_wp.exe can be customized using the root configuration file, machine.config. Care must be taken to ensure the account has the necessary access rights to certain essential directories in order to function properly.
To enable a custom account, modify the element, located in the machine.config file, as shown here.
Authentication
Authentication is the action of verifying if an individual or machine is in fact who he/she/it claims to be. This is usually done by asking for credentials which are then checked for validity by a given authority. If the credentials are valid, the entity that submitted the credentials is considered an authenticated identity.
ASP.NET implements authentication through authentication providers. Authentication providers are code modules that contain the code necessary to authenticate the requestor’s credentials.
ASP.NET includes three built-in authentication providers:
- Windows (default)
- Forms
- Passport
Alternatively, a custom authentication provider can be used, or no authentication provider at all.
To enable an authentication provider, use the element located in either the machine.config or web.config configuration files as shown here.
Authorization
Once an identity has been authenticated, the authorization process determines what resources the entity has access to. Authorization is the process of controlling access and rights to resources such as services or files.
In ASP.NET, there are two ways to authorize access to a given resource:
- File authorization. File authorization is performed by the FileAuthorizationModule. It checks an ACL to determine whether a user should have access to the file. ACL permissions are verified using the user’s Windows identity when Windows authentication is enabled, otherwise the identity of the ASP.NET process is used.
- URL authorization. URL authorization is performed by the URLAuthorizationModule, which maps users and roles to URLs in ASP.NET applications. This module can be used to selectively allow or deny access to arbitrary parts of an application for specific users or roles.
Evidence Objects
The .NET Framework 4 introduced a new base class, EvidenceBase, which all evidence objects must derive from. This EvidenceBase class:
- Enables constraints on the types of objects that can be used as evidence.
- Provides the ability to add new features and requirements to all evidence objects.
- Ensures that upon instantiation, the evidence object is serializable.
In addition, new evidence requirements can be created in the future by adding new default implementations to the base class.
Identity Permission
Identity Permission Demands are commonly used to restrict callers to only assemblies having a specified identity. If the calling assembly has full trust, demands for identity permissions are ignored to be consistent with the full-trust contract. This is effectively the same as setting the Unrestricted PermissionSet.
Identity Permissions are known to have the following weaknesses:
- An attacker may spoof the evidence needed to grant the identity permission.
- An attacker may spoof an assembly’s origin.
The evidence permissions for identity are:
- SiteldentityPermission for evidence of the web site from which the code originates
- ZoneldentityPermission for evidence of the zone from which the code originates (Local intranet, Internet, Trusted, etc)
- GACIdentityPermission to determine if the code originated in the Global Access Cache
- PublisherldentityPermission for evidence of the software publisher identity for the code
- StrongNameldentityPermission for evidence that the code belongs to a strong-named assembly
- UrlldentityPermission evidence based on the full URL of the originating site for the code
Dangers of Using APTCA(code attribute)
Allow Partially Trusted Callers Attribute (APTCA) is a .NET attribute that allows partially trusted assemblies to interact with fully trusted code. The purpose of this attribute is to remove implicit LinkDemand checks on specified APIs that are publicly exposed. Explicit permission checks will be enforced even if the APTCA attribute is used.
The use of APTCA is known to be dangerous for the following reasons:
- APTCA exposes fully trusted code to luring attacks. Using such attacks, an attacker may direct some fully trusted code into performing a malicious operation.
- APTCA exposes the entire assembly. Since this attribute cannot be used on classes or methods, assemblies must be thoroughly audited for security vulnerabilities before applying APTCA to them.
In .NET 4, APTCA makes your assembly completely Transparent by default. This helps mitigate the risk of using APTCA as compared to previous versions of .NET, but it is still possible to damage the security profile of your code if you explicitly mark your API as safe-critical.
Guidelines for Hosting and Application Domain Sandboxing
Application Domains allow applications to restrict untrusted assemblies to a particular set of permissions.
Keep the following in mind when using Application Domains:
- Use the simple sandboxing CreateDomain API to create sandboxes AppDomains.
- Avoid granting too many or too few permissions to an Application Domain.
- Always set up the Application base.
- Ensure that the primary Application Domain is not contaminated by the use of AppDomain.Load().
- Avoid sharing assemblies across Application Domains.
- Set proper exception handling on the host side to ensure that untrusted code cannot execute within the host’s application domain.
- Do not deserialize untrusted objects from another Application Domain.
- Keep the assemblies on the full trust list short and ensure that they are audited assemblies.