COM+ Security Christof Sprenger Partner Group Microsoft GmbH [email protected] Agenda 1. 2. 3. 4. Security Grundlagen Windows Security Architektur COM+ Security Architektur Do’s & Don’ts.

Download Report

Transcript COM+ Security Christof Sprenger Partner Group Microsoft GmbH [email protected] Agenda 1. 2. 3. 4. Security Grundlagen Windows Security Architektur COM+ Security Architektur Do’s & Don’ts.

COM+ Security
Christof Sprenger
Partner Group
Microsoft GmbH
[email protected]
Agenda
1.
2.
3.
4.
Security Grundlagen
Windows Security Architektur
COM+ Security Architektur
Do’s & Don’ts
2
Abschnitt 1
Security Grundlagen
3
„Definition“

Security ist:
„Definieren und Durchsetzen von
Grenzen des Vertrauens “
(defining and enforcing boundaries of trust)
4
„Definition“

Kurze Definition von Security:
•
•
•
wer (identity  Authentifizierung)
tut was (Zweck/Absicht)
mit wem oder was (Privilege  Authorisation)
5
Security Grundlagen: Begriffe
 „Principal“
 Eine Identität (Sie oder Ihr PC)
 „Credentials“
 Daten um Identität zu beweisen
 „Trust“
 Den Credentials vertrauten
 „Authority“
 Der, der für Principals bürgt
 „Privilege“
 Das Recht etwas zu tun
6
Abschnitt 2
Windows Security Architektur
8
Windows Security Architektur


Authentifizierung
•
•
•
Access Token
Security Identifier
Logon Session
Authorisation
•
•
•
Privileges / User Rights
Access Control List (ACL)
Security Descriptors (SD)
9
Authentifizierung 1/2


Die Frage ist: “Wer bist du?”
„Credentials“ werden beim Logon
überprüft
•


Credentials sind: User/Password oder
Smartcard
Erfolgreiches Logon erzeugt ein
•
•
eine Logon Session und
ein Access-Token
Access Token dient als Zutrittsausweis
10
Authentifizierung 2/2
Logging on...
Logon
Process
(winlogon.exe)
Win32
Subsystem
(system)
Security
Subsystem (LSA)
(lsass.exe)
Authentication
package
Run
Check
Create
process
Validate
Create
user
Shell
CTRL-ALT-DEL
Credentials
With
access
token
Add
Access
group
token
info
(explorer.exe)
(USER/PASS)
Security Account
Manager DB
(SAM)
11
Access Token Bestandteile






User SID
Group SIDs
Privileges
Default für neue Objekte (z.B. Dateien,
Pipes, Shared Memory ....)
Logon Session ID
...
12
Logon-Sessions
5
Arten von logon-session
 SYSTEM
Enthält alle Prozesse, die Teil des OS sind
 INTERACTIVE
Für den interaktiv angemeldeten Benutzer
 NETWORK
Entsteht durch authentifizierten Zugriff auf den
Rechner über das Netzwerk
 SERVICE
Für NT Dienste, die mit einem bestimmten
Benutzerkonto konfiguriert wurden
 BATCH
Für Prozesse die durch die COM Runtime
getartet wurden
14
Logon Sessions Beispiel
AlicesMachine
JoesMachine
Bob‘s network
logon session
Bob‘s Service logon
session
Alice‘s interactive
logon session
Teds‘s network
logon session
Alice‘s network
logon session
TedsMachine
Alice‘s network
logon session
Teds‘s interactive
logon session
16
Impersonation



Ein (Server-)Prozess verrichtet oft
Arbeit für verschiedene Benutzer
Daher kann jedem Thread eine eigenes
Access Token zugeordnet werden
Es gibt also zwei Arten von Access
Token
•
•
Primary Token (für Prozesse)
Impersonation Token (für Threads)
17
Impersonation im Bild
server.exe
Joe
client.exe
Alice
Alice
client.exe
Bob
Bob
18
Authorization



Frage ist: “Was darfst du tun?”
Auch: Access Check oder Access
Control
Wird bestimmt durch:
•
•
•
Art des gewünschten Zugriffs
Access-Token (des aktuellen Threads)
Access Control List (ACL) aus dem
Security Descriptor des Objekts
19
Access Control Lists
DACL
ACE
Everyone Read
ACE
„chrispre“Full Control
ACE
SYSTEM Full Control
ACE
Administrators
Full Control
20
Security Descriptor




Owner SID
Group SID (POSIX)
SACL
DACL
•
•
Permitted users
Permissions
21
Authorisation im Bild
Access-Token
Access?
Process/Thread
OpenSomeObject()
OK!
Token
SRM Check!
(SecurityReferenceMonitor)
Security-Descriptor
SomeObject
DACL
SD
ACE
DACL
User SID
„chrispre”
Group SIDs
Privileges
„chrispre“: Full
22
Netzwerk Authentifizierung



Wie entsteht auf einem entfernten
Rechner eine Logon Session, die den
Benutzer repräsentiert, der über das
Netzwerk zugreift?
Das Kennwort darf nicht einfach über
das Netzwerk versendet werden
Die Bits und Bytes, die das Access
Token bilden dürfen ebenfalls nicht
versendet werden
23
NTLM mit Local Accounts
Client
Server
lsass.exe
4. 5.
client.exe
1. Negotiate
2. Challenge
3. Response
server.exe
24
NTLM mit Domain Accounts
Authority
0.
5.
6.
Client
Server
lsass.exe
4.
7.
1-3
client.exe
server.exe
25
NTLM über Domänengrenzen
Domain A
Authority A
Domain B
Authority B
Client
Server
lsass.exe
client.exe
server.exe
26
Kerberos
Authority
1.
2.
Server
Client
3.
27
Abschnitt 3
COM(+) und Security
28
COM Security Konzepte



Authentifizierung: Wer ist der Client?
•
RPC und damit COM erlaubt dem Client den Grad
der Authentifizierung einzustellen
Access Control: Darf dieser Client dies tun?
•
Programmatisch vs. Deklarativ
Identity: Welche Identity nimmt der Client an? Mit
welcher Identity läuft der Server?
• COM erlaubt es dem Client eine Identity
auszuwählen
• COM startet die Server automatisch und erlaubt es
die Identity des Servers auszuwählen
29
Abschnitt 3.1
Authentifizerung
30
Auswahl des SSP in COM

Jeder Server-Prozess registriert Security
Support Provider (SSP) mit Hilfe von
CoInitializeSecurity
•

Runtime sorgt dafür, daß Proxies
automatisch den passenden SSP verwenden
COM ruft CoInitializeSecurity implizit auf
falls “vergessen”
•
•
•
Beim ersten Marshal oder Unmarshal
Wählt default SSPs des Rechners
Defaultwerte sagen: Security ist an
31
CoInitializeSecurity
HRESULT CoInitializeSecurity(
SECURITY_DESCRIPTOR* pSD,
DWORD cAuthSvc,
SOLE_AUTHENTICATION_SERVICE*
prgAuthSvc,
void* pvReserved1,
DWORD dwAuthnLevel,
DWORD dwImpLevel,
void* pvReserved2,
DWORD dwCapabilities,
void* pvReserved3
);
32
Authentication Level


Mit CoInitializeSecurity wird ein
„Authentication Level“ gewählt
Dies legt fest wann und/oder wie oft
Authentifiziert wird und ob die Daten
verschlüsselt werden
33
RPC_C_AUTHN_LEVEL
RPC_C_AUTHN_LEVEL_NONE
Keine Authentifizierung
RPC_C_AUTHN_LEVEL_CONNECT
Authentifizierung beim ersten
“Kontakt”
RPC_C_AUTHN_LEVEL_CALL
Authentifizierung für das erste
Packet eines jeden Aufrufs
RPC_C_AUTHN_LEVEL_PACKET
Authentifizierung für jedes
Packet
RPC_C_AUTHN_LEVEL_PKT_INTEGRITY
PACKET + Signatur
RPC_C_AUTHN_LEVEL_PKT_PRIVACY
INTEGRITY + Verschlüsselung
34
Authentication Level

Für den Server ist dies die „low watermark“
für eingehende Aufrufe

Unterhalb dieses Levels werden Aufrufe
abgelehnt
•

Alle exportierten Interface Pointer bekommen
diese „low watermark“ als Hinweis mit
COM Runtime wählt dann den höchsten von
•
•
„low watermark“ des Servers
Level der bei Aufruf von CoInitializeSecurity
im Client angegeben wurde
35
Proxy und Security



CoInitializeSecurity legt nur den
„default authentication level“ für jeden
Proxy fest
Die Einstellungen können dann für
jeden Proxy angepasst werden.
Dies geht bei dem Standard-Proxy über
IClientSecurity
•
IClientSecurity wird vom „proxy manager“
implementiert
36
Proxy & Stubs (Interceptors)
Client
Server
ProxyManager
IClientSecurity
IFoo
IFoo
Proxy
Object
Stub
IBaz
IBaz
Proxy
Stub
37
IClientSecurity
interface IClientSecurity : Iunknown
{
HRESULT QueryBlanket( IUnknown* pProxy,
DWORD* pAuthnSvc,DWORD* pAuthzSvc,
OLECHAR** pServerPrincName,
DWORD* pAuthnLevel, DWORD* pImpLevel,
void** ppAuthInfo, DWORD* pdwCapabilites );
HRESULT SetBlanket( IUnknown* pProxy,
DWORD AuthnSvc, DWORD AuthzSvc,
OLECHAR* pServerPrincName,
DWORD AuthnLevel, DWORD ImpLevel,
void* pAuthInfo, DWORD dwCapabilities );
HRESULT CopyProxy( IUnknown* pProxy,
IUnknown** ppCopy );
}
38
Anpassen des Authn Level
HRESULT MakePrivateCall( IBank* pib )
{
IClientSecurity* pics = 0;
pib->QueryInterface( IID_IClientSecurity,
(void**)&pics );
DWORD nAuthnSvc, nImpLevel;
pics->QueryBlanket( pib, &nAuthnSvc, 0, 0, 0,
&nImpLevel, 0, 0 );
pics->SetBlanket( pib, nAuthnSvc, 0, 0,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
nImpLevel, 0, 0 );
pics->Release();
pib->SetCreditCardInfo( g_pszCardNum );
pib->Release();
}
39
Authn Level bei Aktivierung

In COM gibt es einige Aufrufe zur
Aktivierung von COM Objekten
•
•
•



CoCreateInstance(Ex)
CoGetClassObject
CoGetInstanceFromFile
Der Default Authn Level wird durch
CoInitializeSecurity bestimmt
Wie kann der Client den Authn Level
festlegen? (Es gibt noch kein IClientSecurity)
Hierzu dient COSERVERINFO und
COAUTHINFO
40
COAUTHINFO
struct COSERVERINFO {
DWORD
dwReserved1;
WCHAR*
pszHostName;
COAUTHINFO* pAuthInfo;
DWORD
dwReserved2;
};
struct COAUTHINFO {
DWORD
DWORD
WCHAR*
DWORD
DWORD
COAUTHIDENTITY*
DWORD
};
// mbz
// mbz
dwAuthnSvc;
dwAuthzSvc;
pszServerPrincipalName;
dwAuthnLevel;
dwImpLevel;
pAuthIdentityData;
dwCapabilities;
41
„Normales“ Vorgehen


Server setzt die „low watermark“ auf
CONNECT or NONE (Effizienz)
Ein Servers, der den Client identifizieren
muss, setzt mindestens CONNECT
•


Z.B. muss ein Server, der nur bestimmte
Clients zulässt diese auch unterscheiden
können
Server, die anonymen Zugriff erlauben
müssen NONE verwenden.
Clients setzen den Authn Level für
bestimmte Operationen rauf.
42
Überprüfen des Authn Level

Ein Server fordert manchmal einen
höheren Authentication Level als sonst
•



Z.B. um eine PIN oder Kreditkartennummer
zu übetragen
Clients können den Level erhöhen
Server können dies dann überprüfen
IServerSecurity bietet die Möglichkeit
den Kontext des Aufrufs nach dem
Authn Level zu fragen
•
Hierzu ist auch CoGetCallContext nötig
43
IServerSecurity
HRESULT CoGetCallContext( REFIID iid, void** ppv );
interface IServerSecurity : IUnknown
{
HRESULT QueryBlanket( DWORD* pAuthnSvc,
DWORD* pAuthzSvc,
OLECHAR** pServerPrincName,
DWORD* pAuthnLevel,
DWORD* pImpLevel,
void** pPrivs,
DWORD* pCapabilites );
// weitere Methoden ...
}
44
Beispiel QueryBlanket
HRESULT CoBank::SetCreditCardInfo( BSTR pszCardNum )
{
// verlange PRIVACY
DWORD nAuthnLevel
HRESULT hr = CoQueryClientBlanket( 0, 0, 0,
&nAuthnLevel,
0, 0, 0 );
// nicht authentifiziert
if ( FAILED( hr ) )
return E_ACCESSDENIED;
if ( nAuthnLevel < RPC_C_AUTHN_LEVEL_PRIVACY )
return E_ACCESSDENIED;
// ...
}
45
Abschnitt 3.2
Access Control
46
Zwei Arten von Authorisation





COM bietet zwei Arten von
Zugriffskontrolle
Beide arbeiten auf Prozessebene
Access Permissions
•
Welcher Benutzer darf in den Server Aufrufe
absetzen
Launch Permissions
•
Welcher Benutzer kann den Prozess in
Folge eines Aktivierungsaufrufes starten
Es ist möglich, dies feiner abgestuft im
Programmcode zu machen
47
Access Permissions


Werden über CoInitializeSecurity gesetzt
Der erste Parameter kann in
verschiedenen Arten verwendet werden.
•
•
•
•

NULL für unbeschränkten Zugriff
Ein Interface Pointer vom Typ IAccessControl
Ein Security Descriptor
Eine AppID
dwCapabilities (8. Parameter) bestimmt
was im Ersten steht
48
CoInitializeSecurity
HRESULT CoInitializeSecurity(
SECURITY_DESCRIPTOR* pSD,
DWORD cAuthSvc,
SOLE_AUTHENTICATION_SERVICE*
prgAuthSvc,
void* pvReserved1,
DWORD dwAuthnLevel,
DWORD dwImpLevel,
void* pvReserved2,
DWORD dwCapabilities,
void* pvReserved3
);
49
Registry




Wenn in CoInitializeSecurity eine AppID
verwendet wird, wird die Registry
verwendet.
Pro Applikation bzw. AppID
•
•
HKCR/AppID/{appid}
AccessPermission=“01 00 04 80 ..."
Falls dieser Key fehlt
•
•
HCLM/Software/Microsoft/Ole
DefaultAccessPermission=“01 00 04 80 ..."
DCOMCNFG kann die Einträge setzen
50
Launch Permissions




Wer darf einen COM Server starten?
CoInitializeSecurity kann nicht verwendet
werden, da der Prozess ja noch nicht läuft
Hierfür ist die Registry da
•
•
Falls dieser Key nicht existiert wird ein
Default benutzt
•
•

HKCR/AppID/{appid}
LaunchPermission=“01 00 04 80 ...”
HCLM/Software/Microsoft/Ole
DefaultLaunchPermission=“01 00 04 80 ...”
Mit Hilfe von DCOMCNFG können diese Werte
editiert werden
51
Abschnitt 3.3
Role based security
52
Access Control in COM ist grob



Launch Permissions pro Applikation
Access Permissions pro Prozess
Was, wenn man es genauer/feiner
haben möchte?
•
•
•

Access Control pro Klasse
Access Control pro Interface
Access Control pro Methode
Ist möglich, erfordert jedoch viel Code
53
Feinere Zugriffscontrolle



Wie kann dies programmatisch gemacht
werden?
Authn Level ausreichend wählen
Jede Methode macht folgendes
•
•
•
Lade das aktuelle Access Token
•
Dies geht in COM über
IServerSecurity::ImpersonateClient() und
IServerSecurity::RevertToSelf()
Lade einen Security Descriptor für diese
spezielle Methode aus einer DB
Rufe die API AccessCheck auf und gib
einen Fehler zurück das Ergebnis False ist
54
Impersonation Aufruf
interface IServerSecurity : IUnknown
{
HRESULT QueryBlanket( ... );
HRESULT ImpersonateClient();
HRESULT RevertToSelf();
BOOL IsImpersonating();
}
HRESULT CoGetCallContext( REFIID iid,
void** ppv );
oder
HRESULT CoImpersonateClient();
HRESULT CoRevertToSelf();
55
Deklarative Access Control




Das gleiche kann in COM+ deklarativ gemacht
werden
Der Code dazu ist im sogenannten Interceptor
Die nötige Information (DACL) dazu steht im
COM Catalog
Problem:
•
•
•

Zur Designzeit stehen die Benutzer nicht fest
Der Administrator kennt zur Installationszeit die
Semantik der Methoden nicht.
Wer soll also den COM Catalog „füllen“?
Lösung: eine zusätzliche Indirektionsstufe
56
COM+ Roles
57
Abschnitt 3.4
Identity
58
Client Identity



Per Default benutzt der Client das Token
des Prozesses für alle ausgehenden
Aufrufe.
Thread (impersonation) Tokens werden
nicht verwendet
Aber das Verhalten kann man ändern.
59
Impersonation im Bild
server.exe
Joe
client.exe
Alice
Alice
client.exe
Bob
Bob
60
Per-Proxy Client Identity

Die Identity kann für jeden Proxy
verändert werden
interface IClientSecurity : Iunknown {
HRESULT QueryBlanket( ... );
HRESULT SetBlanket( IUnknown* pProxy, ...,
void* pAuthInfo, DWORD dwCapabilities );
HRESULT CopyProxy( ... );
}
61
Explizit

Die Identity kann explizit gesetzt werden
•
Für NTLM und Kerberos ist die folgende Struktur
zu verwenden (für pAuthInfo in SetBlanket)
struct SEC_WINNT_AUTH_IDENTITY_W {
unsigned short* User;
unsigned long UserLength;
unsigned short* Domain;
unsigned long DomainLength;
unsigned short* Password;
unsigned long PasswordLength;
unsigned long Flags;
};
62
Cloaking (W2K)



Eine andere Art ist das sogenannte
Cloaking
Cloaking inspiziert das aktuelle Thread
Token und kopiert die Daten in den Proxy
Aufrufen von IClientSecurity::SetBlanket
mit entsprechendem Parameter für
dwCapabilities
•
•
EOAC_STATIC_CLOAKING
EOAC_DYNAMIC_CLOAKING
63
Aktivierung


Was tun die Aktivierungs-Aufrufe
•
•
•
Der COM SCM erzeugt die Objekte
stellvertretend für den Aufrufer
•


CoCreateInstanceEx
CoGetClassObject
CoGetInstanceFromFile
Impersoniert den Client
Nutzt ebenfalls das Process Token
Clients habe die Möglichkeit dies mit
Hilfe von COAUTHINFO zu
überschreiben
64
COAUTHINFO
struct COAUTHINFO {
DWORD
DWORD
WCHAR*
DWORD
DWORD
COAUTHIDENTITY*
DWORD
};
dwAuthnSvc;
dwAuthzSvc;
pszServerPrincipalName;
dwAuthnLevel;
dwImpLevel;
pAuthIdentityData;
dwCapabilities;
65
Client Identity Zusammenfassung


Jeder COM Aufruf nutzt das Process
Token als Identität des Aufrufers
Einzelne Interface Proxies können dies
überschreiben
•
•

Explizit durch Angabe der Credentials
Über Cloaking (NT5)
Aktivierung von COM Objekten
ebenfalls mit expliziter Angabe einer
anderen Identity möglich
•
COM SCM impersoniert
66
Server Identity




COM SCM startet den COM Server
Prozess via CreateProcessAsUser
CreateProcessAsUser verlangt ein Token
Drei Möglichkeiten für dieses Token
Welche Möglichkeit verwendet wird steht
in der Registry
•
•
HKCR/AppID/{appid}
RunAs=“…”
67
“As Activator”





RunAs-Key ist nicht vorhanden
COM SCM startet den Prozess mit dem Client
Token
Client muss dazu authentifiziert werden
Jeder Client bekommt einen eigenen Server
Prozess
• Schlecht für die Performance
• Nur sehr schwer möglich Resourcen
gemeinsam zu nutzen
Falls es sich um einen Remote Client handelt,
hat der Server keine „network credentials“
• Kann mit Delegation in W2K umgangen
werden
• Wird allgemein als schlecht angesehen
68
“Interactive User”







RunAs=“Interactive User”
COM SCM startet den Prozess mit dem Token
des momentan angemeldeten Benutzers
Sehr nützlich fürs Debuggen
•
•
Server hat „network credentials“
Ein Server Prozess für alle Clients
Server ist in der Lage Fenster zu erzeugen
•
Z.B. für ASSERT oder MsgBox
Nicht besonders nützlich für Release Version
Ohne einen angemeldeten Benutzer schlagen
alle Aktivierungsaufrufe fehl.
Server Prozess muss mit allen möglichen
Benutzern rechnen
69
“Distinguished Principal”



RunAs=“Authority\Principal „
COM SCM ruft LogonUser auf um ein Token
zu erzeugen.
Ideal für Release Version
•
•
•
•


Server hat „network credentials“ des
ausgewählten Benutzers
Ein Serverprozess für alle Clients
Eindeutiger Account erlaubt es die
Rechte/Privilegien genau zu kontrollieren
Läuft auch im Hintergrund
Nicht unbedingt für Debugging geeignet
•
CoRegisterClassObject macht evtl. Probleme
Password wird als „LSA secret“ gespeichert
•
Dies muss von Hand aktualisiert werden
70
Impersonation Level

Es ist möglich die Benutzung des so
erhaltenen Tokens einzuschränken
•
•
Anonymous wird nicht unterstützt
Delegate geht nur mit Kerberos
RPC_C_IMP_LEVEL_ANONYMOUS
RPC_C_IMP_LEVEL_IDENTIFY
RPC_C_IMP_LEVEL_IMPERSONATE
RPC_C_IMP_LEVEL_DELEGATE
71
CoInitializeSecurity

Der Client setzt den Default
Impersonation Level mit
CoInitializeSecurity
HRESULT CoInitializeSecurity(
SECURITY_DESCRIPTOR* pSD,
DWORD cAuthSvc,
SOLE_AUTHENTICATION_SERVICE *prgAuthSvc,
void* pvReserved1,
DWORD dwAuthnLevel,
DWORD dwImpLevel,
void* pvReserved2,
DWORD dwCapabilities,
void* pvReserved3
);
72
IClientSecurity & Imp. Level

Der Client kann die Einstellung für jeden Proxy
ändern
interface IClientSecurity : IUnknown
{
HRESULT QueryBlanket( IUnknown* pProxy, DWORD* pAuthnSvc,
DWORD* pAuthzSvc, OLECHAR** pServerPrincName,
DWORD* pAuthnLevel, DWORD* pImpLevel,
void** ppAuthInfo, DWORD* pCapabilites );
HRESULT
DWORD
DWORD
void*
SetBlanket( IUnknown* pProxy, DWORD AuthnSvc,
AuthzSvc, OLECHAR* pServerPrincName,
AuthnLevel, DWORD ImpLevel,
pAuthInfo, DWORD Capabilities );
HRESULT CopyProxy( IUnknown* pProxy, IUnknown** ppCopy );
}
73
Abschnitt 4
74
Do’s and Don’ts 1/3

Do
•
•
•
Sichern Sie Ihre Server ;-)
Security während (vor) des Designs
bedenken
„Configure Security“
•
•
•
Role Based Security spart Arbeit
‚Interactive user‘ fürs Debugging
‚This user‘ fürs Deployment
75
Do’s and Don’ts 2/3

Don´t
•
•
•
•
Erfinden Sie kein eigenes “security
system”
Vergessen Sie nicht CoInitializeSecurity()
aufzurufen
Vorsicht bei der Verwendung von
Impersonation
•
Skalierbarkeit
Versuchen Sie CoInitializeSecurity() >=
CONNECT zu vermeiden
•
Die Authentifizierung des Servers schlägt evtl.
fehl
76
Do’s and Don’ts 3/3

Don´t
•
Versuchen Sie “callbacks” zum Client zu
vermeiden (falls möglich)
•
Falls nötig: CoInitializeSecurity() mit Authn
Level NONE ist die beste Wahl
77
Fragen?
Fragen
&
Antworten
Presentation
Layer
78
Wo gibt’s weitere Info’s?



MSDN online
•
http://www.microsoft.com/germany/msdn
MSDN TechTalk-Newsgroup
•
msnews.microsoft.com
microsoft.public.de.german.techtalk
Web Seiten
•
•
•
COM Security in Practice
•
http://msdn.microsoft.com/library/techart/msdn_practicom.h
tm
KeithBrown COM Security FAQ
•
http://www.develop.com/kbrown
COM Security FAQ
•
http://support.microsoft.com/
support/kb/articles/Q158/5/08.asp
79
Wo gibt’s weitere Info’s?

Bücher
•
•
•
•
Keith Brown: Programming Windows
Security
•
http://www.develop.com/kbrown
Don Box: Essential COM
Solomon, Russinovich: Inside Windows 2000
•
http://www.sysinternals.com
Kaufman, Perlman, Spencier:
Network Security
80