1. Trang chủ
  2. » Công Nghệ Thông Tin

Storing Data Securely pptx

88 200 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 88
Dung lượng 455,21 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Obtaining security audit information public static void ViewFileRights { // Get security information from a file.. Getting security or audit information for a registry key public stati

Trang 1

Once you have the salt, it is combined with the plain text password and hashed using the SHA512Managed class The salt value is then appended to the end of the hashed value and returned The salt is appended so that when you attempt to vali- date the password, you know what salt was used to create the hashed value The entire value is then base64-encoded and returned:

// Make a hashed password

private string CreateHashedPassword(string password,

// Make a salt of random size

// Create a stronger hash code using RNGCryptoServiceProvider byte[] random = new byte[1];

RNGCryptoServiceProvider rngSize = new RNGCryptoServiceProvider( ); // Populate with random bytes

rngSize.GetBytes(random);

// Convert random bytes to string

Trang 2

int size = Convert.ToInt32(random);

// Create salt array

salt = new byte[size];

// Use the better random number generator to get

// bytes for the salt

// Make storage for both password and salt

byte[] saltedPwd = new byte[pwd.Length + salt.Length];

// Add pwd bytes first

pwd.CopyTo(saltedPwd,0);

// now add salt

salt.CopyTo(saltedPwd,pwd.Length);

// Use SHA512 as the hashing algorithm

byte[] hashWithSalt = null;

using (SHA512Managed sha512 = new SHA512Managed( ))

{

// Get hash of salted password

byte[] hash = sha512.ComputeHash(saltedPwd);

// Append salt to hash so we have it

hashWithSalt = new byte[hash.Length + salt.Length];

Trang 3

have that, you just compare it to thePassword property to see whether you have a match and returntrue orfalse as appropriate:

// Check the password against our storage

public bool IsPasswordValid(string password)

{

// Get bytes for password

// This is the hash of the salted password and the salt

byte[] hashWithSalt = Convert.FromBase64String(Password);

// We used 512 bits as the hash size (SHA512)

int hashSizeInBytes = 512 / 8;

// Make holder for original salt

int saltSize = hashWithSalt.Length - hashSizeInBytes;

byte[] salt = new byte[saltSize];

// Copy out the salt

Array.Copy(hashWithSalt,hashSizeInBytes,salt,0,saltSize);

// Figure out hash for this password

string passwordHash = CreateHashedPassword(password,salt);

// If the computed hash matches the specified hash,

// the plain text value must be correct

// See if Password (stored) matched password passed in

return (Password == passwordHash);

Trang 4

Isolated storage allows an application to store data that is unique to the application and the user running it This storage allows the application to write out state infor- mation that is not visible to other applications or even other users of the same appli- cation Isolated storage is based on the code identity as determined by the CLR, and

it stores the information either directly on the client machine or in isolated stores that can be opened and roam with the user The storage space available to the appli- cation isdirectly controllable by the administrator of the machine on which the application operates.

The Solution uses isolation by User, AppDomain, and Assembly by callingIsolatedStorageFile.GetUserStoreForDomain This creates an isolated store that isaccessible by only this user in the current assembly in the currentAppDomain:

// Get the isolated storage

isoStorageFile = IsolatedStorageFile.GetUserStoreForDomain( );

The Storeadm.exe utility will allow you to see which isolated-storage stores have

been set up on the machine by running the utility with the /LIST command-line

switch Storeadm.exe ispart of the NET Framework SDK and can be located in your Visual Studio installation directory under the \SDK\v2.0\Bin subdirectory.

The output after using theUserSettings class would look like this:

C:\>storeadm /LIST

Microsoft (R) NET Framework Store Admin 1.1.4322.573

Copyright (C) Microsoft Corporation 1998-2002 All rights reserved

Record #1

[Domain]

<System.Security.Policy.Url version="1">

<Url>file://D:/PRJ32/Book/IsolatedStorage/bin/Debug/IsolatedStorage.exe</Url>

</System.Security.Policy.Url>

[Assembly]

<System.Security.Policy.Url version="1">

<Url>file://D:/PRJ32/Book/IsolatedStorage/bin/Debug/IsolatedStorage.exe</Url>

</System.Security.Policy.Url>

Size : 1024

Passwords should never be stored in plain text, period It is a bad habit to get into, so

in theUserSettingsclass, you have added the salting and hashing of the password value via the CreateHashedPassword method and verification through theIsPasswordValid method Adding a salt to the hash helps to strengthen the protec- tion on the value being hashed so that the isolated storage, the hash, and the salt now protect the password you are storing.

Trang 5

The code listing for CallSecureFunctionSafelyAndEfficiently iss hown in Example 17-10.

Example 17-10 CallSecureFunctionSafelyAndEfficiently function

public static void CallSecureFunctionSafelyAndEfficiently( )

// Demand the permission set we have compiled before using Assert

// to make sure we have the right before we Assert it We do

// the Demand to ensure that we have checked for this permission

// before using Assert to short-circuit stackwalking for it, which

// helps us stay secure, while performing better

perm.Demand( );

// Assert this right before calling into the function that

// would also perform the Demand to short-circuit the stack walk

// each call would generate The Assert helps us to optimize

// our use of SecureFunction

Trang 6

The code listing forSecureFunction is shown here:

public static void SecureFunction( )

func-In order to do this, you need the permission to callAssert

The problem comesin with thisAssert, asit opensup a potential luring attack whereSecureFunction iscalled via CallSecureFunctionSafelyAndEfficiently, which callsAssertto stop theDemandstackwalks fromSecureFunction If unauthorized code with-out ReflectionPermission were able to call CallSecureFunctionSafelyAndEfficiently,theAssertwould prevent theSecureFunction Demandcall from determining that there is some code in the call stack without the proper rights This is the power of the call stack checking in the CLR when aDemand occurs

In order to protect against this, you issue a Demand for the ReflectionPermissionneeded by SecureFunction in CallSecureFunctionSafelyAndEfficientlyto close this

perm.Assert( );

// We call the secure function 100 times but only generate

// the stackwalk from the function to this calling function

// instead of walking the whole stack 100 times

Trang 7

hole before issuing theAssert The combination of thisDemandand theAssertcauses you to do one stackwalk instead of the original 100 that would have been caused by theDemand inSecureFunction.

Security optimization techniques, such as using Assert in thiscase (even though it isn’t the primary reason to useAssert), can help classlibrary aswell ascontrol devel-operswho are trusted to performAsserts in order to speed the interaction of their code with the CLR; but if used improperly, these techniques can also open up holes

in the security picture This example shows that you can have both performance and security where secure access is concerned.

If you are usingAssert, be mindful that stackwalk overrides should never be made in

a class constructor Constructors are not guaranteed to have any particular security context, nor are they guaranteed to execute at a specific point in time This lack leads

to the call stack not being well defined, and Assert used here can produce pected results.

unex-One other thing to remember withAssertisthat you can have only one activeAssert

in a function at a given time If you Assert the same permission twice, aSecurityException isthrown by the CLR You must revert the originalAssert first usingRevertAssert Then, you can declare the secondAssert

See Also

The “CodeAccessSecurity.Assert Method,” “CodeAccessSecurity.Demand Method,”

“CodeAccessSecurity.RevertAssert Method,” and “Overriding Security Checks” ics in the MSDN documentation.

Specific Permissions

Problem

When your assembly requests optional permissions (such as asking for disk access to enable users to export data to disk as a product feature) using theSecurityAction.RequestOptionalflag, it might or might not get those permissions Regardless, your assembly will still load and execute You need a way to verify whether your assembly actually obtained those permissions This can help prevent many security exceptions from being thrown For example, if you optionally requested read/write permissions

on the registry but did not receive them, you could disable the user interface trols that are used to read and store application settings in the registry.

Trang 8

Regex regex = new Regex(@"http://www\.oreilly\.com/.*");

WebPermission webConnectPerm = new WebPermission(NetworkAccess

Discussion

The IsGranted method is a lightweight way of determining whether permission is granted for an assembly without first incurring the full stackwalk that aDemandgives you Note, however, that once you exercise the code that performs theDemand, thefull stackwalk will then take place The drawback to this approach is that the code is still subject to a luring attack ifAssertis misused, so you need to consider where the call toIsGranted is being made in the overall scheme of your security

Some of the reasons you might design an assembly to have optional permissions is for deployment in different customer scenarios In some scenarios (such as desktop applications), it might be acceptable to have an assembly that can perform more robust actions (talk to a database, create network traffic via HTTP, etc.) In other scenarios, you can defer these actions if the customer does not wish to grant enough permissions for these extra services to function.

See Also

The “WebPermission Class,” “SecurityManager Class,” and “IsGranted Method” topics in the MSDN documentation.

Trang 9

17.9 Minimizing the Attack Surface of an Assembly

Problem

Someone attacking your assembly will first attempt to find out as many things as possible about your assembly and then use this information in constructing the attack(s) The more surface area you give to attackers, the more they have to work with You need to minimize what your assembly is allowed to do so that, if an attacker is successful in taking it over, the attacker will not have the necessary privi- leges to do any damage to the system.

Solution

Use the SecurityAction.RequestRefuse enumeration member to indicate, at an assembly level, the permissions that you do not wish this assembly to have This will force the CLR to refuse these permissions to your code and will ensure that, even if another part of the system is compromised, your code cannot be used to perform functions that it does not need the rights to do.

The following example allows the assembly to perform file I/O as part of its minimal permission set but explicitly refuses to allow this assembly to have permissions to skip verification:

[assembly: FileIOPermission(SecurityAction.RequestMinimum,Unrestricted=true)] [assembly: SecurityPermission(SecurityAction.RequestRefuse,

SkipVerification=false)]

Discussion

Once you have determined what permissions your assembly needs as part of your normal security testing, you can use RequestRefuseto lock down your code If this seems extreme, think of scenarios in which your code could be accessing a data store containing sensitive information, such as social security numbers or salary informa- tion This proactive step can help you show your customers that you take security seriously and can help defend your interests in case a break-in occurs on a system that your code is part of.

One serious consideration with this approach is that the use ofRequestRefusemarks your assembly as partially trusted This in turn prevents it from calling any strong- named assembly that hasn’t been marked with the AllowPartiallyTrustedCallersattribute.

Trang 10

17.10 Obtaining Security/Audit Information

Example 17-11 Obtaining security audit information

public static void ViewFileRights( )

{

// Get security information from a file

string file = @"c:\FOO.TXT";

FileSecurity fileSec = File.GetAccessControl(file);

foreach (FileSystemAccessRule ace in

fileSec.GetAccessRules(true, true, typeof(NTAccount)))

foreach (FileSystemAuditRule ace in

fileSec.GetAuditRules(true, true, typeof(NTAccount)))

Trang 11

These methods produce the following output:

Example 17-12 Getting security or audit information for a registry key

public static void ViewRegKeyRights( )

{

// Get security information from a registry key

using (RegistryKey regKey =

Trang 12

These methods produce the following output:

GetSecurityDescriptorSddlForm: 5-21-329068152-1383384898-682003330-513D:

O:S-1-5-21-329068152-1383384898-682003330-1004G:S-1-AI(A;ID;KR;;;BU)(A;CIIOID;GR;;;BU)(A;ID;KA;;;BA)(A;CIIOID;GA;;;BA)(A;ID;KA;;;SY)(A;CI IOID;GA;;;SY)(A;ID;KA;;;S-1-5-21-329068152-1383384898-682003330-

foreach (RegistryAccessRule ace in

regSec.GetAccessRules(true, true, typeof(NTAccount)))

Console.WriteLine("\tIsInherited: {0}", ace.IsInherited);

Console.WriteLine("\tPropagationFlags: {0}", ace.PropagationFlags);

Console.WriteLine(" -\r\n\r\n");

}

foreach (RegistryAuditRule ace in

regSec.GetAuditRules(true, true, typeof(NTAccount)))

Trang 14

IdentityReference.Value: CREATOR OWNER

reg-TheRegistrySecurity andFileSecurityobjects each contain a list of security rules that has been applied to the system object that it represents TheRegistrySecurityobject containsa list ofRegistryAccessRuleobjects, and theFileSecurityobject con- tainsa list ofFileSystemAccessRuleobjects These rule objects are the equivalent of the Access Control Entries (ACE) that make up the list of security rules within a DACL.

System objects other than just the Fileclass andRegistryKeyobject allow security privileges to be queried Table 17-1 lists all the NET Framework classes that return a security object type and what that type is In addition, the rule-object type that is contained in the security object is also listed.

Table 17-1 List of all *Security and *AccessRule objects and the types to which they apply

Directory DirectorySecurity FileSystemAccessRule

DirectoryInfo DirectorySecurity FileSystemAccessRule

EventWaitHandle EventWaitHandleSecurity EventWaitHandleAccessRule

RegistryKey RegistrySecurity RegistryAccessRule

Semaphore SemaphoreSecurity SemaphoreAccessRule

Trang 15

The abstraction of a system object’s DACL through the *Security objectsand the abstraction of a DACL’s ACE through the*AccessRuleobjects allows easy access to the security privileges of that system object In previous versions of the NET Frame- work, these DACLs and their ACEs would have been accessible only in unmanaged code With the NET 2.0 Framework and later, you now have access to view and program these objects.

See Also

Recipe 17.11; the “System.IO.File.GetAccessControl Method,” “System.Security AccessControl.FileSecurity Class,” “Microsoft.Win32.RegistryKey.GetAccessCon- trol Method,” and “System.Security.AccessControl.RegistrySecurity Class” topics in the MSDN documentation.

17.11 Granting/Revoking Access to a File or Registry

Example 17-13 Granting and revoking the right to perform write actions on a registry key

public static void GrantRevokeRegKeyRights( )

{

NTAccount user = new NTAccount(@"WRKSTN\ST");

using (RegistryKey regKey = Registry.LocalMachine.OpenSubKey(

@"SOFTWARE\MyCompany\MyApp"))

{

GrantRegKeyRights(regKey, user, RegistryRights.WriteKey,

InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow); RevokeRegKeyRights(regKey, user, RegistryRights.WriteKey,

Trang 16

The code shown in Example 17-14 grants and then revokes the ability to delete a file.

PropagationFlags propFlags,

AccessControlType actFlags)

{

RegistrySecurity regSecurity = regKey.GetAccessControl( );

RegistryAccessRule rule = new RegistryAccessRule(user, rightsFlags, inherFlags, propFlags, actFlags);

RegistrySecurity regSecurity = regKey.GetAccessControl( );

RegistryAccessRule rule = new RegistryAccessRule(user, rightsFlags, inherFlags, propFlags, actFlags);

regSecurity.RemoveAccessRuleSpecific(rule);

regKey.SetAccessControl(regSecurity);

}

Example 17-14 Granting and revoking the right to delete a file

public static void GrantRevokeFileRights( )

{

NTAccount user = new NTAccount(@"WRKSTN\ST");

string file = @"c:\FOO.TXT";

GrantFileRights(file, user, FileSystemRights.Delete, InheritanceFlags.None,

FileSecurity fileSecurity = File.GetAccessControl(file);

Example 17-13 Granting and revoking the right to perform write actions on a registry key

Trang 17

When granting or revoking access rights on a file or registry key, you need two things The first is a valid NTAccount object This object essentially encapsulates a user or group account A validNTAccountobject isrequired in order to create either a newRegistryAccessRuleor a newFileSystemAccessRule TheNTAccountidentifiesthe user or group this access rule will apply to Note that the string passed in to theNTAccountconstructor must be changed to a valid user or group name that exists on your machine If you pass in the name of an existing user or group account that has been disabled, an IdentityNotMappedException will be thrown with the message

“Some or all identity references could not be translated.”

The second item that isneeded iseither a validRegistryKeyobject, if you are ing security access to a registry key, or a string containing a valid path and filename

modify-to an existing file These objects will have security permissions either granted modify-to them or revoked from them.

Once these two items have been obtained, you can use the second item to obtain a security object, which contains the list of access-rule objects For example, the fol- lowing code obtains the security object for the registry key HKEY-LOCAL_ MACHINE\SOFTWARE\MyCompany\MyApp:

RegistryKey regKey = Registry.LocalMachine.OpenSubKey(

@"SOFTWARE\MyCompany\MyApp");

RegistrySecurity regSecurity = regKey.GetAccessControl( );

FileSystemAccessRule rule = new FileSystemAccessRule(user, rightsFlags,

FileSecurity fileSecurity = File.GetAccessControl(file);

FileSystemAccessRule rule = new FileSystemAccessRule(user, rightsFlags,

Trang 18

The following code obtains the security object for the FOO.TXT file:

string file = @"c:\FOO.TXT";

FileSecurity fileSecurity = File.GetAccessControl(file);

Now that you have your particular security object, you can create an access-rule object that will be added to this security object To do this, you need to create a new access rule For a registry key, you have to create a newRegistryAccessRuleobject, and for a file, you have to create a new FileSystemAccessRule object To add this access rule to the correct security object, you call theSetAccessControl method on the security object Note that RegistryAccessRule objectscan be added only toRegistrySecurity objects, and FileSystemAccessRule objectscan be added only toFileSecurity objects

To remove an access-rule object from a system object, you follow the same set of steps, except that you call the RemoveAccessRuleSpecific method instead ofAddAccessRule.RemoveAccessRuleSpecificaccepts an access-rule object and attempts

to remove the rule that exactly matchesthisrule object from the security object As always, you must remember to call the SetAccessControl method to apply any changes to the actual system object.

For a list of other classes that allow security permissions to be modified ically, see Recipe 17.12.

programmat-See Also

Recipe 17.10; the “System.IO.File.GetAccessControl Method,” “System.Security AccessControl.FileSecurity Class,” “System.Security.AccessControl.FileSystemAc- cessRule Class,” “Microsoft.Win32.RegistryKey.GetAccessControl Method,” “Sys- tem.Security.AccessControl.RegistrySecurity Class,” and “System.Security AccessControl.RegistryAccessRule Class” topics in the MSDN documentation.

17.12 Protecting String Data with Secure Strings

Trang 19

To pull the text out of aSecureString object, use the following method:

public static void ReadSecureString(SecureString secretStr)

{

// In order to read back the string, you need to use some special

methods

IntPtr secretStrPtr = Marshal.SecureStringToBSTR(secretStr);

string nonSecureStr = Marshal.PtrToStringBSTR(secretStrPtr);

// Use the unprotected string

Another feature of a SecureStringobject isthat when theMakeReadOnly method is called, theSecureStringbecomesimmutable Any attempt to modify the string data within the read-onlySecureStringobject causes anInvalidOperationExceptionto be thrown Once aSecureStringobject ismade read-only, it cannot go back to a read/ write state However, you need to be careful when calling the Copymethod on an existing SecureString object Thismethod will create a new ins tance of theSecureStringobject on which it wascalled, with a copy of itsdata However, this newSecureStringobject isnow readable and writable You should review your code

Trang 20

to determine if thisnewSecureStringobject should be made read-only similarly to its originalSecureString object.

The SecureStringobject can be used only on Windows 2000 (with

Service Pack 3 or greater) or later operating system

In thisrecipe, you create aSecureStringobject from data read in from a stream This data could also come from a char* using unsafe code TheSecureStringobject con- tainsa constructor that acceptsa parameter of thistype in addition to an integer parameter that takesa length value, which determinesthe number of charactersto pull from thechar*

Getting data out of aSecureStringobject isnot obviousat first glance There are no methodsto return the data contained within a SecureString object In order to accomplish this, you must use two static methods on theMarshal class The first is the SecureStringToBSTR, which acceptsyour SecureString object and returnsanIntPtr This IntPtr is then passed into the PtrToStringBSTR method, also on theMarshal class ThePtrToStringBSTR method then returnsan unsecureString object containing your decrypted string data.

Once you are done using the SecureString object, you should call the staticZeroFreeBSTRmethod on theMarshal class to zero out any memory allocated when extracting the data from the SecureString As an added safeguard, you should callthe Clearmethod of the SecureStringobject to zero out the encrypted string from memory If you have made yourSecureStringobject read-only, you will not be able

to call theClearmethod to wipe out its data In this situation, you must either call theDispose method on theSecureStringobject (the use of ausing block would be preferable here) or rely on the garbage collector to remove theSecureStringobject and its data from memory.

Notice that when you pull a SecureStringobject into an unsecure String, itsdatabecomes viewable by a malicious hacker So it may seem pointless to go through the trouble of using aSecureStringwhen you are just going to convert it into an inse- cureString However, by using aSecureString, you narrow the window of opportu-nity for a malicioushacker to view thisdata in memory In addition, some APIs accept aSecureStringas a parameter so that you don’t have to convert it to an unse- cureString TheProcessStartInfo, for example, accepts a password in itsPasswordproperty as aSecureString object

TheSecureStringobject is not a silver bullet for securing your data It

is, however, another layer of defense you can add to your application

Trang 21

See Also

The “SecureString Class” topic in the MSDN documentation.

17.13 Securing Stream Data

Problem

You want to use the TCP server in Recipe 17.1 to communicate with the TCP client

in Recipe 17.2 However, you need to encrypt the communication and verify that it has not been tampered with in transit.

Solution

Replace theNetworkStreamclass with the more secureSslStreamclass on both the ent and the server The code for the more secure TCP client,TCPClient_SSL, isshown

cli-in Example 17-15 (changes are cli-in boldface).

Example 17-15 TCPClient_SSL class

class TCPClient_SSL

{

private TcpClient _client = null;

private IPAddress _address = IPAddress.Parse("127.0.0.1");

private int _port = 5;

private IPEndPoint _endPoint = null;

public TCPClient_SSL(string address, string port)

using (SslStream sslStream = new SslStream(_client.GetStream( ),

false, new RemoteCertificateValidationCallback(

CertificateValidationCallback)))

{

sslStream.AuthenticateAsClient("MyTestCert2");

// Get the bytes to send for the message

byte[] bytes = Encoding.ASCII.GetBytes(msg);

Trang 22

// Send message.

Console.WriteLine("Sending message to server: " + msg);

sslStream.Write(bytes, 0, bytes.Length);

// Get the response

// Buffer to store the response bytes

bytes = new byte[1024];

// Display the response

int bytesRead = sslStream.Read(bytes, 0, bytes.Length);

string serverResponse = Encoding.ASCII.GetString(bytes, 0, bytesRead);

Console.WriteLine("Server said: " + serverResponse);

private bool CertificateValidationCallback(object sender,

X509Certificate certificate, X509Chain chain,

Console.WriteLine("The X509Chain.ChainStatus returned an array " + "of X509ChainStatus objects containing error information."); }

Console.WriteLine("SSL Certificate Validation Error!");

Example 17-15 TCPClient_SSL class (continued)

Trang 23

The new code for the more secure TCP server, TCPServer_SSL, isshown in Example 17-16 (changes are in boldface).

private TcpListener _listener = null;

private IPAddress _address = IPAddress.Parse("127.0.0.1");

private int _port = 55555;

get { return _address; }

set { _address = value; }

}

public int Port

{

get { return _port; }

set { _port = value; }

Trang 24

// Fire up the server.

listener.Start( );

// Enter the listening loop

while (true)

{

Console.Write("Looking for someone to talk to ");

// Wait for connection

TcpClient newClient = _listener.AcceptTcpClient( );

Console.WriteLine("Connected to new client");

// Spin a thread to take care of the client

ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessClient), newClient);

// Buffer for reading data

byte[] bytes = new byte[1024];

string clientData = null;

using (SslStream sslStream = new SslStream(newClient.GetStream( ))) {

sslStream.AuthenticateAsServer(GetServerCert("MyTestCert2"), false, SslProtocols.Default, true);

// Loop to receive all the data sent by the client

int bytesRead = 0;

while ((bytesRead = sslStream.Read(bytes, 0, bytes.Length)) != 0)

{

// Translate data bytes to an ASCII string

clientData = Encoding.ASCII.GetString(bytes, 0, bytesRead); Console.WriteLine("Client says: {0}", clientData);

Example 17-16 TCPServer_SSL class (continued)

Trang 25

For more information about the inner workingsof the TCP server and client and how to run these applications, see Recipes 17.1 and 17.2 In this recipe, you will cover only the changes needed to convert the TCP server and client to use theSslStream object for secure communication

TheSslStreamobject uses the SSL protocol to provide a secure encrypted channel on which to send data However, encryption is just one of the security features built into theSslStreamobject Another feature ofSslStreamisthat it detectsmaliciousor even accidental modification to the data Even though the data isencrypted, it may become modified during transit To determine if this has occurred, the data is signed with a hash before it is sent When it is received, the data is rehashed and the two hashes are compared If both hashes are equivalent, the message arrived intact; if the hashes are not equivalent, then something modified the data during transit.

The SslStream object also has the ability to use client and/or server certificates to authenticate the client and/or the server as well as allowing the client to pass a certifi- cate to the server if the client also needs to prove identity to the server These certifi- cates are used to prove the identity of the issuer For example, if a client attaches to a server using SSL, the server must provide a certificate to the client that is used to prove that the server is who it says it is In order to do this, the certificate must be

// Thank them for their input

bytes = Encoding.ASCII.GetBytes("Thanks call again!");

// Send back a response

Trang 26

issued by a trusted authority All trusted certificates are stored on the client in its root certificate store.

To allow the TCP server and client to communicate successfully, you need to set up

an X.509 certificate that will be used to authenticate the TCP server To do this, you

set up a test certificate using the makecert.exe utility Thisutility can be found in the

<drive>:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\Bin directory.

The syntax for creating a simple certificate is as follows:

makecert -r -pe -n "CN=MyTestCert2" -e 01/01/2036

The final argument to the makecert.exe utility isthe output filename, in thiscase c:\ MyAppTestCert.cer Thiswill create the certificate in the c:\MyAppTestCert.cer file on

the hard drive.

The next step involves opening Windows Explorer and right-clicking on the c:\ MyAppTestCert.cer file This will display a pop-up menu with the Install Certificate

menu item Click thismenu item and a wizard will be started to allow you to import

this cer file into the certificate store The first dialog box of the wizard is shown in

Figure 17-1 Click the Next button to go to the next step in the wizard.

The next step in the wizard allows you to choose the certificate store in which you want to install your certificate This dialog is shown in Figure 17-2 Keep the defaults and click the Next button.

The final step in the wizard is shown in Figure 17-3 On this dialog, click the Finish button.

Trang 27

After you click the Finish button, the message box shown in Figure 17-4 is played, warning you to verify the certificate that you wish to install Click the Yes button to install the certificate.

dis-Finally, the message box in Figure 17-5 is displayed, indicating that the import was successful.

At this point, you can run the TCP server and client, and they should communicate successfully.

To use theSslStreamin the TCP server project, you need to create a newSslStreamobject to wrap theTcpClient object:

SslStream sslStream = new SslStream(newClient.GetStream( ));

Before you can use this new stream object, you must authenticate the server using the following line of code:

sslStream.AuthenticateAsServer(GetServerCert("MyTestCert2"),

false, SslProtocols.Default, true);

TheGetServerCertmethod finds the server certificate used to authenticate the server Notice the name passed in to this method; it is the same as the publisher’s certificate

name switch used with the makecert.exe utility (see the –n switch) This certificate is

returned from the GetServerCert method asan X509Certificate object The next

Figure 17-1 The first step of the Certificate Import Wizard

Trang 28

argument to theAuthenticateAsServermethod isfalse, indicating that a client icate isnot required TheSslProtocols.Defaultargument indicatesthat the authenti- cation mechanism (SSL 2.0, SSL 3.0, TLS 1.0, or PCT 1.0) is chosen based on what is

certif-Figure 17-2 Specifying a certificate store in the Certificate Import Wizard

Figure 17-3 The last step of the Certificate Import Wizard

Trang 29

available to the client and server The final argument indicates that the certificate will

be checked to see whether it has been revoked.

To use theSslStreamin the TCP client project, you create a newSslStreamobject, a bit differently from how it was created in the TCP server project:

SslStream sslStream = new SslStream(_client.GetStream( ), false,

new

RemoteCertificateValidationCallback(CertificateValidationCallback));

Figure 17-4 The security warning

Figure 17-5 The import successful message

Trang 30

Thisconstructor acceptsa stream from the_clientfield, afalseindicating that the stream associated with the_clientfield will be closed when theClosemethod of theSslStream object iscalled, and a delegate that validatesthe server certificate TheCertificateValidationCallbackmethod iscalled whenever a server certificate needs

to be validated The server certificate is checked, and any errors are passed into this delegate method to allow you to handle them as you wish.

TheAuthenticateAsClient method is called next to authenticate the server:

sslStream.AuthenticateAsClient("MyTestCert2");

As you can see, with a little extra work, you can replace the current stream type you are using with theSslStream to gain the benefits of the SSL protocol

See Also

The “SslStream Class” topic in the MSDN documentation.

17.14 Encrypting web.config Information

Problem

You need to encrypt data within a web.config file programmatically.

Solution

To encrypt data within a web.config file section, use the following method:

public static void EncryptWebConfigData(string appPath,

string protectedSection,

string dataProtectionProvider) {

System.Configuration.Configuration webConfig =

WebConfigurationManager.OpenWebConfiguration(appPath); ConfigurationSection webConfigSection = webConfig

To decrypt data within a web.config file section, use the following method:

public static void DecryptWebConfigData(string appPath, string

protectedSection)

{

System.Configuration.Configuration webConfig =

WebConfigurationManager.OpenWebConfiguration(appPath);

Trang 31

ConfigurationSection webConfigSection = webConfig.

The EncryptWebConfigDatamethod uses the virtual path passed into it to open the

web.config file Thisisdone using the OpenWebConfiguration static method of theWebConfigurationManager class:

System.Configuration.Configuration webConfig =

WebConfigurationManager.OpenWebConfiguration(appPath);

Thismethod returnsaSystem.Configuration.Configurationobject, which you use to

get the section of the web.config file that you wish to encrypt This is accomplished

through theGetSection method:

ConfigurationSection webConfigSection = webConfig

GetSection(protectedSection);

Thismethod returnsaConfigurationSectionobject that you can use to encrypt the section This is done through a call to theProtectSection method:

webConfigSection.SectionInformation.ProtectSection(dataProtectionProvider);The dataProtectionProvider argument isa string identifying which data protection provider you want to use to encrypt the section information The two available provid- ersareDpapiProtectedConfigurationProviderandRsaProtectedConfigurationProvider.TheDpapiProtectedConfigurationProviderclass makes use of the Data Protection API (DPAPI) to encrypt and decrypt data The RsaProtectedConfigurationProvider class makesuse of theRsaCryptoServiceProviderclass in the NET Framework to encrypt and decrypt data.

Trang 32

The final step to encrypting the section information is to call theSavemethod of theSystem.Configuration.Configurationobject Thissavesthe changesto the web.con- fig file If this method is not called, the encrypted data will not be saved.

To decrypt data within a web.config file, you can call the DecryptWebConfigDatamethod with the following parameters:

DecryptWebConfigData("/WebApplication1", "appSettings");

The first argument is the virtual path to the web application; the second argument is the section that you want to encrypt.

EncryptWebConfigData method, except that it callsthe UnprotectSection method to

decrypt the encrypted data in the web.config file:

webConfigSection.SectionInformation.UnprotectSection( );

If you encrypt data in the web.config file using this technique, the data will cally be decrypted when the web application accesses the encrypted data in the web config file.

Action This property returns aSecurityAction enumeration value indicating the

cause of the security check failure Possible values can be any of the following:Assert

DemandDemandChoiceDeny

Trang 33

LinkDemandChoicePermitOnlyRequestMinimumRequestOptionalRequestRefuseusingData AnIDictionary of user-defined key-value pairs

Demanded Returns the permission(s) that caused theDemand to fail The returned object

needs to be cast to aPermission,PermissionSet, orPermissionSetCollection type in order to access its information You canuse theiskeyword to determine which one of these types this property returned.DenySetInstance Returns the denied permission(s) that caused theDemand to fail This property

contains a value whenever a Deny higher up in the stack causes aDemand to fail.The returned object needs to be cast to aPermission,PermissionSet, orPermissionSetCollection type in order to access its information You canuse theiskeyword to determine which one of these types this property returned.FailedAssemblyInfo Returns anAssemblyName object for the assembly where this exception

occurred (i.e., the assembly where theDemand that failed was called)

FirstPermissionThatFailed Returns anIPermission object of the first permission that failed This is useful

when several permissions in a permission set were demanded at one time Thisproperty identifies which permission caused the exception to occur

Method Returns aMethodInfoobject for the method where this exception originated If

the cause of the exception was due to aDeny orPermitOnly, the method taining theDeny orPermitOnly will be returned by this property From thisobject you can also obtain information on the type and assembly that contain thismethod

con-PermitOnlySetInstance Returns the permission(s) that were set by aPermitOnlyat the point where the

security exception was thrown The returned object needs to be cast to aPermission,PermissionSet, orPermissionSetCollection type inorder to access its information You can use theis keyword to determine whichone of these types this property returned

URL Returns a string representing the URL of the assembly where this exception

originated

Zone Returns aSecurityZone enumeration value indicating the zone of the

assem-bly where this exception originated Possible values can be any of the following:Internet

IntranetMyComputerNoZoneTrusted

Table 17-2 SecurityException Properties (continued)

Trang 34

These new properties on theSecurityExceptionclass provide much more insight into what caused the exception to be thrown For example, if you think a Demand has failed, you can examine the Action property to determine that it wasin fact theDemand Next, you can use the Demanded property to find out exactly what permis- sion(s) the Demand attempted to demand You can compare thisto the GrantedSetproperty, which contains the permission(s) that were granted to the assembly Now that you know what caused the Demand to fail, you can use the Method,FailedAssemblyInfo, andURL properties to determine where the failure occurred.TheDataproperty can be a very useful property to a developer This property con- tainskey-value pairsthat the developer createsand fillswith information concerning why thisexception occurred In thisproperty, you can place variable namesand the data they contained at the time of the exception Thiscan give you even more clues asto why thisexception wasthrown Be very careful that you do not leak thisinfor- mation out to the user An attacker can use this information to gain more under- standing of your application and overcome its defenses See Recipe 17.11 for more information on theException.Data property

See Also

The “SecurityException” topic in the MSDN documentation.

17.16 Achieving Secure Unicode Encoding

Or use the constructor for theUTF8Encoding class that accepts two parameters:

UTF8Encoding encoding = new UTF8Encoding(true, true);

Trang 35

When error detection isturned on, errorssuch asthe following are dealt with by throwing anArgumentException:

• Leftover bytesthat do not make up a complete encoded character sequence exist.

• An invalid encoded start character was detected For example, a UTF8 character does not fit into one of the following classes: Single-Byte, Double-Byte, Three- Byte, Four-Byte, Five-Byte, or Six-Byte.

• Extra bits are found after processing an extra byte in a multibyte sequence.

• The leftover bytes in a sequence could not be used to create a complete ter.

charac-• A high surrogate value is not followed by a low surrogate value.

• In the case of theGetBytesmethod, thebyte[] that is used to hold the resultingbytes is not large enough.

• In the case of theGetCharsmethod, thechar[] that is used to hold the resultingcharacters is not large enough.

If you use a constructor other than the one shown in this recipe or if you set the last parameter in thisconstructor to false, any errorsin the encoding sequence areignored, and no exception is thrown.

// Wrap our file handle in a safe handle wrapper object

using (Microsoft.Win32.SafeHandles.SafeFileHandle safeHFile =

new Microsoft.Win32.SafeHandles.SafeFileHandle(hFile, true))

{

// Open a FileStream object using the passed-in safe file handle using (FileStream fileStream = new FileStream(safeHFile,

Trang 36

{

// Flush before we start to clear any pending unmanaged actions fileStream.Flush( );

// Operate on file here

string line = "Using a safe file handle object";

// Write to the file

byte[] bytes = Encoding.ASCII.GetBytes(line);

con-Discussion

ASafeFileHandleobject contains a single handle to an unmanaged file resource This classhastwo major benefitsover using anIntPtrto store a handle—critical finaliza- tion and prevention of handle recycling attacks TheSafeFileHandle isseen by the garbage collector asa critical finalizer, due to the fact that one of theSafeFileHandle’s base classes isCriticalFinalizerObject The garbage collector sep-aratesfinalizersinto two categories: critical and noncritical The noncritical finaliz- ers are run first, followed by the critical finalizers If aFileStream’sfinalizer flushesany data, it can assume that the SafeFileHandle object is still valid, because theSafeFileHandle finalizer is guaranteed to run after theFileStream’s

TheClosemethod on theFileStreamobject will also close its

underly-ingSafeFileHandle object

Since theSafeFileHandlefallsunder critical finalization, it meansthat the underlying unmanaged handle isalwaysreleas ed (i.e., the SafeFileHandle.ReleaseHandlemethod isalwayscalled), even in situationsin which theAppDomainiscorrupted and/

or shutting down or the thread is being aborted This will prevent resource handle leaks.

Trang 37

TheSafeFileHandleobject also helps to prevent handle recycling attacks The ing system aggressively tries to recycle handles, so it is possible to close one handle and open another soon afterward and get the same value for the new handle One way an attacker will take advantage of this is by forcing an accessible handle to close

operat-on operat-one thread while it is possibly still being used operat-on another in the hope that the handle will be recycled quickly and used as a handle to a new resource, possibly one that the attacker does not have permission to access If the application still has this original handle and is actively using it, data corruption could be an issue.

Since thisclassinheritsfrom theSafeHandleZeroOrMinusOneIsInvalidclass, a handle value of zero or minus one is considered an invalid handle.

See Also

The “Microsoft.Win32.SafeHandles.SafeFileHandle Class” topic in the MSDN documentation.

Trang 38

Chapter 18

CHAPTER 18

A thread represents a single flow of execution logic in a program Some programs

never need more than a single thread to execute efficiently, but many do, and that is what this chapter is about Threading in NET allows you to build responsive and efficient applications Many applications have a need to perform multiple actions at the same time (such as user interface interaction and processing data), and threading providesthe capability to achieve this Being able to have your application perform multiple tasks is a very liberating and yet complicating factor in your application design Once you have multiple threads of execution in your application, you need to start thinking about what data in your application needs to be protected from multi- ple accesses, what data could cause threads to develop an interdependency that could lead to deadlocking (Thread A hasa resource that Thread B iswaiting for, and Thread B has a resource that Thread A is waiting for), and how to store data you want to associate with the individual threads You will explore some of these issues

to help you take advantage of thiswonderful capability of the NET Framework You will also see the areas where you need to be careful and items to keep in mind while designing and creating your multithreaded application.

18.1 Creating Per-Thread Static Fields

Problem

Static fields, by default, are shared between threads within an application domain You need to allow each thread to have its own nonshared copy of a static field, so that this static field can be updated on a per-thread basis.

Trang 39

using System.Threading;

public class ThreadStaticField

{

public static string bar = "Initialized string";

public static void DisplayStaticFieldValue( )

Trang 40

This code displays output that resembles the following:

9 contains static field value of: Initialized string

10 contains static field value of: Initialized string

9 contains static field value of: Initialized string

In the preceding example, the current thread’shash value is9, and the new thread’s hash value is 10 These values will vary from system to system Notice that both threads are accessing the same staticbarfield Next, add theThreadStaticAttribute

to the static field:

public class ThreadStaticField

{

[ThreadStaticAttribute( )]

public static string bar = "Initialized string";

public static void DisplayStaticFieldValue( )

Now, output resembling the following is displayed:

9 contains static field value of: Initialized string

10 contains static field value of:

9 contains static field value of: Initialized string

Notice that the new thread returnsanullfor the value of the staticbarfield Thisis the expected behavior Thebarfield is initialized only in the first thread that accesses

it In all other threads, this field is initialized tonull Therefore, it isimperative thatyou initialize thebar field in all threads before it is used

Remember to initialize any static field that is marked with

ThreadStaticAttribute before it is used in any thread That is, this

field should be initialized in the method passed in to theThreadStart

delegate You should make sure to not initialize the static field using a

field initializer as shown in the prior code, since only one thread gets

to see that initial value

Thebarfield isinitialized to the"Initialized string"string literal before it is used

in the first thread that accesses this field In the previous test code, thebarfield was accessed first, and, therefore, it was initialized in the current thread Suppose you were to remove the first line of theTestStaticField method, as shown here:

public static void TestStaticField( )

{

// ThreadStaticField.DisplayStaticFieldValue( );

Ngày đăng: 12/08/2014, 09:22

TỪ KHÓA LIÊN QUAN