Essential .NET Security

368
Essential .NET Security Security on the new platform

Transcript of Essential .NET Security

Page 1: Essential .NET Security

Essential .NET SecuritySecurity on the new platform

Page 2: Essential .NET Security

2

Introductions

• What is your first name?• What sort of job do you do?• What does security mean to you?• What programming languages are you fluent in?• Do you have any particular expectations?

Page 3: Essential .NET Security

3

Goals of the class

• Learn what threats are out there• Learn what it takes to design secure systems• Examine security features of the .NET platform• Learn how to use them correctly

Page 4: Essential .NET Security

4

Module Outline

• Threats and Mitigation• Conventional Cryptography and Kerberos• Public Key Cryptography and SSL• Windows Security 101: Basics• Windows Security 102: Impersonation and Delegation• Code Access Security Part 1, Policy• Code Access Security Part 2, Enforcement• Securing Web Applications• Securing Web Services• Securing System.Runtime.Remoting• Securing COM+• Dumb Code: avoid writing code with silly security holes

Page 5: Essential .NET Security

5

Logistics

• Hours• Food• Facilities• Materials

Page 6: Essential .NET Security

Threats and Mitigation

Page 7: Essential .NET Security

7

Objectives

• What types of threats are out there?• Ways of mitigating those threats• A process for designing secure code• Some guiding principals for writing secure code• Authentication• Authorization• Other security techniques and technologies

Page 8: Essential .NET Security

8

The STRIDE Threat Model

• STRIDE– Spoofing Identity– Tampering with data– Repudiation– Information Disclosure– Denial of Service– Elevation of Privilege

Page 9: Essential .NET Security

9

Spoofing identity

• Attacker pretends to be someone he is not– there are two flavors of this attack

• Spoofing client identity– access a server and pretend to be a legitimate user– gain access to sensitive data– run potentially dangerous queries/processes on the server– gain administrative access to the server

• Spoofing server identity– pretend to be a legitimate server to unsuspecting clients– collect sensitive data from clients– provide false data to clients– often opens the door for other attacks

Page 10: Essential .NET Security

10

Mitigating the spoofing threat

• Strong authentication is the best defense– authentication is a secure process for validating identity– clients can prove their identities to servers– servers can prove their identities to clients

• Identity can be proved in several ways– something you have– something you know– something you are

• Authenticating over a network requires cryptography– more on this later…

Page 11: Essential .NET Security

11

Tampering with data

• Attackers often gain advantage by tampering with data• Tampering with persistent data

– change prices for products they want to buy online– modify audit logs to cover their tracks– modify password data to gain access to other user accounts– corrupt data files to crash, or even take over a server– deface web pages– add viruses or Trojan horses to files– tamper with network topology (routing tables, DNS, etc.)

• Tampering with network packets– tampering with packets on the wire

Page 12: Essential .NET Security

12

Mitigating the tampering threat

• Protect persistent data– hash codes– digital signatures– encryption– example: NTFS Encrypting File System (EFS)

• Protect network packets– network authentication protocols usually offer integrity and

confidentiality protections via cryptography– Kerberos– SSL/TLS– IPSec

Page 13: Essential .NET Security

13

Repudiation

• Attacker denies an action, and victim cannot prove otherwise– an attacker might:

• claim he didn’t delete a file• claim he didn’t make a purchase or return• claim he didn’t receive goods/services

Page 14: Essential .NET Security

14

Mitigating the repudiation threat

• Mitigation techniques are called nonrepudiation– audit actions in the OS and protect the audit logs– require receipts as acknowledgement– use timestamps– digital signatures can help with electronic transactions

Page 15: Essential .NET Security

15

Information disclosure

• Attacker sees data he shouldn’t be seeing– local files– data traveling between computers

• Attacker sees information about the system architecture– banners that display software type and version– helps the enemy narrow down potential attacks

Page 16: Essential .NET Security

16

Mitigating the information disclosure threat

• Use strong authentication and consistent access control• Encryption might help

– NTFS EFS, for example• Turn off banners on publicly exposed services

– or expose purposely misleading banners– obscurity is not security but sometimes it helps

• Disable tracing and debugging features in production apps• Avoid sending verbose error information to clients

– Pipe this information to internal logs instead

Page 17: Essential .NET Security

17

Denial of service (DoS)

• Attacker causes your service to become unavailable– usually associated with services provided over a network

• syn flood attacks• distributed denial of service attacks (DDoS)• amplification attacks such as smurf• all designed to consume precious bandwidth!

– the anonymity of TCP/IP doesn’t help• DoS attacks are quite troublesome because the attacker

can spoof his source ip address randomly

Page 18: Essential .NET Security

18

Mitigating the denial of service attack

• Increase availability and reliability– make sure your system doesn’t melt under high loads– have a strategy for throttling requests– consider clustering– buy more bandwidth

• Filtering and throttling– block incoming ICMP broadcasts (for example)– throttle anonymous requests

• Be a good neighbor– egress filtering (verify source IP addr on outgoing packets)– automate virus checking to avoid DDoS zombies

Page 19: Essential .NET Security

19

Elevation of privilege

• Attacker finds a way to gain more privileges on the system– the ultimate goal is to gain administrative privileges– most common exploit is the buffer overflow (more on this later)– bugs in the operating system itself can allow this

Page 20: Essential .NET Security

20

Mitigating the elevation of privilege threat

• Produce and consume only quality, robust code– avoid common security errors like buffer overflows– fear user input

• more on this later– run code with only the privileges it really needs

• known as Principal of Least Privilege– eliminate dead code

• code paths that are never used• features of third party software that you don’t need

– keep up to date with the latest operating system patches• HFNETCHK.EXE + Baseline Security Analyzer• http://www.microsoft.com/security

Page 21: Essential .NET Security

21

Summary of STRIDE threats and mitigation

• STRIDE– Spoofing Identity

• strong authentication– Tampering with data

• hash codes, digital signatures, encryption– Repudiation

• audit logs, receipts, digital signatures, timestamps– Information Disclosure

• strong authentication, access control, encryption, obscurity– Denial of Service

• increase availability, reliability, and be a good neighbor– Elevation of Privilege

• robust code, least privilege, OS patches

Page 22: Essential .NET Security

22

The three components of a secure system

• Just as with physical security, we need all three– protection– detection– reaction

• You don’t need unbreakable protection– you really can’t achieve this anyway– many developers throw up their hands if they can’t design a

perfect solution (it feels frustrating)• Design detection and reaction into your systems

– protection then becomes a way to slow down the attacker– once detected, an attack can be halted by a sysadmin– diagnose and patch the problem quickly

Page 23: Essential .NET Security

23

A process for developing secure apps

• Security should be an integral part of the design process– write down your security goals– examine the system architecture– determine the threats using STRIDE– prioritize threats

• risk = (potential damage) x (likelihood of success)– choose a response

• accept the risk as is• warn the user (transfer the risk)• remove the feature (remove the risk)• fix the problem (mitigate the risk)

– revisit your security strategy with each iteration!

Page 24: Essential .NET Security

24

General principals to live by

• Security is a feature• Use least privilege• Layer your defenses• Pay attention to failure modes• Prefer secure defaults• Cryptography doesn’t ensure security• Firewalls don’t ensure security

Page 25: Essential .NET Security

25

Security is a feature

• Security is a crosscutting feature– Similar to performance

• Impossible to bolt on security at the end of a project– Requires constant attention and iteration

• Be sure you have a security feature team• Need to convince management you need security?

– It’s amazing what a demonstration can do

Page 26: Essential .NET Security

26

Use least privilege

• Run your code with only the privileges it requires– most services don’t need to run as SYSTEM– most desktop apps don’t need admin privileges

• Use WinXP and .NET Server’s built in low-privilege accounts– NT Authority \ LocalService– NT Authority \ NetworkService

• Don’t be lazy– open kernel objects for only the permissions you really need– test your code in a non-administrative environment– or go one step further and WRITE your code in a non-

administrative environment!

Page 27: Essential .NET Security

27

Layer your defenses

• Don’t assume someone else will save you– Consider your code the last bastion of defense– Validate input data

Page 28: Essential .NET Security

28

Pay attention to failure modes

• Developers focus on normal paths of execution• Attackers focus on failure modes

devote at least as much time to design, code, and test error handling paths as you do for

normal paths of execution

Page 29: Essential .NET Security

29

Prefer secure defaults

• Don’t ship code with every possible feature enabled– This just broadens the attack surface area

• Case in point– IIS 5 installed on every workstation by default in Win2k– IIS 5 enabled several features that few people needed– Those unused features harbored bugs that went unnoticed

until hackers found and exploited them

Page 30: Essential .NET Security

30

Cryptography doesn’t ensure security

• So what if you’re using 128-bit encryption?– Are the keys generated from low entropy passwords?– Where are the keys stored?– How are the keys exchanged?– How much data is encrypted with a single key?– Did you realize that encryption does not ensure integrity?

Page 31: Essential .NET Security

31

Firewalls don’t ensure security

• Any application exposed through the firewall must be robust– Dumb code in exposed applications leads to compromise

• How do you manage trust across a firewall?– Do you trust the authority outside the firewall to authenticate

external clients?

Page 32: Essential .NET Security

32

Books every Windows programmer should own

• Secrets and Lies– Schneier

• Hacking Exposed (latest edition)– McClure, et al.

• Writing Secure Code– Howard & LeBlanc

• .NET Framework Security– LaMacchia, et al.

• Programming Windows Security– Brown

Page 33: Essential .NET Security

33

Summary

• Security is a feature, design it as such!• STRIDE helps us categorize threats• Design protection, detection, and reaction into your systems

Page 34: Essential .NET Security

Conventional Cryptography and Authentication

Cryptography, passwords, and Kerberos

Page 35: Essential .NET Security

35

Outline

• Conventional cryptography• Using passwords as keys• Conventional crypto from .NET• Network authentication using passwords• The Kerberos authentication protocol• SSPI, the unmanaged interface to Kerberos• Using Kerberos from managed code

Page 36: Essential .NET Security

36

Conventional cryptography

• Conventional cryptography uses symmetrical algorithms– same key material used to encrypt and decrypt

plaintext ciphertextkey

encrypt

plaintext ciphertextkey

decrypt

Page 37: Essential .NET Security

37

Uses of cryptography

• Encrypting static data– generate a random key– encrypt the data– store the key somewhere safe, offline for instance– provide key at later date to allow decryption

• Encrypting network traffic– generate a random key– share it secretly with a peer on the network– use the shared key to encrypt message before sending– use the shared key to decrypt message upon reception

• Network authentication– Can use cryptography to prove knowledge of a password

Page 38: Essential .NET Security

38

Stream Ciphers

• How a stream cipher works– key is used as a seed for a pseudo-random-number generator– run the PRNG continuously to get a key stream– XOR each bit of plaintext with corresponding bit in key stream– Most common example is RC4

• Benefits– easy to implement, blazingly fast– ciphertext is always exactly the same length as plaintext

• Drawbacks– incredibly easy to misuse– most software that uses stream ciphers has at one time been

buggy and insecure• System.Security.Cryptography doesn’t expose them at all

Page 39: Essential .NET Security

39

Block Ciphers

• How a block cipher works– input is broken up into fixed size blocks (typically 8 or 16 bytes)– transformation f() applied to key, result xor’d into block– this is known as a “round” – 16 to 32 rounds is typical

f()

f() xor Round 1

Round N

key plaintext block

xor

ciphertext block

Page 40: Essential .NET Security

40

Block Ciphers (cont.)

• Problem: redundancy– Two blocks of plaintext with the same content produce two

blocks of ciphertext that are equivalent• Feedback modes were introduced to hide redundant blocks

– Electronic Code Book (ECB) means no feedback– Cipher Block Chaining (CBC) xors ciphertext from previous

block into plaintext for next block– other modes available, but ECB and CBC most common

• Using a feedback mode requires an initialization vector (IV)– random block of data to get the feedback loop started– don’t need to keep the IV secret, can send with ciphertext

Page 41: Essential .NET Security

41

Block cipher padding

• Block ciphers need to operate on fixed size blocks– what if plaintext length isn’t a multiple of the block size?– need to pad the plaintext

• PKCS deals with these sorts of issues– PKCS = Public Key Cryptography Standards, by RSA Security

• PKCS#7 specifies a simple way to pad plaintext– if 1 byte of padding is required, pad with the byte 0x01– if 2 bytes of padding are required, pad with the byte 0x02– and so on…– all messages must be padded for this to work

• The .NET Framework classes automate this– add padding before encryption, remove it after decryption– calculate the ciphertext length with padding in mind!– C = P + BS – (P mod BS)

Page 42: Essential .NET Security

42

Encrypting data in .NET

• Setting up– choose an algorithm and implementation– choose a feedback mode– choose a padding mode– generate an initialization vector (IV)– choose a key

• Encrypting– record the initialization vector for use during decryption– create a CryptoStream object based on your key– pump data through the stream to encrypt it

Page 43: Essential .NET Security

43

Algorithms and implementations in .NET

SymmetricAlgorithm

DES

RC2

Rijndael

TripleDES

DESCryptoServiceProvider

RC2CryptoServiceProvider

RijndaelManaged

TripleDESCryptoServiceProvider

note that these are all block ciphers

Page 44: Essential .NET Security

44

Example: encrypting a file

static void _encrypt(FileStream s, FileStream d) {SymmetricAlgorithm alg = new RijndaelManaged();alg.Mode = CipherMode.CBC;alg.Padding = PaddingMode.PKCS7;alg.GenerateIV();_writeIV(alg, d); // writes alg.IV to the stream

// this example uses a password as a key// more on this later...alg.Key = _keyFromPassword(_getPassword());

Stream cryptOutput = new CryptoStream(d,alg.CreateEncryptor(),CryptoStreamMode.Write);

_pump(s, cryptOutput);cryptOutput.Close();

}

Page 45: Essential .NET Security

45

Decrypting data in .NET

• Setting up– choose the same algorithm you used to encrypt (duh!)– choose the same feedback mode– choose the same padding mode– retrieve the initialization vector (IV) used during encryption– retrieve the key

• Decrypting– create a CryptoStream object based on your key– pump data through the stream to decrypt it– close the CryptoStream immediately when done decrypting– this causes it to eat any leftover padding from the input stream

Page 46: Essential .NET Security

46

Example: decrypting a file

static void _decrypt(FileStream s, FileStream d) {SymmetricAlgorithm alg = new RijndaelManaged();alg.Mode = CipherMode.CBC;alg.Padding = PaddingMode.PKCS7;_readIV(alg, s);

alg.Key = _keyFromPassword(_getPassword());

Stream cryptOutput = new CryptoStream(d,alg.CreateDecryptor(),CryptoStreamMode.Write);

_pump(s, cryptOutput);cryptOutput.Close();

}

Page 47: Essential .NET Security

47

Key Length

• Some algorithms have hardcoded key lengths– DES is limited to a 56-bit key, TripleDES is 56 * 3

• Other algorithms offer a variety of key lengths– RC2, Rijndael (AES), for example

• The longer the key, the harder it is to break the encryption– assuming the key comes from a good random source

• The chart on the next slide is from 1995, but gives you a visceral look at how key length affects security

Page 48: Essential .NET Security

48

Brute force encryption breaking

Attacker Budget HardwareTime & Cost Secure Key Length

40 bit 56 bit 1995 2015

Pedestrian Tiny PC 1 week Infeasible 45 59

Hacker $400 FPGA 5 hours$0.08

38 years$5,000 50 64

SmallBusiness $10K FPGA 12 min

$0.08556 days

$5,000 55 69

CorporateDepartment $300K

FPGA 24s$0.08

19 days$5,000

60 74ASIC 0.18s

$0.0013 hr$38

BigCompany $10M

FPGA 0.7s$0.08

13 hr$5,000

70 84ASIC 0.005s

$0.0016 min$38

IntelligenceAgency $300M ASIC 0.0002s

$0.00112s$38 75 89

Page 49: Essential .NET Security

49

Passwords as keys

• Passwords or phrases can be turned into conventional keys– variable length passphrase converted into a fixed length key– hash of password produces fixed length key

• Passwords are often long term secrets– we limit their use as much as possible to avoid compromise– shorter term secrets known as session keys are often used– long term secrets such as passwords are usually used to help

exchange short term secrets such as session keys• Use short term keys to encrypt data whenever possible

– attacker has less ciphertext to work with to break the key

Page 50: Essential .NET Security

50

Turning a password into a key

static byte[] _keyFromPassword(string s) {// encode string into a byte arrayMemoryStream media = new MemoryStream();BinaryWriter writer = new BinaryWriter(media);writer.Write(s);writer.Flush();media.Seek(0, SeekOrigin.Begin);

// compute the 20 byte SHA hashbyte[] shaHash = SHA1.Create().ComputeHash(media);

// take the first 16 bytes for use as a 128 bit keybyte[] key = new byte[16];Array.Copy(shaHash, 0, key, 0, 16);

return key;}

Page 51: Essential .NET Security

51

Reality check – password entropy

• The code you just saw has a huge flaw– it accepts passwords of arbitrary quality– it always produces a 128-bit key– it gives the illusion that you have the protection of a 128-bit key

• A password that truly has 128-bits of entropy is rare indeed– this requires 20 random characters from the following:

• upper and lower case alpha (A-Z, a-z)• digits (0-9)• punctuation

• Be sure to give the user feedback on password quality!– consider rejecting passwords with too little entropy

Page 52: Essential .NET Security

52

Calculating the entropy of a password

Note this calculation is totally bogus if password contains words found in a dictionary!

static double _passwordEntropy(string s) {if (0 == s.Length) return 0;

// first determine the type of characters usedint permutations = 0;

// psuedo-code for brevityif (usesLowerCaseAlpha) permutations += 26;if (usesUpperCaseAlpha) permutations += 26;if (usesNumerics) permutations += 10;if (usesPunctuation) permutations += 32;

double passwordEntropy =Math.Log10(Math.Pow(permutations, s.Length)) /Math.Log10(2);

return passwordEntropy;}

Page 53: Essential .NET Security

53

Estimating the required length of a password

static double _minPasswordLength(double permutations,double minEntropy) {

return Math.Log(Math.Pow(10, requiredEntropy *Math.Log10(2)),

permutations);}

char set permutationslower case alpha 26+ upper case alpha 52+ digits 62+ punctuation 94

Page 54: Essential .NET Security

54

Password lengths

Page 55: Essential .NET Security

55

Choosing an algorithm

• Narrow down your choices– 1) use well-known algorithms. Avoid obscure ones.– 2) use an algorithm that supports your required key length– 3) prefer a block cipher to a stream cipher– 4) pick an algorithm that performs well on your platform

• some algorithms perform better in hardware (DES)• some perform well in software (RC2, IDEA)

• Sources for information on Crypto Algorithms– Applied Cryptography, 2cnd Ed, by Bruce Schneier– Peter Gutmann’s crypto tutorial

• http://www.cs.auckland.ac.nz/~pgut001/tutorial/index.html

Page 56: Essential .NET Security

56

Network authentication using passwords

• Password only known by two parties– the principal who owns the account– the authority who issued the account (i.e., domain controller)

• To authenticate with the authority– principal must prove knowledge of password to authority– this is pretty easy to accomplish

• To authenticate with some other server– server doesn’t know client’s password– this is more complex

• Kerberos is a client-server authentication protocol– Helps client and server develop trust in each other’s identity– Helps client and server discover a session key

Page 57: Essential .NET Security

57

The Kerberos authentication protocol

• Kerberos is based on conventional cryptography– three parties are involved: client, server, authority– client and server must have accounts with authority– authority “introduces” client and server, helping them develop

trust in each other’s identity– Only has meaning if client and server trust the authority

Authority

trust trust

Client Server

Page 58: Essential .NET Security

58

Kerberos tickets

• Authority generates a session key– this session key is for the client and server to share

• Authority whispers session key to client– session key is sent to client encrypted with client’s master key

• Authority gives the client a “ticket” to send to the server• Ticket contains (among other things)

– client’s name– copy of the session key

• Ticket is encrypted with server’s master key• If server decrypts ticket successfully

– server trusts that contents were generated by the authority– server obtains a copy of the session key

Page 59: Essential .NET Security

59

Using a ticket to authenticate the client

• Is a ticket enough to prove the client’s identity?– ticket was sent to the client in the clear– ticket is sent to the server in the clear– thus anyone could have a copy of the ticket

• Client needs to prove knowledge of the session key– remember, the authority “whispered” this to the client– only someone with the client’s master key could have

decrypted it• How do we prove knowledge of a key without disclosing it?

Page 60: Essential .NET Security

60

Proving knowledge of a key

• Two common ways to prove knowledge of a key– encrypt a random challenge obtained from the server– encrypt a timestamp– in both cases, the proof is called an “authenticator”

Alice Bob

Alice Bob

Kerberos uses this method

get challenge

send response

Page 61: Essential .NET Security

61

Ticket usage

Alice Bob

Authority

1 Request tkt for Bob

1

2 Issue tkt, whisper key

2

3 Send tkt + authenticator

3

Ticket for Bobsession key4

4 Cache tkt + key for later use

5

5 Optional mutual authn step

Page 62: Essential .NET Security

62

Kerberos

• Clients shouldn’t need to keep their master key in memory– required to decrypt session keys coming from authority

• Kerberos introduced the “Ticket Granting Ticket” to fix this– at login, when client password is available, client uses it to

request a ticket + session key for the authority itself– this ticket is known as the TGT, or Ticket Granting Ticket– new session keys are “whispered” to client using session key

instead of master key• Practically speaking

– this means one extra round trip to authority at login time– Windows still caches master key to allow access to NT4 boxes

Page 63: Essential .NET Security

63

Kerberos credentials

• Windows caches credentials for each client logon session– credentials are a ticket plus the session key for that ticket

• Windows gathers group SIDs during authentication– hence group membership information is cached inside tickets

• Logging out clears your ticket cache– good idea to log out and log back in if groups change, or– LsaCallAuthenticationPackage can clear the cache manually

Page 64: Essential .NET Security

64

After authentication

• Client and server have developed trust in the other’s identity• Session key should now be used to protect data sent between

client and server– can integrity protect and authenticate the data– can encrypt the data as well– if you don’t protect the data stream, an attacker could be

modifying or replaying packets, or simply injecting his own!• Encryption != Integrity Protection

Page 65: Essential .NET Security

65

Integrity protection and the MAC

• MAC == Message Authentication Code– simple idea– hash that can be computed only if you know the session key

• Forming a MAC– include the session key in the payload when hashing*, or– encrypt a hash of the payload with the session key

• MAC protecting messages accomplishes two things– integrity protects the data– authenticates the data

• Still need to protect against replays– sequence numbers can help with this

payload MAC

Page 66: Essential .NET Security

66

Where is Kerberos used?

• Domain controller + Active Directory == Kerberos authority• Lots of subsystems use Kerberos in Windows• Using Kerberos over the Internet is tricky

– clients usually can’t reach the Kerberos authority on port 88– next generation of MS Passport will use Kerberos, likely

tunneling requests to the authority over port 80• Using Kerberos on an intranet is much more common

– authenticated RPC and DCOM calls– file and printer sharing, remote administration tools– IPSEC

• On Windows, SSPI can be used to “Kerberize” an application– SSPI = Security Support Provider Interface

Page 67: Essential .NET Security

67

Security Support Provider Interface (SSPI)

• SSPI is a generic interface to authentication providers– Kerberos– NTLM (for local accounts and NT4 boxes)– SSL / TLS

• Designed for use by C / C++ programmers– generic support for any authentication protocol– being generic makes it tough to use for most people

• .NET Framework currently has no official wrappers for SSPI– but a sample written by the .NET remoting team provides this– http://msdn.microsoft.com/library/en-us/dndotnet/html/remsspi.asp

Page 68: Essential .NET Security

68

Using SSPI from .NET (initial authentication)// client code to obtain ticket for serverClientCredential cred =

new ClientCredential(Credential.Package.Kerberos);

ClientContext ctx = new ClientContext(cred,@"MyDomain\MyServerPrincipal",ClientContext.ContextAttributeFlags.None);

byte[] authnData = ctx.Token; // ticket + authenticator

// server code to process incoming ticketServerCredential cred =

new ServerCredential(Credential.Package.Kerberos);ServerContext ctx = new ServerContext(cred, authnData);

// server code to look at client’s nameWindowsIdentity clientIdentity =

new WindowsIdentity(ctx.ClientSecurityToken);

string clientName = clientIdentity.Name;

Page 69: Essential .NET Security

69

Using SSPI from .NET (protecting the channel)

// client code to MAC protect and encrypt a messagebyte[] ciphertext = ctx.EncryptMessage(plaintext);

// server code to decrypt and verify the MACtry {

byte[] plaintext = ctx.DecryptMessage(ciphertext);}catch {

// message integrity violation!}

Page 70: Essential .NET Security

70

Summary

• Conventional cryptography is all about secret keys• Passwords are commonly hashed to form keys• The .NET Framework has great support for cryptography• Kerberos is an authentication protocol• Authn protocols help exchange keys and validate identity• SSPI is an unmanaged interface to Kerberos• Currently no support for raw Kerberos in .NET Framework

Page 71: Essential .NET Security

Public Key Cryptography and Authentication

Cryptography, certificates, and SSL

Page 72: Essential .NET Security

72

Outline

• Public key cryptography• Encryption• Signatures• Certificates• Using public keys from the .NET Framework• CAPICOM examples• SSL and TLS

Page 73: Essential .NET Security

73

Origins of public key cryptography

• In 1976, Whitfield Diffie and Martin Hellman made a discovery– public key cryptography was born

In real-world terms, it allows you and a friend to shoutnumbers at each other across a crowded coffeehousefilled with mathematicians so that when you are done,both you and your friend know the same random number,and everyone else in the coffeehouse is completely clueless.

- Bruce Schneier, Secrets and Lies

Page 74: Essential .NET Security

74

Public and private keys

• Keys are generated in pairs– public key– private key

• How sensitive are these keys?– public key not sensitive, anyone can know it– private key very sensitive, only one party knows it– not possible to calculate the private key given the public key

• Encryption– plaintext encrypted with the public key– ciphertext decrypted with the corresponding private key– much, much slower than conventional cryptography!

• RSA is the most well-known public key algorithm

Page 75: Essential .NET Security

75

Public key cryptography

plaintext ciphertextpublic key

encrypt

plaintext ciphertextprivate key

decrypt

Page 76: Essential .NET Security

76

Signatures

• Public key cryptography can also be used for signatures– say we want to “sign” some piece of data– private key used to encrypt the data– if you can decrypt the data with Bob’s public key, then you

develop trust that Bob encrypted it originally• Goals are twofold

– verify that we know who created the signature– verify that the data hasn’t been tampered with since signed

Page 77: Essential .NET Security

77

Reality checks

• Nobody encrypts or signs bulk data with public keys– it’s way too slow!– we encrypt data with a conventional key, the “session key”– we use a public key to encrypt the session key– when signing, we encrypt a hash of the data, not the data itself

• Public key cryptography is not a silver bullet!– the public key isn’t secret but it does need some protection– imagine a central database of public keys, and you want Bob’s– if an attacker can swap his public key for Bob’s public key:

• he can decrypt any ciphertext you send to Bob• he can fake Bob’s signature to you

– digital certificates can help…

Page 78: Essential .NET Security

78

Digital certificates

• Certificate couples a name with a public key– contents of certificate are signed by some trusted authority,

Verisign being the most notable nowadays– authority’s public key is well-known

• ships with browsers and other software– by verifying the authority’s signature on the certificate, you

develop trust in the contents of the certificate• Certificates are the most common way to communicate public

keys over insecure channels

Bob’s public keyBob

Verisign’s sigprotects

Page 79: Essential .NET Security

79

Public key encryption in the .NET Framework

• The current story is incomplete– there is a class representing an X.509 certificate– there is a class representing an RSA key– there isn’t any clear path between them

• If you want to use standards (PKCS), use CAPICOM– can easily use CAPICOM via COM interop– although this means that mobile code won’t be doing this stuff

• If you want to work with raw public and private keys, can use RSACryptoServiceProvider, but be careful– how will you securely transmit the public key?– how will you securely store the private key?– how will you interop with other systems?

Page 80: Essential .NET Security

80

Using CAPICOM from .NET

• Step 1: Get the redistributable– capicom.dll doesn’t ship with Windows– http://www.microsoft.com/msdownload/platformsdk/sdkupdate– downloads : redistributables

• Step 2: Install it– log in as a local administrator– install it somewhere secure (\windows\system32 works)– regsvr32 capicom.dll

• Step 3: Run TLBIMP– tlbimp capicom.dll– alternatively, add a reference to it from your Visual Studio

project

Page 81: Essential .NET Security

81

Encrypting data using certs and CAPICOM

• Setting up– serialize the data you want to send into a string– choose the recipient(s) for the message– locate their certificates in the various certificate stores– choose a symmetric encryption algorithm– choose an encoding for the resulting ciphertext

• Encrypting– create an EnvelopedData object– add certificates for each recipient– set the content string– set the encryption algorithm– call Encrypt

Page 82: Essential .NET Security

82

Example: encryption using certs and CAPICOM

Store s = new Store();s.Open(CAPICOM_STORE_LOCATION.CAPICOM_CURRENT_USER_STORE,

"AddressBook",CAPICOM_STORE_OPEN_MODE.CAPICOM_STORE_OPEN_READ_ONLY);

EnvelopedData env = new EnvelopedData();env.Recipients.Add((Certificate)s.Certificates[1]);env.Recipients.Add((Certificate)s.Certificates[2]);env.Algorithm.Name = CAPICOM_ENCRYPTION_ALGORITHM.CAPICOM_ENCRYPTION_ALGORITHM_3DES;

env.Content = "Here is the plaintext.";

string ciphertext =env.Encrypt(CAPICOM_ENCODING_TYPE.CAPICOM_ENCODE_BASE64);

note 1 basedindexing

Page 83: Essential .NET Security

83

What we just produced

data encryptedwith session key

recipient 1Cert issuer

Cert serial numbersession key

encrypted with thepublic key of recipient 1

Entire package encoded with base64 for ease of transmission

recipient 2Cert issuer

Cert serial numbersession key

encrypted with thepublic key of recipient 2

Page 84: Essential .NET Security

84

Decrypting an enveloped message

EnvelopedData env = new EnvelopedData();

env.Decrypt(ciphertext);

string plaintext = env.Content;

looks in personal certificate storefor a cert that matches one ofthe recipients in the envelope

Page 85: Essential .NET Security

85

Signing data using CAPICOM

• Setting up– serialize the data you want to send into a string– choose a certificate to use for the signature– remember you must have the private key for this certificate– choose an encoding for the resulting signed message

• Signing– create a Signer object– load the Signer with the certificate you’ll be using– create a SignedData object and add the Signer to it– set the content property of SignedData– call SignedData.Sign to create the signed message– can optionally CoSign to add more signatures

Page 86: Essential .NET Security

86

Example: signing data

Store my = new Store();my.Open(CAPICOM_STORE_LOCATION.CAPICOM_CURRENT_USER_STORE,

"MY",CAPICOM_STORE_OPEN_MODE.CAPICOM_STORE_OPEN_READ_ONLY);

Signer me = new Signer();me.Certificate = (Certificate)my.Certificates[1];

SignedData sd = new SignedData();sd.Content = "Here is the message to be signed";

string signedMessage = sd.Sign(me, false,CAPICOM_ENCODING_TYPE.CAPICOM_ENCODE_BASE64);

Page 87: Essential .NET Security

87

What we just produced

plaintext message

signer 1Cert issuer

Cert serial numberhash of message

encrypted with theprivate key of signer 1

Entire package encoded with base64 for ease of transmission

Page 88: Essential .NET Security

88

Verifying signed data

• Verification is a two step process– Step 1: call SignedData.Verify– Step 2: look at each signer and see if the signature is valid– Note that this does not check cert revocation lists

SignedData sd = new SignedData();sd.Verify(Console.In.ReadToEnd(), false,

CAPICOM_SIGNED_DATA_VERIFY_FLAG.CAPICOM_VERIFY_SIGNATURE_AND_CERTIFICATE);

Console.WriteLine(sd.Content);Console.WriteLine("Signature validity:");foreach (Signer s in sd.Signers) {

Console.Write(s.Certificate.IsValid().Result ?"Valid: " : "Invalid: ");

Console.WriteLine(s.Certificate.SubjectName);}

Page 89: Essential .NET Security

89

Verifying certificates

• Just because the signature matches the public key doesn’t mean it’s a valid signature– you need to check the validity of the certificate itself– this means looking all the way up the chain of trust– this means looking for revoked certificates

• Certificate Revocation Lists (CRL) are important– authorities that issue certificates also publish CRLs regularly– CAPICOM allows you to check against CRLs, but it’s not

automatic

Page 90: Essential .NET Security

90

Example: verifying a certificate

static void validateCert(Certificate certToValidate) {certToValidate.IsValid().CheckFlag =

CAPICOM_CHECK_FLAG.CAPICOM_CHECK_SIGNATURE_VALIDITY |CAPICOM_CHECK_FLAG.CAPICOM_CHECK_TIME_VALIDITY |CAPICOM_CHECK_FLAG.CAPICOM_CHECK_TRUSTED_ROOT |CAPICOM_CHECK_FLAG.CAPICOM_CHECK_OFFLINE_REVOCATION_STATUS |CAPICOM_CHECK_FLAG.CAPICOM_CHECK_ONLINE_REVOCATION_STATUS;

if (certToValidate.IsValid().Result) {return; // cert is fine

}

// something is wrong, find out the detailsChain chain = new Chain();chain.Build(certToValidate);

// fail and provide a description of the reason_throwBadCertException(chain.get_Status(0));

}

Page 91: Essential .NET Security

91

Authentication using certificates

• A certificate simply makes a statement– authority X asserts that this is subject Y’s public key

• Certificates are not secret– so when someone presents you a cert over the wire, can you

use that to figure out the identity of the sender?– sender needs to prove that she knows the corresponding

private key!• This is what SSL is all about

Page 92: Essential .NET Security

92

SSL and TLS

• SSL == Secure Sockets Layer– developed by Netscape in early ’90s– became a de-facto standard on the web

• TLS == Transport Layer Security– really just SSL 3.1 put into an IETF standard (RFC 2246)

• Authentication protocol based on certificates• Remember that authentication does two things

– helps you develop trust in the identity of your peer– helps you and your peer exchange a session key

Page 93: Essential .NET Security

93

Who does SSL authenticate?

• SSL always authenticates the server• SSL can also authenticate the client, if desired

– this means the client has to have a certificate– not common for the average computer user– very common in B2B scenarios

Page 94: Essential .NET Security

94

The SSL handshake

Client Hello

Server Helloserver cert

encrypted pre-master secret(client cert)

(certificate verify code)message authn code

message authn code

Page 95: Essential .NET Security

95

Using SSL

• SSL can be used directly via SSPI– very tricky to implement correctly

• Most people use IIS to get SSL support– ASP.NET web applications have IIS as a front end– web services have IIS as a front end– secure .NET remoting uses IIS as a front end

Page 96: Essential .NET Security

96

Summary

• Public key cryptography is used to create signatures and encrypt keys

• Certificates help authenticate public key material• CAPICOM can be used from the .NET Framework• CAPICOM helps you encrypt/sign using certificates• SSL is an authentication protocol based on certificates

Page 97: Essential .NET Security

Windows Security 101A whirlwind tour of operating system security concepts on the .NET Platform

Page 98: Essential .NET Security

98

Outline

• Windows security primer• Processes and tokens• Role based security• Tracking client identity• Logon sessions and window stations

Page 99: Essential .NET Security

99

Trusted Computing Base (TCB)

• The TCB is a theoretical boundary– the TCB must enforce security policy– normal software is subject to the security policy of the machine

• TCB consists of most hardware and some software– “Act as part of the operating system” privilege puts you in TCB– SYSTEM (a.k.a. “Local System”) has this privilege

• The administrator’s role– define and defend the TCB– define security policy (groups, privileges, etc.)

trustednormal

normalnormal

normal

normalnormal

Page 100: Essential .NET Security

100

Principals, accounts, and authorities

• An authority issues an account for each principal– local authority issues local accounts– domain authority issues domain accounts

• Fully qualified name includes two parts: authority\principal– MAC5\Alice– SalesDomain\Bob

• Domain accounts rely on Kerberos authentication– can be authenticated anywhere in the domain– can be authenticated in any other trusting domain

• Local accounts use an older authentication protocol (NTLM)– two reasons to use a local account:

• no network credentials are needed, or• no domain is present

Page 101: Essential .NET Security

101

S-1-5-11

Security Identifiers (SIDs)

• Used to identify both users and groups– Unique in space and time– Similar to a GUID, but has a structure you can parse

S-1-5-21-94726516-39827771-32661612-1001

Sales\Alice

S-1-5-21-72829217-47627842-48264738-1001

MAC5\Bob

authority principal

NT Authority\Authenticated Users a “well-known” SID

Page 102: Essential .NET Security

102

Groups

• There are four types of groups– Some follow you all over the network (unlimited scope)– Others only show up in the scope where they are defined

(machine or domain scope)

UniversalGlobal

Domain LocalLocal

active directoryactive directoryactive directory

registry

yesyesyesno

unlimitedunlimited

single domainsingle machine

type of group stored in nest? scope

Page 103: Essential .NET Security

103

Privileges

• Groups typically used to grant permissions on objects– via access control lists (ACLs)

• Privileges are broader rights granted to users– privileges are bestowed via security policy

• secpol.msc for local machine policy• gpedit.msc for group policy

• Some interesting privileges– bypass traverse checking– backup, restore– debug programs– shut down the system– generate security audits– act as part of the operating system (part of the TCB, that is)

Page 104: Essential .NET Security

104

Processes and tokens

• Each process has a security identity– this associates the process with a principal– required to enforce access control policies– required to audit actions performed by each principal

• This info is stored in a kernel object known as a token– user SID– group SIDs– privileges

• Even a daemon must have a token– NT services– COM+ applications– Web application worker processes

Page 105: Essential .NET Security

105

Token propagation

• When a new process is created, it needs a token– created by copying token from parent process

• When a daemon is started, it also needs a token– created from user name and password configured for daemon

Page 106: Essential .NET Security

106

Token propagation

machine

1 machine boots up

SYSTEM

winlogon

SYSTEM

services

1

SQL

mssql

4 cmd: start notepad.exe

4Alice

notepad

3 Alice starts a command shell

3Alice

cmd

5 cmd: net start mssql

5

2 Alice logs in interactively

2

Alice

explorer

Page 107: Essential .NET Security

107

Programming with tokens

• Usually we care about two things in a token– identity of the user– groups in which that user is a member

• The .NET Framework abstracts this with two interfaces

interface IPrincipal {IIdentity Identity { get; }bool IsInRole(string roleName);

}

interface IIdentity {bool IsAuthenticated { get; }string AuthenticationType { get; }string Name { get; }

}

Page 108: Essential .NET Security

108

WindowsIdentity and WindowsPrincipal

• These are simply wrappers for tokens• WindowsPrincipal.IsInRole queries groups in token

– group names must be fully qualified• WindowsIdentity has some useful features:

– GetCurrent() retrieves process token* – GetAnonymous() retrieves a null session token– Impersonate() is also important, but more on this later…

WindowsIdentityWindowsPrincipal has a

IPrincipal IIdentity

implements implements

tokenhas a

Page 109: Essential .NET Security

109

Example: a simple desktop application

• Runs in a single process• Has a process token for the launching user

– it’ll be able to do anything that user can dousing System;using System.Security.Principal;

class WhoAmI {static void Main() { // look at process tokenIIdentity identity = WindowsIdentity.GetCurrent();IPrincipal principal = new WindowsPrincipal(

(WindowsIdentity)identity);if (identity.IsAuthenticated) {Console.WriteLine(“My name is {0}", identity.Name);if (principal.IsInRole(@"BUILTIN\Backup Operators")) {Console.WriteLine("I am a Backup Operator");

}}else Console.WriteLine("I am anonymous.");

}}

Page 110: Essential .NET Security

110

Server applications and tokens

• Server applications are usually packaged as daemons– Web apps (w3wp.exe)– COM+ applications (dllhost.exe)– NT services (*.exe)

• Server application identity is configurable– Web apps configured via “application pools”– COM+ apps configured via Component Services catalog– NT services configured via control panel applet

• For each authenticated client, server gets another token– Kerberos ticket sent from client is turned into a token– server looks at client token to make security decisions– can check client’s groups via IsInRole, for example

Page 111: Essential .NET Security

111

Example: a server application

client machine server machine

Alice NetworkService

NT serviceclientapplication

service identity configuredstatically on server machine

kerberoshandshake

Aliceclient identity

discovered dynamicallyvia Kerb authentication

== token

Page 112: Essential .NET Security

112

Keeping track of your clients

• FCL provides a variable to help servers track client identity– Thread.CurrentPrincipal– as it’s name implies, this variable is kept on a per-thread basis

• Pattern for usage– plumbing sets it (ASP.NET, for example, or your own code)– application gets it (business logic) to make security decisions

• This is key to “Role Based Security” infrastructure in .NET• This is not impersonation

– Thread.CurrentPrincipal is simply for application bookkeeping– the operating system doesn’t ever see or use this information– we’ll talk about impersonation in the next module…

Page 113: Essential .NET Security

113

Tracking client identityusing System.Threading;using System.Security.Principal;

class Plumbing {public static void DoHeavyLifting() {IPrincipal client = AuthenticateUserSomehow();Thread.CurrentPrincipal = client;Application.ImplementBusinessLogic();

}}

class Application {public static void ImplementBusinessLogic() {if (Thread.CurrentPrincipal.IsInRole("Managers")) {// do something privileged

}}

}

Page 114: Essential .NET Security

114

using System.Security.Permissions;

[PrincipalPermission(SecurityAction.Demand, Authenticated=true)]class PetStore {public void PetAnimals() { ... }public void BuyAnimals() { ... }

[PrincipalPermission(SecurityAction.Demand, Role="Staff")]public void FeedAnimals() { ... }

[PrincipalPermission(SecurityAction.Demand, Role="Managers")]public void GiveRaise() { ... }

}

More fun with Thread.CurrentPrincipal

• PrincipalPermissionAttribute uses Thread.CurrentPrincipal– allows you to add declarative checks against client identity– JIT compiler inserts the checks at the start of the method

Page 115: Essential .NET Security

115

Thread.CurrentPrincipal and asynchrony

• What if I make an asynchronous call?– BeginInvoke copies Thread.CurrentPrincipal to worker thread– Thread.Start copies Thread.CurrentPrincipal to new thread

• Watch out for these special cases– ThreadPool.QueueUserWorkerItem doesn’t copy it– System.Threading.Timer doesn’t copy it

Page 116: Essential .NET Security

116

Defaults for Thread.CurrentPrincipal

• What if no plumbing has set Thread.CurrentPrincipal?• An AppDomain property controls this…

using System;using System.Security.Principal;

class SimpleConsoleApp {static void Main() {

// must set this before anyone accesses// Thread.CurrentPrincipalAppDomain.CurrentDomain.SetPrincipalPolicy(

PrincipalPolicy.WindowsPrincipal);

DoSomeWork();}

// ...}

NoPrincipalUnauthenticatedPrincipalWindowsPrincipal

Page 117: Essential .NET Security

117

Logon sessions

• A logon session is a data structure in the kernel– represents an instance of a principal on a machine– holds network credentials (kerb tickets, pwd hash, etc.)– a token (and thus a process) is tied to a single logon session– “logging off” tears down processes tied to the logon session

• You can have more than one logon session for one principal– interactive user could be Alice– service could be running as Alice– if the interactive Alice logs off, this has no effect on the service

• There are several built-in logon sessions– #999: SYSTEM– #998: Null Session (the anonymous logon)– #997: Local Service– #996: Network Service

Page 118: Essential .NET Security

118

Logon sessions, illustrated

SYSTEM

winlogon

SYSTEM

services

SQL

mssql

Alice

notepad

Alice

cmd

Alice

explorer

machine

logon sessionboundaries

Page 119: Essential .NET Security

119

Window stations

• Window and GDI objects have no individual security settings– compare this to files, registry keys, processes, each of which

has a security policy saying who can manipulate them• The entire windowing environment is sandboxed

– this sandbox is known as a Window Station• Window stations have:

– a set of one or more desktops on which windows are created– a clipboard and atom table

• Each process has an attribute indicating which window station it belongs to

Page 120: Essential .NET Security

120

Window stations, illustrated

SYSTEM

winlogon

SYSTEM

services

SQL

mssql

Alice

notepad

Alice

cmd

Alice

explorer

note that services running as SYSTEMcan choose to run in the interactive WS(“interact with the desktop” checkbox)

window station boundary

logon session boundary

interactive window station(winsta0)

Page 121: Essential .NET Security

121

Why care about window stations?

• Two common reasons to care about window stations– cannot send window messages across winstation boundaries– only interactive window station (winsta0) bound to hardware

• Rules to live by– don’t use window messages for interprocess communication– don’t put up dialog boxes unless you’re running interactively

• dialogs displayed in noninteractive winstations will hang!• server code should beware of ASSERT macro in C/C++

• MessageBox can be used with a special flag– MB_SERVICE_NOTIFICATION (C++)– MessageBoxOptions.ServiceNotification (CLR)– causes the message box to show up on the interactive

desktop, even if initiated from a noninteractive window station

Page 122: Essential .NET Security

122

Running applications in alternate logon sessions

• Secondary Logon service makes this easy– handles details such as granting permission to enter winsta0

• What you provide– path to the app you want to run, plus user name and password

• What the service does– authenticates user name and password getting a token– starts new process with that token in winsta0– loads user profile if you desire– logs off any secondary logons when interactive user logs off*

• CreateProcessWithLogonW is the API that makes it happen– runas utility or shift-right-clicking via explorer

Page 123: Essential .NET Security

123

Example: starting a command prompt as Alice// See labs/extraSamples/secondaryLogon.zip for full sampleStartupInfo si = new StartupInfo();si.cb = Marshal.SizeOf(typeof(StartupInfo));si.title = "This command prompt is running as Alice";

ProcessInfo pi = new ProcessInfo();string app = Path.Combine(Environment.SystemDirectory,

"cmd.exe");

bool result = CreateProcessWithLogonW("alice", ".", promptUserForPassword(),LogonFlags.LOGON_WITH_PROFILE,app, null,0, IntPtr.Zero, null,ref si, out pi);

if (result) {result = CloseHandle(pi.hProcess);result = CloseHandle(pi.hThread);

}

Page 124: Essential .NET Security

124

Summary

• Authorities vouch for principals at runtime• Groups and privileges are part of security policy• Administrator specifies security policy, TCB enforces it• Local and Domain accounts are both possible• Every process has a token, even daemons• Servers track client identity using Thread.CurrentPrincipal• Logon sessions cache credentials and help determine

process lifetime• Window stations are used to sandbox the interactive GUI• For further info, consult Programming Windows Security

Page 125: Essential .NET Security

Windows Security 102Continuing our whirlwind tour of operating system security concepts on the .NET Platform

Page 126: Essential .NET Security

126

Outline

• Servers and client identity• Impersonation• Delegation in Windows 2000• Delegation in Windows Server 2003

Page 127: Essential .NET Security

127

Network authentication using Kerberos

• Secure servers require clients to be authenticated– Kerberos most typical on today’s intranets

• Successful authentication results in a logon session and token for the client on the server machine– almost as if the client had logged on locally

Page 128: Essential .NET Security

128

client machine server machine

Network authentication, illustrated

Alice NetworkService

serverapplication

clientapplication

kerberoshandshake

Alice

Page 129: Essential .NET Security

129

Impersonation

• After authentication, the server can do two things with the client’s token

• Look at it and make access control decisions– perhaps to verify client is in a required role– perhaps to perform an access check against some resource

• Use it to impersonate the client– place the client’s token on the server’s thread and call out to

some other secure resource manager• file system• SQL Server• etc.

Page 130: Essential .NET Security

130

client machine server machine

Impersonation example: the file server

Alice NetworkService

serverservice

SYSTEM

NTFSfile system

clientapplication

kerberoshandshake

Alice

A

Local NTFS file system usesAlice’s token for access check

impersonation

OpenFile

Page 131: Essential .NET Security

131

C# impersonation examplevoid impersonationFun(WindowsIdentity client) {

// id is basically a wrapper around a tokenConsole.WriteLine("Client name is {0}", client.Name);

// slap the client’s token on this thread temporarilyWindowsImpersonationContext ctx = client.Impersonate(); try {

// this request to the file system will only succeed// if the client has access to the filenew FileStream("someFile.txt", FileMode.Open);

}finally {

ctx.Undo(); // remove client’s token from this thread}

// this request to the file system will only succeed// if the server process has access to the filenew FileStream("someFile.txt", FileMode.Open);

}

Page 132: Essential .NET Security

132

Impersonation is now a privileged operation

• .NET Server 2003 added a new privilege– SeImpersonatePrivilege

• This change is being backported to older operating systems– Windows 2000 SP4 (released June 26, 2003)– Windows XP (future service pack)

• Must have this privilege granted and enabled to impersonate– It’s enabled by default if it’s granted to you by policy

• Granted by default to– SYSTEM– Network Service– Local Service

• If you run under a custom account, you’ll need to grant this privilege explicitly in order to impersonate

Page 133: Essential .NET Security

133

Impersonation is fragile: use it sparingly!

• Operating system doesn’t auto-propagate thread token• Beware asynchronous operations while impersonating• Beware unforeseen thread switches due to COM

“apartments”

SYSTEM

ASP.NET thread (MTA)

here is an easy to misselevation of privilege vulnerability

in ASP.NET when callinginto a typical COM object

impersonating a low-privilege account

VB6object

COM thread (STA)not impersonating anyone

w3wp.exe

Page 134: Essential .NET Security

134

When impersonating, you’re in a wacky state

• The thread token:– is used for access checks against local kernel objects– is used as network identity in many cases (SQL Server

integrated security, named pipes, etc.)• The process token:

– is copied to new child processes– is used for outgoing DCOM calls by default– is one security context an attacker can use if he takes over

your process (say, via a buffer overflow)

Page 135: Essential .NET Security

135

Role based security and impersonation

• Use Thread.CurrentPrincipal to track client identity– rely on PrincipalPermissionAttribute for role checks– call IsInRole when the attribute doesn’t suffice

• Use impersonation if necessary, but keep to a minimum– impersonate temporarily to access external resources as client– stop impersonating immediately– reduces complexity and helps avoid opening security holes

• Carefully consider how asynchrony affects your design– Asynchrony can cause unexpected changes in security context

if you’re impersonating (and it sometimes can effect Thread.CurrentPrincipal)

Page 136: Essential .NET Security

136

Exampleusing System.IO;using System.Security.Principal;using System.Security.Permissions;using System.Threading;

[PrincipalPermission(SecurityAction.Demand, Authenticated=true)]void DoSomeWorkForMyClient() {

WindowsIdentity client = (WindowsIdentity)Thread.CurrentPrincipal.Identity;

// temporarily impersonate the client to access a fileWindowsImpersonationContext ctx = client.Impersonate();try {

// open a file on the client's behalfusing (Stream s = new FileStream("someFile.txt", FileMode.Open)) {

// use the client's file...}

}finally {

ctx.Undo();}

}

Page 137: Essential .NET Security

137

Tokens and network credentials

• Tokens for remote clients are usually weak– authentication helped to verify the client’s credentials, but most

likely did not transmit them to the server• While impersonating a remote client

– server will likely be able to access local resources as that client– server will likely NOT be able to access remote resources as

that client

Page 138: Essential .NET Security

138

Delegation

• Kerberos allows client to send a network credential to server– this feature is known as delegation– very dangerous feature that must be controlled carefully

• Servers must be highly trusted to receive these credentials– a server in domain A could get the delegated network

credentials of a domain administrator in domain B• Windows 2000 and Windows Server 2003 differ in how they

address this issue

Page 139: Essential .NET Security

139

Windows 2000 unconstrained delegation

• Server machine or service account flagged as special in Active Directory– “trusted for delegation”

• Individual user accounts may be restricted from participating– Active Directory will not issue delegated tickets for any client

account marked “sensitive and cannot be delegated”• This is the only option on Windows 2000

– it’s very rarely used in practice because it’s so loose

Page 140: Essential .NET Security

140

FinancialReports

Sales Plans

DomD\Server

Unconstrained delegation, illustrated

Engineering\Alice

Active Directory

Engineering\Alicecredentials

Anonymous Attacker

Finance\Admin

Finance\Admin

Sales\Rajesh

Sales\Rajesh

SQL Server

Page 141: Essential .NET Security

141

Windows Server 2003 constrained delegation

• Server machine or service account may be flagged as trusted– for unconstrained delegation, as in Win2k– or for constrained delegation– or for protocol transition, which we’ll talk about later…

• Authority only issues delegated tickets for services on the list– this is called the “allowed-to-delegate-to” list

• Individual user accounts may be restricted from participating– Active Directory will not issue delegated tickets for any client

account marked “sensitive and cannot be delegated”– just like in Win2k

Page 142: Essential .NET Security

142

Configuring constrained delegation

“Constrained delegation”

Page 143: Essential .NET Security

143

FinancialReports

Sales Plans

DomD\Server

Constrained delegation, illustrated

Engineering\Alice

Active Directory

Engineering\Alicecredentials

Anonymous Attacker

Finance\Admin

Finance\Admin

Sales\Rajesh

Sales\Rajesh

SQL Server

Page 144: Essential .NET Security

144

Delegation and scalability

• Most typical use of delegation is to allow access to databases• But this flies in the face of connection pooling

– you must make a choice here• COM+ 1.0 was designed with this issue in mind

– COM+ role-based security authorizes requests in middle tier– middle tier accesses database under a single trusted identity– allows for connection pooling

Page 145: Essential .NET Security

145

Delegation, no connection poolingbob

SQLServer

systemalice

willy

susan

ACCESS

CHECKS

a

w

s

alice

willy

susan

a

s

w

bobian

mary

joe

i

m

ian

mary

j joe

i

j

m

Page 146: Essential .NET Security

146

Connection poolingbob

SQLServer

systemalice

willy

susan

bobian

mary

joe

access

checks

b

b

access

checks

alice

willy

susan

ian

mary

joe

Page 147: Essential .NET Security

147

Authorization woes

• The authorization problem– Windows has always coupled authentication and authorization– group SIDs are collected during Kerb network authentication– this coupling is to avoid extra round-trips to authorities

• It’s expensive (infeasible, really) to discover groups manually– need to visit both client’s and server’s authorities– esoteric features like group nesting, SID history, and domain

quarantine make it really hard to do correctly in all cases• Thus we must authenticate using Kerb to discover groups

– but what if the client isn’t able to use Kerberos?

Page 148: Essential .NET Security

148

Getting a token for the client

• The safe way to discover group SIDs is to get a token– traditionally this was done via LogonUser– but this required the server to know the client’s password– example: IIS certificate mapping or basic authentication

• Bad practice to have the server exposed to client passwords– only authority should be privy to these

• But how can we get a token without a password?– enter protocol transition…

Page 149: Essential .NET Security

149

Windows Server 2003 protocol transition

• Protocol transition allows trusted servers to obtain tickets on a client’s behalf– without knowing the client’s password

• Tickets can be translated into tokens– token can be used to discover groups– token can be impersonated to access local resources (service

must be granted SeImpersonatePrivilege to do this)• Token may also be used to access network resources

– via constrained delegation– only possible if “allowed-to-delegate-to” list is populated

• Thus the term “protocol transition”– Server is trusted to transition from one authentication protocol

(used to authenticate the client) into Kerberos on the back end

Page 150: Essential .NET Security

150

Configuring protocol transition

“Protocol transition”

Page 151: Essential .NET Security

151

FinancialReports

Sales Plans

DomD\Server

Protocol transition, illustrated

RSA SecurID: 5628792

Active Directory

Engineering\Alicecredentials

Anonymous Attacker

Account U88223X

Finance\Admin

FormsAuth User: Rajesh

Sales\Rajesh

SQL Server

Page 152: Essential .NET Security

152

Summary

• Thread.CurrentPrincipal is a great way to track client identity• Threads may have a token (think impersonation)• Not all tokens have network credentials (think delegation)• Windows 2000 only supports unconstrained delegation• Windows Server 2003 supports constrained delegation and

protocol transition• For more information on security in the Windows operating

system, see Programming Windows Security– http://www.develop.com/books/pws

Page 153: Essential .NET Security

Code Access SecuritySecuring mobile code in the .NET FrameworkPart 1: motivation, permissions, and policy

Page 154: Essential .NET Security

154

Outline

• The problem of mobile code• Code Access Security (CAS)• Evidence• Permissions• Policy

Page 155: Essential .NET Security

155

What is mobile code?

• Code not explicitly installed on local machine called mobile– typically obtained from a network– often delivered via web page

• Mobile code packaging– native code in the COM era– assembly in the .NET era

• Mobile code sources– your company’s intranet– the public Internet

Page 156: Essential .NET Security

156

The old model: Full Trust

• In the COM era there were only two options for mobile code– full trust– completely untrusted

• User had to decide on trust level at download time– user presented with certificate– asked whether they trusted the vendor and their code

• NO = mobile code not allowed to execute– usually means websites don’t work

• YES = mobile code allowed to execute– might give richer browsing experience– could run more buggy and vulnerable code base– could install virus or Trojan horse

Page 157: Essential .NET Security

157

The COM loader and trust levels

• Every line of COM code runs with the same level of privilege within a single process– COM code is packaged in native DLLs– DLL becomes an integral part of the process when loaded– can’t differentiate DLL code from original application code

Page 158: Essential .NET Security

158

The COM loader, illustrated

client process

foo.ocx

foo.ocxBob

Uh, sure, if I have to…

Network

Do you trust foo.ocx to do anything you

can do?

Page 159: Essential .NET Security

159

The .NET assembly loader and trust levels

• Each .NET assembly may run with different privileges– explicitly installed code usually trusted– mobile code typically restricted

• .NET uses Code Access Security (CAS) model– assembly loader gathers evidence like source and public key– security policy used to evaluate evidence– assembly permissions determined from evidence and policy– CLR restricts assembly to actions allowed by its permissions– user never asked trust questions

Page 160: Essential .NET Security

160

The .NET loader, illustrated

client process

Bob

foo.dll

CLR

permissionsverified type safety

foo.dll

Network

.NET Security Policy

Page 161: Essential .NET Security

161

The importance of type safety

• CLR enforces permissions to constrain mobile code– possible because CLR type system is watertight– code is verified before execution to guarantee type safety– any bugs in the verification process compromises this system

• COM based systems could not enforce type safety– C++ allowed arbitrary casts– VB6 wasn’t exempt either– no way to verify behavior of code

Page 162: Essential .NET Security

162

Type safety in C++

• Without runtime type enforcement– lots of funny business can go undetected at runtime

• With runtime type enforcement– invalid casts result in exceptions at runtime

class DiskQuota {private long _maxBytes;// ...

};

void EvilCode(DiskQuota* pDiskQuota) {*(long*)pDiskQuota = MAX_LONG;

}

Page 163: Essential .NET Security

163

Evidence

• Evidence comes from properties of assembly– source: url, zone, site, application directory– author: strong name, publisher (Authenticode)– contents: hash

EvidenceUrl: http://www.develop.com/asm/foo.dllZone: InternetSite: www.develop.com

Hash: 624a88fd26c510ba5…Strong Name: “foo, version=1.0.0.0,

culture=neutral,publicKeyToken=2d537cad3c7e22c9”

foo.dll

Page 164: Essential .NET Security

164

Evidence representation

• FCL supplies classes used to represent evidence– in System.Security.Policy namespace

ZoneUrlSiteApplicationDirectoryStrongNamePublisherHash

Page 165: Essential .NET Security

165

Access to evidence

• Evidence tracked with assembly– available programmatically using reflection

class App {static void Main(string[] args) {Assembly a = Assembly.Load(args[0]);

IEnumerator it = a.Evidence.GetEnumerator();

// each item in this collection is an instance// of an evidence class (e.g., Site, Zone)while (it.MoveNext())Console.WriteLine(it.Current);

}}

Page 166: Essential .NET Security

166

Permissions

• Permissions limit what an assembly can do– run if code not verifiable?– access file system?– access the network?– access certain environment variables?– call native code (COM objects, DLLs)?– access files or printers without asking user?

Page 167: Essential .NET Security

167

CAS permission classes

• FCL supplies classes to represent permissions– in System.Security.Permissions namespace

DBDataPermissionPrintingPermissionMessageQueuePermissionDnsPermissionSocketPermissionWebPermissionEnvironmentPermissionFileDialogPermissionFileIOPermissionIsolatedStorageFilePermissionReflectionPermissionRegistryPermissionSecurityPermissionUIPermission

Page 168: Essential .NET Security

168

Security policy

• Security policy determines permissions granted to assembly– evidence given to policy– policy grants permissions based on the evidence– resulting permissions assigned to assembly

PolicyEvidence Permissions

Assembly

Page 169: Essential .NET Security

169

Setting policy

• By default, policy is defined based on Internet Explorer zones– My Computer– Local Intranet– Trusted Sites– Restricted Sites– Internet

MyComputer

Internet

RestrictedSites

Local Intranet

Trusted Sites

Policy

Page 170: Essential .NET Security

170

Policy levels

• Policy comes from four sources– enterprise– machine– user– appdomain

MyComputer

Internet

RestrictedSites

Local Intranet

Trusted Sites

machine

MyComputer

Internet

RestrictedSites

Local Intranet

Trusted Sites

user

MyComputer

Internet

RestrictedSites

Local Intranet

Trusted Sites

enterprise

MyComputer

Internet

RestrictedSites

Local Intranet

Trusted Sites

appdomain

Page 171: Essential .NET Security

171

Policy interaction

• Permission determined by intersecting applicable policies– all policies must agree before a permission is granted

user

appd

omain

machine

ente

rpris

eintersectionis granted

Page 172: Essential .NET Security

172

Default permissions

• Default permission set for each policy source– enterprise, user, appdomain grant full trust to all code– machine has several restrictions

My Computer

Local Intranet

Trusted Sites

Internet

Restricted Sites

Full Trust (no limitations at all)

Medium Trust

Low Trust

Low Trust

Nothing (cannot execute)

default machine policy

Page 173: Essential .NET Security

173

Customizing policy

• Can customize each policy level• Framework supplies tools to simplify task

– predefined permission sets– wizards to select settings– editors for finer-grained control

• Framework supplies policy classes– System.Security.Policy namespace– can alter policy programmatically for maximum control

Page 174: Essential .NET Security

174

Using a wizard to adjust policy

• Allows you to choose one of four permission sets– Full Trust– Medium Trust– Low Trust– No Trust

Page 175: Essential .NET Security

175

Full trust

• No CAS restrictions whatsoever• Code doesn’t have to be verifiable

– all code is verified by default unless it requests SkipVerification• Can call out to native code without restriction

– DLLs– COM objects

• Don’t forget that the operating system still controls access to external resources based on tokens– File system, kernel objects, etc.– DCOM– Databases

Page 176: Essential .NET Security

176

Medium trust

• Code may execute.• Code must be verifiable and may not call directly into unmanaged code.• Allowed to assert permissions (more on this later).• May not suspend, resume, interrupt, abort other threads, or stop its own threads from being aborted by

more trusted code.• May not modify security policy.• May not change the managed principal on a thread.• May not create or control AppDomains.• May not serialize objects using a SerializationFormatter (allows access to private state).• May not inject evidence for assemblies or AppDomains.• May not configure System.Runtime.Remoting or add extensions such as remoting sinks.• Denied access to all environment variables, except you may read USERNAME.• May read or write to the local file system, but only by using open/save dialogs to get a stream

(exception: may read directly from AppBase directory and any subdirectories)• Unlimited isolated storage space for your assembly, scoped by user, assembly, and machine.• May use reflection, but only to access public members of public types or to emit new types.• May read and write from the clipboard and put up windows of any shape or size.• May use DNS (Domain Name Service) without restriction.• May submit print jobs directly to the default printer, or to any other printer using a common dialog.• May read or write to existing event logs, and create event sources and logs.• May not access the registry, SQL databases, message queues• May use sockets, but only to connect to the site from which the code originated

Page 177: Essential .NET Security

177

Low trust

• Same as Medium Trust, with the following further restrictions:• May not assert permissions.• May not read/write ANY environment variables.• May not use the FileSave dialog to open files for writing (can still use

FileOpen to read).• May not read (via File IO) from AppBase directly without a dialog.• Isolated storage further restricted by quota (10240 bytes), also must be

scoped not only by assembly and user, but also by application.• May only display “safe top-level windows” which is supposed to help keep

mobile code from spoofing login dialogs and the like.• While writing to the clipboard is unrestricted, only intrinsic controls such as

the TextBox may read from the clipboard – user controls cannot.• Cannot use reflection to emit code.• Cannot use DNS (Domain Name Service) to resolve names.• May not send print jobs directly to any printers. Must use the common print

dialog in order to obtain the user’s consent.• Only code from trusted sites can connect back to the original site

Page 178: Essential .NET Security

178

No Trust

• No permissions are granted• Code is not even allowed to execute

Page 179: Essential .NET Security

179

Named permission sets

• Permissions are organized into sets to ease administration• Four built-in permission sets used by the wizards

– FullTrust– LocalIntranet (a.k.a. “medium trust”)– Internet (a.k.a. “low trust”)– Nothing (a.k.a. “no trust”)

• Three other built-in permission sets– Everything (all permissions defined by Microsoft)– SkipVerification (grants the right to run unverifiable code)– Execution (grants the right to execute)

• Can create others...

Page 180: Essential .NET Security

180

Drilling into security policy

• Policy is organized in several levels– allows delegation of administration– restrictions at one level cannot be overridden in a lower level

• View/edit using .NET Framework Configuration MMC snapin

policylevels

Page 181: Essential .NET Security

181

Drilling into a policy level

• A policy level consists of a tree of code groups and a list of named permission sets

code groups

namedpermission sets

policy level

Page 182: Essential .NET Security

182

Code groups

• Each code group has two properties– a membership condition (a single test of the evidence)– a reference to a named permission set

• Permission grant for a policy level comes from the union of all matching code groups– child nodes evaluated only if parent node matches

Page 183: Essential .NET Security

183

Evaluating a policy level

URL: http://sales/routing.dllZone: IntranetStrongName: a53fa82d942c5b01

evidence:

All CodeNothing

Zone: My ComputerFullTrust

Zone: IntranetIntranet

Zone: Trusted SitesIntranet

All CodeSame Site Access

Strong Name: a53fa82d942c5b01FullTrust

Strong Name: b77a5c561934e089FullTrust

All CodeSame Site Access

machinepolicy level

(excerpt)

permission grants:NothingIntranet

Same Site AccessFullTrust

= FullTrust

Page 184: Essential .NET Security

184

Assembly permission requests

• Permissions gathered from policy specify the “maxgrant” for the assembly– This set of permissions can be filtered by the assembly itself

// requesting minimal + optional permissions// (any permissions not requested are implicitly refused)[assembly: PermissionSet(SecurityAction.RequestMinimum,

Name="Internet")][assembly: PermissionSet(SecurityAction.RequestOptional,

File="optional.xml")]

// refusing a permission explicitly[assembly: FileIOPermission(SecurityAction.RequestRefuse,

Unrestricted=true)]

Page 185: Essential .NET Security

185

Assembly permission requests

• Minimum permission set– if maxgrant doesn’t include all these permissions, fail to load– this is an easy way to make sure that the core functionality in

the assembly can be provided without security exceptions• Optional permission set

– permissions the assembly is willing to accept, but doesn’t absolutely need to perform its core functionality

• Refused permission set– permissions the assembly absolutely does not want

• Permission requests can break your code if you’re not careful– very often turns a fully trusted assembly into a partially trusted

assembly– more on this later

Page 186: Essential .NET Security

186

Viewing assembly permission requests

C:\>permview \windows\microsoft.net\...\mscorlib.dll

minimal permission set:<PermissionSet class="System.Security.PermissionSet"

version="1"><IPermission class="System.Security.Permissions.SecurityPermission"

version="1"Flags="SkipVerification"/>

</PermissionSet>

optional permission set:Not specified

refused permission set:Not specified

permview.exe is your friend

Page 187: Essential .NET Security

187

Programmatically adjusting policy

• Often the policy wizard is a bit heavy handed– zone-wide adjustments– even with further refinement, only have four choices for trust

• Full, medium, low, or none• Can edit code groups and permission sets via UI

– automating this almost always necessary• For full control, can program against policy manually

– use SecurityManager to discover policy levels– use NamedPermissionSet to add new permission sets– use UnionCodeGroup to add new code groups– don’t forget to save your changes via

SecurityManager.SavePolicyLevel

Page 188: Essential .NET Security

188

Example: programmatically adjusting policy

PolicyLevel machineLevel = null;IEnumerator policyLevelEnumerator = SecurityManager.PolicyHierarchy();while (policyLevelEnumerator.MoveNext()) {

PolicyLevel lvl = (PolicyLevel)policyLevelEnumerator.Current;if ("Machine" == lvl.Label) {

machineLevel = lvl;break;

}}

first need to find the policy level you plan on adjusting (typically machine policy)

Page 189: Essential .NET Security

189

Example: programmatically adjusting policy

NamedPermissionSet nps = new NamedPermissionSet("AcmeExpense Permissions", PermissionState.None);

nps.AddPermission(new FileIOPermission(PermissionState.Unrestricted));if (null != machineLevel.GetNamedPermissionSet(nps.Name)) {

machineLevel.ChangeNamedPermissionSet(nps.Name, nps);}else {

machineLevel.AddNamedPermissionSet(nps);}

add a named permission set that describes whatever permissions you need

Page 190: Essential .NET Security

190

Example: programmatically adjusting policy

CodeGroup myCodeGroup = new UnionCodeGroup(new StrongNameMembershipCondition(

new StrongNamePublicKeyBlob(pubkey), "AcmeExpense",null),

new PolicyStatement(nps));myCodeGroup.Name = "AcmeExpense Application";myCodeGroup.Description = "Grants the AcmeExpense app access to ...";

machineLevel.RootCodeGroup.AddChild(myCodeGroup);SecurityManager.SavePolicyLevel(machineLevel);

add a code group that associates a membership condition with your named

permission set use secutil.exe to get public keys…

save the policy level when you’re done

Page 191: Essential .NET Security

191

Extracting a public key into a byte arrayC:\>secutil –s someSignedAssembly.dll

Microsoft (R) .NET Framework SecUtil 1.0.3705.0Copyright (C) Microsoft Corporation 1998-2001. All rights reserved.

Public Key = { 0, 36, 0, 0, 4, 128, 0, 0, 148, 0, 0, 0, 6, 2, 0, 0, 0, 36, 0, 0, 82, 83, 65, 49, 0, 4, 0, 0, 1, 0, 1, 0, 39, 248, 152, 209, 178, 241, 251, 168, 253, 210, 19, 210, 216, 222, 225, 229, 140, 57, 195, 183, 124, 162, 125, 84, 69, 41, 216, 50, 235, 108, 84, 140, 112, 4, 244, 1, 169, 135, 9, 176, 43, 34, 138, 250, 129, 52, 71, 209, 167, 94, 166, 18, 124, 230, 36, 132, 190, 79, 63, 162, 166, 103, 81, 129, 131, 182, 63, 79, 78, 136, 246, 15, 137, 91, 174, 76, 220, 67, 246, 187, 66, 171, 250, 78, 127, 248, 23, 153, 124, 113, 14, 195, 150, 176, 230, 158, 85, 244, 152, 111, 109, 11, 177, 96, 241, 114, 2, 49, 235, 42, 186, 65, 24, 215, 109, 174, 38, 162, 2, 162, 6, 136, 2, 2, 154, 207, 4, 177 }Name =someSignedAssemblyVersion =1.0.982.19355Success

Page 192: Essential .NET Security

192

CAS can be completely disabled on a machine

• You should be aware of this• Requires admin privileges

– caspol -s off• Can turn code access security back on via a similar command

– caspol -s on• Can check programmatically

using System;using System.Security;

class CheckSecurity {static void Main() {

Console.WriteLine(".NET Code Access Security is currently {0}",SecurityManager.SecurityEnabled ? "enabled" : "DISABLED!!");

}}

Page 193: Essential .NET Security

193

Policy wrap-up

• Loader discovers evidence• Evidence is fed as input into policy• Each of the four policy levels are evaluated, one at a time

– union of permission grants for each matching code group• Intersect the permissions granted at each level• Apply any assembly permission requests• Result is permissions granted to assembly

Page 194: Essential .NET Security

194

Summary

• CAS is the .NET security model for dealing with mobile code• Evidence is discovered by the loader• Policy takes evidence and turns it into permissions• Permissions say what your code can and cannot do

• …no point to any of this if CAS is disabled on the machine

Page 195: Essential .NET Security

Code Access SecuritySecuring mobile code in the .NET FrameworkPart 2: enforcement, tips, and custom permissions

Page 196: Essential .NET Security

196

Outline

• Enforcement• Tips for writing mobile code• Using Isolated Storage• Applying CAS to local code• Implementing custom permissions

Page 197: Essential .NET Security

197

Enforcing security

• At runtime, the .NET Framework classes demand permissions before performing sensitive operations– Type safe managed code can’t get around these checks– Mobile code restricted from calling unmanaged code directly

• Demands may be implemented two ways– Imperative – write the code to call Demand()– Declarative – use an attribute to force a demand

Page 198: Essential .NET Security

198

Enforcing security

managed & verified, mobile code

FileStream OpenFileDialog

KERNEL32.DLLP/Invoke

1 2

3

4 5

6

7

2 demand FileIOPermission5 demand FileDialogPermission8 demand SecurityPermission

Secu

rityE

xcep

tion!

8

1 new FileStream(@"c:\temp\foo.xml");

4 openFileDialog.ShowDialog();

7 CreateFile(@"c:\temp\foo.xml", ...);

Page 199: Essential .NET Security

199

Example: the file stream constructor

// excerpt from mscorlib.dllpublic FileStream(string path, FileAccess desiredAccess) {

FileIOPermissionAccess access = _calcAccess(desiredAccess);

// describe the action we are going to performCodeAccessPermission perm = new FileIOPermission(access,

path);// demand that the caller can do thisperm.Demand();

// call through interop to get a real file handleWin32Native.CreateFile(...);

}

This is an “imperative” demand – note we are calling Demand() programmatically

Page 200: Essential .NET Security

200

Example: declarative demands

// excerpt from mscorlib.dllnamespace System.Threading {public class Thread {

[SecurityPermission(SecurityAction.Demand,ControlThread=true)]

public void Suspend() {this.SuspendInternal(); // actually do the work

}}

}

Page 201: Essential .NET Security

201

Other types of demands

• LinkDemand– Checks at JIT time whether calling assembly satisfies demand– Often used to deny access to mobile code

• LinkDemand that caller has full trust– Often used to constrain caller by strong name

• Allows types to be exposed publicly from an assembly while constraining who can use them

• InheritanceDemand– Checks at load time whether derived class satisfies demand– Same uses as LinkDemand, but helps constrain who can

override methods• Both typically make use of “identity permissions”

Page 202: Essential .NET Security

202

Example: LinkDemand

[StrongNameIdentityPermission(SecurityAction.LinkDemand,PublicKey="00240000048000009400000006020000" +

"00240000525341310004000001000100" +"6F8DC651FF981820321523DB748F4EB7" +"0E08C658CB37D355A81A3162B8BB2440" +"1AF243F0C698623CD3A0916B3055F1C9" +"9148F350D4750AF7231245CD54761964" +"0C21F6EE3633EC0D44C708EA50A7010D" +"15521719C33D1BBD5987AE9930B35637" +"9DBB7A5367592046E5AEC0725623B378" +"04566E5BC92B5E9508CE19DB49FEDBD3")]

public class AcmeHelper {public void DoSomethingHelpful() {

// this class can only be called by code// that has been signed by the private key// associated with the above public key// (or someone hacked their CLR to skip this check)

}}

Page 203: Essential .NET Security

203

Viewing declarative demands, asserts, etc.

C:\>permview /decl \windows\microsoft.net\...\mscorlib.dll

Method System.Threading.Thread::Suspend() Demand permission set:<PermissionSet class="System.Security.PermissionSet"

version="1"><IPermission class="System.Security.Permissions.SecurityPermission"

version="1"Flags="ControlThread"/>

</PermissionSet>

Method System.AppDomain::SetData() LinktimeDemand permission set:<PermissionSet class="System.Security.PermissionSet"

version="1"><IPermission class="System.Security.Permissions.SecurityPermission"

version="1"Flags="ControlAppDomain"/>

</PermissionSet>...

permview.exe is your friend, once again

Page 204: Essential .NET Security

204

Security demands walk the stack

• Prevents less trusted components from “luring” more trusted components into doing their dirty work– (note that link time demands are an exception to this rule)

fully trusted local code

FileStream OpenFileDialog

KERNEL32.DLLP/Invoke

1 2

3

4 5

6 Secu

rityE

xcep

tion!

7

managed & verified, mobile code

Page 205: Essential .NET Security

205

The stack walk is almost always a good thing

• Except when you’re trying to build a secure gateway– such as the FileStream object

• If the stack walk wasn’t controllable, creating a FileStream would actually require two permissions, not just one– FileIOPermission demanded by FileStream– SecurityPermission(UnmanagedCode) demanded by P/Invoke

partially trusted code

FileStream

P/Invoke

1 2

3

Secu

rityE

xcep

tion!

2

4

success on demand FileIOPermission

4 failure on demand for unmanaged code

Page 206: Essential .NET Security

206

Controlling the stack walk

• For calling to native code (most common)– use SuppressUnmanagedCodeSecurityAttribute– suppresses the stack-walking demand for UnmanagedCode,

turning it into a LinkDemand that only affects the direct caller– thus direct calling assembly must have UnmanagedCode perm– important performance optimization!

• For all other cases– use Assert– an assembly that calls Assert must have the permission it is

asserting, and must also have SecurityPermission(Assertion)– Stack walk still occurs, it’s just halted when assertion marker is

found on the stack

Page 207: Essential .NET Security

207

Example: SuppressUnmanagedCodeSecurity// excerpt from mscorlib.dllpublic FileStream(string path, FileAccess desiredAccess) {

FileIOPermissionAccess access = _calcAccess(desiredAccess);

// describe the action we are going to performCodeAccessPermission perm = new FileIOPermission(access,

path);// demand that the caller can do thisperm.Demand();

// call through interop to get a real file handle// note that no stack walk will occur!Win32Native.CreateFile(...);

}// also in mscorlib.dll[SuppressUnmanagedCodeSecurity]internal class Win32Native {

[DllImport("kernel32.dll")]internal static extern int Createfile(...);

}

Page 208: Essential .NET Security

208

Example: Assert

// this function needs to read an environment variable in order to// do its work, but callers might not have permission to read FOO// themselvespublic static void DoSomeWork() {CodeAccessPermission perm = new EnvironmentPermission(

EnvironmentPermissionAccess.Read,"FOO");

// For this to work, this assembly (not its callers) must have// 1) the permission we are trying to assert// 2) the right to assert (SecurityPermission(Assertion))perm.Assert();

string foo = Environment.GetEnvironmentVariable("FOO");

// do some more work...}

Page 209: Essential .NET Security

209

Don’t misuse Assert and SUCS

// this totally subverts security policy using Assertpublic static string ReadEnvironmentVariable(string name) {new EnvironmentPermission(EnvironmentPermissionAccess.Read,

name).Assert();

return Environment.GetEnvironmentVariable(name);}

// subverts security policy via SuppressUnmanagedCodeSecuritypublic static string CallSleep(int milliseconds) {Sleep(milliseconds);

}

[SuppressUnmanagedCodeSecurity][DllImport("kernel32.dll")]internal static extern void Sleep(int milliseconds);

dumb code alert

dumb code alert

Page 210: Essential .NET Security

210

CAS stack markers: Assert, Deny, PermitOnly

• An assertion is really just a marker on the stack– when an assertion marker is encountered during a stack walk,

if the asserting assembly has the permission being asserted, that permission is granted immediately (the stack walk ends)

• Deny and PermitOnly markers work similarly– when a deny marker is encountered during a stack walk, the

permission will be denied immediately (the stack walk ends)• Deny and PermitOnly can be used to choke down

permissions before calling to less trusted code– helps secure extensibility points in your application

• Deny and PermitOnly are helpless against fully trusted code– fully trusted code can just Assert and party on

Page 211: Essential .NET Security

211

Partially trusted code

• Partially trusted code can’t call strongly named assemblies– not unless the target assembly explicitly allows it– local assemblies without strong names cannot be seen by

typical mobile code (browser’s AppBase is nowhere near your code)

– assemblies with strong names can be GACked, thus the restriction

• Why worry?• Isn’t CAS strong enough to allow this?

Page 212: Essential .NET Security

212

What if mobile code could use this class?

public class HopeThisIsntUsedByEvilCodeBecauseItsNotRobust {public string Name;public string Password;

// this entire function consists of// horribly bad code you should NEVER EVER usepublic bool IsValidUser() {

new DbDataPermission(PermissionState.Unrestricted).Assert();SqlConnection conn = new SqlConnection(

"initial catalog=accounts;user id=sa;password=;")conn.Open();cmd.CommandText = string.Format(

"select count(*) from users where name='{0}'" +"and password='{1}'", Name, Password);

return ((int)cmd.ExecuteScalar()) > 0;}

}

dumb code alert

dumb code alert

Page 213: Essential .NET Security

213

How to allow partially trusted code to call you

• Step 1: review your code for security holes• Step 2: fix the holes• Step 3: goto step 1 until you’re really comfortable

– Microsoft is still in this loop with many of its assemblies• Step 4: apply an attribute to your strongly named assembly

– System.Security.AllowPartiallyTrustedCallersAttribute– step 4 is much, much easier than steps 1-3, so be vigilant

using System.Reflection;using System.Security;[assembly: AssemblyKeyFile("publicKey")][assembly: AssemblyDelaySign(true)][assembly: AllowPartiallyTrustedCallers]

Page 214: Essential .NET Security

214

Applying CAS to non-mobile code

• Why not use CAS for local code?– it’s a good idea in theory– each assembly runs with only the permissions it needs

• In practice there is a major roadblock– most system assemblies aren’t marked with

AllowPartiallyTrustedCallersAttribute• AllowPartiallyTrustedCallersAttribute not present on:

– System.Runtime.Remoting.dll– System.Management.dll– and others…

• Microsoft is working on it…– for now, beware restricting local code with CAS

Page 215: Essential .NET Security

215

Tips for writing mobile Intranet code

• Use only managed, verifiable code– don’t use Managed C++ or C# /unsafe switch

• Avoid System.Runtime.InteropServices– that is, don’t call to COM objects or unmanaged DLLs

• Avoid using System.Runtime.Serialization– consider using System.Xml.Serialization instead

• Avoid using System.Runtime.Remoting– consider using System.Web.Services instead

• Use common dialogs– OpenFileDialog, SaveFileDialog, PrintDialog

• Only reflect against accessible members– don’t try to use reflection to get to private stuff

• Use AllowPartiallyTrustedCallersAttribute where necessary• Consider using Isolated Storage…

Page 216: Essential .NET Security

216

Isolated storage

• Allowing partially trusted code to specify file names and paths is dangerous– past experience tells us this*

• The .NET Framework provides a virtualized file system– tucked away in a protected directory in the real file system

• Goal is to allow partially trusted code to persist data without exposing the real file system

• There are actually several isolated stores– each provides a virtualized file system– code chooses a store based on scope requirements

Page 217: Essential .NET Security

217

How isolation scoping works

• Always isolated based on user and assembly– Assembly ID based on strong name, publisher, URL, site, zone

• May isolate also based on AppDomain– This is the assembly name of the main application in which you

are loaded • May also choose to have storage roam with user

– Roaming storage is a different store than non-roaming storage• Moral of the story

– If you want your data back, you need to make the same choices about AppDomain and roaming

• Physical storage on hard driveDocuments and Settings\user\[Local Settings\]Application Data\IsolatedStorage

for non-roaming

Page 218: Essential .NET Security

218

The four supported isolated storage scopesuser

assembly

application(domain)

machine

1

2 34

2

AssemblyIsolationByRoamingUser

DomainIsolationByRoamingUser

1 GetStore(User | Assembly | Roaming)

GetStore(User | Assembly | Domain | Roaming)

AssemblyIsolationByUser

DomainIsolationByUser

3

4

GetStore(User | Assembly)GetUserStoreForAssembly()GetStore(User | Assembly | Domain)GetUserStoreForDomain()

Permission required Which method to use on IsolatedStorageFile

Page 219: Essential .NET Security

219

Using isolated storage

IsolatedStorageFile s = IsolatedStorageFile.GetUserStoreForDomain();Console.WriteLine("Current Size: {0}", s.CurrentSize);Console.WriteLine("Maximum Size: {0}", s.MaximumSize);if (s.GetFileNames("foo").Length > 0) {

using (FileStream media = new IsolatedStorageFileStream("foo",FileMode.Open, FileAccess.Read, FileShare.Read, s))

using (StreamReader r = new StreamReader(media)) {Console.WriteLine(r.ReadToEnd());

}}else {

using (FileStream media = new IsolatedStorageFileStream("foo",FileMode.Create, FileAccess.Write, FileShare.None, s))

using (StreamWriter w = new StreamWriter(media)) {w.Write("Testing 123");

}}

Page 220: Essential .NET Security

220

Extending security policy with custom gateways

• What if you need mobile code to be able to access a set of COM components or DLLs?– choice 1: modify policy to make that code fully trusted– choice 2: write your own gateway that demands a custom

permission, then grant that permission to the mobile code• Steps to building a custom gateway

– Write and deploy a permission assembly• custom permission class• corresponding custom attribute for declarative use

– Write the gateway– Adjust policy with your new permission

Page 221: Essential .NET Security

221

Implementing a permission

• Derive a class from CodeAccessPermission or ResourcePermissionBase– implement IUnrestrictedPermission– implement all required methods– try to avoid dependencies on assemblies other than mscorlib

bool IsUnrestricted();IPermission Copy();IPermission Intersect(IPermission target);bool IsSubsetOf(IPermission target);SecurityElement ToXml();void FromXml(SecurityElement element);

Page 222: Essential .NET Security

222

Implementing a permission attribute

• For each permission, provide a corresponding attribute– allows users declarative as well as imperative control

[AttributeUsage(AttributeTargets.Assembly |AttributeTargets.Class |AttributeTargets.Struct |AttributeTargets.Method |AttributeTargets.Constructor)]

public sealed class BeepPermissionAttribute :CodeAccessSecurityAttribute {

public int MaxBeeps;public BeepPermissionAttribute(SecurityAction action)

: base(action) {base.Unrestricted = false;

}public override IPermission CreatePermission() {

return new BeepPermission(base.Unrestricted, MaxBeeps);}

}

Page 223: Essential .NET Security

223

Working with permission assemblies

• Preparing the permission assembly– include your permission and permission attribute– strongly name it– mark it with AllowPartiallyTrustedCallersAttribute– install it into the GAC and keep the GAC fresh*

• Add the assembly to the list of trusted policy assemblies– use mscorcfg to do this

Page 224: Essential .NET Security

224

Writing a gateway class

• Before accessing the guarded resource, demand an appropriate permission– may need to use assert or SuppressUnmanagedCodeSecurity

to “convert” a generic demand to a more specific one

public class Beeper {public static void Beep(int howManyBeeps) {

new BeepPermission(howManyBeeps).Demand();for (int i = 0; i < howManyBeeps; ++i)

Win32.MessageBeep(0);}

}[SuppressUnmanagedCodeSecurity]internal class Win32 {

[DllImport("user32.dll")]internal static extern void MessageBeep(uint n);

}

Page 225: Essential .NET Security

225

Injecting custom permissions into policy

• Write a little program to create or augment a permission set– import with mscorcfg and refer code groups to it

static void Main() {NamedPermissionSet ps = new NamedPermissionSet(

"MyPermissionSet",PermissionState.None);

int maxBeeps = 5;ps.AddPermission(new BeepPermission(maxBeeps));Console.WriteLine(ps.ToXml());

}

<PermissionSet class="System.Security.NamedPermissionSet"version="1"Name="MyPermissionSet">

<IPermission class="DM.Security.BeepPermission, ..."version="1"MaxBeeps="1"/>

</PermissionSet>

Page 226: Essential .NET Security

226

Summary

• Permission demands walk the stack to avoid luring attacks• Writing mobile code means understanding CAS• Isolated storage is a reasonable way to store per-user state

from partially trusted code• CAS can be applied to local code as well – this will get easier

in the future• You can extend CAS to guard custom resources or change

the way policy works

Page 227: Essential .NET Security

Web Application SecurityAuthentication and Authorizationin IIS6 and ASP.NET

Page 228: Essential .NET Security

228

Outline

• IIS 6 process model• ASP.NET security contexts• The HTTP pipeline• Authentication• Authorization• Forms Authentication

Page 229: Essential .NET Security

229

IIS 6

• IIS is not installed by default• When installed, “locked down” – only serves static content

– use IIS Manager: Web Service Extensions to enable dynamic content

• Application Pools– represents an instance of w3wp.exe– can configure identity of worker process via pool

Page 230: Essential .NET Security

230

IIS 6 process model

• IIS 6 provides a process model that encourages isolation and running with least privilege– requests routed directly from kernel to worker process– unlike IIS 5 where process isolation caused an extra context

switch (from inetinfo.exe to the worker process)• Number of worker processes is configurable

– each “application pool” has its own worker process– one application pool by default, but you can create more– can configure identity and other settings via pool properties

• Web application isolation is configurable– each web application (virtual directory) assigned to a pool

Page 231: Essential .NET Security

231

Isolation via application pools

Web apps must be assigned to a pool, with each pool having its own worker process

Page 232: Essential .NET Security

232

Isolation via application pools

kernel mode

user mode

http.sys

FTPSMTPNNTPetc.

inetinfo.exew3wp.exew3wp.exe

NetworkService Bob SYSTEM

Each worker process can be configured with its own identity

Web apps must be assigned to a pool, with each pool having its own worker process

vdir1

vdir2

vdir3

vdir4

Incoming requests are routed from the kernel directly into the appropriate worker process

Page 233: Essential .NET Security

233

The HTTP pipeline in ASP.NET

• ASP.NET handles requests via a pipeline• Handler is endpoint for request

– an ASPX page is an example of a handler• Modules are pluggable extensions

– act like filters in the channel

Page 234: Essential .NET Security

234

The HTTP pipeline from 25,000 feet

Application

Handler (ASPX page)

Module

w3wp.exe

Page 235: Essential .NET Security

235

The importance of modules

• Modules get to pre- and post-process each request• Perfect place to put security code

– page developers can’t “forget” to call your security logic• This is where you’ll find all the built-in security

– windows authentication– forms authentication– passport authentication– file authorization– url authorization

• Understanding how modules work is critical– modules register for a fixed set of events– events are fired in order

Page 236: Essential .NET Security

236

The pipeline in more detail

Application

Aut

hent

icat

eReq

uest

Aut

horiz

eReq

uest

EndR

eque

st

Res

olve

Req

uest

Cac

he

Acq

uire

Req

uest

Stat

e

PreR

eque

stH

andl

erEx

ecut

e

Post

Req

uest

Han

dler

Exec

ute

Rel

ease

Req

uest

Stat

e

Upd

ateR

eque

stC

ache

Handler (ASPX page)WindowsAuthentication

W

UrlAuthorization

U

OutputCache

O O

Session

S S

FormsAuthentication

Fo Fo

PassportAuthentication

P P

FileAuthorization

Fi

Mod

ules

Page 237: Essential .NET Security

237

Security contexts

• ASP.NET apps track both server and client identity• Token tracks who the SERVER is

– process token– thread token (if you choose to turn on impersonation)– discover via WindowsIdentity.GetCurrent()

• Managed identity tracks who the CLIENT is– discover via HttpContext.User or Page.User

Page 238: Essential .NET Security

238

Process and thread token

P

w3wp.exe

app 1

T

app 2

process token configured once per application pool, affects all web apps running in that pool

impersonation configurable by each individual web application

Page 239: Essential .NET Security

239

<!-- excerpt from machine.config --> <processModel

...User='MACHINE'Password='Autogenerate'...

/>

Configuring the process token

• In IIS 6, use application pool configuration• In IIS 5, use machine.config:

Page 240: Essential .NET Security

240

<!-- web.config --><configuration><system.web><identity impersonate='false|true'/>

</system.web></configuration>

• Can turn on impersonation with a switch in web.config– thread token will be obtained from IIS– emulates IIS 5 where every call impersonated the client (or the

anonymous user account, typically IUSR_MACHINE)

Configuring impersonation

Page 241: Essential .NET Security

241

Client authentication and HttpContext.User

• ASP.NET provides several ways to authenticate clients– native Windows authentication (default)– forms-based authentication– Passport authentication

• Use <authentication> tag to control this• Results stored in HttpContext.User

– also accessible via Page.User

<!-- web.config --><configuration><system.web><authentication mode='Windows|Forms|Passport|None'/>

</system.web></configuration>

Page 242: Essential .NET Security

242

Authentication modes

• None– HttpContext.User refers to an anonymous identity

• Windows– HttpContext.User refers to a WindowsPrincipal– wraps the token IIS got for the principal

• Forms– HttpContext.User refers to a GenericPrincipal– name is whatever name you specify– roles empty by default (you can inject roles, more later)

• Passport– HttpContext.User refers to a PassportIdentity

Page 243: Essential .NET Security

243

Authentication in the pipeline

• HttpContext.User is initialized during AuthenticateRequest– usually via one of the built-in modules

• WindowsAuthenticationModule• FormsAuthenticationModule• PassportAuthenticationModule

• There is an undocumented event that fires immediately after– its name is “DefaultAuthentication”– one hardwired module always registers for this event, its name

is “DefaultAuthenticationModule”– this module has only one job

• copy HttpContext.User Thread.CurrentPrincipal• This allows you to use PrincipalPermissionAttribute

Page 244: Essential .NET Security

244

Accessing the three ASP.NET security contexts<%@import namespace='System.Security.Principal'%><%@import namespace='System.Runtime.InteropServices'%>

<%IPrincipal myClient = this.User;

IPrincipal myThreadToken =new WindowsPrincipal(WindowsIdentity.GetCurrent());

RevertToSelf(); // remove any thread token

IPrincipal myProcessToken =new WindowsPrincipal(WindowsIdentity.GetCurrent());

%>

<script runat='server'>[DllImport("advapi32.dll")]static extern bool RevertToSelf();</script>

Page 245: Essential .NET Security

245

Authorization

• You can write code to do manual authorization– declarative principal checks via PrincipalPermissionAttribute– imperative principal checks via HttpContext.User.IsInRole

• You can also leverage two modules in the pipeline– FileAuthorizationModule– UrlAuthorizationModule

Page 246: Essential .NET Security

246

File-based authorization

• Always (and only) in effect with Windows authentication– <authentication mode='Windows'/>

• The managed principal in this case is a WindowsPrincipal– holds a Windows access token

• Token used in access check against file system DACL– DACL = Discretionary Access Control List

• This is exactly how classic ASP used to work• IIS already enforces this for unmanaged resources

– static HTML files– images– etc.

Page 247: Essential .NET Security

247

<configuration><system.web><authorization><allow roles='Managers,Friends'/><deny users='?'/>

</authorization></system.web>

</configuration>

• Controls access to all managed resources– this form of authorization works with all types of authentication

• Does NOT control access to unmanaged resources by default– only controls access to file extensions mapped to ASP.NET– you can change this mapping if you like (may reduce perf)

URL-based authorization in web.config

Page 248: Essential .NET Security

248

URL-based authorization in subdirectories

• You can drop an authorization section in a subdirectory

• You can also use a location tag– control subdirectories– control individual files

<configuration><system.web><authorization><allow roles='Subscribers'/>

</authorization></system.web>

</configuration>

<configuration><location path='subscriptionOnlyDirectory'><system.web><authorization><allow roles='Subscribers'/>

</authorization></system.web>

</location></configuration>

Page 249: Essential .NET Security

249

Form-based authentication

• Uses least-common-denominator technologies for portability– simple HTML forms for gathering authentication information– cookies for maintaining a session

• Designed to be flexible and extensible– most of its internals are publicly documented classes– optional password management

• Requires cookies– no direct support for URL munging, for instance– the forms auth cookie is distinct from the session cookie

Page 250: Essential .NET Security

250

Cookies

• To understand Forms auth you must understand cookies– cookie mechanism documented in RFC 2965– web site sends state to user agent– user agent echoes state back to server with each request– user agent must not leak state across domains– cookies can be transient or persistent– nothing stops a client from modifying state in a cookie– nothing stops an eavesdropper from recording a cookie being

sent over the Internet using raw HTTP

Page 251: Essential .NET Security

251

Basics

• Basic Forms Authentication– easy to get started with forms auth– turn it on in your root web.config file– design a login form that collects a user name and password/pin– upon submission, verify the password/pin and call

FormsAuthentication.RedirectFromLoginUrl()– set authorization requirements to force a login

Page 252: Essential .NET Security

252

<!-- web.config in vroot --><configuration><system.web><authentication mode='Forms'><forms name='ASPXAUTH'

loginUrl='login.aspx'protection='All'requireSSL='false'timeout='30'slidingExpiration='false'path='/'

/></authentication>

</system.web></configuration>

Enabling forms authentication

shown here are the defaultvalues for each attribute

Page 253: Essential .NET Security

253

<%@page language='c#' %><%@import namespace='System.Web.Security' %>

<form runat='server'>

<table><tr><td>Name:</td><td><asp:TextBox id='name' runat='server'/></td></tr><tr><td>Password:</td><td><asp:TextBox id='pwd' TextMode='password'

runat='server'/></td></tr></table><p><asp:CheckBox id='persist' runat='server'Text='Log me in automatically from this computer'/>

<p><asp:Label id='msg' runat='server'/><p><asp:Button Text='Login' runat='server'/>

</form>

Example: a simple login form

Page 254: Essential .NET Security

254

<script runat='server'>void OnLogin(Object sender, EventArgs eventArgs) {if (authenticateUserSomehow(name.Text, pwd.Text)) {// only redirect if password is validFormsAuthentication.RedirectFromLoginPage(

name.Text, persist.Checked);}else {// otherwise leave them on this pagemsg.Text = "Unknown user name or password";

}}</script>

Example: handling login

Page 255: Essential .NET Security

255

Mechanics

• Forms Authentication Mechanics– FormsAuthenticationModule preprocesses all requests– cookie turned into IPrincipal and associated with context– if no cookie and auth is required, redirects to login page– after login, redirected back to original page, sending cookie– cookie contains version, name, timestamp, optional user data– cookie protected with encryption and MAC (by default)

Page 256: Essential .NET Security

256

http request

(including cookie)

FormsAuthenticationModule

1) Decrypt Cookie2) Verify MAC3) Populate Context.User4) Fire "Authenticate" Event5) Set Thread.CurrentPrincipal == Context.User

HttpHandler(your code, an aspx page,

for instance)

Transparent conversion of cookies to context

Page 257: Essential .NET Security

257

http request(no cookie)

UrlAuthorizationModule

2) Check if authentication required for request3) If so, return 401 Unauthorized

FormsAuthenticationModule

1) No cookie, so do nothing...

FormsAuthenticationModule

4) Convert 401 Unauthorizedinto 302 redirect to login page

redirect

HttpHandler(your code, an aspx page,

for instance)

Transparent redirection to login page

Page 258: Essential .NET Security

258

Postprocessing

• Postprocessing after Authentication– often useful to do some additional work after

FormsAuthenticationModule does its magic– add roles to principal...– convert user data in cookie to session state...– to do any of these things, need to hook the

AuthenticateRequest event– can do this via global.asax or by writing a module– to add roles, just replace the principal!

Page 259: Essential .NET Security

259

<%@application language='C#'%><%@import namespace='System.Security.Principal'%>

<script runat="server">void Application_AuthenticateRequest(object sender, EventArgs args) {

// get the principal produced by forms authenticationIPrincipal originalPrincipal = HttpContext.Current.User;

if (null != originalPrincipal) {IIdentity id = originalPrincipal.Identity;

// TODO: lookup real roles based on id.Namestring[] roles = { "ClubMember", "Swimmer" };

// replace the principal with a new one with rolesHttpContext.Current.User = new GenericPrincipal(id, roles);

}}</script>

Adding roles using global.asax

Page 260: Essential .NET Security

260

Forms authentication in a web farm

• Remember cookies are MAC protected and encrypted– ASP.NET creates new keys each time it’s installed– this breaks a web farm

• Can synchronize keys across a web farm– set the <machineKey> element in machine.config

<system.web><machineKey validationKey='[128 hexadecimal digits]'

decryptionKey='[48 hexadecimal digits]'validation='SHA1'/>

</system.web>

Page 261: Essential .NET Security

261

Protecting cookies

• The security of authentication cookies is weak unless they are protected– cookies can be undetectably altered by users unless protected

by a MAC– cookies can be stolen by an eavesdropper if sent over a non-

secure channel– persistent cookies can be stolen off a user's hard drive– use SSL to encrypt all traffic to your secure site, or use the

Secure option on your cookies (this is a SHOULD, not a MUST in RFC 2965 though) via requireSSL=‘true’

– cookie paths don't work well with IIS due to case insensitivity (cookies are case sensitive, but IIS is not)

Page 262: Essential .NET Security

262

Summary

• Your code runs within several security contexts– process token– thread token– managed identity

• Forms authentication provides an application level authentication mechanism– as opposed to an operating system level mechanism– don’t need to give web clients NT accounts

• If you use forms authentication, use SSL as well!

Page 263: Essential .NET Security

Web Service SecurityMaking the web secure for ecommerce

Page 264: Essential .NET Security

264

Outline

• Today’s methods– SSL– Client authentication– Intermediaries

• The future: WS-Security– Xml Canonicalization– Xml Signature– Xml Encryption

Page 265: Essential .NET Security

265

Web service security today

• Most web services today are not secure• Most web services published at xmethods.com, for example

– run over http, not https– don’t bother with authentication at all, or– require user name and password be sent in the clear– email passwords to clients

• Most secure web services are private– not published in web service directories– used by a cooperating group of business partners– security almost always based on SSL

Page 266: Essential .NET Security

266

Using SSL to secure a web service

• Benefits– most HTTP stacks already support SSL– SSL provides authentication, integrity, and confidentiality– XML carried over secure transports doesn’t have to conform to

any particular security standard• Drawbacks

– SSL itself has some issues• establishing SSL sessions is expensive• SSL is very session oriented, making load balancing hard

– intermediaries break end-to-end security– SSL is only widely supported over HTTP, while web services

can run over other protocols such as SMTP

Page 267: Essential .NET Security

267

Transport level security and intermediaries

• SSL is a transport level security mechanism– who does the client see?– who does the server see?

ClientApplication

ServerApplication

Transport Stack Transport Stack

IntermediaryApplication

Transport StackSSL SSL

Page 268: Essential .NET Security

268

Guidelines on using SSL

• Decide how to authenticate clients– certificates are powerful but hard to manage by clients– passwords are easier but often chosen or managed badly

• Manage your own private key carefully– buy your server certificate from a well-known authority– store backup copy of password protected PFX file in one vault– store password in another vault

• Harden the web server as much as possible– see http://www.microsoft.com/security for tools

• Remember SSL only secures the pipe– need to write secure code and consider insider attacks as well

Page 269: Essential .NET Security

269

Client authentication using certificates

• Issue your own client certificates– no need to involve a third party (like Verisign) unless client

needs a single certificate for use with multiple vendors– certificate server is a good way to do this on the .NET platform

• Require SSL with client certificates in IIS– tell IIS which authorities you trust via a Certificate Trust List– decide whether or not to map certs to NT accounts

• Educate your clients about their private key– most people don’t have a clue that it even exists– teach them how to back it up (export to password protected

PFX file)– teach them what to do if it’s compromised (alert you so you can

revoke it!)

Page 270: Essential .NET Security

270

Client authentication using passwords

• Manage passwords carefully– do not store cleartext passwords on your server – store salted

hashes instead– never send password material via unsecured email– don’t accept low entropy passwords

• Make sure every web method requires SSL– most implementations require username and password or

session token to be sent with each request, so protect them• Be careful with session tokens

– if you issue them, make sure that guessing one is infeasible (use a long number generated from a good random source)

Page 271: Essential .NET Security

271

The future of web service security: GXA?

• GXA = Global Xml (Web Services) Architecture• WS-Security written by Microsoft, IBM, VeriSign

– transferred to Oasis for standardization– see http://www.oasis-open.org/committees/wss/

• Hoists security up from transport– allows for end-to-end security in the face of intermediaries– opens the door for alternatives to SSL

Page 272: Essential .NET Security

272

Implementations of WS-Security

• Web Services Enhancements (WSE) from Microsoft– http://msdn.microsoft.com/webservices/building/wse

• Web Service Toolkit from IBM– http://www.alphaworks.ibm.com/tech/webservicestoolkit

Page 273: Essential .NET Security

273

WS-Security

• WS-Security spec focuses on three main mechanisms– packaging security tokens in XML– message integrity– message confidentiality

• Leverages existing W3C specs– Details how these specs should be applied to SOAP

Page 274: Essential .NET Security

274

Foundations of WS-Security

• To understand WS-Security, need to spend some time looking at the underlying specs– XML Canonicalization– XML Signature– XML Encryption

Page 275: Essential .NET Security

275

The need for canonicalization

• XML 1.0 serialization is pretty relaxed

• While the XML infoset represented by these documents are equivalent, the serialized forms are different– When encoded into byte streams, they have different values– Thus their signatures will be different

• Need to agree on a canonical serialized form before signatures will make any sense

<person name='Bob' age='24'/>

<person age="24" name="Bob" />

<person name="Bob" age='24'></person>

These documents are all equivalent as far as XML 1.0 is concerned

Page 276: Essential .NET Security

276

Canonical XML

• Canonical XML 1.0– http://www.w3.org/TR/xml-c14n (also RFC 3076)– W3C Recommendation 15 March 2001

• Describes the transformation of an XML document into a canonical byte stream– UTF-8 encoding– CDATA sections replaced with their character content– <foo/> converted to <foo></foo>– Attribute values delimited by double quotes– Attributes and namespaces are arranged lexicographically– Whitespace outside of the document element and within start

and end tags is normalized– and so on…

Page 277: Essential .NET Security

277

Example of canonicalization

<person name='Bob' age='24'/>

<person age="24" name="Bob" />

<person name="Bob" age='24'></person>

<person age="24" name="Bob"></person>

Canonical XML

Page 278: Essential .NET Security

278

Canonicalization and SOAP

• SOAP is all about enveloping XML fragments for transport– Canonical XML doesn’t address the context changes that

occur during enveloping– Can cause problems with resulting signatures

<foo></foo>

<x:bar xmlns:x='http://xyz'><foo></foo>

</x:bar>

<foo xmlns:x='http://xyz'></foo>

applying canonical xmlto both fragments results in differences due to the context change

Page 279: Essential .NET Security

279

Exclusive Canonical XML

• Exclusive XML Canonicalization 1.0– http://www.w3.org/TR/xml-exc-c14n– W3C Recommendation 18 July 2002

• Provides better support for fragments

<foo></foo>

<x:bar xmlns:x='http://xyz'><foo></foo>

</x:bar>

<foo xmlns:x='http://xyz'></foo>

applying canonical xmlto both fragments results in differences due to the context change

<foo></foo> result of applying exclusive canonical xml

Page 280: Essential .NET Security

280

XML Signature

• XML-Signature Syntax and Processing– http://www.w3.org/TR/xmldsig-core (also RFC 3275)– W3C Recommendation 12 February 2002

• What XML Signature does– Signs fragments of XML documents– Records the details and the signature value itself in a

<Signature/> element– Provides hints about which key was used for the signature

Page 281: Essential .NET Security

281

An XML signature in the wild

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <CanonicalizationMethodAlgorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>

<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/> <Reference URI="http://www.w3.org/TR/2000/REC-xhtml1-20000126/"> <Transforms> <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>

</Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue>

</Reference> </SignedInfo> <SignatureValue>MC0CFFrVLtRlk=...</SignatureValue><KeyInfo> <KeyValue><DSAKeyValue>...</DSAKeyValue>

</KeyValue> </KeyInfo>

</Signature>

Page 282: Essential .NET Security

282

Inside an XML signature

• A typical signature contains three parts– the data being signed– the actual bits of the resulting signature– information about the key used for the signature

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> +<SignedInfo> <SignatureValue>MC0CFFrVLtRlk=...</SignatureValue> +<KeyInfo>

</Signature>

the signature

the bits we signed

optional informationabout the key

Page 283: Essential .NET Security

283

What really gets signed?

• SignedInfo contains all the bits that are physically signed– contains detailed instructions on how to

• canonicalize SignedInfo• digest (hash) SignedInfo• encrypt the resulting digest to form the final signature

– indirectly references XML node sets• this is the information that is logically being signed

<SignedInfo> <CanonicalizationMethod Algorithm="..."/> <SignatureMethod Algorithm="..."/> +<Reference>

</SignedInfo>

how to digest and encryptSignedInfo to form the signature

how to canonicalizeSignedInfo

references to the real datawe wanted to sign

Page 284: Essential .NET Security

284

Referencing real XML we want to sign

• References link the signature to the XML we wanted to sign– pulls in a digest (hash) of each reference to be signed– signing the digest value binds the content to the signer’s key

<Reference URI="#stuffIWantSigned"> <Transforms> <Transform Algorithm="..."/>

</Transforms> <DigestMethod Algorithm="..."/> <DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue>

</Reference>

fragment identifier or URL, for instance,points us to XML we want signed

optional transforms take us from XMLto octets (e.g., canonicalization)

how to digestthose octets

the actualdigest value

Page 285: Essential .NET Security

285

WS-Security and signatures

• XML Signature binds XML to a key• WS-Security takes this one step further

– binds the signature to a claim– <KeyInfo/> contain a WS-Security element called

SecurityTokenReference– security tokens (may contain key material) can be packaged

inside the document or be pulled from external sources• Example of usage

– bind a web service request to a capability issued by a licensing service as opposed to a user’s identity

– allows for interesting authorization and delegation scenarios

Page 286: Essential .NET Security

286

Security tokens

• Security token is a collection of one or more claims– claims can be about identity, group membership, key

ownership, capability, etc.• Example: Kerberos ticket issued by Active Directory

– contains one identity claim– contains zero or more group membership claims– claim is signed by some authority (domain controller)

• Example: X.509 certificate issued by VeriSign– claim binds a name to a public key– claim is signed by an authority (VeriSign)

• Example: User name– contains one identity claim– signed (endorsed) by no one

Page 287: Essential .NET Security

287

Packaging security tokens into XML

• WS-Security provides a means to do this– Binary security tokens– User name security tokens

Page 288: Essential .NET Security

288

Binary security tokens

• Binary security tokens have two important attributes• @ValueType

– Kerberos ticket granting ticket - wsse:Kerberosv5TGT– Kerberos server ticket - wsse:Kerberosv5ST– X.509 certificate - wsse:X509v3

• @EncodingType– Base 64 - wsse:Base64Binary– Hex - wsse:HexBinary

• Both values and encodings are extensible– Just use a namespace other than that for WS-Security

• Content is the encoded value of the token

Page 289: Essential .NET Security

289

A binary security token

<wsse:BinarySecurityToken wsu:Id="myKerbTicket"ValueType="wsse:Kerberosv5ST"EncodingType="wsse:Base64Binary">

MIIEZzCCA9CgAwIBAgIQEmtJZc0...</wsse:BinarySecurityToken>

wsse is the conventional prefix for the WS-Security namespace:http://schemas.xmlsoap.org/ws/2002/04/secext

Page 290: Essential .NET Security

290

Binding a signature to a claim

<ds:Signature><!-- signature body omitted for brevity --><ds:KeyInfo><wsse:SecurityTokenReference><wsse:Reference URI='#myKerbTicket'/>

</wsse:SecurityTokenReference></ds:KeyInfo>

<ds:Signature>

this signature is now linked to a binary securitytoken defined elsewhere in the document

ds is the conventional prefix for the XML Signaturenamespace: http://www.w3.org/2000/09/xmldsig#"

Page 291: Essential .NET Security

291

The user name token

• Allows for passing a user name– and optionally password information

• Password can be sent in the clear, or digested– in both cases, need a secure channel or it’s pointless

• Password can also be digested with a nonce and timestamp– if nonce and/or timestamp present, digest calculated as follows

• SHA1(nonce + timestamp + password)

<wsse:UsernameToken><wsse:Username>NNK</wsse:Username><wsse:Password Type="wsse:PasswordDigest">FEdR...</wsse:Password><wsse:Nonce>FKJh...</wsse:Nonce><wsu:Created>2001-10-13T09:00:00Z </wsu:Created>

</wsse:UsernameToken>

Page 292: Essential .NET Security

292

A problem with user name tokens

• To validate the digested password, must have access to cleartext password on server– passwords are normally used when humans are involved– humans use the same password everywhere– forcing servers to have access to cleartext passwords is bad– leads to domino effect if one server is compromised

• A better way– client_master_key = SHA1(realm + password)– where realm is a string provided by the web service– use client_master_key as the “password” described for

UserNameToken and you’ll be much better off

Page 293: Essential .NET Security

293

XML Encryption

• XML-Encryption Syntax and Processing– http://www.w3.org/TR/xmlenc-core– W3C Candidate Recommendation 02 August 2002

• What XML Encryption does– pulls out selected fragments of an XML document and replaces

with an <EncryptedData> element– supports key encryption via the <EncryptedKey> element– supports <KeyInfo> from XML Signature as well to bind

encrypted data to a key

Page 294: Essential .NET Security

294

Example: encrypting XML

<user><name>Alice</name><creditCards>

<card type='Visa'>1234 4321 1234 4321</card><card type='Discover'>4321 1234 4321 1234</card>

</creditCards></user>

<user><name>Alice</name><xenc:EncryptedData Type='http://www.w3.org/2001/04/xmlenc#Element'>

<xenc:CipherData><xenc:CipherValue>A9CgAwIBAgI...</xenc:CipherValue>

</xenc:CipherData></xenc:EncryptedData>

</user>

Page 295: Essential .NET Security

295

Key encryption

• Public keys are never used to encrypt bulk data• Need a way to communicate encrypted session keys• XML Encryption provides this via <EncryptedKey>

– also provides a way to reference <EncryptedData> elements that are encrypted with the key via <ReferenceList>

– WS-Security recommends using this feature

Page 296: Essential .NET Security

296

Example: key encryption<root> <!-- namespace declarations omitted for brevity --><xenc:EncryptedKey>

<xenc:EncryptionMethod Algorithm='...'/><ds:KeyInfo>

<ds:KeyName>Alice</ds:KeyName></ds:KeyInfo><xenc:CipherData>

<xenc:CipherValue>A9CgAwIBAgI...</xenc:CipherValue></xenc:CipherData><xenc:ReferenceList>

<xenc:DataReference URI='#encryptedFragment'/><xenc:DataReference URI='cid:image'/> <!-- attachment -->

</xenc:ReferenceList></xenc:EncryptedKey>

<xenc:EncryptedData Id='encryptedFragment'><xenc:EncryptionMethod Algorithm='...'/><xenc:CipherData>

<xenc:CipherValue>6caySYw68209shI...</xenc:CipherValue><xenc:CipherData>

</xenc:EncryptedData></root>

Page 297: Essential .NET Security

297

Framing

• WS-Security defines a SOAP header for security– security tokens– signature elements– encrypted keys

• Defines order of operations within header– should be able to “unwind” a message by traversing Security

header in document order– intermediaries should maintain this order by adding any new

operations to the top of the header• Defines recipient of header

– only one Security header may omit actor attribute– others are destined for named intermediaries (SOAP actors)

Page 298: Essential .NET Security

298

Example: SOAP with WS-Security header<soap:Envelope

xmlns:soap="http://www.w3.org/2001/12/soap-envelope"xmlns:ds="http://www.w3.org/2000/09/xmldsig#"xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">

<soap:Header><wsse:Security>

<wsse:BinarySecurityToken ...<xenc:EncryptedKey ...<ds:Signature ...

</wsse:Security></soap:Header><soap:Body>

<xenc:EncryptedData ...</soap:Body>

</soap:Envelope>

Note order of operationsallows you to correctlyunwind message

Page 299: Essential .NET Security

299

Summary

• Web services security is still in its infancy• For now, stick with tried and true methods like SSL• WS-Security applies existing specs to web services

– XML Canonicalization– XML Signature– XML Encryption

• Expect churn during standardization• Don’t expect a standard solution anytime soon

Page 300: Essential .NET Security

RemotingSecuring System.Runtime.Remoting

Page 301: Essential .NET Security

301

Why bother securing .NET remoting?

• .NET remoting will mainly be used on a corporate intranet– the corporate intranet is protected by firewalls– so aren’t we safe from external attacks?

• Firewalls can slow down external attacks, but they aren’t a silver bullet– the best defenses are layered ones– insider attacks can be much more devastating– ignore security on the intranet at your own peril

Page 302: Essential .NET Security

302

Solution one: hosting in IIS

• ASP.NET comes with a special handler for remoting– HttpRemotingHandlerFactory

• Reads server remoting configuration from web.config• Passes HTTP requests through to remoting channel

– requires that you use Http channel– you can use any formatter you like (binary, soap, custom)

Page 303: Essential .NET Security

303

Hosting in IIS

worker process

ASP.NET Pipeline

modulesHttpRemotingHandlerFactory

http://acme.com/myApp/foo.soap

class foo : MarshalByRefObject

Page 304: Essential .NET Security

304

How to host in IIS

• Set up a virtual directory in IIS• Build server object into a library assembly (.DLL)

– drop this assembly into “bin” directory under vroot, or install in GAC

• Create a web.config file and wire it all up– must use http channel when hosting in IIS– prefer binary formatter for efficiency– server URI must end with “.soap” or “.rem” to map to .NET

remoting handler in ASP.NET pipeline

Page 305: Essential .NET Security

305

web.config example

<configuration><system.runtime.remoting><application><channels><channel ref='http'><serverProviders><formatter ref='binary'/></serverProviders></channel></channels><service><wellknown mode='Singleton' type='Calc, server'

objectUri='calc.soap'/></service></application>

</system.runtime.remoting></configuration>

Page 306: Essential .NET Security

306

Client configuration

<configuration><system.runtime.remoting><application><channels><channel ref='http' useDefaultCredentials='true'><serverProviders><formatter ref='binary'/></serverProviders></channel></channels><service><wellknown mode='Singleton' type='Calc, server'

objectUri='calc.soap'/></service></application>

</system.runtime.remoting></configuration>

Page 307: Essential .NET Security

307

Security goals

• Authentication• Message Integrity• Message Confidentiality• Authorization

Page 308: Essential .NET Security

308

Security when hosting in IIS

• IIS has many options for authentication– basic– digest– integrated (Kerberos)– SSL (optionally with client certs)

• SSL is required if you want– message integrity– message confidentiality– mutual authentication

Page 309: Essential .NET Security

309

Typical configurations:SSL + Basic Authentication• Benefits:

– works well with firewalls & proxies– passwords easy to work with for clients– provides mutual authentication, integrity, confidentiality

• Drawbacks:– doesn’t leverage single sign on (client must provide cleartext

password)– server code has access to client’s cleartext password

Page 310: Essential .NET Security

310

Typical configurations:Integrated Authentication (Kerberos)• Benefits:

– leverages single sign on– great for Intranet clients

• Drawbacks:– generally does not work with firewalls or proxies– must add SSL into the mix to achieve

• mutual authentication• message integrity• message confidentiality

Page 311: Essential .NET Security

311

Typical configurations:SSL with client certificates• Benefits:

– works well with firewalls & proxies– provides mutual authentication, integrity, confidentiality

• Drawbacks:– human clients have trouble managing personal certificates– certificates aren’t as mobile as passwords

• smart cards can help here

Page 312: Essential .NET Security

312

Authorization

• When hosting in IIS, your server code runs under ASP.NET• To get access to the client principal, be sure to set

authentication mode to “Windows”– this is the default setting in machine.config anyway

• Use normal ASP.NET techniques for authorization– Thread.CurrentPrincipal.IsInRole()– PrincipalPermission– PrincipalPermissionAttribute

• Uncaught exceptions will propagate back to client– this is bad (includes a server-side stack trace)– trap, log, and rethrow exception at top level of call to avoid

giving away too much information– consider using a remoting sink to automate this

Page 313: Essential .NET Security

313

IIS hosting and callbacks

• Callbacks will be completely unsecured– No authentication– No message integrity protection– No message confidentiality protection

• We really need a built-in solution

Page 314: Essential .NET Security

314

Solution two: the SSPI remoting sink

• In August, 2002, Microsoft published two unsupported samples for the .NET Framework– SSPI wrapper[1]– Remoting security channel sinks[2]

• To use, must install both on client and server• Uses SSPI to add security (e.g., Kerberos) to the channel

– authentication– message integrity– message confidentiality

Page 315: Essential .NET Security

315

The SSPI remoting sink

• Does not require IIS• Does not require SSL• Doesn’t fall down in the face of callbacks• Will eventually be built in (but not in Everett)

Page 316: Essential .NET Security

316

Using the SSPI remoting sink

• Wire the sink into the channel via configuration file– must do this on both client and server

• Use remoting like you normally would– current sample autoimpersonates client– this is broken, watch for fix in future

Page 317: Essential .NET Security

317

client.exe.config

<configuration><system.runtime.remoting><application><channels><channel ref='http'><clientProviders><formatter ref='binary'/><provider ref='sspi'

securityPackage='kerberos'impersonationLevel='impersonate'authenticationLevel='packetPrivacy'/>

</clientProviders></channel></channels></application>

</system.runtime.remoting></configuration>

Page 318: Essential .NET Security

318

server.exe.config<configuration><system.runtime.remoting><application><channels><channel ref='http' port='4243'><serverProviders><provider ref='sspi'

securityPackage='kerberos'impersonationLevel='impersonate'authenticationLevel='packetPrivacy'/>

<formatter ref='binary'/></serverProviders>

</channel></channels><service><wellknown type='Bob, server'

mode='Singleton' objectUri='bob'/></service>

</application></system.runtime.remoting></configuration>

Page 319: Essential .NET Security

319

machine.config

• The preceding example config files made use of ref='sspi'– adjust machine.config as follows to make this work

<system.runtime.remoting><!-- other stuff omitted for brevity --><channelSinkProviders><clientProviders>

<formatter id="soap" ... /><formatter id="binary" ... /><provider id="sspi" type="see notes"/>

</clientProviders><serverProviders>

<formatter id="soap" ... /><formatter id="binary" ... /><provider id="sspi" type="see notes"/>

</serverProviders></channelSinkProviders>

</system.runtime.remoting>

Page 320: Essential .NET Security

320

Summary

• .NET remoting has no built in, supported, security model• Can layer security on by hosting in IIS• Can layer security on using an unsupported sample from MS• Expect improvement in the future (not Everett, though )

Page 321: Essential .NET Security

COM+Securing System.EnterpriseServices

Page 322: Essential .NET Security

322

Outline

• Why use COM+?• Security settings• Role-based access checks• Deployment model

Page 323: Essential .NET Security

323

Why use COM+?

• COM+ (a.k.a. Enterprise Services) provides many features that corporate developers need– Secure hosting and networking via DCOM

• Kerberos authentication• Message integrity• Message confidentiality

– Role-based security tied to Windows logon– Distributed transactions– Deployment model

• May also need to simply support existing COM-based code

Page 324: Essential .NET Security

324

Server applications vs. library applications

• COM+ allows both inproc and out-of-proc activation• Library applications have very little control over process-wide

security settings• Process-wide security settings determined by the single

server application in the process

DLLHOST.EXE

serverapp

libraryapp

libraryapp

libraryapp

libraryapp

Page 325: Essential .NET Security

325

Process-wide security settings

• Authentication level• Impersonation level• Role-based access checks

Page 326: Essential .NET Security

326

Authentication level

• Controls how much protection is provided for the channel – Client and server both specify this, and COM uses the most

secure of the two settings

MAC Protect

Headers Payload

Encrypt

PayloadAuthenticateconnectionLevel

None

Packet

Packet Integrity

Packet Privacy

XConnect

X

X

X

X

X X

X X X

use Packet Privacy unless you’ve got a really good reason not to

Page 327: Essential .NET Security

327

Impersonation level

• Servers requiring authentication can impersonate clients• Client can restrict what servers can do while impersonating

– Choose whether to send network credentials to server– Choose whether server can open local objects with credentials

• Note that impersonation level is a client-side setting

Server canlook at tokenLevel

Anonymous

Impersonate

Delegate

Identify

Server can usetoken to openkernel objects

Server can useclient’s network

credentials

X

X X local*

X X remote*

Page 328: Essential .NET Security

328

Role-based access checks

• COM+ has a very nice infrastructure for role-based access control

• It’s all based on the notion of interception• By moving the access checks out of the object and into the

interception layer, they can be configured declaratively

object

access

checks

IFoo

IBar

Client

interceptor

access

checks

IFoo

IBar object

Page 329: Essential .NET Security

329

App designer definitionsvalid for all pet stores

Bob’s definitions validfor his pet store

Supervisors

Employees

Customers

Roles

interface IPetStorePetAnimalBuyAnimalFeedAnimal

interface IEmployerGetEmployeeInfoGiveRaise

Interfaces

Everyone

DomA\Staff

DomA\Contractors

DomA\Bob

Accounts

Roles illustrated

Page 330: Essential .NET Security

330

Role-based access checks

• COM+ performs three stages of access checks– 1) At server process launch, client must be member of a role– 2) At server process entry, client must be member of a role– 3) At application entry, client must be in a role that grants

access to the class, interface, or method being called• Once inside an application, calls between objects are not

checked (we assume they trust each other)

Page 331: Essential .NET Security

331

server app

library app library app

2

3

3

3

2

1

3

pObj1->Foo()

pObj2->Bar()

2

CoCreateInstance

Three stages of COM+ role-based access checks

Page 332: Essential .NET Security

332

Custom logic for role-based access checks

• Server can query the roles of the caller at runtime– Allows you to make runtime decisions based on your own logic

namespace System.EnterpriseServices {public sealed class ContextUtil {public static bool IsCallerInRole(string role);

// ... other non-security related stuff}

}

Page 333: Essential .NET Security

333

public class Bank {public void Withdraw(long accountID, long amount) {

if (amount > 5000 && !ContextUtil.IsCallerInRole("Supervisor"))throw new SecurityException("Must be supervisor");

// ... perform the withdrawal}

}

Example

Page 334: Essential .NET Security

334

Enabling role-based access checks

• Checks must be enabled at both the application and component level– Otherwise all three stages of role-based checks are disabled– Also, IsCallerInRole always returns true

Page 335: Essential .NET Security

335

Deploying managed code in COM+

• System.EnterpriseServices provides everything you need– Derive component from ServicedComponent– Assembly needs a strong name– Assembly level attributes specify COM+ application settings

• ApplicationName• ApplicationActivation• ApplicationAccessControl

– Other attributes you need to know about• ComponentAccessControl• PrivateComponent• SecurityRole• SecureMethod

Page 336: Essential .NET Security

336

Example

[assembly: AssemblyDelaySign(true)][assembly: AssemblyKeyFile(@"..\..\pubkey")][assembly: ApplicationName("Pet Store")][assembly: ApplicationActivation(ActivationOption.Server)][assembly: ApplicationAccessControl(true,Authentication = AuthenticationOption.Privacy,ImpersonationLevel = ImpersonationLevelOption.Identify,AccessChecksLevel = AccessChecksLevelOption.ApplicationComponent)]

[ComponentAccessControl(true)][SecureMethod]public class PetStore : ServicedComponent, IPetStore {

[SecurityRole("Customers")] public void PetAnimal() {}[SecurityRole("Customers")] public void BuyAnimal() {}[SecurityRole("Staff")] public void FeedAnimal() {}[SecurityRole("Owners")] public void GiveAwayMoney() {}

}

Page 337: Essential .NET Security

337

Deploying managed code in COM+

• REGSVCS.EXE installs managed applications into the COM+ catalog– Creates a type library– Creates (and configures) the application– Creates roles– Imports (and configures) all public classes into COM+ catalog

• REGSVCS.EXE must be run with administrative privileges

regsvcs c:\appDir\petstore.dll

regsvcs /u c:\appDir\petstore.dll

install

remove

Page 338: Essential .NET Security

338

Summary

• COM+ provides a complete security framework– Unlike System.Runtime.Remoting at the moment

• Can easily deploy managed code in COM+• COM+ isn’t going away any time soon

Page 339: Essential .NET Security

Dumb CodeHow to avoid coding security holes into your apps

Page 340: Essential .NET Security

340

Outline

• Fear user input– buffer overflow– format string vulnerabilities– canonicalization errors– SQL injection– cross site scripting

• Beware storing secrets• Use good ACLs• Watch for race conditions• Keep attackers guessing• Run with least privilege

Page 341: Essential .NET Security

341

Fear user input

• Must validate all input from any external, untrusted source– best frame of mind is to assume it’s purposely malformed– failure to do this is the lead cause of security vulnerabilities

• Tests you can perform– is the input the right size?– does the input conform to a legal format?

• Application must carefully define what is legal input– don’t try to test for exceptional cases – you’ll always miss one

• Do your own “taint checking”– take a lesson from Perl

Page 342: Essential .NET Security

342

Buffer overflows

• Bug: failure to detect that input is bigger than buffer can hold• Result: attacker sends arbitrary machine code and you run it

– This is the number one security problem in C and C++ code

void main() {foo();

}

void foo() {char buf[1024];readUserName(buf);logUserName(buf);

}

Page 343: Essential .NET Security

343

A stack ripe for smashing

void main() {foo();

}

void foo() {char buf[1024];readUserName(buf);logUserName(buf);

}

void readUserName(char* buf) {strcpy(buf, form.name);

}

Stack frame for foo()

char buf[1024]

return addr to main()

Page 344: Essential .NET Security

344

Smashing the stack and running arbitrary code

nopnopnopopen internet connectiondownload attack EXElaunch attack EXEExitProcess()kernel32.dll:0x77E61EE8

...77E61EDE push ecx 77E61EDF push dword ptr ds:[77ED67E8h] 77E61EE5 push dword ptr [eax+18h] 77E61EE8 call edi 77E61EEA cmp eax,ebx...

Kernel32.dll

Page 345: Essential .NET Security

345

Smashing the heap

• C++ apps have heaps that contain data and function pointers– an object has state, but it also has a “vptr”

• What if a buffer in the heap overflows?– could overwrite vptrs

• First function in vtable usually is virtual destructor– Attacker reroutes destructor to point to other code

• Bottom line: buffer overflows can lead to nasty security compromises, wherever they occur

Page 346: Essential .NET Security

346

Finding buffer overflows in source code

• Search for commonly misused functions– strcpy, strcat, memcpy, sprintf

• must check size of destination buffer manually– strncpy, strncat

• size of buffer specified in characters, not bytes!– see list of functions in Appendix A of Writing Secure Code

• Consider banning some functions from use!

Page 347: Essential .NET Security

347

Format string vulnerabilities

• Bug: allowing the attacker to control a format string• Result: attacker sends arbitrary machine code and you run it

• Spotting the bug:

• Never allow the user to specify any part of a format string

printf(userSuppliedString); // BUG BUGprintf(“%s”, userSuppliedString); // correct

Page 348: Essential .NET Security

348

How a format string attack works

• Format string causes printf to read values up the stack– if no arguments passed to look at, printf is looking at stuff it

shouldn’t be looking at (local variables, return addresses, etc.)

// correct usage of printfint i = 1, j = 2, k = 3;char* s = "Hello world";printf("%d%d%d%s", i, j, k, s);

// bad usage of printfprintf("%d%d%d%s");

this will likely crash the appwhen printf tries to dereferencethe fourth element on the stack,treating it as a string pointer

Page 349: Essential .NET Security

349

How a format string attack works

• Format string can also cause printf to write to the stack– via the somewhat esoteric (but fully supported) %n specifier

// correct usage of printfint i = 1, j = 2, k = 3;int bytesOutputSoFar;printf("%d%d%d%n", i, j, k, &bytesOutputSoFar);

// incredibly bad usage of printfprintf("%d%d%d%n");

this causes printf to walk up the stackand overwrite a four byte value withthe number of bytes it’s output so far

Page 350: Essential .NET Security

350

Avoiding format string vulnerabilities

• Never allow user input to creep into format strings– Keep the attacker in the data channel

• Check all usages of the following functions– printf, wprintf, vprintf, _tprintf, etc.– sprintf, swprintf, vsprintf, _tsprintf, etc.– fprintf, fwprintf, vfprintf, _tfprintf, etc.

• Check logging and tracing functions that take format strings– where most vulnerabilities are being found in Unix today

Page 351: Essential .NET Security

351

Canonicalization errors

• Bug: failure to canonicalize resource names• Result: various security policy violations

• A resource (files for example) can have many names:

• Attackers often use alternate names to get access to files they shouldn’t normally be allowed to see

C:\foo\bar\somelongfilename.txtC:\foo\bar\somelongfilename.txt.C:\foo\bar\somelo~1.txt..\foo\bar\somelo~1.txt.Z:\somelongfilename.txt::$DATA\\server\share\bar\somelong%66ilename.txt

Page 352: Essential .NET Security

352

Tips for avoiding canonicalization errors

• Avoid making decisions based on user provided file names (or names of other resources)

• For server applications, don’t let clients tell you where to find a file– don’t allow clients to specify full paths – you should always

provide the base location yourself– don’t rely on your PATH environment variable to find files

• Don’t let multi-byte encodings surprise you– there are often several ways to encode a single character

• Canonicalize user provided names carefully– see CleanCanon.cpp from Writing Secure Code

Page 353: Essential .NET Security

353

SQL injection attacks

• Bug: concatenating SQL commands with raw user input• What’s wrong with the following C# code?

– imagine this was the code behind an ASP.NET login form

string sql = "select * from users where name='" +txtName.Value +"' and password = '" +txtPwd.Value +"'";

cmd.CommandText = sql;IDataReader reader = cmd.ExecuteQuery();

Page 354: Essential .NET Security

354

SQL injection attacks, cont.

• Here’s the input you’d expect to get from a legitimate user– Name: Bob– Password: nU3!gx7– Resulting SQL:

• Here’s what an attacker might send instead– Name: Bob'--– Password: hack– Resulting SQL:

select * from users where name='Bob' and pwd='nU3!gx7'

select * from users where name='Bob'--' and pwd='hack'

Page 355: Essential .NET Security

355

Avoid SQL injection attacks

• Use parameterized queries or stored procs– stop building SQL statements using string concatenation

// a parameterized query// keeps the attacker out of the control channelstring sql = "select * from users where name=@n and pwd=@p";cmd.CommandText = sql;cmd.Parameters.Add(new SqlParameter("@n", name.Text));cmd.Parameters.Add(new SqlParameter("@p", password.Text));IDataReader reader = cmd.ExecuteQuery();

Page 356: Essential .NET Security

356

Never echo unfiltered input back as HTML

• Known as “cross site scripting”• The basic problem

– one can submit HTML that is then served to another– HTML can contain scripts

• What can happen to a victim– cookies can be stolen– COM objects can instantiated and scripted with untrusted data– user input can be intercepted

• How to avoid cross site scripting– all user input should be filtered, as usual– all output that may contain user data should be escaped

• HttpServerUtility.HtmlEncode is your friend!

Page 357: Essential .NET Security

357

Don’t rely on client side validation for security

• Know what client side validation is for– gives clients a better user experience– reduces load on your server from accidental bad input

• Client side validation provides no real security– clients don’t have to use your form to submit requests– always validate input when it arrives at the server– think about Perl’s “taint checking” and try to apply the same

ideas to your own code• ASP.NET validation controls are a great utility

– provides client with immediate feedback on errors via Jscript– provides server protection by validating input on server side

Page 358: Essential .NET Security

358

Beware storing secrets

• Storing secret data on a machine is tricky– how do you protect it?– how do you read it?– what stops someone else from reading it as well?

• Can encryption help?– where do you store the encryption key?

• Avoid storing sensitive data in config files

<configuration><system.web><identity userName='Bob' password='HereIsMySecret'/>

</system.web></configuration>

Page 359: Essential .NET Security

359

Data protection API

• DPAPI consists of two functions that simplify secret storage– CryptProtectData, CryptUnprotectData– Supported on Windows 2000, XP, .NET Server

• Protection derived from up to three sources

rawdata

protecteddata

user logincredential

applicationsecret

user providedpassword

Page 360: Essential .NET Security

360

ASP.NET and DPAPI

• A patch for ASP.NET allows you to encrypt passwords– See knowledge base article 329290– You’ll need the patch and a tool called aspnet_setreg.exe

• Uses DPAPI with the machine’s credentials– if the machine is compromised, the attacker can decrypt these

strings– but if you absolutely must specify these passwords, this is

better than using cleartext

<identity impersonate='true'userName='registry:HKLM\...\ASPNET_SETREG,userName'password='registry:HKLM\...\ASPNET_SETREG,password' />

Page 361: Essential .NET Security

361

Use good ACLs

• What should you pass for lpMutexAttributes?

• Most sample code passes NULL• Who will have access to the mutex if you do this?

HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName

);

Page 362: Essential .NET Security

362

Passing NULL for LPSECURITY_ATTRIBUTES

• Passing NULL can do one of three things– in a hierarchical system (files, registry, directory service) the

parent object provides inheritable entries in its DACL– in a flat system (processes, mutexes, named pipes, etc.) the

default DACL in the caller’s token is used• SYSTEM granted full permissions• Default owner granted full permissions

– might do something different depending on the type of object• Creating objects shared by different principals is tricky

– a mutex used to synchronize a service and a client app– a named pipe used to communicate over the network

Page 363: Essential .NET Security

363

The NULL DACL

• A NULL DACL is not the same as passing NULL

// passing NULL to CreateMutex// allows SYSTEM or the creator to use itHANDLE h = CreateMutex(NULL, FALSE, "MyMutex");

// creating a mutex with a NULL DACL// allows anyone (even null sessions) to use itSECURITY_DESCRIPTOR sd;InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);

SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);SECURITY_ATTRIBUTES sa = { sizeof sa, &sd, FALSE };HANDLE h = CreateMutex(&sa, FALSE, "MyMutex");

Page 364: Essential .NET Security

364

Avoid using NULL DACLs

• Granting full control to everyone opens several holes• Anyone who can reference the object can:

– delete the object (if it’s deletable)– change the DACL– take ownership away from you so you can’t get it back

• NULL DACLs are easy to code up, thus tempting• Resist the temptation – figure out an access control policy

that makes sense, then use it– you can adjust the default DACL in your token to allow you to

pass NULL and get a reasonable ACL for new objects– or use the low level ACL apis to create simple DACLs– use the access control editor UI for more sophisticated DACLs

Page 365: Essential .NET Security

365

Watch for race conditions

• Timing bugs can lead to compromises– Thread one loads plaintext into a buffer– Thread one begins to encrypt the buffer– Thread two begins to read the buffer before encryption is

finished• Howard suggests using separate buffers for plaintext and

ciphertext– Thread two would be reading from a ciphertext only buffer– Race condition is still a bug, but doesn’t compromise security

Page 366: Essential .NET Security

366

Keep attackers guessing

• Security errors should lead to two distinct outputs– vague message to user, with instructions on how to proceed– detailed error message to internal log– give user an identifier so tech support can find the detailed

message• Avoid giving away free information

– one of the first stages of an attack is reconnaissance– banners or headers that give away system information should

be omitted or changed wherever possible– you must still assume an attacker knows what you’re running

• TCP/IP fingerprinting is pretty effective• see http://uptime.netcraft.com/up/graph/ for an example

Page 367: Essential .NET Security

367

Run with least privilege

• Code should run with minimum possible permissions– by doing this, you’re allowing the OS to erect walls around you– if your code has a bug, this limits the damage it can do– if an attacker exploits a bug, this limits the damage he can do– it’s all about giving you time to detect and react (patch the bug)

• Server code– choose your process identity wisely– factor highly privileged code into a separate process

• Mobile code– make use of the CAS sandbox

Page 368: Essential .NET Security

368

Summary

• Fear user input• Don’t rely on client-side validation for security• Beware storing secrets• Use good ACLs• Don’t give attackers free information• Run with least privilege