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

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.

Related

ColdFusion adding extensions to names of uploaded files?

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>

testing for html/script injection and getting kicked from a server

In researching an idea I came across a good YouTube video on security (with nodejs) which covered a lot more than the usual SQL injection. One such was simple script and html injection through html encoding. javascript buffers etc.
In researching this for a project I'm working on I came across this script from the php.net documentation website:
<?php
if ($_POST) {
echo '<pre>';
echo htmlspecialchars(print_r($_POST, true));
echo '</pre>';
}
?>
<form action="" method="post">
Name: <input type="text" name="personal[name]" /><br />
Email: <input type="text" name="personal[email]" /><br />
Beer: <br />
<select multiple name="beer[]">
<option value="warthog">Warthog</option>
<option value="guinness">Guinness</option>
<option value="stuttgarter">Stuttgarter Schwabenbräu</option>
</select><br />
<input type="submit" value="submit me!" />
</form>
Looking at the code, I believed the html injection was safe and as I didn't have somewhere to test this script out, I just uploaded it to a hosting domain I have and played with it remotely. When I tried a basic alert injection:
<script>alert("test");</script>
I got an error from the server (a 403 Forbidden). I thought I malformed the html so I tried some minor variations and before I knew it I was banned from my server :D (I was able to reset it, that's not the concern).
Tonight I deployed a VM with apache and php and started playing with it, and when I used the same code, I actually saw what I'd originally expected to see. The array output is presented as expected because of the htmlspecialchars.
Array
(
[personal] => Array
(
[name] => <b>bold</bold>
[email] => <script>alert("test");</script>
)
[beer] => Array
(
[0] => stuttgarter
)
)
What I'd like to know is:
1. Does the browser do some manipulation that nullifies the script tags since there's nothing in the form that does that? My guess is that nothing is an issue until it's attempted to be parsed by the page on form submission. Correct?
2. When I ran it locally the output was as expected (ie, no alert box and correct parsing) which infers that the values are somewhat "safe" until php attempts to parse them via the print_r. If I remove the htmlspecialchars the page fails to load ERR_BLOCKED_BY_XSS_AUDITOR (so that's good). If the original page never parses the raw code, why would the remote server ban my IP if it's correctly escaped within the output code? Again, I'm guessing, but would it be the host is just preemptively trying to prevent attacks and processing all $_POST vars for XSS?

Grails doesn't update data object when a file is included in GSP form?

I'm a Grails newbie, but I thought I was doing ok until I started messing about with file uploads. I'm trying to upload a file to S3 and store the file location in my data object.
My problem is I can upload a file fine, and I can update my data object fine, but for some crazy reason I can't do both at the same time!
Here's the simplified test code:
GSP Form:
<form method="post" url="[resource:fileBundleInstance, action:'test']" enctype="multipart/form-data">
<input type="file" name="bundle">
<g:actionSubmit class="save" action="test" value="Test" />
</form>
Controller:
#Transactional
def test(FileBundle fileBundleInstance) {
def file = request.getFile('bundle')
println file ? "found " + file.originalFilename : "no file"
fileBundleInstance.state = "test" // only works if no file input in form
redirect (action:'edit', id: fileBundleInstance.id)
}
So this code gets the file just fine, but doesn't update the state of the FileBundleInstance. However, if I comment out the file upload form element:
<form method="post" url="[resource:fileBundleInstance, action:'test']" enctype="multipart/form-data">
<!--input type="file" name="bundle"-->
<g:actionSubmit class="save" action="test" value="Test" />
</form>
... suddenly the state gets updated fine (but of course I have no file)!
I suspect I'm fundamentally misunderstanding something here about how GSP forms work in grails - can anyone set me right?
Oops... embarrassingly this is my mistake :-/.
It turns out that the name I was using for my file, 'bundle', was also the name of a field in my data object. Grails was throwing a data exception, and I didn't have good error handling (newbie, remember :-) ).
When I add lines:
fileBundleInstance.save();
fileBundleInstance.errors.allErrors.each {error ->
println error.toString()}
I see my nice shiny error - and if I change the name from 'bundle' to 'myfile' everything works. Oops.

How do I process a form using a CFC in ColdFusion 11?

I am currently creating an engine for a client to submit XML to our web site, and I would like to process the data to a CFC. In order to test this, I have set up a simple form in a regular CFM file, as such...
<!DOCTYPE html>
<html>
<head>
<title>Testing CFC processing</title>
</head>
<body>
<cfsavecontent variable="variables.testxml">
<?xml version="1.0" encoding="UTF-8"?>
<xmlRequest><headers>data</headers><body><Notification><Result Success="1"/><participantID>[ID number]</participantID><transactionNumber>000</transactionNumber></Notification></body></xmlRequest>
</cfsavecontent>
<form method="post" action="[site url]/main.cfc?method=testData">
<cfoutput>
<textarea name="data" cols="150" rows="5">#variables.testxml#</textarea>
</cfoutput>
<br/>
<input type="submit" name="submit" value="Process Test" />
</form>
</body>
</html>
In the main.cfc I have a method called testData which is set up as follows...
remote void function testData(data) {
writeOutput(arguments.data);
}
This test is just to check to see if the method is receiving the data it is sent. When I run it, it does not error, but it also does not output the XML data from the form.
In case it is pertinent, I have the component declared as follows...
component displayname="[name]" accessors="true" output="true"
I can't figure out why the CFC is not receiving the form data (or if it is, why it is not outputting the form data). Can anyone offer any assistance?
I found the answer. It turns out there is no problem with the code above. The problem was in the Application.cfc. I had a method onCFCRequest that didn't have any code in it. It was blocking the CFC from receiving the data. After removing the function from my Application.cfc the method was able to receive the data without issue.

JSP: Encoding of input parameter in form: Difference between IE and Firefox

i have a JSP with
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
in the head section, with following code i try to set the content to UTF-8:
<%#page contentType="text/html;charset=utf-8" %>
response.setCharacterEncoding("UTF-8");
request.setCharacterEncoding("UTF-8");
Within a form is an input field:
<input type="text" value="LastName*" class="input required" name="lastName" id="lastName" />
I have now problems with german special characters.
When i use request.getParameter("lastName"), this works fine in FireFox, but not in IE.
String encodedLastName = new String(request.getParameter("lastName").getBytes("iso-8859-1"), "UTF-8");
works on IE, but not in Firefox.
I tried to change everything to iso-8859-1, added accept-charset="UTF-8" to the form, ...
Now it is more guessing than working.
Can this only configured within the server (Tomcat) but why there is a difference between the behaviour of the browsers?
Thank, Markus
There were two problems which interfere with each other:
1) When using a normal post, i have to encode correct via
<%#page contentType="text/html;charset=utf-8" %>
and decode correct via
String encodedLastName = new String(request.getParameter("lastName").getBytes("iso-8859-1"), "UTF-8");
2) When using jquery, adding
contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
in the $.ajax call.