Skip to content

Instantly share code, notes, and snippets.

@rip747
Created September 27, 2010 21:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rip747/599828 to your computer and use it in GitHub Desktop.
Save rip747/599828 to your computer and use it in GitHub Desktop.
From 8922990286e83f9d9307d07dbc286b7d4ecb348e Mon Sep 17 00:00:00 2001
From: Tony Petruzzi <tpetruzzi@gmail.com>
Date: Mon, 27 Sep 2010 16:59:40 -0400
Subject: [PATCH] saving work
---
wheels/controller/layouts.cfm | 2 +-
wheels/controller/rendering.cfm | 1 +
wheels/global/appfunctions.cfm | 2 +
wheels/global/cfml.cfm | 18 +++++
wheels/global/functions.cfm | 1 +
wheels/global/sanitize.cfm | 81 ++++++++++++++++++++++++
wheels/tests/_assets/views/test/_xssAttack.cfm | 1 +
wheels/tests/global/sanitize/rendering.cfc | 21 ++++++
wheels/tests/global/sanitize/values.cfc | 34 ++++++++++
9 files changed, 160 insertions(+), 1 deletions(-)
create mode 100644 wheels/global/sanitize.cfm
create mode 100644 wheels/tests/_assets/views/test/_xssAttack.cfm
create mode 100644 wheels/tests/global/sanitize/rendering.cfc
create mode 100644 wheels/tests/global/sanitize/values.cfc
diff --git a/wheels/controller/layouts.cfm b/wheels/controller/layouts.cfm
index 1e897db..54032be 100644
--- a/wheels/controller/layouts.cfm
+++ b/wheels/controller/layouts.cfm
@@ -116,7 +116,7 @@
{
loc.include = loc.include & "/" & "layout.cfm";
}
- loc.returnValue = $includeAndReturnOutput($template=loc.include);
+ loc.returnValue = $includeAndReturnOutput($template=loc.include, $sanitize=true);
}
else
{
diff --git a/wheels/controller/rendering.cfm b/wheels/controller/rendering.cfm
index 1e01bf9..22c82b8 100644
--- a/wheels/controller/rendering.cfm
+++ b/wheels/controller/rendering.cfm
@@ -377,6 +377,7 @@
<cfargument name="$type" type="string" required="true">
<cfscript>
var loc = {};
+ arguments.$sanitize = true;
if (arguments.$type == "partial")
{
if (StructKeyExists(arguments, "query") && IsQuery(arguments.query))
diff --git a/wheels/global/appfunctions.cfm b/wheels/global/appfunctions.cfm
index 1d0949f..4eb6c61 100644
--- a/wheels/global/appfunctions.cfm
+++ b/wheels/global/appfunctions.cfm
@@ -2,10 +2,12 @@
<cfinclude template="cfml.cfm">
<cfinclude template="internal.cfm">
<cfinclude template="public.cfm">
+ <cfinclude template="sanitize.cfm">
<cfinclude template="../../events/functions.cfm">
<cfelse>
<cfinclude template="wheels/global/cfml.cfm">
<cfinclude template="wheels/global/internal.cfm">
<cfinclude template="wheels/global/public.cfm">
+ <cfinclude template="wheels/global/sanitize.cfm">
<cfinclude template="events/functions.cfm">
</cfif>
\ No newline at end of file
diff --git a/wheels/global/cfml.cfm b/wheels/global/cfml.cfm
index 33b4b7b..c48d295 100644
--- a/wheels/global/cfml.cfm
+++ b/wheels/global/cfml.cfm
@@ -129,13 +129,31 @@
<cffunction name="$includeAndReturnOutput" returntype="string" access="public" output="false">
<cfargument name="$template" type="string" required="true">
+ <cfargument name="$sanitize" type="boolean" required="true" default="false">
<cfset var loc = {}>
+
+ <cfset var _orgArguments = "">
+ <cfset var _orgVariables = "">
+
+ <cfif arguments.$sanitize>
+ <cfset _orgArguments = duplicate(arguments)>
+ <cfset _orgVariables = duplicate(variables)>
+ <cfset arguments = sanitize(arguments)>
+ <cfset variables = sanitize(variables)>
+ </cfif>
+
<cfif StructKeyExists(arguments, "$type") AND arguments.$type IS "partial">
<!--- make it so the developer can reference passed in arguments in the loc scope if they prefer --->
<cfset loc = arguments>
</cfif>
+
<!--- we prefix returnValue with "wheels" here to make sure the variable does not get overwritten in the included template --->
<cfsavecontent variable="loc.wheelsReturnValue"><cfoutput><cfinclude template="../../#LCase(arguments.$template)#"></cfoutput></cfsavecontent>
+
+ <cfif arguments.$sanitize>
+ <cfset variables = _orgVariables>
+ </cfif>
+
<cfreturn loc.wheelsReturnValue>
</cffunction>
diff --git a/wheels/global/functions.cfm b/wheels/global/functions.cfm
index 8b0da07..c38ae13 100644
--- a/wheels/global/functions.cfm
+++ b/wheels/global/functions.cfm
@@ -1,4 +1,5 @@
<cfinclude template="cfml.cfm">
<cfinclude template="internal.cfm">
<cfinclude template="public.cfm">
+<cfinclude template="sanitize.cfm">
<cfinclude template="../../events/functions.cfm">
\ No newline at end of file
diff --git a/wheels/global/sanitize.cfm b/wheels/global/sanitize.cfm
new file mode 100644
index 0000000..daf2b84
--- /dev/null
+++ b/wheels/global/sanitize.cfm
@@ -0,0 +1,81 @@
+<cffunction name="sanitize" access="public" returntype="any" output="false">
+ <cfargument name="scope" type="any" required="true">
+ <cfscript>
+ var loc = {};
+ if (IsArray(arguments.scope))
+ {
+ loc.iEnd = ArrayLen(arguments.scope);
+ for (loc.i = 1; loc.i lte loc.iEnd; loc.i++)
+ {
+ try
+ {
+ arguments.scope[loc.i] = sanitize(arguments.scope[loc.i]);
+ }
+ catch(Any e)
+ {
+ $dump(arguments.scope[loc.i]);
+ }
+ }
+ }
+ else if (IsStruct(arguments.scope))
+ {
+ for (loc.item in arguments.scope)
+ {
+ try
+ {
+ if (Left(loc.item, 1) != "$" && !IsCustomFunction(arguments.scope[loc.item]))
+ {
+ //$dump(loc.item);
+ arguments.scope[loc.item] = sanitize(arguments.scope[loc.item]);
+ }
+ }
+ catch(Any e)
+ {
+ $dump(loc.item, false);
+ $dump(arguments.scope);
+ }
+ }
+ }
+ else if (IsQuery(arguments.scope))
+ {
+ arguments.scope = sanitizeQuery(arguments.scope);
+ }
+ if (IsSimpleValue(arguments.scope))
+ {
+ arguments.scope = XMLFormat(arguments.scope);
+ }
+ </cfscript>
+ <cfreturn arguments.scope>
+</cffunction>
+
+<cffunction name="sanitizeQuery" returntype="query" access="public" output="false" hint="Encodes all string values within a query to help protect against cross-site scripting attacks.">
+ <cfargument name="qry" type="query" required="true">
+ <cfscript>
+ var loc = {};
+ loc.stringCols = $getStringColumnsListFromQuery(arguments.qry);
+ for (loc.row=1; loc.row lte arguments.qry.recordcount; loc.row++)
+ {
+ for (loc.i=1; loc.i lte ListLen(loc.stringCols); loc.i++)
+ {
+ loc.columnName = ListGetAt(loc.stringCols, loc.i);
+ QuerySetCell(arguments.qry, loc.columnName, XMLFormat(arguments.qry[loc.columnName][loc.row]), loc.row);
+ }
+ }
+ </cfscript>
+ <cfreturn arguments.qry>
+</cffunction>
+
+<cffunction name="$getStringColumnsListFromQuery" returntype="string" access="public" output="false">
+ <cfargument name="qry" type="query" required="true">
+ <cfscript>
+ var loc = {};
+ loc.returnValue = "";
+ loc.arrMetaData = GetMetaData(arguments.qry);
+ for (loc.i=1; loc.i lte ArrayLen(loc.arrMetaData); loc.i++)
+ {
+ if (ListFindNoCase("char,nchar,varchar,nvarchar,text,ntext", loc.arrMetaData[loc.i].typeName))
+ loc.returnValue = ListAppend(loc.returnValue, loc.arrMetaData[loc.i].name);
+ }
+ </cfscript>
+ <cfreturn loc.returnValue>
+</cffunction>
\ No newline at end of file
diff --git a/wheels/tests/_assets/views/test/_xssAttack.cfm b/wheels/tests/_assets/views/test/_xssAttack.cfm
new file mode 100644
index 0000000..15bee3c
--- /dev/null
+++ b/wheels/tests/_assets/views/test/_xssAttack.cfm
@@ -0,0 +1 @@
+<cfoutput>#params.xss#</cfoutput>
\ No newline at end of file
diff --git a/wheels/tests/global/sanitize/rendering.cfc b/wheels/tests/global/sanitize/rendering.cfc
new file mode 100644
index 0000000..fed90b9
--- /dev/null
+++ b/wheels/tests/global/sanitize/rendering.cfc
@@ -0,0 +1,21 @@
+<cfcomponent extends="wheelsMapping.test">
+
+ <cffunction name="setup">
+ <cfset $$oldViewPath = application.wheels.viewPath>
+ <cfset application.wheels.viewPath = "wheels/tests/_assets/views">
+ <cfset xss = '<script>alert("here");</script>'>
+ </cffunction>
+
+ <cffunction name="teardown">
+ <cfset application.wheels.viewPath = $$oldViewPath>
+ </cffunction>
+
+ <cffunction name="test_rendering_partial">
+ <cfset params = {controller="test", action="test", xss=xss}>
+ <cfset loc.controller = controller(name="test").new(params)>
+ <cfset result = loc.controller.renderPartial(partial="xssAttack")>
+ <cfset loc.e = XMLFormat(xss)>
+ <cfset assert("loc.controller.response() eq loc.e")> --->
+ </cffunction>
+
+</cfcomponent>
\ No newline at end of file
diff --git a/wheels/tests/global/sanitize/values.cfc b/wheels/tests/global/sanitize/values.cfc
new file mode 100644
index 0000000..ad0f824
--- /dev/null
+++ b/wheels/tests/global/sanitize/values.cfc
@@ -0,0 +1,34 @@
+<cfcomponent extends="wheelsMapping.Test">
+
+ <cffunction name="test_nested_params">
+ <cfset loc.a = {}>
+ <cfset loc.a.params = {
+ author = {
+ firstName="tony",
+ lastName="o'connor",
+ profile = {
+ dateOfBirth="10/02/1970 18:01:00",
+ bio="<script>alert(""here"");</script>"
+ }
+ }
+ }
+ >
+ <cfset loc.a = sanitize(loc.a)>
+ <cfset assert('loc.a.params.author.firstname eq "tony"')>
+ <cfset assert('loc.a.params.author.lastname eq XMLFormat("o''connor")')>
+ <cfset assert('loc.a.params.author.profile.bio eq XMLFormat("<script>alert(""here"");</script>")')>
+ </cffunction>
+
+ <cffunction name="test_query">
+ <cfset loc.a = QueryNew("firstname,lastname,bio")>
+ <cfset QueryAddRow(loc.a)>
+ <cfset QuerySetCell(loc.a, "firstname", "tony")>
+ <cfset QuerySetCell(loc.a, "lastname", "o'connor")>
+ <cfset QuerySetCell(loc.a, "bio", "<script>alert(""here"");</script>")>
+ <cfset loc.a = sanitize(loc.a)>
+ <cfset assert('loc.a.firstname[1] eq "tony"')>
+ <cfset assert('loc.a.lastname[1] eq XMLFormat("o''connor")')>
+ <cfset assert('loc.a.bio[1] eq XMLFormat("<script>alert(""here"");</script>")')>
+ </cffunction>
+
+</cfcomponent>
\ No newline at end of file
--
1.6.1.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment