Whenever you have a form open to public, other users could easily replicate the form, put it on their site/server and submit to your site from there. That means they don't have to come to your site to submit. This is particularly common with bots as very often the submission is initiated from their systems somehow, somewhere.
Validate the request to make sure that it in fact comes from your site.
This can be done by validating the CGI.HTTP_REFERER value to make sure that it contains your website's url. For those who don't know, this variable tells you where the request comes from. Eg, user is standing on page a.html, then click on a link to page b.html, the CGI.HTTP_REFERER variable will contain the full URL of the page a.html because user "comes to page b.html FROM page a.html".
The same thing applies to form submission. When user submits a form by visiting the page first, the CGI.HTTP_REFERER value will be the page that contains the form.
In this example, let's say you have a contact form at http://mysite.com/contact
The first thing we need to do is to make sure CGI.HTTP_REFERER starts with the contact page you expect:
<cfif reFindNoCase("^http://mysite.com/contact", CGI.HTTP_REFERER)>
<!--- Good, submitted from my site --->
<cfelse>
<!--- Spam ---->
</cfif>
Please note that I do not compare the 2 values directly using string comparison. The reason is sometimes, depending on how user gets to your site, the page they stand on might contain some url variables such as http://mysite.com/contact?something=something. In that case an exact string comparison will fail.
This is enough in most cases. However, sometimes when the request is submitted by bots, it can contain multiple URLs inside that CGI.HTTP_REFERER variable! Below is what the CGI.HTTP_REFERER value looks like in one of my bot submissions:
http://customerservicechicken.com/pollsarchive/, http://www.justafive.com/user/krisicash, http://bpost-photo.ning.com/profiles/blogs/buy-cheap-clozaril-online, http://xhtmlthis.com/, http://chapmanphotography.typepad.com/my_weblog/2010/09/samantha-and-wes-wdw-wedding-pavilion-aug-9-2010.html, http://www.kirstafloat.com/2010/09/st-stephens-beach-stanley.html, http://blog.vinhkhoa.com/article/Coldfusion-variable-scopes-in-CFCs
The last one is the correct referer, my blog url. But imagine that your site url is not the last, but the first one on the list. In the case, the above comparison will not be enough to capture this scenario. So we need to do one more thing that is to make sure that the CGI.HTTP_REFERER contains only one URL.
This can be done with the isValid() function in CF8:
<cfif isValid("url", CGI.HTTP_REFERER) AND reFindNoCase("^http://mysite.com/contact", CGI.HTTP_REFERER)>
<!--- Good, submitted from my site --->
<cfelse>
<!--- Spam ---->
</cfif>
However, if you use a previous CF version, what you can do is to remove your site URL and then check if there is any URL left.
<cfset expectedReferer = "http://mysite.com/contact">
<cfif reFindNoCase("^" & expectedReferer, CGI.HTTP_REFERER) AND NOT
reFindNoCase("https?://", reReplaceNoCase(CGI.HTTP_REFERER, "^" & expectedReferer, ""))>
<!--- Good, submitted from my site --->
<cfelse>
<!--- Spam --->
</cfif>
Hope you find it useful.
+