|
|
|
date: Mon, 26 Nov 2007 22:02:03 -0800 (PST),
group: microsoft.public.platformsdk.internet.server.isapi-dev
back
Interesting problem? Or so obvious it's painful :)
I have a question and it might seem "stupid" to some but I was hoping
that others may have a nifty trick to help me. I'm here for help and I
want to understand the "how" AND the "why" of what will work in my
situation. Please, please...no replies that are meant to degrade...
Also, let me apologize in advance for the cryptic nature of this post
but there are security issues here so I can't be too specific. I'm
sorry for that.
I have an ISAPI filter that does some things on PREPROC_HEADERS
running on WIndows Server 2003/IIS 6.0 The ISAPI filter is actually
based on a MIcrosoft ISAPI filter made publicly available (from the
readme.txt)
KB 837104 code sample
------------------------------------------------------------------------------
ISAPI filter workaround to handle changes to credentials allowed in
URLs
introduced beginning with MS04-004 (KB 832894).
If a certain condition is true, I need to redirect to a URL. I am
currently using the following code
pfc->ServerSupportFunction(pfc, SF_REQ_SEND_RESPONSE_HEADER, "302",
(ULONG_PTR)pszBuffer, NULL);
with pszBuffer containing "Location: %s%s\r\n\r\n" where the first %s
is the fully qualified URL to the target URL and the second %s is a
URL Parameter noting the original URL asked for when the redirect
occurred:
i.e. Location: http://www.myserver.com/directoryname/redirected.aspx?requrl=http://www.myserver.com/default.aspx\r\n\r\n
and then I am returning SF_STATUS_REQ_FINISHED. To be honest, I'm
confused as I've seen posts that say I should return
SF_STATUS_REQ_FINISHED and also those that say I should call
pfc->ServerSupportFunction(pfc, SF_REQ_DISABLE_NOTIFICATIONS, NULL,
SF_NOTIFY_SEND_RAW_DATA | SF_NOTIFY_END_OF_REQUEST, 0);
So my first question is what is the appropriate and safe way to
efficiently redirect the user to another URL? Should I just return
the SF_STATUS_REQ_FINISHED or should I call the ServerSupportFunction?
My second question pertains to what happens when the redirected.aspx
page is requested. It contains links to other things such as
images,
<img src="/images/image1.gif"/>
style sheets,
<link href="/MyStyles/OrangeTheme.css" type="text/css"
rel="stylesheet" />
and js includes,
<script language="javascript" src="/MyScripts/functions.js" type="text/
javascript"></script>
After dubugging the filter I see that my check for redirection is
being executed for the cases noted above (images, scripts, css). Now,
based on the fact that the condition I mentioned above is still true
and that is why I am redirecting to begin with, that same condition is
still true for all of the "includes" noted above so I once again
redirect when fetching my images...etc... Of course this is not my
intention. My initial thought was to check what path the URL is in
and if I am in the same directory as the redirected.aspx page
(directoryname), then do not send the 302. I can't use the URL to
"short circuit" the redirect because as you can tell the URL's for the
images, stylesheets, etc... are NOT in the same directory as the page
I am redirecting too. And for other reasons I can't go into, copying
these files into the same directory as the redirected.aspx page is not
doable.
So I'm literally in a catch 22. I want to redirect to a page
(redirected.aspx) in a directory (directoryname) and exclude all files
fetched from (directoryname) from redirection, and in addition those
"included" with any file located in (directoryname). Is there anyway
to do this?
Oh, to complicate matters I don't the user to be able to fetch any of
those included files directly and bypass my condition so hardcoding an
exclude rule from the condition won't work. That would mean the user
could issue a http://www.myserver.com/MyScripts/image1.gif and see the
image without my condition being true and not being redirected to the
redirected.aspx page.
I hope this makes sense. I'll be happy to answer any questions you
have.
Thanking you all in advance...
date: Mon, 26 Nov 2007 22:02:03 -0800 (PST)
author: FrankT
Re: Interesting problem? Or so obvious it's painful :)
Thanks for the well worded and detailed post.
1. Returning SF_REQ_STATUS_FINISHED is sufficient after the filter has
sent back a proper HTTP response. In fact, it is exactly what URLScan
does on its fast-path 404 security rejection response.
SF_REQ_DISABLE_NOTIFICATIONS is needed when you choose not to finish
request processing with SF_REQ_STATUS_FINISHED *and* you listen to
filter events that fire in the future *and* you don't want certain
future filter events to fire for that request. The classic ones are
SF_NOTIFY_SEND_RAW_DATA and SF_NOTIFY_END_OF_REQUEST because they kill
response caching and async IO (if you think about the nature of those
events, you'd realize that they defeat async IO by requiring the async
state itself be synchronously available to the filter and is generally
not good for performance nor caching -- for example, if you have a
filter that listen to either SendRawData or EndOfRequest *and* you do
not disable those events for an ISAPI Extension making the
HSE_REQ_TRANSMIT_FILE API call, you will defeat the async IO and
kernel optimizations of the Win32 TransmitFile() API call...).
In your case, you want to finish the request in
SF_NOTIFY_PREPROC_HEADERS with a 302 redirection, so you don't really
care about disable notifications nor should your filter listen to
those events for redirections.
FYI: If you are setting Location: header based on client-provided URL/
querystring, please make sure to %-encode them or else your filter is
vulnerable to cross-site-scripting attacks.
2. You have a set of conflicting requirements which really suggest you
need to think out your proprietary protocol before trying to implement
it in ISAPI. ISAPI is not going to magically solve your problem.
This is my reading and understanding of your requirements -- please
correct me if I'm wrong. It seems like you are writing a custom
authentication filter, where the filter redirects all un-authenticated
requests to a special logon URL (with its special graphics, scripts,
etc), and all protected content (scripts, HTML, jpg, etc) cannot be
accessed without first authenticating through the special logon URL.
Clearly, all URLs associated with the special logon URL need to be
accessible without the filter redirecting them.
In this situation, your catch-22 of the filter redirecting the
requests can be solved by hard/soft-coding the URLs involved with the
special logon URL to be excluded from the redirection. In Microsoft's
sample code, this is accomplished by pre-defining certain URLs, like /
Logon or /Logoff, to be ignored by the filter issuing 302s.
As for how to allow the filter to determine if a request should be
redirected or not, that is best accomplished with client-persisted
state, such as cookies or session-less-state like ASP.Net.
Authenticated users have authenticated state, and filter simply
redirects all requests with non-authenticated state AND those soft-
coded URL that are excluded for special logon.
There are other ways to persist state -- you can look at Basic, NTLM,
Kerberos, and Passport protocols for examples of how to persist and
transmit the authentication state between client and server.
//David
http://w3-4u.blogspot.com
http://blogs.msdn.com/David.Wang
//
On Nov 26, 10:02 pm, FrankT wrote:
> I have a question and it might seem "stupid" to some but I was hoping
> that others may have a nifty trick to help me. I'm here for help and I
> want to understand the "how" AND the "why" of what will work in my
> situation. Please, please...no replies that are meant to degrade...
> Also, let me apologize in advance for the cryptic nature of this post
> but there are security issues here so I can't be too specific. I'm
> sorry for that.
>
> I have an ISAPI filter that does some things on PREPROC_HEADERS
> running on WIndows Server 2003/IIS 6.0 The ISAPI filter is actually
> based on a MIcrosoft ISAPI filter made publicly available (from the
> readme.txt)
>
> KB 837104 code sample
> -------------------------------------------------------------------------------
> ISAPI filter workaround to handle changes to credentials allowed in
> URLs
> introduced beginning with MS04-004 (KB 832894).
>
> If a certain condition is true, I need to redirect to a URL. I am
> currently using the following code
>
> pfc->ServerSupportFunction(pfc, SF_REQ_SEND_RESPONSE_HEADER, "302",
> (ULONG_PTR)pszBuffer, NULL);
>
> with pszBuffer containing "Location: %s%s\r\n\r\n" where the first %s
> is the fully qualified URL to the target URL and the second %s is a
> URL Parameter noting the original URL asked for when the redirect
> occurred:
>
> i.e. Location:http://www.myserver.com/directoryname/redirected.aspx?requrl=http://w...r\n\r\n
>
> and then I am returning SF_STATUS_REQ_FINISHED. To be honest, I'm
> confused as I've seen posts that say I should return
> SF_STATUS_REQ_FINISHED and also those that say I should call
>
> pfc->ServerSupportFunction(pfc, SF_REQ_DISABLE_NOTIFICATIONS, NULL,
> SF_NOTIFY_SEND_RAW_DATA | SF_NOTIFY_END_OF_REQUEST, 0);
>
> So my first question is what is the appropriate and safe way to
> efficiently redirect the user to another URL? Should I just return
> the SF_STATUS_REQ_FINISHED or should I call the ServerSupportFunction?
>
> My second question pertains to what happens when the redirected.aspx
> page is requested. It contains links to other things such as
>
> images,
>
> <img src="/images/image1.gif"/>
>
> style sheets,
>
> <link href="/MyStyles/OrangeTheme.css" type="text/css"
> rel="stylesheet" />
>
> and js includes,
>
> <script language="javascript" src="/MyScripts/functions.js" type="text/
> javascript"></script>
>
> After dubugging the filter I see that my check for redirection is
> being executed for the cases noted above (images, scripts, css). Now,
> based on the fact that the condition I mentioned above is still true
> and that is why I am redirecting to begin with, that same condition is
> still true for all of the "includes" noted above so I once again
> redirect when fetching my images...etc... Of course this is not my
> intention. My initial thought was to check what path the URL is in
> and if I am in the same directory as the redirected.aspx page
> (directoryname), then do not send the 302. I can't use the URL to
> "short circuit" the redirect because as you can tell the URL's for the
> images, stylesheets, etc... are NOT in the same directory as the page
> I am redirecting too. And for other reasons I can't go into, copying
> these files into the same directory as the redirected.aspx page is not
> doable.
>
> So I'm literally in a catch 22. I want to redirect to a page
> (redirected.aspx) in a directory (directoryname) and exclude all files
> fetched from (directoryname) from redirection, and in addition those
> "included" with any file located in (directoryname). Is there anyway
> to do this?
>
> Oh, to complicate matters I don't the user to be able to fetch any of
> those included files directly and bypass my condition so hardcoding an
> exclude rule from the condition won't work. That would mean the user
> could issue ahttp://www.myserver.com/MyScripts/image1.gifand see the
> image without my condition being true and not being redirected to the
> redirected.aspx page.
>
> I hope this makes sense. I'll be happy to answer any questions you
> have.
>
> Thanking you all in advance...
date: Tue, 27 Nov 2007 02:12:25 -0800 (PST)
author: David Wang
Re: Interesting problem? Or so obvious it's painful :)
It's not clear to me whether I understood and helped you on your
question #2 or not.
The main conflicting statement was this:
> Oh, to complicate matters I don't the user to be able to fetch
> any of those included files directly and bypass my condition
> so hardcoding an exclude rule from the condition won't work.
You seem to indicate that you don't want to allow users to directly
fetch nor be redirected on access to the included files of
redirected.aspx. That's a contradiction as stated, so you have to
define what you want to happen. If you say that's not a contradiction,
then you need to introduce a third state condition and define the
lifetime of that condition.
//David
http://w3-4u.blogspot.com
http://blogs.msdn.com/David.Wang
//
On Nov 27, 8:42 am, FrankT wrote:
> David,
>
> 1. Thank you for the information on the SF_REQ_STATUS_FINISHED and the
> clearly written explanation of why. I already had that implemented
> but was confused by another post on this site that talked about using
> the other approach.
>
> The tip on the 302 redirection and cross site scripting is an
> excellent point. I am NOT setting the actual location for the 302 via
> a client provided URL but I am appending the "original url" to a
> querystring parameter based on the user's original request to my
> webserver. I think you have a valid point about the querystring URL
> parameter however. I am going to make sure that the domain of the
> querystring URL parameter is my server's domain (i.e. myserver.com)
> just to make sure that the user is not going to be redirected outside
> of my server's infrastructure after the completion of the user input
> associated with the redirected.aspx page. Thank you for pointing that
> out.
>
> 2. I thought I was barking up the wrong tree. You are absolutely
> correct that I have a set of conflicting requirements and I knew that
> this was going to be a problem before I started. My post was simply
> directed as "Has anyone encountered this before? And have they found a
> simple, elegant solution". That's why I am posting here. We have a new
> requirement and I am in the proof of concept phase right now trying to
> determine IF it can even be done. By no means am I going to implement
> this. I want to stress test, send the source code to our security
> "gods", etc... Lot's of work to be done. I was simply trying to
> determine if there was an option...any option to this problem.
date: Tue, 27 Nov 2007 13:14:29 -0800 (PST)
author: David Wang
Re: Interesting problem? Or so obvious it's painful :)
On Nov 27, 2:06 pm, FrankT wrote:
> Regarding #2, you confirmed my suspicions about what we need the
> filter to do and that it's not going to work as planned. I've solved
> the problem by taking just what the redirected.aspx needs to render
> correctly and putting it in a subdirectory of the redirected.aspx. I
> can then skip the redirection on any requests that are incoming that
> fetch the images js files, etc...
>
> Thanx again,
> Frank
Ok, thanks. Yes, that would be a good approach, to have a soft-
configured list of resources that should not be redirected because it
is used by redirection. :-)
For security, I also suggest that the subdirectory whose redirection
is skipped does NOT have any extraneous Application Mappings,
especially without "Check if File Exists" enabled. Because if you
don't, then your skipped subdirectory becomes a potential security
vulnerability to execute non-existent code using different resource
extensions defined by the extraneous Application Mappings.
For example, this security premise is the basic flaw which allowed the
Code Red worm to spread on IIS5. It is closed on IIS6, but you need to
make sure you don't inadvertently open up things like that when you
choose to skip by subdirectory.
//David
http://w3-4u.blogspot.com
http://blogs.msdn.com/David.Wang
//
date: Tue, 27 Nov 2007 15:18:31 -0800 (PST)
author: David Wang
|
|