Re: Securing data to a process principal
- From: "Steve Schuler" <sjschu@xxxxxxxxxx>
- Date: Wed, 5 Mar 2008 17:15:21 -0800
Yes, I understand. The intent is not to "boil the ocean" but to demonstrate
reasonable controls that protect against "casual" abuse. Protection via ACLs
means that an admin can copy the data for an offline attack. Point taken
that anyone willing to do that is probably also willing to use debugging
tools or to write a hook (assuming they have the skills). But that's much
more intrusive and is more likely to be noticed. Also there's doing away
with the embedded obfuscated "master key" - that's objectively an improved
design.
So yes, I still want encryption with process principal granularity, but if
it means that it will break in current or future versions of Windows when
NTLMv1 is not supported, then I will probably drop this. ... Unless I can
find a way to do it that doesn't depend on the NTLM SSP. (As an aside, I'll
comment that lack of a function like CryptDataProtect, but at process
principal granularity, seems like a blind spot. Providing a "vault" for
non-interactive application use just seems like such an obviously useful
feature to me. In fact, we - being Safeco - have been asking Microsoft where
this feature was for a decade. What's changed was that the idea outlined
below only occurred to me recently.)
Thanks,
Steve Schuler
Safeco Insurance
"lelteto" <lelteto@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:9E6242DE-98D0-4DBC-ABC3-7436FFCC5B63@xxxxxxxxxxxxxxxx
You are mistaken on one important point: local admins will ALWAYS be able
to
retrieve your secrets, monitor your code, etc. Yes, you can protect
against
them "somewhat" (ie. casual browsing would not show them the keys), but it
is
always possible to write a debugging code (or simply a monitoring tool
which
hooks into your encryption function) and you cannot prevent an admin using
that.
So IF you accept that you cannot protect against admins (at least not in
software) do you still need stronger protection than ACLs?
Laszlo Elteto
SafeNet, Inc.
"Steve Schuler" wrote:
Hi again Laslo -
Yes, the accounts would be domain accounts. However, they are not "user"
accounts but are service accounts, so nobody ever does an interactive
logon
using these accounts.
On your suggestions, the problem with #1 is that the password is not
always
the same. There are 100s of these service accounts and my utility will
not
"own" them. On #2, a variation of this (using ACLing) is what I'm doing
today to lock down the keys. The problem with ACling is that it does not
protect secrets from local admins of the box, and it does not protect a
secret it "gets loose" from its ACLed container. What I'm after is
something
better.
Let me explain a little more about the use cases for this - we have a
current utility and workflow it facilitates, and I am seeking to upgrade
the
utility with a stonger protection model.
Use cases & workflow:
1) Risk Management analyst creates domain service ID & password (an
account
not in Domain Users default group, but in a ServiceIDs group in the
domain).
The RM analyst also uses an app that has an embedded obfuscated key (I'll
call it the "master" key) to encrypt the ID/PW and put it into a strongly
ACLed SQL DB (the "service ID DB"). In addition to the service ID and PW,
the RM analyst specifies the "component type" (e.g., IIS worker process,
service, ODBC connection object) the ID / PW can be configured to, and a
group of servers or "component level" (e.g., "development", "acceptance
testing", "production") that the service ID / PW can be applied to. Some
component types - e.g., ODBC connection strings - also take the name of a
second domain ID or group (I'll call this the "app ID") that is allowed
to
access the component type (I'll explain this further in #2 & #3).
2) A resource owner (e.g., an IIS admin) who is a local admin of some
resource is ACLed to be able to call a second app service (which also has
the master key) that can read from the service ID DB. This second app
"knows" how to drive the configuration APIs of all "component types" and
it
checks that the specified component type in the service ID DB matches the
type the resource owner is asking it to configure. In the case of
components
that take an ID and password at configure time such as an IIS application
pool or service Run As, that is done immediately. In the case of a
component
type like an ODBC connection object, where the password is used at run
time
by an application, the "package" service ID, PW, component type and level
remains encrypted, and is copied into the registry of target servers. It
is
also ACLed to the app ID that is allowed to access it.
3) At run time, for resources like ODBC connection object where the PW is
not pre-configured, an app running as the ACLed app ID can call a utility
DLL that has the master key embedded in it, and pass in a connection
object.
The utilty DLL decrypts the package, checks that the requested use
matches
the component type and either server name or test level (we have naming
conventions for our servers), and then applies the service ID / PW to the
component (in this case a connection object), and then passes it back to
the
caller.
While this may seem elaborate, note that it accomplishes two things: 1)
separation of duties (only Risk Management knows the passwords, but they
don't have to know how to configure the apps, resource owners can
confgure
apps without knowing passwords, developers can write code that doesn't
embed
passwords), and 2) it can protect apps from each other on the same box
because of the ACLing that is done for resources like ODBC connection
objects, where the secret is stored in the registry.
I'm trying to create a better approach to the ACLing step. The basic idea
is
that in step #1 above, if provisioning a service ID for step #3, the
encryption would be done with a key that was associated with the app ID.
In
particular, the app ID is itself a service ID in the service ID DB, so if
I
can use a login context of the app ID itself as the encryption key as
I've
outlined below, then instead of using an embedded master key, I can have
the
RM analyst app in step #1 do a LogonUser with the app ID, and then use
the
approach outlined below to use the thread's impersonation context to
encrypt
the service ID. Then in step #3, the running security context of the app
ID
can do the decrypt, without requiring that the utility DLL have an
embedded
master ID. So not only would this be an improvement over ACLing because
the
service ID / PW can't "get loose", but it removes another problem - the
need
to embed a master key in the utility.
Again, thanks for any comments.
Thanks,
Steve Schuler
Safeco Insurance
"lelteto" <lelteto@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:DEF1759A-02E7-4DB5-BD51-B690CC860E99@xxxxxxxxxxxxxxxx
Steve,
You say that you want to lock to a "principal" - but then you say the
same
application should be able to decrypt data on another computer. So are
you
talking about a DOMAIN user? If not, how do you know if the user has
the
same
password on multiple computers?
In case of domain, you may use domain objects (just create a random
encryption key first time for the user - and use it later). That would
be
the
simplest.
If you need to support independent computers obviously you need some
SHARED
secret (key). There are two ways you could do it:
(1) if you assume that the password is always the same, you can derive
the
key from it (you already know this part) - but then you need the
principal's
password - which should be available when you start the process AS the
principal. One possible way to do this is to have YOUR dll loaded into
the
process's address space (the one which handle the
EncryptAsProcessPrincipal
function - and INJECT the derived key into the dll's data area. (Again,
load
as debug suspended - then you have control over the child process'
address
space and can inject data into it.)
(2) IF you can "pre-set" the computers for each principal (user) then
you
can use CAPI: you would need to use CAPI containers. Those are by
default
protected TO the principal.
Laszlo Elteto
SafeNet, Inc.
"Steve Schuler" wrote:
Hello Dave and Laslo - thanks for your replies
I should probably be more careful in choice of wording. Instead of
saying
"Process Identity" (which many will read as PID), I'm now going to say
"Process Principal" to make clear that the granularity I'm after is
that
any
process or thread running with a security context representing the
same
Windows domain Principal can decrypt a secret that was encrypted by a
process or thread running as that same Principal.
To restate my goal, I want something that helps isolate an
application's
secrets from other applications on the same shared box.
CryptProtectData
with machine context doesn't do that. And CryptProtectData at user
context
doesn't work because there's not necessarily an interactive user -
it's
my
understanding that CryptProtectData actually requires a loaded user
profile,
but I'm talking about a non-interactive app doing the decryption -
e.g.,
a
service or an IIS app host. (Is all that's really needed a loaded
profile?
If so, could I "manually" load a registry hive and profile to make it
work?
I recall seeing code that did that before.) Also, I need the
decryption
to
work on multiple machines, which are going to be different than the
machine
that did the encryption. Would CryptProtectData work in any form in
that
case - the docs seem to say no.
To Laslo - I don't need the encryption / decryption to be transparent
and
callers will be calling explicit EncryptAsProcessPrincipal or
DecryptAsProcessPrincipal, so I don't need to go down the file driver
path.
In any case, I don't think a file driver would address my main
requirement,
which is locking things to the calling Principal.
The reason Laslo's #1 is difficult though, even though I have freedom
to
specify how apps will call this code, is that I don't want to embed
the
pOptionalEntropy (or more broadly, "secret") in the apps. That would
just
push the problem one link up the chain - I would now have the issue of
securing pOptionalEntropy. (And yes, obfuscation of a key is the
"solution"
that's currently in use in a similar utility.) Instead, my idea is
based
on
this question: is there already some secret "owned" by the running
thread
that has the right granularity? And which the thread can get at? The
first
answer is yes: the NT password hash. But the answer to the second
question
is seemingly, "not easily". (And yes, the caveat that only Logon Types
2,
4
and 5 will work is OK - my targets for this are IIS app processes,
services,
and interactive apps. And I'll deal with the issue of an impersonating
thread running under a network logon by RevertToSelf-ing and then
restoring
the impersonation token.)
My idea is basically to use the password hash indirectly, via an NTLM
SSPI
operation. It seems like it should work, but I've already spotted one
problem. Namely that I'm not in complete control of whether NTLM or
NTLMv2
is done by the NTLM SSP. The introduction of the nonce and timestamp
in
NTLMv2 mean that it won't work for what I want (v2 would not generate
the
same challenge-response the next time it was called), and it appears
that
there's no way to force SSPI to do NTLMv1 if the LMCompatibilityLevel
is
set
to 3 (and here, if someone knows a way to force this, please chime
in).
If anyone can see a better way to accomplish the granularity I need,
I'd
appreciate the advice.
Thanks,
Steve Schuler
Safeco Insurance
"lelteto" <lelteto@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:8F5884BE-504B-4FCA-86C8-906C39CEBF37@xxxxxxxxxxxxxxxx
CryptProtectData is good for the actual encryption - but Steve's
issue
is
how
to get the PER PROCESS SECRET (pOptionalEntropy).
Steve,
1. It is not clear from your description what type of data
protection
(encryption) you want. If the APPLICATION is calling your code (eg.
your
DLL)
than it's relatively simple - but I guess that you want TRANSPARENT
encryption for any (arbitrary) process without modifying that
application's
code. This is actually very hard: you would need to write a File
System
Filter Driver. Don't even think about starting from scratch - would
be
a
multi-year project in itself (and probably still misses a lot). I
would
strongly recommend contacting OSR and buying their toolkit.
(http://www.osr.com/toolkits_fddk.shtml) It's not cheap, but would
actually
allow you to do what you want.
One note: You MAY think that instead of a filter driver you can
simply
hook
into the file I/O APIs (kernel32, ntdll). That would work for many
applications - and I wrote such hook in the past (part of SSI's /
Rainbow's /
SafeNet's Shell "automatic data protection" feature; also wrote a
Win9x
file
system filter driver for the same). However, this doesn't work for
programs
using memory mapped files - and there are lots of such apps. The
only
way
I
know to work transparently with ALL applications is using File
System
Filter
Driver.
2. Seems you already have a process which KNOWS the processes you
start.
So
here is what you would need to do: set up a communication between
your
starting program and your filter driver. Whenever you start an
application
you
- generate some encryption key from the password
- start it with suspended mode => get process id
- pass the {process_id, key} pair to your filter driver
- maybe you also want to pass path / filename information what to
encrypt
(or what NOT to encrypt like executables, dlls, parameter files -
whatever)
From this point your filter driver can monitor each and every file
I/O
of
each process your start program REGISTERED - and ignore any other
process.
It's not trivial, but certainly doable.
Laszlo Elteto
SafeNet, Inc.
"DaveMo" wrote:
On Mar 3, 8:42 am, "Steve Schuler" <sjs...@xxxxxxxxxx> wrote:
x-posted to microsoft.public.security and
microsoft.public.security.crypto
Hello all -
I've been looking for a way to do this, and I'm hoping someone
either
can
point me at the obvious API that does this that I somehow missed
after
searching long and hard, or else can comment on an idea I'll
outline
below
that I think would get me there.
First, here's what I'm trying to do: I want something similar to
DPAPI,
but
with process identity granularity. I'm going to have an
administrative
UI
that would take a service ID and password, call LogonUser, and
then
call my
encryption API to encrypt data based on something unique to the
security
context created by LogonUser. Later, I want a process configured
to
run
as
that service ID / password identity - and *only* processes
running
with
that
identity - to be able to call a decryption API on that data. (As
for
.
- Follow-Ups:
- Re: Securing data to a process principal
- From: DaveMo
- Re: Securing data to a process principal
- From: lelteto
- Re: Securing data to a process principal
- References:
- Securing data to a process identity
- From: Steve Schuler
- Re: Securing data to a process identity
- From: DaveMo
- Re: Securing data to a process identity
- From: lelteto
- Re: Securing data to a process principal
- From: Steve Schuler
- Re: Securing data to a process principal
- From: lelteto
- Re: Securing data to a process principal
- From: Steve Schuler
- Re: Securing data to a process principal
- From: lelteto
- Securing data to a process identity
- Prev by Date: Re: Securing data to a process principal
- Next by Date: Error
- Previous by thread: Re: Securing data to a process principal
- Next by thread: Re: Securing data to a process principal
- Index(es):
Relevant Pages
|