dev354 distributed security practices juval löwy
TRANSCRIPT
DEV354
Distributed Security Practices
Juval Löwy
www.idesign.net
About Juval LöwySoftware architect
Consults and trains on .NET migration and design
MS Regional Director for the Silicon Valley
AuthoredProgramming .NET components (2003, O’Reilly)
COM and .NET component services (2001, O’Reilly)
Participates in the .NET design reviews
Contributing editor and columnist to the Visual Studio Magazine
Contact at www.idesign.net
Outline
.NET role-based security
Web services security
.NET remoting and security
Enterprise Services security
Design guidelines and example (time permitting)
©2003 IDesign Inc. All rights reserved
.NET Role-Based Security
Role-Based Security
User, instead of code permission
What a particular security identity is allowed to do
Identity is user or accountAuthorize based on identity
Roles are by default NT user groupsCan define with some work other options
Declare in code required role memberships
Can apply on methods, but not interfaces
Must set the principal policy first per app domainTypically done in Main()
Role-Based Security
static void Main() { AppDomain currentDomain = Thread.GetDomain(); currentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);}
[PrincipalPermission(SecurityAction.Demand,Role=@"<domain>\Manager")]public class MyClass{}
Can demand a particular user (with or without role):
Can demand only that user is authenticated:
Role-Based Security
[PrincipalPermission(SecurityAction.Demand, Role =@"<domain>\Manager", Name ="Bill")]public class MyClass{}
[PrincipalPermission(SecurityAction.Demand,Authenticated=true)]public class MyClass{}
Principal
public interface IPrincipal { IIdentity Identity {get;} bool IsInRole(string role);}
Principal implements IPrincipal System.Security.Principal
An object representing identity and role(s) information
Everything you need to know to make authorization decision
Principal
Every thread has a principal
Available implementations GenericPrincipal
WindowsPrincipal
When decision requires runtime parameters
[PrincipalPermission(SecurityAction.Demand,Role =@"<domain>\Customers")][PrincipalPermission(SecurityAction.Demand,Role =@"<domain>\Tellers")] public void TransferMoney(double sum,long accountSrc,long accountDest){ IPrincipal principal; principal = Thread.CurrentPrincipal; bool callerInRole = false; callerInRole = principal.IsInRole(@"<domain>\Customer"); if(callerInRole)//The caller is a customer { if(sum > 5000) { string msg = @"Caller does not have sufficient credentials to transfer this sum"; throw(new UnauthorizedAccessException(msg)); } } DoTransfer(sum,accountSrc,accountDest);//Helper method }
Programmatic RBS
©2003 IDesign Inc. All rights reserved
Web Services Security
Security
Based on IIS/ASP.NET
No user/UI pages/formsClient must set credentials programmatically
Windows authenticationBasic, Digest, Integrated
Client has Windows account on server
Set authentication to Windows in config file
All calls are authenticated
Security
CustomGranular control
Must enable anonymous access
Set authentication to None in config file
Various optionsLogon method with cookie
SOAP header
SOAP extension
Windows Authentication - Basic
Client provides credentials
Set Credentials property of wrapper classICredentials
null by default
Available implementationsNetworkCredentials,CredentialCache
Provide domain, user name and password
Can enable pre-authentication
Client sets credentials dynamically
Client may not be a Windows station
using System.Net;
SecureCalculator calc = new SecureCalculator();ICredentials credentials;credentials = new NetworkCredential("UserName","Password","Domain");calc.Credentials = credentials;calc.PreAuthenticate = true; //Optional
int res = calc.Add(2,3);Debug.Assert(res == 5);
Windows Authentication - Basic
using System.Net;
public class SecureCalculator : SoapHttpClientProtocol { public SecureCalculator () { ICredentials creds; creds = new NetworkCredential("UserName","Password","Domain"); Credentials = creds; Url = "http://www.CalculationServices/SecureCalculator.asmx"; } //Method wrappers…}
Windows Authentication - Basic
Can encapsulate in constructor ofproxy class if credentials are static
Windows Authentication - Digest
Send hash of passwordIIS verifies password
Requires Active Directory
Client may not be a Windows stationSecureCalculator calc = new SecureCalculator();ICredentials credentials = new CredentialCache();Uri uriPrefix = new Uri(@"http://www.CalculationServices/");ICredentials creds;creds = new NetworkCredential("UserName","Password","Domain");
credentials.Add(uriPrefix,"Digest",creds);
calc.Credentials = credentials;calc.PreAuthenticate = true; //Optionalcalc.Add(2,3);
using System.Net;
SecureCalculator calc = new SecureCalculator();calc.Credentials = CredentialCache.DefaultCredentials; calc.PreAuthenticate = true; //Optional
int res = calc.Add(2,3);Debug.Assert(res == 5);
Windows Authentication - Integrated
Password not sent in clear textProprietary Windows Protocol
Client must be a Windows station
Client sends default current user creds
Log-in Method
Method accepting user name and passwordUseful in conjunction with licensing, billing, 3rd party authentication services
Can also have log-out method
Somewhat less secure than continuous authentication
Server side:Store flag in session state
Manually verify in every other method
Log-in Method
Client side:Enable cookies
Use log-in method before calling sensitive methods
Can encapsulate in wrapper class constructor
public class SecureCalculator : WebService{ bool IsAuthenticated { get{ object state = Session["IsAuthenticated"]; if(state != null) { return (bool)state; } //Must be first request in session IsAuthenticated = false; return false; } set { Session["IsAuthenticated"] = value; } } [WebMethod(EnableSession=true)] public bool LogIn(string userName,string password) { UserManager userManager = new UserManager(); bool authenticated = userManager.Authenticate(userName,password); IsAuthenticated = authenticated; return authenticated; }
[WebMethod(EnableSession=true)] public void LogOut() { IsAuthenticated = false; } [WebMethod(EnableSession=true)] public int Add(int num1,int num2) { if(IsAuthenticated == false) { throw new UnauthorizedAccessException("Invalid user name or password passed to this web service"); } return num1+num2; }} //Client-sideSecureCalculator calc = new SecureCalculator();calc.LogIn("UserName","Password");calc.Add(2,3);
calc.LogOut();calc.Add(2,3); //Throws exception
Log-in Method
Can factor logon functionality to a base class
Constructor installs custom principal
Web methods declaratively demand authentication
public class LogInCalculator : LogInWebService{ [PrincipalPermission(SecurityAction.Demand,Authenticated = true)] [WebMethod(EnableSession=true)]//Required! public int Add(int num1,int num2) { return num1+num2; }}
Soap Headers AuthenticationCan add custom information to payload
Not just security
Header-state managed automatically
Server side:Derive a class from SoapHeader
Add credentials as public member
Add header as public member to web service definition
Use SoapHeader attribute on sensitive methods identifying member by name
Manually authenticate
using System.Web.Services.Protocols;public class AuthenticationHeader : SoapHeader{ public string UserName; public string Password;}public class SecureCalculator { public AuthenticationHeader AuthHeader; bool Authenticate()//Helper method { UserManager userManager = new UserManager(); return userManager.Authenticate(AuthHeader.UserName, AuthHeader.Password); } [SoapHeader("AuthHeader")] [WebMethod] public int Add(int num1,int num2) { if(Authenticate()== false) { throw new UnauthorizedAccessException("Invalid user name or password passed to this web service"); } return num1+num2; }}
Soap Headers Authentication
Client side: WSDL-generated wrapper class has member corresponding to header
Named after type suffixed by Valuenull by default
Instantiate header object
Provide credentials
Assign to wrapper class
Can encapsulate by wrapper class if credentials static
public class AuthenticationHeader : SoapHeader { public string UserName;//Members only, no properties public string Password;}
public class SecureCalculator : SoapHttpClientProtocol { public AuthenticationHeader AuthenticationHeaderValue; //Method wrappers…}
SecureCalculator calc = new SecureCalculator();
calc.AuthenticationHeaderValue = new AuthenticationHeader(); calc.AuthenticationHeaderValue.UserName = "UserName";calc.AuthenticationHeaderValue.Password = "Password"; int res = calc.Add(2,3);Debug.Assert(res == 5);
Soap Headers AuthenticationSoap Headers Authentication
Soap Headers Authentication
Can issue cookie to optimize credentials lookup
Payload still contains header info
SOAP Extension
Affects all web methods in web service Intercepts message before service invocation
Effectively, .NET to .NET
Can provide generic guest credentials for unauthenticated users
Can provide processing common to multiple services
Authentication in Global class
SOAP Extension Can provide custom message encryption/decryption
Before message converted into objects
Keys distribution is problematic Not ideal for true public services
SSL is easier
Encrypts all communication, even non-sensitive
Requires client-side configurationProgrammatic
Administrative
Will be obsolete by GXA / WS-I
WS Security Authentication Summary
WS Impersonation
When using Windows security, .NET automatically impersonates client
Regardless of authentication mode
When using custom authentication, WS runs under designated anonymous identity
Even if client provides Windows credentials
With custom identities, service typically impersonates a designated identity
WS Impersonation
Can manually impersonate clientLog on a Windows account
Impersonation requires authentication
Server-side impersonationObtain credentials from login method or SOAP header
Log-on client using interop
LogonUser()
Security and Impersonation
Server-side impersonation (cont’)If logon successful
Duplicate security token
Create new Windows Identity
Save impersonation context
Save old security principal
Replace the security principal on both the HTTP context and current thread
Revert to old identity on call return
©2003 IDesign Inc. All rights reserved
.NET Remoting and Security
Remoting and Security
In .NET 1.1, remoting does not provide secure channels
No authentication
No call context propagationIdentity
Credentials
Impersonation
Remoting and Security
Can install a custom secure remoting channelNTLM /Kerberos
Call context propagationhttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/remsspi.asp
www.idesign.net
Likely to be incorporated in .NET 2.0
©2003 IDesign Inc. All rights reserved
Enterprise Services Security
ES Security
Only way in .NET 1.1 for authentication of remote calls out of the boxGranular control
Encryption
Rich role-based security Independent of Windows groups
Full security call context propagation
ES Application Security
ApplicationAccessControl attribute Turning authorization on/off
Security level
Authentication level
Impersonation level
Server app
[assembly: ApplicationActivation(ActivationOption.Server)][assembly: ApplicationAccessControl( true,//Authorization AccessChecksLevel=AccessChecksLevelOption.ApplicationComponent, Authentication=AuthenticationOption.Packet, ImpersonationLevel=ImpersonationLevelOption.Identify)]
Application Security
[assembly: ApplicationActivation(ActivationOption.Library)][assembly: ApplicationAccessControl( true,// Authorization AccessChecksLevel=AccessChecksLevelOption.ApplicationComponent,
//use AuthenticationOption.None to turn off authentication, //and any other value to turn it on Authentication=AuthenticationOption.None)]
Application Security
Library app:
[ComponentAccessControl(true)]public class MyComponent :ServicedComponent,IMyInterface{}
Turn component level access checks on or off using ComponentAccessControl attribute
Default constructor turns security on [ComponentAccessControl]
Component Access Checks
[assembly: SecurityRole("Manager", Description = "Can access all components")][assembly: SecurityRole("Teller", Description = "Can access IAccountsManager only")]
Adding Roles to Application
Use SecurityRole attribute
Description property is optional
Overloaded constructors
Use the Marshaler role to create components
SecureMethod attribute to prevent marshaler from abusing reflection
At class or method level
[assembly: SecurityRole("Manager")] [assembly: SecurityRole("Manager", false)] [assembly: SecurityRole("Manager",SetEveryoneAccess = false)]
[assembly: SecurityRole("Marshaler",SetEveryoneAccess = true)]
Adding Roles to Application
[assembly: SecurityRole("Role1")][assembly: SecurityRole("Role2")][assembly: SecurityRole("Role3")] [SecurityRole("Role2")]interface IMyInterface{ [SecurityRole("Role3")] void MyMethod();} [SecurityRole("Role1")]public class MyComponent :ServicedComponent,IMyInterface{}
Assigning Roles to Component, Interface, Method
SecurityRoleattribute
Done via SecurityCallContext objectCurrent call is a static property of same type
using System.Security;//for the security exception public class Bank : ServicedComponent{ void TransferMoney(int sum,long accountSrc,long accountDest) { bool callerInRole = false; callerInRole = SecurityCallContext.CurrentCall.IsCallerInRole("Customer"); if(callerInRole)//The caller is a customer { if(sum > 5000) throw(new UnauthorizedAccessException(@"Caller does not have sufficient
credentials to transfer this sum")); } DoTransfer(Sum,accountSrc,accountDest);//Helper method } //Other methods}
Verifying Caller’s Role Membership
©2003 IDesign Inc. All rights reserved
Design Guidelines and Best Practices
Code-Access Security
Crank it all the way up until someone complains
Design and deploy separate policies for clients and server
Prefer content to origin based evidence
Identities
The further from the user, the less relevant its identity
Middle tier components should run under designated identity
Separate from the user
Separate processes
Class library/Server process based on running under client identity
Authentication
At every crossing of tier boundary
Privacy is good
Class library/Server based on required authentication
Library can be very useful
Resources should implicitly trust middle tier Only authenticate its identity
Authorization
At every crossing of boundary
Can resort to custom RBS
Should impersonate only for authorization, then revert
More at TechEd
C# Best Practices DEV312
Distributed Security PracticesDEV354
Building High-Performance Applications with Visual Studio .NET
DEV326
Application and Library VersioningDEV343
Software Legends – VS.NET and C# tips and tricksSWL004
ResourcesResourcesProgramming .NET components
By Juval Lowy, O'Reilly April 2003
www.idesign.net
.NET Master Class3-4 annually
Upcoming events onwww.idesign.net
Community Resources
Community Resourceshttp://www.microsoft.com/communities/default.mspx
Most Valuable Professional (MVP)http://www.mvp.support.microsoft.com/
NewsgroupsConverse online with Microsoft Newsgroups, including Worldwidehttp://www.microsoft.com/communities/newsgroups/default.mspx
User GroupsMeet and learn with your peershttp://www.microsoft.com/communities/usergroups/default.mspx
evaluationsevaluations
SOFTWARE LEGENDSOFTWARE LEGENDJuval LowyJuval Lowy
THURSDAY 3rd JULY at 16.15-16.45 hrs
Meet the Author’sMeet the Author’s Book signingBook signing
© 2003 Microsoft Corporation. All rights reserved.© 2003 Microsoft Corporation. All rights reserved.This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.