Saturday, January 26, 2008

Code Access Security (CAS)

Evidence: represents the origin of code (Application Directory, Hash, Permission Request, Publisher, Site Web, Strong Name, URL, Zone).

NOTE: For configuring the .NET Framework security we use the mscorcfg.msc.

Policy Levels

Enterprise (%Systemroot%\Microsoft.NET\Framework\version\Config\enterprise.config)
Machine (%Systemroot%\Microsoft.NET\Framework\version\Config\security.config)
User (%UserProfile%\Application Data\Microsoft\CLR Security Config\version\security.config)
AppDomain

For every Policy Level we have the All_Code group and several Permissions Sets. From the All_Code group, we can get others code groups specific for every Zone we have (Internet, Intranet, Restricted, Trusted, My_Computer, ...).

We can create our custom Code Group and assign to them our custom Permission Set.

Here one practical sample from developer.com

Sample:
- Create the strong naming key: "sn.exe -k mycas.snk"
- Assign it to our project: Project Properties\Signing or setting the option [assembly: AssemblyKeyFile(@"..\..\mycas.snk")] in AssemblyInfo.cs.
- Create a new Code Group below the User Policy level. For the membership condition, use the Strong Name and import it from the assembly.
- Create a new Permission set for this group and specify permissions like [File IO, C:\, Read only], [File Dialog, Open only], [User Interface, Unrestricted access] and [Security, Enable Assembly Execution].

IMPORTANT: For the new created group ensure that you have checked the option: This policy level will only have the permissions from the permission set associated with this code group

Running the following code will thrown an exception because we dont have write access to c:\.

private void button1_Click(object sender, EventArgs e)
{
    try
    {
        StreamWriter sw = File.CreateText(@"c:\filename.txt");
        sw.WriteLine("test line");
        sw.Close();
    }
    catch (SecurityException securityEx)
    {
        MessageBox.Show(securityEx.Message, "Security Exception");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Exception");
    }
}
Using imperative security check:
private void button1_Click(object sender, EventArgs e)
{
    FileIOPermission filePermission = new FileIOPermission(FileIOPermissionAccess.Write, @"c:\filename.txt");
    try
    {
        filePermission.Demand(); // Permission demand
 
        StreamWriter sw = File.CreateText(@"c:\filename.txt");
        sw.WriteLine("test line");
        sw.Close();
    }
    catch (SecurityException securityEx)
    {
        MessageBox.Show(securityEx.Message, "Security Exception");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Exception");
    }
}
We can also use the Security Manager to verify we have permissions before demand it.

private void button1_Click(object sender, EventArgs e)
{
    FileIOPermission filePermission = new FileIOPermission(FileIOPermissionAccess.Write, @"c:\filename.txt");
    try
    {
        if (SecurityManager.IsGranted(filePermission))
        {
            filePermission.Demand(); // Permission 
 
            StreamWriter sw = File.CreateText(@"c:\filename.txt");
            sw.WriteLine("test line");
            sw.Close();
        }
        else
            MessageBox.Show("You don't have access to c:\\filename.txt", "Access Denied");
    }
    catch (SecurityException securityEx)
    {
        MessageBox.Show(securityEx.Message, "Security Exception");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Exception");
    }
}
Using Declarative security check:

An exception is thrown before the application run the code, so our method is more simple now:

[FileIOPermission(SecurityAction.Demand, Write=@"C:\filename.txt")]
private void button1_Click(object sender, EventArgs e)
{
    try
    {
        StreamWriter sw = File.CreateText(@"c:\filename.txt");
        sw.WriteLine("test line");
        sw.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Exception");
    }
}
Bypass check using Assert:

private void button1_Click(object sender, EventArgs e)
{
    FileIOPermission filePermission = new FileIOPermission(FileIOPermissionAccess.AllAccess, @"c:\filename.txt");
    
    try
    {
        filePermission.Assert(); // Bypass permission
 
        StreamWriter sw = new StreamWriter(@"c:\filename.txt");
        sw.WriteLine("test line");
        sw.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Exception");
    }
}
Assembly Declarations:

The following declaration checks if we have access to c:\temp\filename.txt, otherwise an exception is thrown:

[assembly: FileIOPermission(SecurityAction.RequestMinimum, ViewAndModify=@"c:\temp\filename.txt")]
If we want to allow only access to specific resources, we should use RequestOptional. Example, by using the following declaration, if we try to access other file than c:\temp\filename.txt, an exception will be thrown.
[assembly: FileIOPermission(SecurityAction.RequestOptional, ViewAndModify=@"c:\temp\filename.txt")]
For refuse access to specific resources, we can use RequestRefuse:

[assembly: FileIOPermission(SecurityAction.RequestRefuse, ViewAndModify = @"c:\windows\")]
Permission Requests:

Assert: Bypass permission check. Assemblies must have the Assert Any Permission That Has Been Granted security permission setting.

Demand: Instructs the runtime to throw an exception if the caller and all callers higher in the stack lack the specified permission.

Deny: Causes the runtime to reduce the method’s access by removing the specified permission.

InheritanceDemand: Instructs the runtime to throw an exception if the assembly inheriting from the class lacks the specified permission.

LinkDemand: Causes the runtime to throw an exception if the immediate caller, but not callers higher in the stack, lack the specified permission.

PermitOnly: Instructs the runtime to reduce the method’s access by removing all permissions except for the specified permission.

References:

Code Access Security with Microsoft .NET Framework, Part 2
Managing .NET Code Access Security (CAS) Policy
Configuring .NET Code Access Security
Code Access Security / .NET Reference Guide
Code Access Security in the .NET Framework

1 comments:

Professor Howdy said...





There is a time for everything,
a season for every activity
under heaven. A time to be
born and a time to die. A
time to plant and a time to
harvest. A time to kill and
a time to heal. A time to
tear down and a time to
rebuild. A time to cry and
a time to laugh. A time to
grieve and a time to dance.
A time to scatter stones
and a time to gather stones.
A time to embrace and a
time to turn away. A time to
search and a time to lose.
A time to keep and a time to
throw away. A time to tear
and a time to mend. A time
to be quiet and a time to
speak up. A time to love
and a time to hate. A time
for war and a time for peace.

Best wishes for continued ascendancy,
Dr. Howdy

P.S. Here's some blogs & videos
that I found of interest as
I negotiated my way through
cyberspace:


Video With Above Poem
Every Student
My Blog Video
Religion Comparison
Avoid This Place
Danish Cartoons
Arabic Cartoons
Muhammad or Jesus???
Answering Islam
Is Jesus God?
A Short Look At Six World Religions
God's Word in different languages...
How to become a Christian
Who Is Jesus?
See The Word
Watch The Jesus Movie
Spanish Cartoons
German Cartoons
Chinese Cartoons
Italian Cartoons
Greek Cartoons
Japanese Cartoons
Portuguese Cartoons
Many Languages
Around the Well
French Cartoons
Hindi Cartoons
Russian Cartoons
Little Girl
Get Saved?
You & Sin City
Mysterious Disappearance
Evolution Video
The Departure
You Need To See This
'Thought & Humor'


Tell me sometime what your
thoughts are about all this:O)


View My Stats