<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>E-Dribble &#187; form</title>
	<atom:link href="http://www.infosprite.com/tag/form/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.infosprite.com</link>
	<description>vaccuum packed mindless ramblings</description>
	<lastBuildDate>Tue, 08 Nov 2011 15:23:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>If you build it, the spamming pieces of shit will come.</title>
		<link>http://www.infosprite.com/2010/02/11/if-you-build-it-the-spamming-pieces-of-shit-will-come/</link>
		<comments>http://www.infosprite.com/2010/02/11/if-you-build-it-the-spamming-pieces-of-shit-will-come/#comments</comments>
		<pubDate>Fri, 12 Feb 2010 03:03:42 +0000</pubDate>
		<dc:creator>schwim</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[bot]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[protection]]></category>
		<category><![CDATA[Spam]]></category>

		<guid isPermaLink="false">http://www.infosprite.com/?p=817</guid>
		<description><![CDATA[I&#8217;m speaking, of course, about forms.  I&#8217;ve written in the past about my attempts to build a bot proof and spam resistant form.  I use the two terms independently because they are two very different things.  Even if you block bots, you&#8217;ve not necessarily stopped the humans that post to test the forms as well [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m speaking, of course, about forms.  I&#8217;ve written in the past about my attempts to build a bot proof and spam resistant form.  I use the two terms independently because they are two very different things.  Even if you block bots, you&#8217;ve not necessarily stopped the humans that post to test the forms as well as posting actual spam. If you&#8217;ve built the form correctly, it&#8217;s actually impossible to completely block spam.  A human posting spam is indistinguishable from a human using your form for legitimate purposes.  Well, aside from the fact that they&#8217;re stupid.  And evil.</p>
<p>I digress.  Let&#8217;s get to the form bits.  In my past posts, I&#8217;ve spoken about broad concepts that have worked for me.  This time, I&#8217;m going to provide the actual code I&#8217;m using.    With my latest change of checking for a valid MX record, I&#8217;ve completely stopped spam on the form that I&#8217;m using this on for over a month.</p>
<p><span id="more-817"></span></p>
<p>Since I&#8217;m passing variables via a session, at the top of the file, I&#8217;m going to go ahead and start the session before anything else is done in the file.</p>
<blockquote><p>&lt;?php<br />session_start();</p>
</blockquote>
<p>Then I create a couple session variables:</p>
<blockquote><p>/*Anti-Spam*/<br /> /*-We&#8217;re going to seed the input with a hidden and random value and we&#8217;re timing to find the slowpokes.*/</p>
<p> $_SESSION['AS_seed'] =  mt_rand(1000, 9999); //Pull a random number out of our ass between 1k and 9999.<br /> $AS_seed = $_SESSION['AS_seed']; //We are going to use the random number to change the form element names.<br /> $_SESSION['AS_substart'] = mktime(); //Pass the form generation time to a session var.</p>
</blockquote>
<p>Now in the form, we&#8217;re going to create the inputs like so:</p>
<blockquote><p>&lt;input type=&#8217;text&#8217; name=&#8217;&#8221;.$AS_seed.&#8221;email&#8217; size=&#8217;20&#8242;&gt;</p>
</blockquote>
<p>So what we&#8217;ve done is we&#8217;ve made sure that every time this page is generated, the element name is different.  The reason for this method of protection is the fact that one method the spammers use to submit form spam is by crawling the site(or manually browsing), saving the page HTML and then using a bot to automatically parse the page to shoot spam off.  Since the element name is different each time, saving a copy of the form will result in erroring out on the submittal side.</p>
<p>So on the entry side, we&#8217;ve created a start time and we&#8217;ve given the elements a random name.  Now we need to do some things on the submission side.</p>
<blockquote><p>/*Let&#8217;s submit the form!*/<br /> case &#8220;submit&#8221; :</p>
<p> /*AS: Anti-Spam measures*/</p>
<p> /*Setting a time to compare to the form generation*/<br /> $AS_subend = mktime();</p>
<p> /*First a value set by the submission form.  This should defeat bots that simply contact the form processor, bypassing the actual form page.*/<br /> if((!ISSET($_SESSION['AS_seed']))OR(!ISSET($_SESSION['AS_substart']))){ //If either session variable is missing, then we know that the submittal was not made via the proper method(form).<br /> $stop =&#8217;1&#8242;;<br /> echo(&#8220;Text to let them know that there were no session variables present in the form.&#8221;);<br /> }</p>
<p> /*If it took them less than 5 seconds to submit the form, they&#8217;re not human.*/<br /> if($AS_subend &lt;= ($_SESSION['AS_substart']+5)){<br /> $stop =&#8217;1&#8242;;<br /> echo(&#8220;Text to let them know that the post took less than 5 seconds to make.  Send them packing.&#8221;);<br /> }</p>
<p> /*If it took them longer than 30 minutes to submit the form, they fell asleep and their comment is probably really too boring anyway. Send them back to start*/<br /> if($AS_subend &gt;= ($_SESSION['AS_substart']+3600)){<br /> $stop =&#8217;1&#8242;;<br /> echo(&#8220;Text to let them know that the post took longer than 30 minutes to make.&#8221;);<br /> }</p>
<p>/* If they made it this far, then all we need to do is verify the sender. */<br /> // email address validation function.  This does not check for a valid domain, only a valid structure.<br /> // kudos to http://iamcal.com/publish/articles/php/parsing_email/<br /> function is_valid_email_address($email) {<br /> $qtext = &#8216;[^\\x0d\\x22\\x5c\\xa6-\\xff]&#8216;;<br /> $dtext = &#8216;[^\\x0d\\x5b-\\x5d\\xa6-\\xff]&#8216;;<br /> $atom = &#8216;[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c'.<br /> '\\x3e\\x40\\x5b-\\x5d\\xa6-\\xff]+&#8217;;<br /> $quoted_pair = &#8216;\\x5c[\\x00-\\xa5]&#8216;;<br /> $domain_literal = &#8220;\\x5b($dtext|$quoted_pair)*\\x5d&#8221;;<br /> $quoted_string = &#8220;\\x22($qtext|$quoted_pair)*\\x22&#8243;;<br /> $domain_ref = $atom;<br /> $sub_domain = &#8220;($domain_ref|$domain_literal)&#8221;;<br /> $word = &#8220;($atom|$quoted_string)&#8221;;<br /> $domain = &#8220;$sub_domain(\\x2e$sub_domain)*&#8221;;<br /> $local_part = &#8220;$word(\\x2e$word)*&#8221;;<br /> $addr_spec = &#8220;$local_part\\x40$domain&#8221;;<br /> return (preg_match(&#8220;!^$addr_spec$!&#8221;, $email));<br /> }</p>
<p> $email = $_POST[$_SESSION['AS_seed'].&#8217;user_email&#8217;];</p>
<p> if(!is_valid_email_address($email)){<br /> $stop =&#8217;1&#8242;;<br /> echo(&#8220;Text to let them know that the email structure was invalid.&#8221;);<br />}else{<br />/* If the &#8220;if&#8221; checked out, then we are dealing with a properly structured email address.  Now, the &#8220;else&#8221; will determine whether the email domain actually has an MX record. That means that the domain is not only registered but also is set up to accept email.*/<br />function verify_email_dns($email){<br /> // This will split the email into its front<br /> // and back (the domain) portions<br /> list($name, $domain) = split(&#8216;@&#8217;,$email);</p>
<p> if(!checkdnsrr($domain,&#8217;MX&#8217;)){<br /> // No MX record found<br /> return false;<br /> } else {<br /> // MX record found, return email<br /> return $email;<br /> }<br /> }</p>
<p> if(!verify_email_dns($email)){<br /> $stop =&#8217;1&#8242;;<br /> echo(&#8220;Text to let them know that the submission failed due to no MX record.&#8221;);<br />}</p>
<p>//So, lets see if any flags popped up.<br /> if(!ISSET($stop)){ //If &#8220;stop&#8221; is not set, then none of the checks above triggered it and we&#8217;re ok to submit the form.</p>
<p> $username = strip_tags (substr ($_POST[$_SESSION['AS_seed'].&#8217;username&#8217;], 0, 50));<br /> $name = strip_tags (substr ($_POST[$_SESSION['AS_seed'].&#8217;name&#8217;], 0, 50));<br /> $user_email = strip_tags (substr ($_POST[$_SESSION['AS_seed'].&#8217;user_email&#8217;], 0, 50));<br /> $comment = strip_tags (substr ($_POST['comment'], 0, 2000));</p>
<p> $to = me@here.com&#8217;; <br /> $subject = &#8220;Your site -|- Contact form submission&#8221;; <br /> $message = &#8220;Here&#8217;s a submission for you:\r\n <br />User: $username \r\n <br />Name: $name \r\n<br />Email: $user_email \r\n <br />Comment: \r\n <br />$comment&#8221;; </p>
<p> $headers = &#8220;From: $user_email&#8221; . &#8220;\r\n&#8221; . &#8220;X-Mailer: PHP/&#8221; . phpversion(); </p>
<p> mail($to, $subject, $message, $headers);</p>
<p> echo(&#8220;Text to let them know that the submission was a success.&#8221;);</p>
<p> }</p>
<p> break;</p>
</blockquote>
<p>Before I added the mx check, I was getting a single spamming piece of whale shit that kept hitting me with the same test post:</p>
<blockquote><p>Here&#8217;s a submission for you:</p>
<p> User: bunqwputd</p>
<p> Name: bunqwputd</p>
<p> Email: <a href="mailto:aaivnq@gjpluc.com">aaivnq@gjpluc.com</a></p>
<p> Comment:</p>
<p> QHq9CT  exmlpcvlbyvq, [url=<a href="http://ywepjoknkzps.com/%5Dywepjoknkzps%5B/url" target="_blank">http://ywepjoknkzps.com/]ywepjoknkzps[/url</a>],  [link=<a href="http://fzzqigwvqeao.com/%5Dfzzqigwvqeao%5B/link" target="_blank">http://fzzqigwvqeao.com/]fzzqigwvqeao[/link</a>], <a href="http://zpedowpklfhx.com/" target="_blank">http://zpedowpklfhx.com/</a></p>
</blockquote>
<p>which doesn&#8217;t make much sense at first, but here&#8217;s the deal.  Most spammers don&#8217;t read the language of the page they&#8217;re on and they don&#8217;t have the time to decipher each form&#8217;s purpose.  They&#8217;ve got shit to post.  To help in their effort, they post bullshit like this and then see what happens.  If the resulting page shows their spam, then they know it&#8217;s a form they want to hit.  If it doesn&#8217;t, it&#8217;s time to move on.</p>
<p>I lucked out here because they use a random string for a domain name.  I suspect they do this to protect themselves from forms that block posts from known webmail domains that historically house spam accounts.  If it&#8217;s a bogus domain, then it&#8217;s definitely not going to be on any blacklist.</p>
<p>It will also not return a valid mx record <img src='http://www.infosprite.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>That&#8217;s it.  Months have gone by with no more spam.  If it changes, I&#8217;ll start playing with other things to try short of a CAPTCHA. I imagine I&#8217;ll begin running the content through Akismet.  For now though, this is doing the trick.  Hope it helps someone else.</p>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.infosprite.com/2010/02/11/if-you-build-it-the-spamming-pieces-of-shit-will-come/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

