Rip's Domain

Securing your scheduled tasks

Posted in ColdFusion, Security by rip747 on October 10, 2007

Securing your schedule tasks is probably the last thing on your mind when you launch an application, but it’s something that you might want to consider.

Here is something that I’m running into. I’ve been moving several clients off their shared hosting plans to our VPS. Now during the time they were on the shared hosting plans, they were moved from one shared server to another. In some cases if the client was moved to a new server without us knowing, or to be fair even with us knowing, the scheduled tasks that were created for that client were never deleted from the old server.

As you can see this can cause a problem. In our case we have scheduled tasks that runs every night and send out email notifications, which something I think every developer has done sometime in their carrier. Since the scheduled tasks on the old server was pointing to the domain name, the tasks were firing twice; once on the new server and once on the old. Obviously the clients weren’t too happy about getting two emails. Now this isn’t such a big deal, but you can image the havoc this could cause if the scheduled tasks did something more, like process orders or something.

So how can we prevent this from happening? Well I came up with a way to do this and I thought that it was pretty slick. Before we start though, I will say that I put all my scheduled tasks into their own folder. For the purpose of this post, let’s just say that that folder is called scheduletasks and it’s off the webroot. Also I use the application.cfc.

The first thing to do in our half-ass security to make sure that anything accessing the directory is authorized to do so. What I did was pick a url variable, it could be anything you want, but for now let’s just use secure. So if we wanted to launch our task we would have to set the url of the task property to:

http://www.example.com/scheduletasks/mytasks.cfm?secure

Now to secure this from within application, we can use the onRequestStart method in our application.cfc. Within the onRequestStart we add the following code:

<cfif FindNoCase(“/scheduletasks”, cgi.SCRIPT_NAME) AND NOT StructKeyExists(url, “secure”)>
<cflocation url=”/” addtoken=”No”>
</cfif>

Great! now if anyone is trying to access the task from the url, they will be blocked because they most likely won’t know about the secure variable. But this isn’t going to help the problem that I was having because the old tasks that I setup would have the secure variable already in their configuration. Hmmmmm what to do.

The answer came to me just the other day, why not assign the secure variable a value that’s random for the application! The only problem was what could be random between my application? The answer was the application name itself!

A long time ago I read a post by Raymond Camden that was just the cat’s ass. In the post he used a hash of the directory name of where the application was for the application name itself. It was brilliant! Since then I’ve always used this method so I don’t have to worry about naming my applications. As such all my application names are like so in my application.cfc:

<cfset variables.appname = left(hash(GetDirectoryFromPath(GetCurrentTemplatePath())), 64)>
<cfset this.name = variables.appname>

In order to use our application name for the security of our scheduled tasks, we just have to use the application.applicationname variable. To implement, we change the url property of the schedule tasks to read:

http://www.example.com/scheduletasks/mytasks.cfm?secure=#application.applicationname#

and then change our security inside the onRequestStart method to:

<cfif FindNoCase(“/scheduletasks”, cgi.SCRIPT_NAME) AND NOT StructKeyExists(url, “secure”) and url.secure NEQ application.applicationname>
<cflocation url=”/” addtoken=”No”>
</cfif>

In conclusion here is a striped down version of our application.cfc:

<cfcomponent output=”false”>
<cfset variables.appname = left(hash(GetDirectoryFromPath(GetCurrentTemplatePath())), 64)>
<cfset this.name = variables.appname>

<cffunction name=”onApplicationStart” returnType=”boolean” output=”false”>
<cfargument name=”chapter” type=”string” default=””
hint=”this is the chapter that we want to set as the current”>

<cfschedule action=”UPDATE”
task=”mytasks”
operation=”HTTPRequest”
url=” http://www.example.com/scheduletasks/mytasks.cfm?secure=#application.applicationname#&#8221;
startdate=”#DateFormat(now(), ‘mm/dd/yyyy’)#”
starttime=”11:00:00 PM”
interval=”daily”
resolveurl=”No”
publish=”No”>

<cfreturn true>
</cffunction>

<cffunction name=”onApplicationEnd” returnType=”void” output=”false”>
<cfargument name=”applicationScope” required=”true”>
</cffunction>

<cffunction name=”onRequestStart” returnType=”boolean” output=”false”>
<cfargument name=”thePage” type=”string” required=”true”>

<cfif FindNoCase(“/scheduletasks”, cgi.SCRIPT_NAME) AND NOT StructKeyExists(url, “secure”) and url.secure NEQ application.applicationname>
<cflocation url=”/” addtoken=”No”>
</cfif>

<cfreturn true>
</cffunction>

<cffunction name=”onRequest” returnType=”void”>
<cfargument name=”thePage” type=”string” required=”true”>
<cfinclude template=”#arguments.thePage#”>
</cffunction>

<cffunction name=”onRequestEnd” returnType=”void” output=”false”>
<cfargument name=”thePage” type=”string” required=”true”>
</cffunction>

<cffunction name=”onError” returnType=”void” output=”true”>
<cfargument name=”exception” required=”true”>
<cfargument name=”eventname” type=”string” required=”true”>
</cffunction>

<cffunction name=”onSessionStart” returnType=”void” output=”false”>
</cffunction>

<cffunction name=”onSessionEnd” returnType=”void” output=”false”>
<cfargument name=”sessionScope” type=”struct” required=”true”>
<cfargument name=”appScope” type=”struct” required=”false”>
</cffunction>

</cfcomponent>

Hopefully this will be helpful to someone and if you have a better way, I would love to hear it, so leave a comment.

2 Responses

Subscribe to comments with RSS.

  1. Nolan Dubeau said, on November 26, 2007 at 5:48 pm

    Great Article. So does that mean that when you setup your task in cfadmin, you need to append the hash variable to the scheduled task url? Thx.

  2. rip747 said, on November 27, 2007 at 6:15 am

    @nolan,

    Yep. If you were setting up the scheduled task in cfadmin, make sure that you append the hash to the url. However, if you look at the application.cfc code that I provide in the post, you will see that I’m doing that automatically with the cfschedule tag.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: