Encoding E-Mail Addresses: EncodeForHTML or EncodeForURL - coldfusion

When a user registers on a site, should we use EncodeForHTML() or EncodeForURL() before storing the value in a DB?
The reason I ask this is that when I send an e-mail to someone that includes a URL that contains an email address as a URL variable, I have to use EncodeForURL(). But if this email address is already encoded using EncodeForHTML(), it will mean I have to Canonicalize() it before using EncodeForURL() on it again.
I would therefore think that EncodeForURL() is probably good, but is it 'safe' and 'correct' when storing the value in a database?
Update: Upon reading the docs it says that EncodeForURL is only for using a value in a URL. Thereofore it seems to make sense that I should store it as EncodedForHTML, but then Canonicalize and re-encode for URL when using it in a URL context. I don't know how much of a performance hit all this encoding is going to take on my server...??

Copying this from my company's internal documentation. Not sure if the images uploaded correctly since imagr is blocked # work. If so, I'll re-upload them later. I'll be publishing this and more related content to a Githib repo in the future.
You should store it as simple text, but make sure you scrub your data on the way in using an AntiSamy library. Once the data is safe, make sure to encode the data on the way out using the proper encoder. And FYI, there's a big difference between the output of encodeForHTML() and encodeForHTMLAttribute().
In the below examples, substitute the variables that define email addresses with data from the DB.
PROTIP: Don't use these encoders in CFFORM tags. Those tags take care of the encoding for you. CF 9 and below use HTMLEditFormat(), CF 10 and above most likely use encodeForHTMLAttribute().
Simple Implementation
A basic implementation is to include a single e-mail address in order to populate the "To" field of a new e-mail window.
CFML
<cfset email = "someone#example.com" />
E-mail
HTML Output
E-mail
CFML with Proper Encoding
<cfset email = "someone#example.com" />
E-mail
Encoded HTML Output
Notice that the "#" symbol is properly percent encoded as "%40".
E-mail
Results when clicked
And if you plan on showing the e-mail address on the page as part of the link:
<cfset email = "someone#example.com" />
#encodeForHTML(email)#
Attack Vector
An advanced implementation includes e-mail addresses for "To" & "CC". It can also pre-populate the body and subject of the new e-mail.
CFML without encoding
<cfset email = "someone#example.com" />
<cfset email_cc = "someone_else#example.com" />
<cfset subject = "This is the subject" />
<cfset body = "This is the body" />
E-mail
HTML Output
E-mail
Results when clicked
Notice that the subject and body parameters contain spaces. While this string will technically work, it is still prone to attack vectors.
Imagine the value of body is set by the result of a database query. This record has been "infected" by a malicious user and the default body message has an appended "BCC" address, so some evil user can get copies of e-mails sent via this link.
Infected Data
<cfset body = "This is the body&bcc=someone#evil.com" />
HTML Output
E-mail
Results when clicked
In order to stop this MAILTO link from being infected, this string needs to be properly encoded.
CFML with HTML Attribute Encoding
Since "href" is an attribute of the <a> tag, you might think to use the HTML Attribute encoder. This would be incorrect.
<cfset email = "someone#example.com" />
<cfset email_cc = "someone_else#example.com" />
<cfset subject = "This is the subject" />
<cfset body = "This is the body&bcc=someone#evil.com" />
E-mail
HTML Output
E-mail
Results when clicked
CFML with URL Encoding
The correct encoding of a MAILTO link is done with the URL encoder.
<cfset email = "someone#example.com" />
<cfset email_cc = "someone_else#example.com" />
<cfset subject = "This is the subject" />
<cfset body = "This is the body&bcc=someone#evil.com" />
E-mail
HTML Output with Correct Encoding
Notice these things about the URL encoder:
Each space (" ") is converted to a plus sign ("+") instead of its expected percent value ("%20").
Encoding is otherwise done using percent ("%") values.
Since the individual query paramters are encoded, the ampersands ("&") connecting each paramter were not encoded.
When the "body" paramter is encoded, it includes the "&body=" string that was maliciously injected. This entire string is now part of the message body, which prevents the unintended "bcc" of the e-mail.
E-mail
Results when clicked
What's with the plus signs? It is up to the individual mail client (e.g. Outlook, GMail, etc.) to correctly decode these URL encoded values.

Store the email addresses in plain text, then encode them when you use them, depending on the context. If it's going to be a part of URL, use EncodeForURL(). If it's going to be displayed in HTML as text, use EncodeForHtml().

Related

reCaptcha v3 with ColdFusion

I'm trying to integrate reCaptcha (v3) to a ColdFusion site. I'm not too hot on the CF syntax and currently I'm seemingly getting nothing back from the verify request on the server side.
Can anyone see anything obviously wrong and/or point me in the right direction please?
Client Side:
<script src='https://www.google.com/recaptcha/api.js?render=6..."></script>
<script>
grecaptcha.ready(function() {
grecaptcha.execute('6...', {action: 'contact'})
.then(function(token) {
$("#recaptchaToken").val(token);
});
});
</script>
I've got a hidden field recaptchaToken in my form and I can see the token value going in to it.
Server Side:
<cfhttp
url="https://www.google.com/recaptcha/api/siteverify"
method="POST"
result="captchaResponse">
<cfhttpparam
type="formfield"
name="secret"
value='6...'
/>
<cfhttpparam
type="formfield"
name="response"
value='#form.recaptchaToken#'
/>
</cfhttp>
<cfdump var=#captchaResponse.filecontent# />
I'm getting a red box output titled object of java.io.ByteArrayOutputStream
I've tried to dump both captchaResponse and captchaResponse.filecontent to no avail.
I'm expecting data in the form of:
{
"success": true|false, // whether this request was a valid reCAPTCHA token for your site
"score": number // the score for this request (0.0 - 1.0)
"action": string // the action name for this request (important to verify)
"challenge_ts": timestamp, // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)
"hostname": string, // the hostname of the site where the reCAPTCHA was solved
"error-codes": [...] // optional
}
Update
The solution seems to be as Alex suggested below:
<cfdump var=#toString(captchaResponse.filecontent)# />
This gives me a JSON string in the format expected so I can convert this to an object and complete the verification.
Whenever cfhttp is not sure how to treat a response, the raw content stays untouched and is kept as Byte array. This usually indicates that the Content-Type header is not specified by the responding server or the content was only partially retrieved.
To force a string representation of the content, you can use toString() to convert the raw Byte array, e.g. toString(captchaResponse.filecontent). The function is quite robust and can also handle already converted strings, so it is usually safe to use.
However, there is something else to be aware of here. When using cfhttp without setting the throwOnError attribute to true (the default value is false), failed HTTP requests will still return a result, a crippled result. The struct will not contain the fileContent key and thus cause an exception at runtime. You might want to add error handling here, in case https://www.google.com/recaptcha/api/siteverify is not reachable or the accepted TLS protocol is not supported by your JRE. We had this issue with SNI and TLS 1.2 with a former version of ColdFusion, namely 8. Be warned.

Why does cflocation strip characters and not visit the URL?

I have a URL stored as:
<cfset VisitURL = 'http://www.toysexample.com/search.aspx?searchBox=christmasgifts≠Sort=high&search=new' />
(The above URL string actually comes from a database field that I have no control over)
When I ask cflocation to visit the above URL like this:
<cflocation url="#EncodeForURL(VisitURL)#" addtoken="no" />
It visits the URL as a subfolder within my site. So I end up going to the URL http://www.volumeoneexample.com/http:/www.toysexample.com/search.aspx?searchBox=christmasgifts≠Sort=high&search=new
As you can see it has dropped one of the forward-slashes from the http:// part and also appended the URL as a folder within my site. I don't get why its doing this?
As mentioned in the comments, you're "over encoding". The EncodeForURL() should only be on the URL parameters.
Since you're not able to retrieve the URL and parameters separately, you might be able to get away with treating them like a list.
<cflocation url="#ListFirst(VisitURL,"?")#?#EncodeForURL(ListRest(VisitURL,"?"))#" />
If things get a little wonky you'll need to do more manipulation than that.

CFMail sending to first recipient of query result only

When attempting to send an email to multiple recipients using ColdFusion, only the first row is receiving the email and it seems to be hit three times but only sending once. This works but all recipients are visible and the cfoutput is displayed as many times are there are recipients:
<cfmail
to = "#ValueList(getEmail.Schd_Email)#"
from="test#test.edu"
subject="This is a Test"
type="HTML"
query="getEmail"
failto="test#test.com">
The location has been moved to <b><cfoutput>#location#</cfoutput></b><br/>
</cfmail>
This only sends to the first person listed in the query and the cfoutput in the body is still listed as many times as there are recipients.
<cfmail
to = "#Schd_Email#;"
from="test#test.edu"
subject="This is a Test"
type="HTML"
query="getEmail"
failto="test#test.com">
The location has been moved to <b><cfoutput>#location#</cfoutput></b><br/>
</cfmail>
I can output the query to the page and see all emails listed. Not sure why the latter does not work. Any ideas?
I think you should use ';' delimiter in valueList(). the default delimiter for valueList() is ','. If you pass delimiter ';' it might work.
Try this one #ValueList(getEmail.Schd_Email,";")#
Since you are using the query attribute of the cfmail tag you do not need to use the ValueList() function. The query attribute handles that functionality for you. It also negates the need for using a delimeter between each of the "to" addressees. It should work like this assuming you have valid email addresses in your query results.
<cfmail
to="#getEmail.Schd_Email#"
from="test#test.edu"
subject="This is a Test"
type="HTML"
query="getEmail"
failto="test#test.com">
<div>The location has been moved to <b><cfoutput>#location#</cfoutput></b></div>
</cfmail>

How to change the user image using cfldap?

I'm able to get all the values that I want from cfldap.
But when I try to update the user image I don't know how to send the correct value for the binary image attribute.
I tried getting the image variable from the cffile upload
<cffile action="UPLOAD" filefield="file" destination="c:\inetpub\wwwroot\test" nameconflict="OVERWRITE" result="image" />
Also tried using cfimage with a static image -
<cfimage action="read" source="c:\inetpub\wwwroot\test\image.png" name="anotherImage">
Or even with
<cffile action="READBINARY" file="c:\inetpub\wwwroot\test\image.png" variable="BinaryImageContent">
But in any case, when I call
<cfldap action="modify"
DN="#results.dn#"
attributes="thumbnailPhoto=#obj.image#"
modifytype="replace"
server="myserver"
username="mydomain\myuser"
password="mypass">
The #results.dn# is the DN from the user that I get before (Everything ok on that)
I created the #obj.image# to be able to try all types of variables
Also tried these params:
<cfset obj.test1 = BinaryImageContent />
<cfdump var="#imageGetBlob(anotherImage)#" />
<cfdump var="#toString(obj.test1)#" />
By the way, the error that I get its
One or more of the required attributes may be missing or incorrect or
you do not have permissions to execute this operation on the server.
The problem is that I'm using the domain administrator account to update that
(THIS ERROR IS SOLVED - The network guys hadn't given me this permission... now I have it).
Now what I'm using is the following:
<cffile action="UPLOAD" filefield="file" destination="c:\inetpub\wwwroot\test" nameconflict="OVERWRITE" result="imagem" />
<cfset filename = "C:\inetpub\wwwroot\test\#imagem.serverFile#">
<cffile action="readbinary" file="#filename#" variable="img">
<cfset imgStr = BinaryEncode(img, "hex")>
<cfset imgStr2 = REReplace(imgStr, "..", "\\\0", "ALL")>
<cfldap
action="modify"
DN="#results.dn#"
attributes="thumbnailPhoto=#imgStr2#"
modifytype="replace"
server="myserver"
username="mydomain\myuser"
password="mypass"
>
but I get this binary code
Whats strange, is that before I had a binary code like -1-41 and now, nothing similar...
and when I try to show the pic
And this is one correct image....
EDIT: The original code sample below shows how it could work if ColdFusion wouldn't have a bug (or "very unfortunate design decision") in CFLDAP.
CFLDAP encodes the parameter values you pass to it before sending them to the server. This is nice because you don't have to worry about value encoding. But... it is also not helpful because it means you can't send encoded values yourself anymore, since CF invariably encodes them again.
Bottom line: As far as LDAP is concerned, encoding a file into a hex-string is correct, but CFLDAP mangles that string before sending it to the server. Combined with the fact that CFLDAP does not accept raw binary data this means that you can't use it to update binary attributes.
The comments contain a suggestion for a 3rd-party command line tool that can easily substitute CFLDAP for this task.
You need to send an encoded string to the server as the attribute value. The encoding scheme for binary data in LDAP queries has the form of attribute=\01\02\03\ab\af\cd.
Read your image into a byte array, encode that array into a hex string and prefix every encoded byte with a backslash.
<cffile action="readbinary" file="#filename#" variable="img">
<cfset imgStr = BinaryEncode(img, "hex")>
<cfset imgStr = REReplace(imgStr, "..", "\\\0", "ALL")>
<cfldap
action="modify"
DN="#results.dn#"
attributes="thumbnailPhoto=#imgStr#"
modifytype="replace"
server="myserver"
username="mydomain\myuser"
password="mypass"
>
Also don't forget what the documentation has to say about modifyType.

Converting Unicode Characters from Twitter JSON API feed using ColdFusion

I'm trying to use the Twitter API to pull down statuses from the Lists API using ColdFusion and am parsing everything I need just fine using the JSON format and a JSON component.
The problem I've come across is trying to convert the Unicode characters so they display correctly on screen.
here is the sample data that comes from the JSON feed
F\u00e0bregas
Is there some regex I could use to convert this?
Currently I have it writing out the raw data from the JSON feed
#node.user.name#
Which is fine, but it contains the \u00e0 which I need to convert so it displays as Fàbregas with the correct accent over the 'a'.
First up I think this is more of an character encoding issue than a regex issue.
How are you getting the Twitter data? If it's using <cfhttp> you could try setting the charset attribute to UTF-8. This will ensure that the data from Twitter arrives in UTF-8.
Then you should explicitly set the character encoding on the page you are trying to output the data on (the FORM and URL encoding while you are at it). For example:
<!--- URL and FORM encoding to UTF-8 --->
<cfset setEncoding("URL", "UTF-8") />
<cfset setEncoding("FORM", "UTF-8") />
<cfcontent type="text/html; charset=UTF-8" />
<cfoutput>#node.user.name#</cfoutput>
You'll find some more info here. Hope that helps!
There has to be a better way but until then I think this works
<cfset y = 'F\u00e0bregas'/>
<cfset x = evaluate(de(rereplace(y,'\\u([a-fA-f0-9]{4})','##chr(inputbasen(''\1'',16))##','all')))/>