ColdBox allows direct access to cfm files anywhere in your app

It appears that the standard Application.cfc generated by ColdBox
contains this in onRequestStart:
   if(findNoCase("index.cfm", listLast(arguments.targetPage, "/")))
      processColdBoxRequest();

This gets ColdBox involved only for pages named 'index.cfm'. Site
visitors can access cfm files anywhere in your app that have any other
name. They'll often crash without their expected CB setup (rc etc),
but you can hit them nevertheless. That's very unusual, and generally
very undesirable for a front controller framework, where you typically
want the framework to be managing all requests, except possibly
certain defined exceptions.

Is there some "standard" modification to Application.cfc that's
usually used to achieve this? If so, why isn't it standard? Usually
I'd wonder if there was some ColdBox convention or configuration I
missed (there usually is), but in this case, ColdBox just doesn't get
called for files other than index.cfm, so it doesn't matter how it's
set up.

In FW/1 for instance, it does manage all requests, except ones covered
by two configs, unhandledExtensions and unhandledPaths. Are people
doing something similar with CB?

Thanks,
Dave

I had wondered the same thing actually... In Fusebox the thing to do
was use an onRequest handler in application.cfc to reject any request
except for /myapp/index.cfm -- but you could easily add rules to
bypass that check.

I haven't gotten around to trying it yet, but I imagine the same would
work for CB too.

Sure it would, that's how Application.cfc works (:-). I'm just
wondering why it's not part of the standard ColdBox Application.cfc,
and wondering what people do about that.

Seems like the ColdBox Way would be some sort of exemption config, and
everything that didn't match that and wasn't index.cfm at the root
would redirect to index.cfm at the root. Since this code runs before
ColdBox, probably those configs would be in the variables scope of
Application.cfc, set up in the constructor.

Just my $0.00002.

Dave

Actually, I love that CB is like this.

Slow integrating CB into a legacy system is incredible easy since it only goes through an individual .cfm file.

I don’t have to then worry about it running into other requests than what I specifically intend.

If you want to change it for your application, overwrite the onRequestStart() method in the Application.cfc, and remove the if statement.

Realistically though, it’s not CB’s job to stop people accessing .cfm page that are in your web root… if you don’t want them to be accessed, (a) don’t put them in the web root (b) use your web server config to control access.

Although that’s just my opinion :slight_smile:

Mark

+1 to Marks comments.

Aaron Greenlee

http://aarongreenlee.com/
Twitter: aarongreenlee

I get that it makes gradual integration with legacy apps smoother.

CFC methods not set to remote access can't be called directly. Views
aren't a big risk, since they don't modify anything, and they'll
probably crash before displaying anything when rc doesn't exist. Code
you cfmodule to will also blow up because the attributes scope won't
exist.

So the real risks I think are two: The actual risk is from any
cfincludes you have that do or reveal anything. Depending on the
coding style of the app, that may be none, or not. The other risk is
political. Any commercial app with fair market penetration will
eventually be subject to security review, and so will some custom
apps. It's hard to know how this behavior would be seen, but probably
not positively.

In cases where it matters, by no means always, customizing
Application.cfc seems like the way to go. Just removing the 'if'
doesn't prevent the module from being called, and normal handler
security infrastructure probably won't work correctly outside its
usual context. You'd probably need additional logic to redirect or
block any requests not made to index.cfm at the root. (BTW, the
existing logic processes files anywhere whose names end in
'index.cfm'. I don't mean to be critical, but that seems like an odd
design.)

Dave

My applications keep all files I do nit want to be executable outside
of the root.

Is that not possible in your app?

Thanks for the discussion.

Aaron Greenlee

http://aarongreenlee.com/
Twitter: aarongreenlee

If that’s what you want… leave in the if, and it doesn’t pass, do an else and cfabort?

Really though, why not just drop it an .htaccess to change your apache config (or if you use IIS, the equivennt) and block those dirs?

I’m really not seeing the concern or issue here?

Mark

The app I work on most at work doesn't allow this kind of open access.
Doesn't seem like it's is a concern here, done.

Dave

Or you could drop an Application.cfm with a in it in the dirs you don’t want people to access.

Lots of ways of skinning the cat 360.gif

Mark

I don’t understand what you say about errors when a file is accessed that is not index.cfm. There isn’t any RC at that point it is a normal cfm template being executed. The framework will not process the request but ignore it, due to that if. It does not create errors or any other behavior. So I am not understanding your point.

Luis F. Majano
President
Ortus Solutions, Corp

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

360.gif

Mr. David,

If I'm far off base here - please let me know.

@Louis: When I navigate the browser directly to a view cfm, ColdBox
doesn't process that request, as you say. In most cases, views contain
references to data in rc, which hasn't been set up, so they'll crash.
For that reason, it probably won't reveal anything it shouldn't, even
though ColdBox and any security interceptor aren't in play.
   One possible exception to that is hitting a viewlet directly, since
as I understand it (haven't used them) they're self-contained, calling
services to get their data themselves; I'm not certain if that would
work without ColdBox having run in that request. If it does, your
security interceptor won't be in play, so it's possible people might
see things they weren't intended to.

@Aaron: What exactly do you keep in your web-servable app directory?
Clearly non-cf assets (css/js/img/etc) have to be there, but I did
wonder if you could leave only those, plus Application.cfc and
index.cfm, and move everything else outside the web root. Haven't
tried it, may or may not work at all, but it would be the most secure
option. Do you do anything like that?

@Mark: It's not that I don't know various ways to lock things down, I
was just identifying the fact that ColdBox apps are open in this way,
and where you care about that, you should probably address it. It's
not a decision that's mentioned in the docs, far as I know.

@Rus: I see the behavior I described above to Louis when I use the
correct url to hit a view page directly. I'm on M6.

Big picture, I'm not trying to be critical of ColdBox, I'm loving it
more every day. I wasn't looking for trouble, ran into this question
looking at the default Application.cfc code in relation to something
else. I'm not saying it's unsolvable with ColdBox as it is today, just
pointing out that this is a layer of application design that's not
dealt with by the framework, so it's something you should consider
when you care about this behavior.

IMO, even if it doesn't reveal anything or allow any unintended
actions, it's unprofessional to have urls in your app that you know
will crash. It's also odd for ColdBox to process files whose names end
in 'index.cfm' ('publicationIndex.cfm' for instance), in any
directory, only.

Not trying to be a chicken little, just pointing out what the behavior
is, asking if folks are aware of it, and if so, what they do about it.

Dave

...

@Aaron: What exactly do you keep in your web-servable app directory?
Clearly non-cf assets (css/js/img/etc) have to be there, but I did
wonder if you could leave only those, plus Application.cfc and
index.cfm, and move everything else outside the web root. Haven't
tried it, may or may not work at all, but it would be the most secure
option. Do you do anything like that?

I do. It works really well. =)

This ability is one of the benefits to using a framework, generally.

Here's how I structure my projects:

project
  /pub
    index.cfm
    Application.cfc
    /images
    /css
    /js

  /src
    /coldbox
    /myCFMLsources
    ...
...

The project/pub dir is the DocumentRoot in Apache, so all apache can
ever accidentally serve out in plain text is those two cfml files.
Which can be very empty! Depending on your setup, you can even have a
sole Application.cfc in pub/, which extends another cfc in /src, which
uses onRequest-- leaves you with a single line of potentially
expose-able cfml code (component extends="my.app.Application"{}).

And because of the way JEE works, if you put your components/sources
in WEB-INF, the application server itself won't be able to
accidentally serve out CFML either.

There are several really swell tutorials out there on "hardening"
CFML. Probably a search for "hardening coldfusion" would work to find
them. I just search every now and again myself, as there's sometimes
new stuff.

I'm happy to see the interest in securing your applications. Good
stuff to be interested in!

:Den

Very cool Den, definitely the most secure option in general, one
benefit of which is that this whole ColdBox behavior issue just goes
away. I'll be moving the main personal project I'm working on to a
layout like this when I get home. I wondered if that would work.

Only potential hang that occurs to me is access to utilities you cf
module to. I don't use those a lot, and often they're in the same
directory as their callers so just hte filename isneeded, not path.
However, you wouldn't be able to call a general-purpose utility from
everywhere as <cfmodule template="/myapp/utilities/sql/mymodule.cfm">
any more, like you could when it was inside your app. You could create
a mapping to your src directory that would allow that, but that'd
expose the code in any mapped directories to direct requests too I
think. Typically the only time I use cfmodule in recent apps is for
SQL utilities that contain cfqueryparam, because for some antique
reason the language won't let you use that tag inside a function or
method (at least on ACF, haven't tried Railo, maybe on CF9 either).

Also, what do you mean by "if you put your components/sources in
WEB-INF, the application server itself won't be able to accidentally
serve out CFML either"? The CFML engine should never return the
*contents* of a CFML file, just its rendered output, so I don't
understand what circumstances you're thinking about in moving things
into WEB-INF, or in having your real Application.cfc extend on outside
the web root.

Good stuff.

Dave

Ahh now I understand what you are saying, you are saying that if you know the paths to a view you could hit the view and it would fail.

We have several approaches, but this I guess is more of the concern of the developer than maybe ColdBox, not sure here. But you can in the Application.cfc block access to the conventions directly which is what I do. If not, you can drop a similar Application.cfm or cfc that the config folder has in your folders.

I personally would favor locking it down at the Application.cfc level. ANyways, if there is enough backing for this, I can add this to the vanilla Application.cfc templates and if users don’t want it, it can be removed. Ideas suggestsion?

Luis F. Majano
President
Ortus Solutions, Corp

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

Right Louis, exactly. The issue isn't limited to views either, any cfm
can be accessed directly; how it will behave depends on what it does
and how.

I personally think this should either be dealt with by the framework,
best, or documented as something you should think about before going
into production.

What do you think about Den's approach, where the only CF files in the
web root are Application.cfc and index.cfm, and everthing else is in a
'src' directory outside there? That seems to me to be the most
complete solution. Do you see any problems with that? If not, either
just building the default site that way or having an option to do so
when you first create it would be great.

Dave

Very cool Den, definitely the most secure option in general, one
benefit of which is that this whole ColdBox behavior issue just goes
away. I'll be moving the main personal project I'm working on to a
layout like this when I get home. I wondered if that would work.

Totes! =)

Here's a little extended structure, that I've found nice to work with:

project/
  pub/ (covered)
  src/ (covered)
  build/ (scripts for deploying app, etc.)
  docs/ (developer documentation - usually empty =]p)
  tests/ (tests, generally MXUnit)
  conf/ (things like the Apache config - optional)
  lib/ (java libraries - optional)

Only potential hang that occurs to me is access to utilities you cf
module to. I don't use those a lot, and often they're in the same
directory as their callers so just hte filename isneeded, not path.
However, you wouldn't be able to call a general-purpose utility from
everywhere as <cfmodule template="/myapp/utilities/sql/mymodule.cfm">
any more, like you could when it was inside your app. You could create
a mapping to your src directory that would allow that, but that'd
expose the code in any mapped directories to direct requests too I
think. Typically the only time I use cfmodule in recent apps is for

...

On Railo, mappings will be accessible directly to requests, but on ACF
and OpenBD, they are not.

With mappings though, you don't have to worry about the web server
accidentally serving out raw source.

And I really like rewrite rules, which are extremely powerful as far
as request-based access control goes.

...

Also, what do you mean by "if you put your components/sources in
WEB-INF, the application server itself won't be able to accidentally
serve out CFML either"? The CFML engine should never return the
*contents* of a CFML file, just its rendered output, so I don't
understand what circumstances you're thinking about in moving things
into WEB-INF, or in having your real Application.cfc extend on outside
the web root.

The CFML engine runs in a servlet container, which is similar to a web
server in certain aspects- one of which being it has to "know" to
process the files, vs sending them as plain text.

There are two ways you can be sure that your source will "never" be
disclosed. One is to use mappings. Mappings will only work if there
is an active CFML engine. Without an engine, the servlet container
(JRun or Tomcat, etc.) won't know where to get those files from.

The other, is to put your source in the WEB-INF directory. The
servlet container "never" serves assets from within that directory.
There's a blog post somewhere that explains this approach.

A structured way of coding will make either of these approaches
easier, and thankfully, that's what frameworks are good a promoting.
=)

Good stuff.

Thanks!

:Den

Under what circumstances would someone (web or app server) serve the
content of cf pages?

Dave

Are we also forgetting that this is entirely driven by conventions?

Are we also forgetting that you can put the files anywhere defined by your
conventions? Trying to guess this will be harder and would result in people
giving up trying to work that out.

Also when it comes to the Application.cfc, you can put your own logic in
here to secure it more. Like don't process anything none ColdBox and capture
any errors with onError so that things are hidden from the user more. Using
SES more and the IIS / Apache rewrite rules will help even more.

Regards,
Andrew Scott
http://www.andyscott.id.au/

From: coldbox@googlegroups.com [mailto:coldbox@googlegroups.com] On
Behalf Of Dave Merrill
Sent: Tuesday, 9 November 2010 1:17 AM
To: coldbox@googlegroups.com
Subject: Re: [coldbox:6604] Re: ColdBox allows direct access to cfm files
anywhere in your app

@Louis: When I navigate the browser directly to a view cfm, ColdBox

doesn't

process that request, as you say. In most cases, views contain references

to

data in rc, which hasn't been set up, so they'll crash.
For that reason, it probably won't reveal anything it shouldn't, even

though

ColdBox and any security interceptor aren't in play.
   One possible exception to that is hitting a viewlet directly, since as

I

understand it (haven't used them) they're self-contained, calling services

to

get their data themselves; I'm not certain if that would work without

ColdBox

having run in that request. If it does, your security interceptor won't be

in

play, so it's possible people might see things they weren't intended to.

@Aaron: What exactly do you keep in your web-servable app directory?
Clearly non-cf assets (css/js/img/etc) have to be there, but I did wonder

if

you could leave only those, plus Application.cfc and index.cfm, and move
everything else outside the web root. Haven't tried it, may or may not

work

at all, but it would be the most secure option. Do you do anything like

that?

@Mark: It's not that I don't know various ways to lock things down, I was

just

identifying the fact that ColdBox apps are open in this way, and where you
care about that, you should probably address it. It's not a decision

that's

mentioned in the docs, far as I know.

@Rus: I see the behavior I described above to Louis when I use the correct
url to hit a view page directly. I'm on M6.

Big picture, I'm not trying to be critical of ColdBox, I'm loving it more

every

day. I wasn't looking for trouble, ran into this question looking at the

default

Application.cfc code in relation to something else. I'm not saying it's
unsolvable with ColdBox as it is today, just pointing out that this is a

layer of

application design that's not dealt with by the framework, so it's

something

you should consider when you care about this behavior.

IMO, even if it doesn't reveal anything or allow any unintended actions,

it's

unprofessional to have urls in your app that you know will crash. It's

also odd

for ColdBox to process files whose names end in 'index.cfm'
('publicationIndex.cfm' for instance), in any directory, only.

Not trying to be a chicken little, just pointing out what the behavior is,

asking