When it comes to security in .NET’s Web services world, it’s going to be vital to know how each application plays its part.
- By Roberta Bragg
- December 01, 2001
In my town, they meet at the Historical Society. Across the world, there
are millions of them. Some are flaunting their colors. Others, dressed
in blend-in-anywhere-casuals, are quietly standing around chatting like
churchgoers after Sunday morning services. They’re not street people—oh,
no. They could be anybody, even you or me. But at night, the fangs, snouts,
cloaks and magic come out. As a group, while not exactly moving along
a pre-determined path, they travel. Sometimes with supporting cards, dice
or other props and other times strictly with verbal tales they become
one organism. How is that possible? Everyone has a role and everyone plays
it. This has always been a successful model for co-existence among peers.
It’s even been a successful model for the implementation of access controls
on trusted computing systems.
This model, role-based access control, is part of the security model
that will be available to users of .NET. (At last! A security model that
even programmers can understand.) Like my interesting friends, .NET uses
other forms of security as well, including Evidence (players recognize
each other or submit to some questioning or other methods of identification)
and Permissions (each player comes with a strict set of rules that defines
what she can do).
To understand how this works, twist your thoughts from the traditional
models of user-based authentication and authorization you’re comfortable
with and focus on the concept of application authentication and authorization.
In a .NET world, applications will span companies and countries. Each
time the application runs, it’ll branch off and connect to Web services
(small pieces of code that perform some function or service).
Instead of tightly controlled processes owned and managed by a single
company; instead of occasional and highly managed links between applications
that span corporate borders; instead of the deep involvement of the end-consumer
in coordinating the results of multiple enquiries, .NET’s vision is one
of a highly distributed network that consists of three things. First,
some Web services will perform a function (query a database, check your
bank account, validate your credit card, accept an order, transfer money,
issue a certificate and so on). Second, other Web services will be consumers
of these services; they’ll transparently connect with and use services,
then disengage. Finally, to find the services they need, the consumers
will locate services by using directory services. Think of it like fireflies
during the mating season. The female firefly sits on vegetation somewhere
and flashes her abdomen. The fickle male firefly flits about madly looking
for these quick flashes of yellow-green light. The female is offering
a service, and the male becomes the consumer. If fireflies were part of
a .NET design, they could consult a directory that would point them to
the location for the fulfillment of their desire.
Fireflies can depend on the laws of nature to assure the strongest survive,
but no such protection will be in place for .NET. In .NET, indeed, in
the use of any Web services-based model, we have to find a way to manage
the security implications of these diverse couplings. How will your Web
services authenticate? How will they know that the Web services they’re
talking to are really the Web services they claim to be? Because Web services
will allow external agents to manipulate, query and modify data, how will
they authorize that access or that action? When information flows between
millions of diverse Web services across the Internet, how can we guarantee
the integrity of the data? How can we be sure that the information sent
is the information received? Furthermore, can the use of Web services
provide non-repudiation—can they reliably show, beyond legal deniability,
that two Web services did connect and do business?
There are various proposals for the management of security in the Web
services world. Before we all get there, many will be more clearly defined.
Current proposals include signed and encrypted XML; XMLDSig (digitally
signed XML); Security Assertion Markup Language (SAML), the proposed Internet
standard for exchanging user and authorization and services over the Internet;
XML Key Management Services (XKMS), which defines the XML messages used
by applications to work with PKI; and S2ML (www.s2ml.org), the Security
Services Markup Language, a proposed standard for secure e-commerce transactions
via XML. We don’t know which of these proposals, or others yet defined,
will become part of our vocabulary. What we do know is that any model
that seeks to work between different Web services developed via different
vendor specifications will have to follow a standard.
However, within each vendor Web service model there may be a wide range
of functional processes to accommodate access to legacy systems or to
enforce their customers’ perceptions of the proper controls. You might
compare this to the processes we’ve used as travelers for many years.
When you travel internationally, your passport serves as identification
that’s recognized by most nations. For domestic travel, a state driver’s
license suffices; in your hometown, authorities may recognize you personally
without formal introduction or official paperwork. Microsoft .NET’s security
process will follow this same model, using standards where they exist
and are relevant and following its own model when working within its own
This month I’d like to talk to you about one of the security mechanisms
defined for .NET: code authorization. Authorization (what you can do once
you’ve proved your identity) in .NET is accomplished via Roles, Permissions,
Permission Sets and Evidence. My description below defines .NET’s implementation
as described in public documents at Microsoft.com and in its two-day .NET
developer training tour. You should keep in mind that, at the time of
this writing, the .NET framework, Windows .NET Server and other paraphernalia
are still in beta. Note that the information has been greatly simplified
in order to provide an overview. The SDK has more information.
.NET Framework Role-Based Security
.NET applications use role-based authorization based on a principal’s
Windows account or custom identity. In the lingo of .NET, we use the term
“principal” to represent an identity that can be authorized to perform
a function or access some resource. Generic principals exist outside the
traditional user and role (group) models of Windows NT and Windows 2000.
Windows principals are the traditional user and role (group) models of
Windows NT and Win2K. Custom principals are defined by an application.
They may exist only for that application.
If a principal has authenticated to the Web service, then, just as in
traditional processing of requests for data or the performance of some
function, .NET must determine if the principal is authorized to do what
it has asked to do. In traditional business processes, policy is often
enforced through the use of roles. The size of a transaction may be limited,
giving clerks one authorized level, supervisors another, and vice presidents
none at all. Some actions, such as the use of color printers by various
roles, may be associated with the time of day. In a .NET application,
roles such as clerk, supervisor or vice president are associated with
the principal and, therefore, are available to the process currently running.
Furthermore, in .NET, the concept of role-based access control can be
extended to an application, a component of that application, or even some
smaller code construct.
Role-based security in .NET is implemented through Role-based security
In .NET, just like familiar file, folder, printers, registry keys and
directory objects, code can be given permission. Three types of permissions
exist: Code Access permissions, Identity permissions and Security permissions.
Table 1 defines these permissions.
File dialog access
Access to DNS.
Read or Write environment variables.
File selected in open dialog box.
Read, Append or Write files or directories.
Access isolated storage (associated with
specific user and some code aspect).
Web site, publisher or signature.
Discover information about data type
Read, Write, Create or Delete keys and values.
Execute, assert permissions, call unmanaged
code, skip verification.
Make or accept connections on transport address.
Access user interface function.
Make or accept connection to Web address.
Software publisher digital signature.
The Web site of code origination.
A unique cryptographic name assigned to some code component.
Zone where code originated.
URL, including protocol prefix (http, https).
|| Several built-in provided classes
and the ability to create custom permission classes.
|Table1. In .NET, code may be given
permission. Three types of permissions exist: Code Access, Identity
A Matter of Trust
The traditional server trusts all applications and seeks to protect its
resources with the use of object permissions and user rights. All applications
are trusted if run by an authorized user. In .NET, all applications are
not created equal. The .NET application can be restricted in its actions
by associating it to a named permission set or group of permissions. This
establishes a policy that defines the code’s permissions. Named permission
sets include Nothing, Execution (operation, but no access to protected
resources), Internet (default for code from an unknown origin), Local
Intranet (default permissions within an enterprise), Everything (all permissions,
except permission to skip verification), and Full Trust (full access to
Note the difference here. Instead of defining access permission on files,
folders, printers and AD objects, a named permission set spells out what
a piece of code can do. This assignment doesn’t mean you should abandon
object permissions; it does, however, provide another administrative tool
for our side of the security war. Three of the permission sets—Internet,
Local Intranet and Everything—can be modified. While developers may assign
code permissions, we, the administrators, can spell out defaults for known
and unknown code. In addition, we can create custom permission sets to
fit specific applications or environments.
Why are we concerned about restricting the access that code can have?
Simply put, it’s code running on a system that either does the required
job or acts to corrupt and destroy the system. While your efforts may
be simply to process information, there are those who write code to corrupt
your system’s message queues, event logs, performance counters, Active
Directory objects and files. They think nothing of the havoc that might
be created by changing priorities of processes and other acts—or perhaps
that’s their intent. The code running on your systems is no longer your
code but comes from a variety of sources, including e-mail; documents
in which it’s embedded; downloaded from the Internet; and brought home
from conventions, meetings and classes.
Network Administrators Need to Know About .NET Now!
|To continue in your role as infrastructure
master, you need to prepare for the explosion in Web services
that .NET and its competitors will be releasing. You need
to be reading about .NET and working with its clients
and servers. I know you’re deeply committed to that roll-out
of Windows 2000 or XP Professional or patching all servers
or… So here are some pressing reasons to convince you
to save a little bit of your time for .NET.
- New security mechanisms permeate the .NET structure.
Code authorization is just one.
- Best practices in .NET suggest that application
information reside in regular files, not in the registry.
Try troubleshooting new .NET applications without
that bit of knowledge.
- Eight million Visual Basic programmers are just
learning this stuff, too. How bulletproof will their
apps be? How will you know? Are they implementing
the security mechanisms that will allow you to protect
your systems properly?
- A new tool, ILDasm.exe, parses .NET Framework .EXEs
and .DLLs and shows the information in a form that
you and I can read—as can everyone else. While knowing
what the code is won’t matter to most people, if your
applications have hard-coded passwords, they’ll be
- How are you going to make these entirely new types
of applications work on entirely new servers and clients?
- You’re the one who’ll get to make solutions work
between disparate vendors. Do you know what’s standard,
what’s proprietary and what solutions there may be
for making them all work together?
To counter the impact of all this code of unknown or untrusted origin,
we now have methods for establishing trust or in limiting its ability
to affect the system if we can’t. Trust, then, must be established not
just for the user of the code, but for the code on its own. We can do
this via recognition of the code’s author, its origination or some custom-designed
evidence. Once identity is established, the policies of the system determine
under which Permission set the code will run.
Putting it All Together
So with all these opportunities for controlling what code can do and touch
in any environment, what determines what it actually can do? A .NET application
is managed by the Common Language Runtime (CLR). The CLR looks at the
three levels of security policy (machine policy, user policy and application
domain policy) and determines what a code group, or logical collection
of code, can do.
In the .NET world, administrators set policy; runtime enforces it.