The other night, I was staring at my neighbor's lower-back tattoo when a new (to me) ColdFusion anti-spam technique popped into my head. I am sure that this is not new or unique, I just haven't explored this before. Until now, all of my ColdFusion-based Anti-Spam methodologies have resorted to CSS and TimeStamp-based tomfoolery. Well, I don't know if it was the graphical nature of my neighbor's sacral inkage, but suddenly I had the idea of using Images.
The idea here is that Spam Bots probably don't ever render the form pages they spam; most likely just grab the HTML and then use that to programmatically submit the form. Because they never render the HTML page itself, they never make subsequent requests to the server to load images, stylesheets, and the like.
That's where this new plan comes into play. On the form page, we have an image tag that pings a ColdFusion page which causes some ID-based flag to be set. This ID is then also submitted with the form. When the request gets processed, you then check to see if the both the flag and the form-submitted ID exist (and match). If they do, then it proves the HTML page was rendered and that it was most likely not a bot.
To demonstrate, let's first look at the ColdFusion template that causes the server side flag to be set:
<!--- Kill extra output. ---> <cfsilent> <!--- Param the URL id. ---> <cfparam name="URL.id" type="string" default="" /> <!--- Try to decrypt it and create a text file. ---> <cftry> <!--- Decrypt the value. ---> <cfset URL.id = Decrypt( URL.id, "that-is-tasty!", "CFMX_COMPAT", "HEX" ) /> <!--- Create the text file that will mark the form submission as valid. Just store it as an empty text file since all we are going to be doing is checking for its existence. ---> <cffile action="write" file="#ExpandPath( './spam/#URL.id#.txt' )#" output="" /> <!--- Catch any errors. ---> <cfcatch> <!--- Something went wrong. ---> </cfcatch> </cftry> <!--- Return an empty image. ---> <cfheader name="content-length" value="0" /> <cfcontent type="image/gif" reset="true" /> </cfsilent>
As you can see, practically nothing going on here. When the request comes in, we are decrypting the form ID in the URL scope. We then create an empty text file based on this form ID. This could just as easily have been an APPLICATION-scoped variable or something, but I figured this would be easier on the server's memory.
Now that we understand how the server-side, ID-based flag is being set, let's take a look at the Form page:
<!--- Kill extra output. ---> <cfsilent> <!--- Param form comments. ---> <cfparam name="FORM.comments" type="string" default="" /> <!--- Param the form ID. This is the value that we will use to check proper form submission (to protect against SPAM form submissions). ---> <cfparam name="FORM.form_id" type="string" default="" /> <!--- Param the form submission. ---> <cftry> <cfparam name="FORM.submitted" type="numeric" default="0" /> <cfcatch> <cfset FORM.submitted = 0 /> </cfcatch> </cftry> <!--- Check to see if the form has been submitted. ---> <cfif FORM.submitted> <!--- Check to see if the FORM is valid by checking to see if the ks_stats.cfm file spawned a file with the given ID. ---> <cfif FileExists( ExpandPath( "./spam/#FORM.form_id#.txt" ) )> <!--- The file exists. This confirms that the FORM page was actually loaded and spawned a second IMG request that then spawned this text file. This is probably NOT a spam bot. ---> <cflocation url="confirm.cfm" addtoken="false" /> </cfif> </cfif> <!--- If we have made it this far, then we are going to be showing the FORM again. Select a new form ID for this display. ---> <cfset FORM.form_id = CreateUUID() /> <!--- Now that we have our form ID, let's encrypt it so that we don't have duplicate values in the body (that might be detectible pattern by a BOT). ---> <cfset FORM.encrypted_form_id = Encrypt( FORM.form_id, "that-is-tasty!", "CFMX_COMPAT", "HEX" ) /> </cfsilent> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>ColdFusion Anti Form Spam Idea</title> </head> <body> <cfoutput> <form action="#CGI.script_name#" method="post"> <!--- This will flag form submission. ---> <input type="hidden" name="submitted" value="1" /> <!--- This is the form ID. ---> <input type="hidden" name="form_id" value="#FORM.form_id#" /> <label for="comments"> Comments: </label> <textarea id="comments" name="comments" cols="50" rows="10" >#FORM.comments#</textarea> <input type="submit" value="Submit Comments" /> </form> <!--- This is the image that we will use to make sure the HTML of the current form page actually renders. I am calling it "ks_stats" just to make it less obvious to prying eyes. ---> <img src="ks_stats.cfm?id=#FORM.encrypted_form_id#" height="1" width="1" style="display: none ;" /> </cfoutput> </body> </html>
If you look at the bottom of the page, you will see that I have an invisible IMG tag that pings our ks_stats.cfm file (the first file shown above) using an encrypted version of the form ID. I have called it ks_stats.cfm just to disguise it. I have also encrypted the ID so that it would be a harder pattern to pickup. This Ping triggers the previously discussed server-side flag to be set. Once the form gets submitted, we then just check to see if the text file (our server-side flag) exists. If it does, then we are deciding that the submitter is NOT a bot. If it doesn't exist, then we are saying that user IS a bot.
Want to use code from this post? Check out the license.