Hacking the Code ASP.NET Web Application Security [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Hacking the Code ASP.NET Web Application Security [Electronic resources] - نسخه متنی

James C. Foster, Mark M. Burnett

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








“Security Tools”

section), and a Microsoft Management Console snap-in, mcscorcfg.msc (see Figure A.27). We’ll use the latter for demonstration purposes because it is more visual and intuitive.




Figure A.27: The .NET Configuration Snap-In


As you can see in Figure A.27, the security policy model comprises the following:





Runtime Security Policy levels





Enterprise Valid for all managed code that is used within the entire organization (enterprise); therefore, this will have “by nature” a restrictive policy because it references a large group of code.





Machine Valid for all managed code on that specific computer. Because this already limits the amount of code, you can be more specific with handing out permissions.





User Valid for all the managed code that runs under that Windows user. This will normally be the account that starts the process in which the CLR and managed code run. Because the identity of the user is very specific, the granted permissions can also be more specific, thus less restrictive.







A code groups hierarchy that exists for each of the three policy levels. We will look at how you can add code groups to the default structure, which already exists for user and machine.





(Named) permission sets. By default, the .NET Framework comes with seven named permission sets:





FullTrust Unlimited access to all protected resources and operations.





EveryThing Granted all .NET Framework permissions, except the security permission SkipVerification.





LocalIntranet The default rights given to an application on the local intranet.





Internet The default rights given to an application on the Internet.





Execution Has only the security permission EnableAssemblyExecution.





SkipVerification Has only the security permission SkipVerification.





Nothing Denied all access to all protected resources and operations.







Evidence, which is the attribute that the code hands over to the CLR and on which it determines the effective permission set. Evidence is used in the construction of code groups.





Policy assemblies that list the trusted assemblies that hold security objects used during policy evaluation. You should add your assemblies to the list that implements the custom permissions. If you omit this step, the assemblies will not be fully trusted and cannot be used during the evaluation of the security policy.





Understand that the evaluation process of the security policy will result in the effective permission set for a specific assembly. For all three policy levels, the code groups are evaluated against the evidence the assembly presents. All the code groups that meet the evidence deliver a permission set. The union of these sets determines the effective permission set for that particular security policy level. After this evaluation is done at all three security levels, the three individual permission sets are intersected, resulting in the effective permission set for an assembly. This means that the code groups within the three security levels cannot be constructed independently, because this can result in a situation in which an assembly is given a limited permission set that is too limited to run. When you take a look at the permission set for the All_Code of the enterprise security policy, you will see that it is Full Trust. Doing the same for the All_Code of the user security policy, you will see Nothing. Because the code group tree of the enterprise is empty, it cannot make evidence decisions; therefore, it cannot contribute to the determination of the effective permission set of the assembly. By setting it to Full Trust, you state that it is up to the machine and user security policy to determine the effective permission set.


Because the user code group already has a limited code group tree, the root does not need to participate in the determination of the permission set. When you set it to Nothing, it is up to the rest of the code groups to decide on the effective permission group for the user security policy.


You can determine the permission set of a code group by performing _these steps:





Run the Microsoft Management Console (MMC) by choosing Start | Run and typing mmc.





Open the .NET Management snap-in, via Console | Add/Remove Snap-in.





Expand the Console Root | .NET Configuration | My Computer.





Expand Runtime Security Policy | Enterprise | Code Groups.





Select the code group All_Code.





Right-click All_Code and select Properties.





Select the Permission Set tab.





The Permission Set field lists the current value.






Creating a New Permission Set



Suppose that you decide that none of the seven built-in permission sets satisfy your need for granting permissions. Therefore, you want to make a named permission set that does suit you. You have a few options:





Create a permission from scratch.





Create a new permission set based on an existing one.





Create a new permission from an XML-coded permission set.





To give you a better understanding of the working of the security policy and some hands-on experience with the tool, we discuss the different security policy issues in the following exercises.


We use the second option and base our new permission set on the permission set LocalIntranet for the user security policy level:





Expand the User runtime security policy, and expand Permission Sets (see Figure A.28).




Figure A.28: The User’s Permission Sets and Code Groups





Right-click the permission set LocalIntranet and select Duplicate; a permission set called Copy of LocalIntranet is added to the list.





Select the permission set Copy of LocalIntranet and rename it PrivatePermissions. Then, right-click it and select Properties. Change the Permission Set Name to PrivatePermissions and, while you’re at it, change the corresponding Permission Set Description.





Change the permissions of the permission set: Right-click the PrivatePermissions permission set, and select Change Permissions.





The Create Permission Set dialog box appears (see Figure A.29). You see two permissions lists: on the left, the Available Permissions that are not assigned, and on the right, the list with assigned permissions.




Figure A.29: Modify the Permission Set Using the Create Permission Set Dialog Box





Between the two Permissions lists are four buttons. The Add and Remove buttons let you move individual permissions between the lists. Note that to prevent you from making mistakes, you cannot select more than one button at a time. You will better understand a given permission if you select that permission in the Assigned Permissions list and press the Properties button. You can use the fourth button (Import) to load an XML-coded permission set.


Now let’s make some modifications to the permission set, because that was the reason to duplicate the permission set:





Add the FileIOPermission to the Assigned Permission list.





Add the RegistryPermission to the Assigned Permission list.





Modify the SecurityPermission properties.





To do so:





Select FileIO in the Available Permissions list. (Notice that if you have selected a permission in the Assigned Permissions list, this permission stays selected.)





Click Add. A Permission Settings dialog box for the FileIO appears (see Figure A.30). (You can also double-click the permission to add it to the Assigned Permissions list. However, do not double-click an assigned permission by accident—this will remove the permission from the assigned permission list.)




Figure A.30: Modify the Settings of FileIO Using the Permission Settings Dialog Box





As you saw earlier in this appendix, this process resembles the way we used FileIOPermission and FileIOPermissionAttribute to demand and request access to specific files in a specific directory. Go ahead and fill in C:\Test\*.cfg. Surprised that you get an error message? The point is that the field demands that you use UNC names. The advantage is that you can reference to files on other servers in the domain. However, the dialog box checks the existence of the path when you click OK, so be sure that the UNC path exists.





Fill the File Path with a valid UNC of the machine you are working on, and because we want to give full access, you can check all four boxes. (Note: If you do not check any of the boxes, this is accepted because you filled in a File Path. However, if you check the properties of FileIO as an assigned permission, you will notice that the line has disappeared—hence, a beta bug!)





Click OK and you have added a permission to the assigned permission list. You are now ready for the next permission.





Double-click the Registry permission, and a Permissions Setting dialog box appears that looks a lot like the one you just saw with FileIO. Keep the option Grant assemblies access to the following registry keys.





Fill the Key field with a valid HKEY value, such as HKEY_LOCAL_MACHINE, and check the Read box, so that we can give read permission to the specified registry tree.





Click OK, and you have added your second permission to your permission set.





The last task is to modify the Security permission. Therefore, select the Security permission in the Assigned Permissions list (do not double-click it, because that will remove the permission from the list) and click Properties.





A Permission Settings dialog box (see Figure A.31) appears. You see that the option Grant assemblies the following security permissions is selected, together with the properties Enable assembly execution, Assert any permission that has been granted, and Enable remoting configuration.




Figure A.31: Modifying the Security Settings Using the Permission Settings Dialog Box






We also want to grant our security policy the security permission properties. Check Allow calls to unmanaged assemblies because we want to make calls to unmanaged code. Also check Allow principal control because we want to be able to modify principal settings. Click OK, and you are done, for now, with modifying your first permission set.





Click Finish. You will probably get a warning message stating that you changed your security policy and you have to save it. Until you save the policy, an asterisk (*) will mark the user policy.





You can save the policy by right-clicking the User runtime security policy and selecting Save.





If you want this permission set to also become part of the machine and/or enterprise permission sets, you can simply copy and paste it.


You will also notice two other options: Reset and Restore Policy. The first, Reset, resets the policy back to the default setting of the policy. You can try it, but it will wipe out all the changes you made until now. The latter choice, Restore Policy, makes it possible to go back to the previous save. This is possible because for each of the runtime security policies, the settings are saved in an XML-coded file that becomes the current one. Before this happens, the system renames the old one with the extension .old. The current one has the extension .cch. The default policy has no extension, so to speak. For the user security policy, you have the following files:





security.config The default security; used by Reset.





security.config.cch The current/active policy.





security.config.old The last saved policy version; used by Restore Policy.





The enterprise security uses the name enterprisesec.config, and the machine uses the name security.config. This is possible because the user security policy is saved in the user’s directory tree in the following folder: Document and Settings\User_Name\Application Data\Microsoft\CLR Security config\_v1.0.xxxx.


The enterprise and machine security policies are saved in the following directory: WINNT\Microsoft.NET\Framework\v1.x.xxxx\CONFIG. The CLR locates this directory through the HiveKey:


HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Catalog42\NetFrameworkv1MachineConfigdirectory


Because the configuration files are XML-coded, you can open and examine them with a Web browser. This will give you additional understanding of how the permission sets are set up. This also means that you can modify the default security policies.



Modifying the Code Group Structure



Now that we have created a security permission set, it makes sense to start using it. We can do so by attaching it to a code group. We will modify the code group structure of the user security policy. By default, the user already has a basic structure (see Figure A.32).




Figure A.32: The Default Code Group Structure for the User Security Policy


A few things might strike you at first sight:





There is a code group called Wizard_Machine_Policy. The description of this group tells you that a wizard, called the Adjust Security Wizard, copied this group from the computer’s policy level and that you should not modify it. This description is not totally true. In fact, if you take a closer look at these code groups, you will see that all groups that end with _Zone have a permission set of Nothing. This means that you, the user, cannot use the machine’s permission sets that are based on the zone evidence. However, if you are given more permissions based on the zone evidence, this will be toned down by the zone-based permission of the machine policy. The user can have permissions based on zoned evidence that is equal to or less than that allowed by the machine. However, you do see zone-based code groups at the same level as the Wizard_Machine_Policy because these are the code groups that are copied from the machine policy.





The zone-based code groups contain NetCodeGroup and FileCodeGroup. As the description states, they are generated by the .NET Configuration Tool; hence, the tool we are working with at the moment. The custom code groups are based on XML-code files and therefore the tool cannot edit them. However, you can use the caspol.exe tool to do so. Without going into detail regarding what exactly these groups entail, it suffices to state that they are necessary for you to use the .NET Configuration Tool. If you do not remove or modify them, you might lock yourself out from using this tool.





Let’s create a small code groups structure that is made up of two code groups directly under the All_Code group and apply our own custom-made permission set PrivatePermissions to the LocalIntranet_Zone group:





If you do not have the MMC with the .NET Management snap-in open, open it now.





Expand the tree to .NET Configuration | My Computer | Runtime Security Policy | User.





Now, expand Code Groups | All_Code.





Right-click All_Code and select New; the Create Code Group dialog box appears.





You are given two options: Create a new code group and Import a code group from a XML File. Use the first option. (Note: For the NetCodeGroup and FileCodeGroup, the latter option is used.)





You have to enter something in at least the Name field. For this example, we choose to enter PrivateGroup_1. Now, click Next.





The dialog box shows you a second page called Choose a condition Type and has just one field called Choose the condition type for this code group. The field has a pull-down menu containing the values from which you can choose. All of these, except the first and last one—All Code and (custom)—are evidence-related (see Figure A.33).




Figure A.33: Select One of the Available Condition Types for a Code Group





Select Site from the drop-down menu. A new field called Site Name appears and is related to the Site condition. For the sake of the example, we’ll choose the MSDN Subscribers download site, so we enter the value msdn.one.microsoft.com in the site field.





Click Next, and the third page, called Assign a Permission Set to the Code Group, appears.





You can choose between the options Use existing permission set and Create a new permission set. Because the site comes from the Internet, that permission set will do.





Select the value Nothing from the drop-down menu (Note: The permission set we just made is also part of the list), and click Next.





Click Finish, and you have created your first code group. While we are at it, let’s create the second code group, which will be the child of the code group we just created.





Right-click the code group PrivateGroup_1 and select New.





Create a new code group named PrivateGroup_2 and click Next.





Select the value Publisher from the drop-down menu. Below the field, a new box called Publisher Certificate Details appears and has to be filled by importing a certificate. You can do this by reading out of a signed assembly using the Import from Signed File button. (Note: It should say Import from signed Assembly.) Or you can import a certificate file using the Import from Certificate File button.





For the purpose of this example, we use the certificate from the msdn.one.microsoft.com site. (In case you have forgotten how this is done, you go to a protected site, thus using SSL. You double-click the icon indicating that the site is protected. This opens up the certificate. Go to the Details tab and click the Copy to File button.)





Click the Import from Certificate File button, browse to the certificate file (the extension is .cer), and open it. You will see that the field in the certificate box is filled (see Figure A.34).




Figure A.34: Importing a Certificate for a Publisher Condition in a Code Group





Click Next.





Select the existing permission group LocalIntranet. We can give more permissions now that we know that the signed assemblies indeed come from Microsoft MSDN but also originate from the corresponding _Web site.





Click Next, and then click Finish.





Before tackling our last task, let’s recap what we have done. We were concerned with creating a permission set for signed assemblies that come from the msdn.one.microsoft.com site. So, what if the assembly comes from this Web site but is not signed? It meets the condition of PrivateGroup_1, so it will get the permission set of this code group. Because this is Nothing, that would mean that these assemblies are granted no permission. However, because the msdn.one._microsoft.com site comes from the Internet Zone, it also meets the condition of the code group Internet_Zone, which grants the Internet permission set to any assembly from this zone. Moreover, because a union is taken from all the granted permission sets, these assemblies will still have enough permissions to run.


Why not make the PrivateGroup_2 a child of Internet_Zone because unsigned assemblies from msdn.one.microsoft.com are granted the Internet permission set anyway? The reason is simple: We only want to give signed assemblies from msdn.one.Microsoft.com additional permission if they also originate from the appropriate Web site. If such a signed assembly originates from another Web site, we treat it as any other assembly coming from an Internet Zone. The reason for giving PrivateGroup_1 the Nothing permission set is that it is only there to force assemblies to meet both conditions, and PrivateGroup_1 is just an intermediate stage to meet all conditions.


Keep in mind that we only discussed how the actual permission set is determined at the user security policy level. This will be intersected with the actual permission set determined on the machine level. Moreover, because at the machine level the assembly will be given only the Internet permission set, our signed assembly will wind up with the effective permission set of Internet. Normally, the actual permission set of the enterprise is also taken into the intersection, but because that code group tree has only the All_Code code group with full trust, it will play no role in the intersection of this example.


Our last task, replacing a permission set, should be straightforward by now:





Right-click the code group LocalIntranet_Zone and select Properties. The LocalIntranet_Zone Properties dialog box appears (see Figure A.35).




Figure A.35: Setting Attributes in the General Tab of the Code Group Permission Dialog Box





Select the Permission Set tab.





Open the pop-up menu with available permission sets and select PrivatePermissions. You will see that the list box will reflect the permissions that make up the PrivatePermissions permission set.





Click Apply and go back to the General tab.





On this tab is a frame called If the membership condition is met, which shows two options:





This policy level will have only the permissions from the permission set associated with this code group This refers to the code group attribute Exclusive.





Policy levels below this level will not be evaluated This refers to the code group attribute LevelFinal.





Both options need some explanation, so let’s go back to our msdn.one.microsoft.com example. Suppose you open the Properties dialog box of the Internet_Zone code group and check the Exclusive option (of course, you have to save it first for it to become active). We received a signed assembly from msdn.one.microsoft.com that also originates from this site. We had established that it would be granted the LocalIntranet_Zone permission at the user policy level. But now the Exclusive option comes into play. Because our signed assembly also meets the Internet_Zone condition, the Internet permission set is valid. The exclusive that is set for the Internet_Zone code group forces all other valid permission sets to be ignored by not taking a union of these permission sets. Instead, the permission set with the exclusive attribute becomes the actual permission set for the user policy level. Because it will be intersected with the actual permission sets of the other security levels, it also determines the maximum set of permissions that will be granted to the signed assembly.


Use this attribute with care, because from all the code groups of which an assembly is a member—hence, meets the condition—only one can have the Exclusive attribute. The CLR determines whether this is the case. When the CLR determines that an assembly meets the condition of more than one code group with the Exclusive attribute, it will throw an exception, and it fails to determine the effective permission set and the assembly is not allowed to execute.


The way the LevelFinal is handled is more straightforward. Understand that by establishing the effective permission set of an assembly, the CLR evaluates the security policies starting at the highest level (enterprise, followed by user and machine). Again, take our MSDN example. We set a LevelFinal in the PrivateGroup_2 code group and removed the Exclusive attribute from Internet_Zone. When the effective permission set for a signed assembly from msdn.one.microsoft.com that originates from that Web site has to be established, the CLR starts with determining the actual permission set of the enterprise policy level. This is for All_Code Full Trust, effectively taking this policy level out of the intersection of actual permission sets. Now the user policy level gets its turn in establishing the actual permission set. As you know by now, this will be equal to the LocalIntranet_Zone permission set. However, the CLR has also encountered the LevelFinal attribute. It refrains from establishing the actual permission set of the machine policy level and intersects the actual permission sets from the enterprise and user policy level. The actual permission set will be equal to LocalIntranet_Zone.


Because the machine policy level is not considered, the actual permission set in this case has more permission than in the situation in which the LevelFinal attribute has not been set.



Remoting Security



Discussing security between systems always provides a new set of security issues. This is no exception for remoting. Let’s start with the communication between systems. If you use an HttpChannel, you can use the SSL encryption. The FtpChannel does not have encryption, but if both servers support IPSec, you are able to create a secured channel through which the FtpChannel can communicate. All Microsoft server systems post NT to include 2000, XP, and 2003 have easy-to-implement IPSec capabilities.


The next issue is to what extent you trust the other system. Even with a secure channel in place, how do you know that the other system has not been compromised? You need at least a sturdy authentication mechanism in place, and you need to avoid the use of anonymous users, although this will not always be possible. At least try to use NTLM or Kerberos for authentication. The latter is a perfect vehicle for handling impersonation between multiple systems. If you need to use anonymous users, you can use IIS as the storefront and let the IIS handle the impersonation. You can also use a proxy to prevent a user from directly accessing your IIS.


The messages that are exchanged should always be signed so that you are able to verify the sender and/or origin. Even when you are sure that a message is transported over a secured channel, you are never sure if the message that is put in this channel has been sent with ill intent.


This chapter has discussed the use of code access and role-based security. The more thoroughly you use this runtime security instrument, the better you can control the remoting security.


/ 96