Blog

Brad Wood

December 08, 2020

Spread the word


Share your thoughts

CommandBox 5.2.0 added a new feature called Server Profiles which allow you to dial in a bevy of development or production lockdown rules in a single setting.  Each profile can be tweaked with individual settings to customize them.

https://commandbox.ortusbooks.com/embedded-server/configuring-your-server/server-profiles#customizing-your-profile

{
  "profile": "production"
  "web": {
    "blockCFAdmin": false
  }
}

Override parts of a default lockdown

However, what if you want to go one step deeper?  For instance, the "blockSensitivePaths" setting blocks a whole bunch of stuff all in one shot.  Turning on web.blockSensitivePaths is the same as adding all of these individual rules:

// track and trace verbs can leak data in XSS attacks
"disallowed-methods( methods={trace,track} )",
// Common config files and sensitive paths in ACF and TestBox
"regex( pattern='.*/(box.json|server.json|web.config|urlrewrite.xml|package.json|package-lock.json|Gulpfile.js|CFIDE/multiservermonitor-access-policy.xml|CFIDE/probe.cfm|CFIDE/main/ide.cfm|tests/runner.cfm|testbox/system/runners/HTMLRunner.cfm)', case-sensitive=false ) -> { set-error(404); done }",
// Any file or folder starting with a period
"regex('/\.') -> { set-error( 404 ); done }",
// Additional serlvlet mappings in Adobe CF's web.xml
"path-prefix( { '/JSDebugServlet','/securityanalyzer','/WSRPProducer' } ) -> { set-error( 404 ); done }",
// java web service (Axis) files
"regex( pattern='\.jws$', case-sensitive=false ) -> { set-error( 404 ); done }"

I had a question from a client today who wants to keep the blockSensitivePaths setting active for his servers, but also wanted to open up JUST the RDS IDE integration for his developers, which funnels through the /CFIDE/main/ide.cfm path which you can see is blocked above.

Order of Server Rule Execution

The solution to this is quite simple and is all based on the ORDER in which your rules are processed as documented here:

https://commandbox.ortusbooks.com/embedded-server/configuring-your-server/server-rules#create-your-rules

  1. Ad-hoc rule array in server.json
  2. External rules files in server.json in the order defined
  3. Ad-hoc rule array in config setting server.defaults
  4. External rules files in config setting server.defaults in the order defined
  5. CommandBox built-in rules (web.blockCFAdmin, web.blockConfigPaths)
  6. Any module listening to server interceptions can inject their rules wherever they please in the array.

You can see that the built-in CommadBox rules are the last to process.  This means that if you highjack the predicates with a custom rule FIRST, you can override the behavior of the built in rules. 

Add a Custom Server Rule

So, if we want to allow access to the /CFIDE/main/ide.cfm path, we just need to add a custom rule that matches that path and then aborts the predicate chain so no further rules fire.  

server set web.rules="['path(/CFIDE/main/ide.cfm)->done']" --append

Which gives you the following server.json

{
    "web":{
        "rules":[
            "path(/CFIDE/main/ide.cfm)->done"
        ]
    }
}

The "done" handler is what bypasses all subsequent rules for the request.  Read more about how server rules work here:

https://commandbox.ortusbooks.com/embedded-server/configuring-your-server/server-rules/rule-language

And a fair warning-- since your custom rules are processed BEFORE the built-in rules, that also means that you have the ability to accidentally bypass security rules by applying another rule that intercepts the request.  By default a custom rule won't block subsequent rules from firing unless you rewrite the request or use the special "done" handler.

Debugging Server Rules

And to test/debug your rules, start your server with the trace flag and tail the console output.  Every hit in your browser will output several lines of debugging for each rule that is processed.

server start --trace --console

With the custom rule above, you'd see something like this:

[DEBUG] requested: '/CFIDE/main/ide.cfm'
[TRACE] io.undertow.predicate: Path(s) [/CFIDE/main/ide.cfm] MATCH input [/CFIDE/main/ide.cfm] for HttpServerExchange{ GET /CFIDE/main/ide.cfm}.
[TRACE] io.undertow.predicate: Predicate [path( '/CFIDE/main/ide.cfm' )] resolved to true. Next handler is [done] for HttpServerExchange{ GET /CFIDE/main/ide.cfm}.
[TRACE] io.undertow.predicate: Predicate chain marked done. Next handler is [Runwar PathHandler] for HttpServerExchange{ GET /CFIDE/main/ide.cfm}.
[WARN ] responded: Status Code 200 (/CFIDE/main/ide.cfm)

 

Add Your Comment

Recent Entries

Are you attending Adobe CFSummit 2024?

Are you attending Adobe CFSummit 2024?

If you are attending the Adobe ColdFusion Summit 2024, this is what you need to know: As always, Ortus Solutions will be sponsoring this years event as Silver Sponsors, we are excited to meet all the new attendees and old friends of the community of Coldfusion developers

Maria Jose Herrera
Maria Jose Herrera
September 10, 2024
New BoxLang Feature: Functional binding to member methods

New BoxLang Feature: Functional binding to member methods

We’re excited to unveil a new feature that makes method referencing in BoxLang even smoother. Building on our recent update introducing functional static binding to built-in functions, we're now bringing the same ease to member methods.

Maria Jose Herrera
Maria Jose Herrera
September 09, 2024