"Invalid padding" exception in ColdFusion encrypt/decrypt - coldfusion

my code throws an exception I can't understand. I'm still new in programming so bear with me. This is my code:
<cfsetting showdebugoutput="false">
<cfprocessingdirective pageencoding="utf-8">
<html>
<head>
<title>Test</title>
</head>
<body>
<cfset key = generateSecretKey("AES")>
<cfscript>
if (isDefined("form")) {
encFieldnamesArr = listToArray(form.fieldnames);
decFieldnamesArr = arrayNew(1);
for (paramName in encFieldnamesArr) {
arrayAppend(decFieldnamesArr, "#decrypt(paramName, key, 'AES', 'HEX')#");
}
}
</cfscript>
<cfform>
<cfinput name="#encrypt("firstName", key, "AES", "HEX")#" type="text" />
<cfinput name="#encrypt("lastName", key, "AES", "HEX")#" type="text" />
<cfinput type="submit" name="#encrypt("action", key, "AES", "HEX")#" value="submit" />
</cfform>
</body>
</html>
It throws this exception:
An error occurred while trying to encrypt or decrypt your input string: Invalid padding..
The error occurred in C:/ColdFusion11/cfusion/wwwroot/test/index.cfm: line 17
15 :
16 : for (paramName in encFieldnamesArr) {
17 : arrayAppend(decFieldnamesArr, "#decrypt(paramName, key, 'AES', 'HEX')#");
18 : }
19 : }
What does "invalid padding" mean? Thanks

When decrypting, you have to use the exact same key used to encrypt the value. Your code is generating a totally new key every time the page loads:
<cfset key = generateSecretKey("AES")>
So the code is using one key to encrypt. Then when the form is submitted, it uses a completely different key to decrypt(). Hence the error.
Example:
<cfscript>
// WORKS: encrypt and decrypt with the same key
key = generateSecretKey("AES");
text = "the quick brown fox jumps over the lazy dog";
encrypted = encrypt(text, key, 'AES', 'HEX');
decrypted = decrypt(encrypted, key, 'AES', 'HEX');
writeOutput("<br>text="& text);
writeOutput("<br>key="& key);
writeOutput("<br>encrypted="& encrypted);
writeOutput("<br>decrypted="& decrypted);
// FAILS: Decrypting with a *different* key will fail
key = generateSecretKey("AES");
writeOutput("<br>key="& key);
decrypted = decrypt(encrypted, key, 'AES', 'HEX');
</cfscript>
I realize the above is just an experiment, but a few tips:
FORM is a system structure, so it should always be defined. Typically you would check for the existence of a specific form field name instead. ie
structKeyExists(FORM, "someFieldName")
Since you are not using any of the extra features of cfform/cfinput (which are not great anyway), just use plain a html <form> and <input> tags. Using the CF versions will cause CF to add a lot of unnecessary javascript code to your page.
No need for double quotes or # signs around the decrypt. Just use:
decrypt(paramName, key, 'AES', 'HEX')

Related

ColdFusion CSRF XSS attack prevention

I have implemented the csrfGenerateToken and csrfVerifyToken functions in trying the prevent a CSRF attack.
I have set up the webpage header with these:
set X-XSS-Protection "1; mode=block"
always set X-Frame-Options SAMEORIGIN
X-Content-Type-Options nosniff
Strict-Transport-Security "max-age=63072000" env=HTTPS
I have done some research and proceed as recommended by Adobe doing something like this:
<cfset tokenVar = 't' & lCase( hash( createUUID() & randRange( 1000, 100000 ), 'MD5', 'UTF-8', 250 ) )>
<form action="updateprofile.cfm" method="post">
<input type="hidden" name="f#hash( 'tokenVar', 'SHA-256', 'UTF-8')#" value="#tokenVar#">
<input type="hidden" name="f#hash( 'formToken', 'SHA-256', 'UTF-8')#" value="#csrfGenerateToken( tokenVar, true )#">
<input type="text" name="emailAddress" value="#EmailAddress#">
<input type="text" name="phoneNumber" value="#PhoneNumber#">
<input type="submit" name="btnSubmit" value="Change Profile Info">
</form>
Updateprofile.cfm would have:
<cfparam name="FORM[ 'f' & hash( 'tokenVar', 'SHA-256', 'UTF-8')]" default="0">
<cfparam name="FORM[ 'f' & hash( 'formToken', 'SHA-256', 'UTF-8')]" default="0">
<cfif not csrfVerifyToken( FORM[ 'f' & hash( 'formToken', 'SHA-256', 'UTF-8')], FORM[ 'f' & hash( 'tokenVar', 'SHA-256', 'UTF-8')] )>
<!--- CSRF attack. Clear cookies and kick user out --->
<cfinclude template="clearcookies.cfm">
<cflocation url="signin.htm" addToken = "no">
</cfif>
This will work if 2 accounts are signed in on the same browsers and if one tries to update the other. However, when I simply saved a copy of the resulting html from one of them and save it as csrf-attack.htm locally:
<html><body>
<script>history.pushState('', '', '/')</script>
<form action="http://www.exsample.com/updateprofile.cfm" method="post">
<input type="hidden" name="f41BE6B4E09CBA69BDB76DBB69B493E8D49F5DD9ED230085913397B4C751D4E60" value="t93315a7c3ecb43d4d1b9422da97ffb09">
<input type="hidden" name="f08DFC2607D4119D7B16B4C01DC5C00F54B044DC937257ABC411F9A7E55BB4191" value="A0EED67C55F5E17683E2E1B21FF3454FE690E0B1">
<input type="text" name="emailAddress" value="test#test.com">
<input type="text" name="phoneNumber" value="1-222-3333">
<input type="submit" name="btnSubmit" value="Change Profile Info">
</form>
</body><html>
I processed the original form to update the phone number to 1-333-4444. Then I came back to the form again. At this time a new CSRFToken should have been created because ForceNew was set to true.
Then I go to the static HTML page that I have saved, and simply changed the value of the email address to test2#test.com instead of test#test.com with the old token, then clicked the "Change Profile Info" button, I was able to update it to the site!!
Am I doing something wrong or is it how it works? It seems that the token is useless if I can simply copy the token values and manipulate the content, then post it. How can I mitigate issue like this on the receiving page?
Thanks in advance.
The csrfVerifyToken result will still pass until you generate another CSRF token with the same key, at that point it will get invalidated. So if you are making single use tokens then you need to invalidate the old token by calling csrfGenerateToken with the same tokenVar after you call csrfVerifyToken
I wrote up a blog entry with a code example to illustrate this: https://www.petefreitag.com/item/856.cfm
Jack, 2 points:
First, things will seem to "not protect anything" if your requests (including that html page) are made from the same browser, thus using the same session cookies for the site, thus using the same cf session.
The generated token is saved in the cf session for that user/browser (saved in a way not visible with a cfdump of the session). And the verify is then checking the passed-in token against that. But if you run the "other" code in another browser, it would NOT share the same session (unless you also copied in the user's cookies).
Second, even if you did duplicate the session cookies, the value in that csrf token field (simulating being grabbed by the bad guy who saw the form and "copied it off" to that other page) will be the value that was created when THEY did that...not the value that a real user would have in their session if they'd been to the page that did the csrfgeneratetoken. So the tokens won't match.
Make sense? It's easy to misconstrue what this is does and does not do, and just as easy to get tripped up setting up a demo prove if it "works", if you don't keep all this in mind.
And I may be lacking in my answer, so am open to comments and criticism.

ColdFusion Dropbox - How to get the token from the response URI

I am trying to implement the OAuth with Dropbox from a ColdFusion application, and I managed how to call the Dropbox method to generate the access token, but... I don't know how to get the generated TOKEN from the response URI. I am getting something like this from Dropbox:
http://localhost/dropbox/generate_token.cfm#access_token=AAAAAAAAYVM_XdCYlbTz0gQOwQkWlg6TDXf84_5h4giikg6J-7Man&token_type=bearer&uid=267693&account_id=dbid%3AAABeDMm-BN0n1DofLZz9kPZAipnQ
How to I retrieve the URL variables in this case? I mean if I do a
<cfdump var="#URL#">
I am getting an empty struct. If I do a
<cfdump var="#CGI#">
I still don't see any of the URL retrieved parameters in the structure. How do I get the variables and their values from the Dropbox response?
UPDATED
At some point I thought I found a way to read the URL but now - for no reason - this doesn't work anymore! I didn't change anything but the solution below doesn't work anymore.
I can read the full URL with JavaScript using document.location but this means to do an extra submit to a ColdFusion page and I don't want to do this. I want to get the Dropbox token from the URL and save it to the database directly in this page...
Any new ideas please?
SOLUTION THAT SEEMED TO WORK AT SOME POINT ...
I found a way to get the URI string using this:
<cfset objRequest = GetPageContext().GetRequest().getParameterMap() />
<cfdump var="#objRequest#">
<cfoutput>
<cfloop collection="#objRequest#" item="i">
<p>
#i# - #objRequest[i][1]#
</p>
</cfloop>
</cfoutput>
From now on, I know how to get the values returned by Dropbox.
I found a way to get the returned parameters by reading the browser URL with JavaScript, so in two steps: first, parse and extract the full URL including the part after the # sign (I found this has a name and it is called the "URL fragment") and second, create a JavaScript form with parsed parameters and resubmitted to the server. Here is the code:
<cfparam name="FORM.action" default="">
<cfif FORM.action IS "save_token">
<cfdump var="#FORM#">
<cfelse>
<form name="main" id="main" method="post">
<input type="hidden" name="action" id="action" value="save_token">
</form>
<script type="text/javascript" language="javascript">
<!--
var parameters = window.location.hash.substr(1).split("&");
function addHidden(theForm, key, value) {
// Create a hidden input element, and append it to the form:
var input = document.createElement("input");
input.type = "hidden";
input.name = key;
input.value = value;
theForm.appendChild(input);
}
// Form reference:
var theForm = document.forms["main"];
for (var i=0; i<parameters.length; i++) {
// Add data:
addHidden(theForm, parameters[i].split("=")[0], parameters[i].split("=")[1]);
}
theForm.submit();
//-->
</script>
</cfif>

Encrypt & Decrypt credit card using coldfusion?

Is there any way to encrypt & decrypt credit card details with custom key using ColdFusion?
I have tried with JAVA file (Should i post the code?).
there is the code in which am getting error.
<cfdump var="#CreateObject('JAVA','StrongAES')#"><cfabort>
I am getting Server Error 500
Thanks
You can use encrypt and decrypt methods to perform encryption and decryption. You can either user generate secret key or use your custom key to do that.
Here is what i will do.
<!--- To generate secret key (you can also use your custom key) --->
<cfset secretKey = generateSecretKey("AES") />
<!--- to encrypt --->
<cfset encryptedDetails = encrypt(cardDetails, secretKey , "AES/CBC/PKCS5Padding", "HEX") />
<!--- to decrypt --->
<cfset cardDetails= decrypt(encryptedDetails , secretKey , "AES/CBC/PKCS5Padding", "HEX") />
For more details see Encrypt and decrypt

How to show custom message when somebody clicks on refresh button of Coldfusion cfGrid (When session is out)?

I am using Coldfusion (9.0.1) cfGrid to populate some data. Code is given below
<cfform id="ViewNewCustomerReport" name="ViewNewCustomerReport">
<div class="buttonClass">
<cfinput type="button" id="generateReport" name="generateReport"
value="Generate Report" />
<cfinput type="hidden" name="filters" id="filters"
bind="javascript:GenerateReport({generateReport#click})"/>
</div>
<br/>
<div id="gridContainer">
<cfgrid name="NewCustomerReport" autoWidth="Yes" colheaderbold="true" selectonload="false" width="710"
bind="url:index.cfm?fuseaction=ReportsCommon.GetNewCustomerReport&page={cfgridpage}&pagesize={cfgridpagesize}&gridsortcolumn={cfgridsortcolumn}&gridsortDirection={cfgridsortdirection}&filter={filters}"
bindOnLoad="false" striperows="true" striperowcolor="##F6F6F6" format="html" pagesize="10">
<cfgridcolumn name="COMPANY_NAME" width="280" header="Company Name" />
<cfgridcolumn name="SUBJECT_ASSIGNED" width="280" header="Subject Assigned" />
<cfgridcolumn name="NO_OF_USERS" header="No. Of users" width="180" />
</cfgrid>
</div>
<div id="wrapperDiv"><label id="lblError" class="CustomError"></label></div>
</cfform>
And this is the javascript part
var GenerateReport = function(filters){
var returnVal;
var checkForm = $('#ViewNewCustomerReport').validationEngine('validate');
returnVal = dateFrom + '|' + dateTo;
if(checkForm)
{
var gridObject = ColdFusion.Grid.getGridObject("NewCustomerReport");
var store = gridObject.getStore();
store.addListener("load",function(){
if(store.data.items == 0)
{
gridObject.setVisible(false);
$("#gridContainer").hide();
$("#wrapperDiv").show();
$("#wrapperDiv").css("text-align","center");
$("#lblError").text("No record found").css({"font-size":"20px","font-weight":"normal"});
}
else
{
gridObject.setVisible(true);
$("#gridContainer").show();
$("#wrapperDiv").hide();
}
});
}
else
{
$('#gridContainer').hide();
}
return returnVal;
};
Now if somebody logout the application in another tab and then refreshes the Grid it show some message like
CFGRID: TOTALROWCOUNT missing from response data [Enable debugging by adding 'cfdebug' to your URL parameters to see more information]
When Session is out in return the Json data collected is like that
{"isSessionOut":true} HTTP Status code 200 HTTP status Message OK
So my Question is instead of showing that default error message i want to show my custom message like session is out please log in to continue.
how can these be achieved ?? Thanks in advance ......
Every bind operation/Ajax call in coldfusion has an OnError/BindError handler function, which can be called at the time of some error, or we can call it with the help of HTTP response by setting the HTTP status code.
Whenever you want some
self generated error message, you can write this code at response/Action page of your site:
error = getpagecontext().getresponse().setstatus(306, "Your session is out");
(you can set HTTP status code any thing more then 300 but i have checked only for 306 and it works)
by this you can call onError function of your CFGRID
I would use a jQuery or similar plugin that runs in the outer page and detects inactivity, then it can even count down when session is timing out and gracefully take your user back to a login page. This way you wont have this issue on any page.
This one is good, there are many others also
jsFiddle

use a startdate on a <cfinput type= "datefield"> in ColdFusion

I am using the <cfinput type="datefield"> and I need to limit the dates that can be chosen. I cannot allow a date that can be selected in the past. Any help here?
Thanks!
Well you have two options validating it strictly server side or additionally adding a client side javascript check.
For the serverside, your cfm processing page could use the DateCompare function like so:
<cfif DateCompare(Date1,Date2) EQUAL -1>
<!--- Date 1 < Date 2 --->
<cfelseif DateCompare(Date1,Date2) EQUAL 0>
<!--- Date 1 = Date 2 --->
<cfelseif DateCompare(Date1,Date2) EQUAL 1>
<!--- Date 1 > Date 2 --->
</cfif>
Documentation and sample code is available for this function at:
http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=functions_m-r_11.html
Another post suggested using the range functionality, however I was not able to get this to work because the Adobe documentation said it was only supported on type numeric.
Alternatively you can use javascript to check if the date is within range live on the page:
<html>
<head>
<script type="text/javascript">
function withinRange(submittedDate) {
var start = Date.parse("08/10/2009");
var end = Date.parse("09/11/2009");
var userDate = Date.parse(document.getElementById('leaveDate').value);
var previousDate = document.getElementById('calendarWorkaround').value;
if (!isNaN(userDate) && ( previousDate != userDate)) {
document.getElementById('calendarWorkaround').value = userDate;
if (start <= userDate && end >= userDate) {
alert("Your date is correct!");
} else {
alert("Date is incorrect.");
}
}
}
</script>
</head>
<body>
<cfform name="testing" id="vacationForm"action="testprocess">
<cfinput name="date" type="datefield" id="leaveDate">
<input type="hidden" name="workaround" id="calendarWorkaround" value="-1">
</cfform>
<!--- To get around onChange bug with cfinput type datefield --->
<cfajaxproxy bind="javaScript:withinRange({leaveDate})">
</body>
</html>
Now I would use the onChange attribute for cfinput on the datefield, however there is a bug that it does not call the javascript function that seems to be documented on a couple of other pages online. The workaround that I used was the cfajaxproxy call with the bind attribute. If you are using cfeclipse, it will give you an error that the syntax is not correct however it worked fine for me.
The hidden input type is necessary because with the cfajaxproxy tag, everytime you click the calendar icon it will call the javascript function which is not what we want. So I store the last value chosen by the user (or -1 on page load) so that the javascript to check if it is within range is only executed if the value changes. It is a bit of a hack, however the implementation of <cfinput type="datefield"> does not work as documented.
You can also modify this example so that coldfusion dynamical generates the start date and end date so it is not hard coded.
Just remember that whichever way you choose, you should always check the value server side just in case the user has javascript disabled.
Try this:
Three datefields.
One is hidden by the hieght = 0. It is your starting point. I used today plus one so the user can select today in the Date Requested field.
<cfformgroup type="horizontal" height="0">
<cfinput type="datefield" name="firstAvailableDate" value="#dateAdd('d', +1,now())#"
</cfformgroup>
The requested date will be only today or before.
<cfformgroup type="horizontal">
<cfinput type="datefield" name="request_date" id="request_date" mask="mm/dd/yyyy" width="100" label=”Date Requested” onFocus="request_date.disabledRanges=[{rangeStart:firstAvailableDate.selectedDate}];" />
The Due Date can only be after the requested date selected.
<cfinput type="datefield" name="datedue" id="datedue" mask="mm/dd/yyyy" width="100" label=”Due Date” onFocus="datedue.disabledRanges=[{rangeEnd:request_date.selectedDate}];" />
</cfformgroup type="horizontal" >
AFAIK, there is no easy way to prevent the client from picking a day in the past. We have fields like that on a few of our forms that we check against the current date on the server side, though. Just remember to generate the date without the time for comparison, or you end up with [today's date] < now().
At first, I thought <cfcalendar> would help, but seems like the startrage and endrange is for disabled range.
I guess if you Really want to limit the range, use something else like jQuery UI Datepicker
Through experimentation, I was able to customize the supporting javascript files to restrict the selectable dates. However the jQuery option sounds good as well.
I just added 100 years on to the endrange attribute for the cfcalendar component, thinking no one will sit and click through that far to beat your validation :
<cfset startRange = #dateformat(now(), 'dd/mm/yyyy')# >
<cfset endRange = dateadd("yyyy", 100, #Now()#)>
<cfset selectedDate = dateadd("d", -1, #Now()#)>
<cfcalendar name="start_period" mask="dd/mm/yyyy" selecteddate="#selectedDate#" startRange="#startRange#" endrange="#endRange#">
Simon.
You can't make a datefield limit the dates that can be chosen. CFINPUT doesn't have any attribute to define this type of rule. You have to go for Jquery datepicker. If you want to use cfinput, you can work around that.
<script language="JavaScript">
$(function() {
$( "#date" ).datepicker({
changeMonth: true,
changeYear: true,
minDate: new Date(1939, 10 - 1, 25),
maxDate: '-1D'
});
});
</script>
<cfinput name="date" type="text" size="30" id="date" >
You should use server side validation as well, but I believe you can use the "range" attribute of cfinput to limit the valid dates.