Groups | Blog | Home
all groups > inetserver iis > november 2007 >

inetserver iis : Impersonation and File Permission problems


Pablo Montilla
10/31/2007 12:00:00 AM
Hello, I have a problem with file permissions in an ASP.NET app. My app
runs correctly on my test server (Windows 2003 SP2 Standard Edition), but
don't work at all in my production server (Windows 2003 SP2 Enterprise
Edition, joined to an Active Directory domain).

The problem seems to be that IIS is not impersonating the user when it's
accessing the aspx file before handing it over to ASP.NET, and is instead
trying to access it as Network Service (as shown by a run of sysinternals
procmon) . I have the web server configured to use Integrated Windows
Security as the only authentication method (anonymous access is disabled),
in the same way I have my test server. The production server holds only
this app, and the problem is effectively one of permissions, as if I
inherit permissions in the inetpub app directory, everything works
(without security, obviously).

Is there any difference in the way impersonation or file access security
is handled in IIS 6 running on an Enterprise or on a Domain joined server?
I've read somewhere that users need a special right to allow them to
impersonate, is that true?

Thanks,
Pablo

--


Cheerleaders do it enthusiastically.

Pablo Montilla
Justin Rich
10/31/2007 11:03:19 AM
from what i have learned, you cant really impersonate with web apps. the app
pool overrides all of that... i worked with it for quiet some time with no
luck.

I basically saw the same thing you did... ran ok on my box but not in
production. basically it ran ok because i run it from my machine which
allowed the network service account access everything it needed to. to get
around this i added the AD computer account of the server to the approprate
groups that it needed for access to the resources.... not really the best
options... and rather odd.. but the intigrated security is used to access
the files, it has nothing to do with the running conext of the web app..



[quoted text, click to view]

Pablo Montilla
11/1/2007 12:00:00 AM
On Wed, 31 Oct 2007 13:03:19 -0200, Justin Rich <jrich523@yahoo.spam.com>
[quoted text, click to view]

Thank you for replying, but I think I wasn't really clear with my problem
explanation. I want to use the client provided credentials, to give or
deny access to the aspx files on the server. The impersonation works
correctly in the ASP.NET context, I get the correct identity there, the
problem appears before.

I always thought that the credentials provided by the client where used to
check ACLs of the files in the server before sending them down the pipe.
Giving access to the network service account will make no difference in my
scenario, as I can access the aspx files simply by letting permissions
inherit from wwwroot...

What I want, is for IIS to honor the permissions set in the aspx files,
something IIS is doing in my test server, but is not doing in the
production server. The only important (I think) difference between these
servers, is that one is a standalone server working in a workgroup net,
and the other is a standalone server joined to an AD domain.

Do I need to check anything else?

Thanks,
Pablo
--


I'm just going into the card shop to look...
-- Famous Last Words

Pablo Montilla
Justin Rich
11/1/2007 12:00:00 AM
well if we are talking about file access then really the only thing you need
to do is turn off anonymous access withing IIS and make sure integrated is
turned on.. your not really doing any impersonating... impersonating is
running code under the context of the user. in asp.net the code is run under
the context of the app pool.

so if you just turn off the anonymous i think you should be all set. that
will use the NTFS permissions on the files to determin whether a user can
access the file or not..


[quoted text, click to view]

Pablo Montilla
11/1/2007 12:00:00 AM
Thanks for your reply I answer below:

On Thu, 01 Nov 2007 10:33:04 -0200, Justin Rich <jrich523@yahoo.spam.com>
[quoted text, click to view]

That's exactly what I tried to do, but it didn't work on my production
server. The permissions are set identically (they are set via script,
actually), and the web site is configured identically too, but I can't get
it to honor the permissions. I've disabled anonymous access and enabled
integrated security in both servers, in one it works, in the other it
doesn't.

[quoted text, click to view]

I don't know how the file access permissions are to be honored if the
server process doesn't change its security context when accessing files.

What I'm missing?

Pablo
--


An eccentric America is a Safe America...

Pablo Montilla
Justin Rich
11/1/2007 12:16:06 PM
from my understanding of this it basically goes like this...

a user requests a page from IIS and IIS checks to see if the user has access
to that page (a combo of layers here, IIS and NTFS security levels) once the
user has access to the page (the file itself) the page is then processed
(server side execution) which is where the app pool and stuff comes in.

provided you have turned off anonymous access in IIS and have the correct
permissions set for the NTFS levels you should be good. what is the error
you are getting? is it a stack trace or a standard HTTP error, like a 404?


[quoted text, click to view]

Justin Rich
11/1/2007 12:37:04 PM
well, an AD server vs a standalone is slightly different and the difference
is that when you pass a username to a server in the AD it will always assume
the username is part of the domain so if you supply "justin" as your
usersname its going to assume "domain\justin" where as a standalone server
assumes "server\justin" but since you arent the one packaging or
manipulating the creds this shouldnt be the issue.

and actually its rather odd your getting a 401. the 401 is for a specific
deny. what that means is most likely somewhere in NTFS you have a deny
access some place.

do you have the sub code? should be like a 401.1 or something.

here is a KB article that goes over how to troubleshoot this kind of
problem.
http://support.microsoft.com/kb/907273


[quoted text, click to view]

David Wang
11/1/2007 2:13:57 PM
[quoted text, click to view]



By default, Application Pools on IIS6 run as Network Service. So, your
test server has non-default configuration which does not match
production. That can cause behavior differences.

Regarding permissions used to execute ASP.Net pages -- on IIS, the
answer always depends on the request handler, in this case ASP.Net.
http://blogs.msdn.com/david.wang/archive/2005/06/29/IIS_User_Identity_to_Run_Code_Part_2.aspx

ASP.Net happens to make this configurable by the user via the
<identity> section, and its inheritance level is defined within
machine.config of the .Net Framework version the application uses. By
default, ASP.Net uses the process identity, but you can configure it
to behave in other ways and at different levels (webroot-wide, per-
application, etc). See:
http://support.microsoft.com/kb/306158

I hope this explains what is going on so that you can ensure the
appropriate configurations.


//David
http://w3-4u.blogspot.com
http://blogs.msdn.com/David.Wang
//
Pablo Montilla
11/1/2007 2:28:26 PM
I'm getting a 401. The problem is not with the ASP.NET app, as it runs
fine (and gets the correct credentials) when permissions to read is given
to the Users group (simply by inheriting the wwwroot default permissions).
I'm really baffled by this, as I don't see where's the problem. My
understanding was exactly as yours (save the part where the IIS check is
done without impersionation).

Is there any difference between the metabase configuration for an IIS in a
server in a workgroup and a server in a domain? I still see that as the
only meaningful difference between the servers. I've run this in two other
servers now, and the three of them work correctly, while the production
server won't.

Pablo

--


To do a lab really well, have your report done well in advance.

Pablo Montilla
Justin Rich
11/1/2007 2:40:34 PM
well, its straight out a security issue so what i would suggest is some
basic testing. add a user account and test with a user account that has
admin access to the server and the slim it down from there until you find
where the deny access is set because i think thats what the problem is.

It sounds like your IIS security is set right so i would start digging
around with NTFS permissions..


[quoted text, click to view]
Using wget to get the page, I get this interaction:

HTTP request sent, awaiting response...
HTTP/1.1 401 Unauthorized
Content-Length: 1656
Content-Type: text/html
Server: Microsoft-IIS/6.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Thu, 01 Nov 2007 17:05:23 GMT
Connection: keep-alive
Reusing existing connection to localhost:80.
HTTP request sent, awaiting response...
HTTP/1.1 401 Unauthorized
Content-Length: 1539
Content-Type: text/html
Server: Microsoft-IIS/6.0
WWW-Authenticate: NTLM
TlRMTVNTUAACAAAAAAAAADgAAAACAgACQ4Fi/qaJ4GMAAAAAAAAAAAA
AAAA4AAAABQLODgAAAA8=
X-Powered-By: ASP.NET
Date: Thu, 01 Nov 2007 17:05:23 GMT
Connection: keep-alive
Reusing existing connection to localhost:80.
HTTP request sent, awaiting response...
HTTP/1.1 401 Unauthorized
Connection: keep-alive
Date: Thu, 01 Nov 2007 17:05:23 GMT
Server: Microsoft-IIS/6.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 8620
Authorization failed.

The user that was used to get this is in a group wich has read access to
the aspx file. If I remove that group and add the Users group instead, I
get a 200 in the last part of the negotiation.

Checking the effective permissions for the user, I get the same
permissions when using the 'Users' or the 'O2 - Operator' group (the one
that should be ensuring access control).

I really don't get it. =(
--


We know what happens to people who stay in the middle of the road.
They get run over.
-- Aneurin Bevan

Pablo Montilla
www.odyssey.com.uy

Pablo Montilla
11/1/2007 3:14:04 PM
Using wget to get the page, I get this interaction:

HTTP request sent, awaiting response...
HTTP/1.1 401 Unauthorized
Content-Length: 1656
Content-Type: text/html
Server: Microsoft-IIS/6.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Thu, 01 Nov 2007 17:05:23 GMT
Connection: keep-alive
Reusing existing connection to localhost:80.
HTTP request sent, awaiting response...
HTTP/1.1 401 Unauthorized
Content-Length: 1539
Content-Type: text/html
Server: Microsoft-IIS/6.0
WWW-Authenticate: NTLM =

TlRMTVNTUAACAAAAAAAAADgAAAACAgACQ4Fi/qaJ4GMAAAAAAAAAAAA
AAAA4AAAABQLODgAAAA8=3D
X-Powered-By: ASP.NET
Date: Thu, 01 Nov 2007 17:05:23 GMT
Connection: keep-alive
Reusing existing connection to localhost:80.
HTTP request sent, awaiting response...
HTTP/1.1 401 Unauthorized
Connection: keep-alive
Date: Thu, 01 Nov 2007 17:05:23 GMT
Server: Microsoft-IIS/6.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Cache-Control: private
Content-Type: text/html; charset=3Dutf-8
Content-Length: 8620
Authorization failed.

The user that was used to get this is in a group wich has read access to=
=

the aspx file. If I remove that group and add the Users group instead, I=
=

get a 200 in the last part of the negotiation.

Checking the effective permissions for the user, I get the same =

permissions when using the 'Users' or the 'O2 - Operator' group (the one=
=

that should be ensuring access control).

I really don't get it. =3D(
-- =



We know what happens to people who stay in the middle of the road.
They get run over.
-- Aneurin Bevan

Pablo Montilla
David Wang
11/1/2007 4:03:07 PM
[quoted text, click to view]


The permissions and entities you attribute to actions are not quite
correct. You want to first read many of my blog entries (see the quick
links bar on the left of my blog) to figure out the right entities and
relationship within IIS and ASP.Net. You should then see what is awry
with what you just said. :-)

Neither IIS nor w3wp.exe run ASPX code
w3wp.exe *IS* IIS
IIS runs with Process Identity until it runs ISAPI or does security
checks
IIS launches ISAPI with impersonated client credentials
ISAPI decides what thread token to execute code
ASP.Net is an ISAPI
ASP.Net uses <identity> to allow user to decide what thread token it
uses to execute ASPX page


//David
http://w3-4u.blogspot.com
http://blogs.msdn.com/David.Wang
//
Justin Rich
11/1/2007 4:15:27 PM
so what your saying is network services didnt have access to the files?


[quoted text, click to view]

Pablo Montilla
11/1/2007 4:58:14 PM
I'll continue digging then, thanks for your help!

Pablo
--


Kareen: "Are you a Romulan?"
Worf: [Growls] "Hardly."
-- "The Schizoid Man", Stardate unknown

Pablo Montilla
Pablo Montilla
11/1/2007 6:12:39 PM
On Thu, 01 Nov 2007 16:40:34 -0200, Justin Rich <jrich523@yahoo.spam.com>
[quoted text, click to view]

I hate it when this happens. I was checking file access with procmon, and
figured what the problem was. I don't really know why, but in all my test
servers, the w3wp.exe process is running under the SYSTEM account (at
least when accessing aspx files), and in my production server it is
correctly running in the NetworkService account. The app pools in my test
servers and in the prod server say they run on the NetworkService account
so there must be a configuration setting I missed in the machine.config,
or something.

Anyway, the case is that IIS is correctly doing the access check on the
aspx files, probably is handling both the process token and the user token
to the w3wp process, the process reads the aspx file while in the context
of the process token, impersonates, and only then executes the page code.

That explains it all, and sounds overly complex and nonsensical so it must
be true..;)

So my solution is to add read access to the network service and cross
fingers.

Many thanks for your time and your help,
Pablo
--


It is easy to be tolerant of the principles of other people
if you have none of your own.
-- Herbert Samuel

Pablo Montilla
Pablo Montilla
11/1/2007 7:35:15 PM
On Thu, 01 Nov 2007 18:15:27 -0200, Justin Rich <jrich523@yahoo.spam.com>
[quoted text, click to view]

Yes, I was able to access the files when the Users group had access
(evidently NetworkService is a member), but had no access when I removed
it and replaced it with the secured group. I gave NetworkService read
access to the aspx files and then all worked correctly. Files got their
access checked, so members of other groups had no access, and ASPNET
impersonated correctly...the problem was the interim when ASPNET was
trying to read the aspx file using the NetworkService account context.

Many thanks for your time.
Pablo

--
Pablo Montilla
Pablo Montilla
11/1/2007 7:48:31 PM
Thanks for your reply, I answer below...

[quoted text, click to view]

That's strange, I won't say I didn't fiddle with the app pools, but they
all say they are running using the NetworkService account...

[quoted text, click to view]

I had the <identity> set to impersonate in the web.config for the app, but
still it didn't work.

[quoted text, click to view]

What I *think* it's happening now is (given a request for an aspx file):
1. IIS (NetworkService) checks permissions using client credentials.
2. w3wp (NetworkService) reads aspx and web.config contents. Sees it needs
to impersonate.
3. w3wp (Client credentials) runs the aspx code.

I'll have a go at the links you've sent, so I can get a better picture of
what is going on.

Am I close to understand what's happening? I'm getting mad! ;o)

Many thanks for your time,
Pablo

--
Pablo Montilla
Justin Rich
11/2/2007 12:00:00 AM
I know your about 10 fold smarter than I am, but I think I disagree with
that. maybe you can clear it up for me.

as a reference I was looking at the IIS 6 arch in MSDN
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/93ddbb51-5826-4ebd-a434-24c5fd103d3a.mspx?mfr=true

based on that:
inetinfo *is* IIS
svchost contains the web service process (not sure what file it loads)
w3wp is the worker process (app pool) which executes the code. which by
default runs as Network Services.

I haven't been able to really find good info on this in MSDN but my gut is
telling me that the web service (svchost in this case) is what does the file
permission check (the web security stuff, in this case integrated security)
and once the user is allowed to execute the file (directory security of the
website) it is then tossed off to the w3wp process to be executed (the bit
about asp.net being an ISAPI makes sense)

now here is where I kind of get confused. I have tried to run things (like
powershell) in my application and tried the web.config identity stuff (that
seems to either work with, or override the setting in IIS) and I have also
tried to code an impersonate (that kb you listed, which works with
windows/console based apps but doesn't seem to work with IIS6) but no matter
what I do, the code always executes under the context of the app pool
(network services)

I think there might be some differences with how IIS5 handles that vs. IIS6
because from what I can tell IIS5 works more like how your describing.

also there is one other bit that has an effect on this, and that's Kerberos
delegation.. and I'll leave that alone for now because I don't understand
what part it plays in this, mostly because I don't fully understand the work
flow of security here...

more than willing to hear some more of your insight :)

Thanks
Justin


[quoted text, click to view]

Pablo Montilla
11/2/2007 12:00:00 AM
Aha! Stupid me, sorry. ;) I think I get it now, but there's something I
still don't understand.

If as you say, IIS launches the ASPNET ISAPI impersonated with the client
credentials, then why does ASPNET fail until I give NetworkService read
access to the files I wish to protect? My web.config has the impersonate
tag, and the aspx writes to the output the current thread identity, and it
is what I provided in the browser, so in the end it is impersonating, but
what happens in the middle?

I've renamed one of the failing aspx files to html (so ASPNET's ISAPI was
not involved), and they passed through fine, and access checks were done,
giving access only to accounts in the group with read access, and denying
it to accounts not in the group. When I renamed it back to aspx, it didn't
work until I gave read access to NetworkService...

Can you please explain what's going on?

Many thanks for your patience and time,
Pablo

--


The one function that TV news performs very well is that when there
is no news we give it to you with the same emphasis as if there were.
-- David Brinkley

Pablo Montilla
David Wang
11/2/2007 11:55:40 AM
[quoted text, click to view]


[quoted text, click to view]



It's not if. IIS *does* launch all ISAPI Extensions, including ASP.Net
ISAPI, impersonated with the client credentials. What is non-obvious
is that ASP.Net ISAPI DLL strips OFF the impersonation token and run
with the process identity... until it reads the <identity> property
and go "oh, I need to put the impersonation back on again".

Furthermore, IIS has (I forget if it was fixed) a habit of touching
the script file itself when you have "Check if File Exists" checked
for an Application Mapping.

Remember, .Net is really flakey when it comes to Windows security
model. For example of that, see how impersonated user tokens just
disappear on .Net Async completions -- because the completion thread
has no idea what token the original thread used (it's not necessarily
the same thread -- this is Async IO).

I'm not saying that your expectations are improper. I'm just saying
that .Net is not so happy with the whole idea of Impersonation. And it
ends up showing up in situations like this.

In the end, the easiest thing to remember is to give IIS_WPG read
access to everything you ever want to serve over the web. If you want
to isolate, you may use the specific Application Pool Identity
(instead of IIS_WPG) to ACL.


//David
http://w3-4u.blogspot.com
http://blogs.msdn.com/David.Wang
//
David Wang
11/2/2007 12:34:21 PM
Let me clear up some confusions: That document only states at a high-
level the components, not how they interact.

My prior newsgroup post applies to all IIS versions past, present, and
future. It is how IIS Core Request Processing Pipeline, ISAPI, and
ASP.Net work, and I highly doubt these fundamental aspects will change
in the future. You may want to rethink what I have said, if you think
I described an IIS5-specific model.

What has changed through time is the organization of that code in
different processes -- for performance, scalability, security reasons.
Without getting into the nitty gritty details (let's get the concepts
straight first, then worry about the one-off details):

In IIS5, IIS5.1, and IIS6 running in IIS5 Compatibility Mode:
1. All requests funnel through to inetinfo.exe in user mode (For IIS6,
HTTP.SYS is configured to funnel all requests to inetinfo.exe -- you
can view IIS6 in IIS5 Compatibility Mode as HTTP.SYS being told there
is one worker process called "inetinfo.exe" that handles all user-mode
requests)
2. Request is parsed and processed inside of inetinfo.exe UNTIL it
comes time to execute the handler specified by an Application Mapping
to do the real work. AuthN/AuthZ checks are done at various stages of
this processing.
3. Depending on Application Isolation, that handler is either:
- Low: load and execute in inetinfo.exe
- Medium: load in one specific dllhost.exe
- High: load in its own dllhost.exe
4. Response is sent back out and logged by inetinfo.exe

In IIS6 running in Worker Process Isolation Mode and IIS7:
1. All requests are funneled through HTTP.SYS in kernel mode. Request
headers are completely parsed by HTTP.SYS to determine appropriate
Application Pool. WAS (Web Activation Service) in svchost.exe
configures HTTP.SYS to direct whether a new w3wp.exe needs to be
started or an existing w3wp.exe already exists to handle requests to
that Application Pool, and the request is routed to the correct
w3wp.exe by HTTP.SYS
2. Request processing continues in user-mode w3wp.exe, which actually
processes the request and executes the handler specified by an
Application Mapping inside the w3wp.exe process. AuthN/AuthZ checks
are done at various stages of this processing.
3. Response is sent back out and logged by HTTP.SYS

As you can see, depending on IIS version:
1. Request Parsing has changed location (inetinfo.exe vs HTTP.SYS)
2. Process Activation to handle request has changed dramatically
(inetinfo.exe/mtx.exe/dllhost.exe vs svchost.exe/w3wp.exe)
3. Request Execution of Handlers has changed (dllhost.exe vs w3wp.exe)
4. Logging handling has changed (inetinfo.exe vs HTTP.SYS)

It should be clear that inetinfo.exe is not exactly IIS even though it
shows up everywhere. The correct statement is that inetinfo.exe holds
the metabase, which is IIS configuration. Think about it this way --
Windows has the Registry to hold configuration, but you don't consider
the Registry "Windows", do you?

So, I would not get too hung up on what "process" constitutes IIS. I
would focus on the entire request processing sequence and how it is
broken up into various processes. For layman reference, I would say
that w3wp.exe is IIS; In IIS5.x modes, inetinfo.exe is IIS. Because
that's where most interesting things happen.

Now, when things get into managed code (like ASP.Net and Powershell),
the idea of "impersonation" within Windows that is used by IIS becomes
less reliable. I haven't really played with that technology yet, so I
can't say anything more about it.


//David
http://w3-4u.blogspot.com
http://blogs.msdn.com/David.Wang
//











[quoted text, click to view]
Pablo Montilla
11/2/2007 5:49:37 PM
On Fri, 02 Nov 2007 16:55:40 -0200, David Wang <w3.4you@gmail.com> wrote=
:

[quoted text, click to view]

OK then, so the stupidity is within ASPNET itself. That's great to know!=
=3D)

Many, many thanks for your answers, at least I have a grip on what's =

happening now.

Thanks,
Pablo

-- =



I knew the gun was loaded but I didn't think he'd kill.
-- Glen Frey

Pablo Montilla
AddThis Social Bookmark Button