I know there is hundreds examples of the question I'm about to ask. But none of them was working for me like a wanted.
So, I have a textarea, in which people can add comments/ reviews. But the commenting box keeps getting spammed.
I guess the regular expression might be the most efficient way to keep spammers out, but I stink at Regex.
Is there any other way to keep the spam out?
Edit: the spammers keep posting something like that:
Brianna
Looking for work Lolita Pics it would of been better if she was fucking in front of the mirror!
its more sexy seeing yourself getting f##$.
just getting horny thinking about it
Preteens Nn Models omg if that
(spoilered, lightly censored to avoid causing folks problems at work)
So i want to block per hyperlink in string
There are many different ways to get rid of spam:
Captcha - for example ReCaptcha, but nowadays you can buy about ~1000 rewritten captcha for less than 3$.
Questions in your language about the most known facts - you can ask your users about some facts that they know, but spammers don't.
Antispam filters - for example Sblam!, Akismet or other anti-spam services. I think it would work best for you.
Alot of Captcha is now bot solvable, and if you're trying to avoid Captcha, then one quick suggestion is to use a simple Text trap.
Under your text area, add a question, such as;
"How many days are in a week?"
Then add another text box, and compare this to say;
7 or Seven etc.
If the test fails, then reject the entry...
You may need to vary your question over time, or even have a list of different questions, but this is a simple and easy method to implement.
The answers here are good, but sometimes fooling bots is a good first step.
The vast majority of bots just read the source code and will fill in all the input fields they can find with garbage, send the request, and then hope it worked. They are pretty stupid, so something like this may fool most bots:
<p style="display:none">Screen readers: Use the next textarea (the first is used to confuse spam bots).</p>
<textarea name="comment" style="display:none"></textarea>
<textarea name="real_comment"></textarea>
And then in your script:
if (isset($_POST['comment']) && strlen($_POST['comment']) > 0) {
die('Bots begone!');
}
$comment = $_POST['real_comment'];
In other words, put a dummy textarea in the HTML, hide it using CSS, and then wait for bots to fill it in.
The simpliest way to do what you want is to search for the string http://
The following if-statement allows up to 3 links in $text
if (substr_count($text,"http://") > 3)
But that's not really a sufficent check, because there is a lot of spam, which doesn't contain any links at all - just rubish.
So the second you have to do, is a black list with "bad words"
$lower = strtolower($text);
foreach ($blockword as $word) {
if (strpos($lower, strtolower($word))>0) {
//handle spam here..
}
}
and after all, you have to maintain a growing list with words and still have to delete a lot of spam..
So you have the option to add an invisible field with random values, which are stored in the session and check if this value is submited correctly
$_SESSION["random_secret"] = //create random string..
and later check
if ($_POST["secret"] == $_SESSION["random_secret"])
with this check, you get rid of a lot of automated spam(but still not all)
and so after all you ended up with captchas
Related
A client contacted us worried about some recent attempts to abuse the contact us form on her site.
Apparently, someone tried to write some code in the message field, most likely, it was an attempt to use the back end script for spam email purposes (email injection using those funky headers).
Currently, the security in place is a JavaScript file that validates the form before it is submitted. There isn't really any checking in the back end.
So, I added some validation in the back end, just some simple stuff, like:
$namePattern = '/^[a-z0-9()\/\'":\*+|,.; \- !?&#$#]{2,75}$/i';
$emailPattern = '/^[^#\s]+#([-a-z0-9]+\.)+[a-z]{2,}$/i';
$phonePattern = '[0-9\.\-]';
$array = $_POST;
//This is the first line of defense.
if (!preg_match ($namePattern, $array['c_firstname']){
die ("Please go back and enter a correct first name");
}
...More if statements to check other fields.
//The second line of defense.
function remove($name){
return( str_ireplace(array( "\r", "\n", "%0a", "%0d", "Content-Type:", "bcc:","to:","cc:" ), " Something Replaced ", $name ) );
}
$array['c_date'] = remove ($array['c_date']);
//Check the rest of the array.
Sorry, if there is something wrong with my logic or my syntax, I haven't actually tested the above yet (since the site is live, I wanted to get as much of the code written as possible before testing).
Is the above enough of a security check? Did I get the pattern checks right (I mostly just copied other peoples patterns because I don't totally understand the notation).
This particular mail form uses Zend Mail, so in theory, it's a bit more secure than regular PHP mail, I think.
Also, this isn't that important, but if someone has the time, could you teach me how to cycle through the array and assign a new value to each element (i.e. instead of writing $array['c_date'] = remove ($array['c_date']); several times, a simple function or something that does the job for me.
Thanks a lot for the help, have a good day!
Generally speaking the key is to ensure that anything coming from user input is not executed. Providing your code generating the email is encoding all the user input then there shouldn't be too many problems.
Pattern matching input can't hurt (unless you specifically want users to be able to enter particular values like html code).
Personally, I would re-assure the client that any script/code inserted to their form isn't executed, and isn't harmful unless executed.
Simply properly sanitize your input should be enough. Use htmlspecialchars() or htmlentities(), You can also strip out any < or > characters, that should be enough.
The most frequent problem with mail forms comes from bad code samples lying around on the web in which the destination email is taken from a hidden field in the form, which allows attackers to replace that email and use the server as a spam hub.
Just make sure the email does not come user input. For the rest, the worst that can happen is that you will receive spam, just will just happen anyway if you want people to contact you.
I need a url obfuscator that a spider should not extract my links like safe_mailto in codeiginitor... is it possible using PHP if so please give an example.
Construct a script tag, that will concatenate the email out of smaller String.fromCharCode calls, maybe with a combination of html entities as #Dominic suggested, you can make it more complex with various approaches. The point is to stop the majority of email grabbers from finding it out.
Would it stop them? Not totally. Spam bots are becoming smarter day after day, and it will take somebody like 5 mins to emulate your algorithm to reconstruct emails out of your output. As mentioned by #ircmaxell: "Security through obscurity is no security at all".
Any good approach?: Yes! Put all emails in a database table, with ids (in case they weren't already stored in such manner), the user will click something like reveal.php?email=1564, that page will display a recaptcha, or any other good captcha, and if valid, it will show them the email.
$link = 'mailto:example#example.com';
$obfuscatedLink = "";
for ($i=0; $i<strlen($link); $i++){
$obfuscatedLink .= "&#" . ord($link[$i]) . ";";
}
As ircmaxell commented, this is a very primitive obfuscation, and really won't deter many spammers.
I have comments enabled on my site and I require users to enter at least 30 characters to publish their comments (Just to get some value because they usualy just submitted "I like it")
But some users now use simple technique to overcome this and enter e.g.:
"I like it. asdsdf dfdsfsdf tt erretrt re"
As you can see the rest of the text is nonsense. Is there a way (algorithm) how to filter these comments out in PHP ?
Get a dictionary of English words from the net. Check the post has a certain % (maybe 50%? maybe 70%?) of words that are in the dictionary. You can't look for 100%, or names and technical jargon will not be found.
users will get around this by entering.
I like it ....................................................
So then add logic to parse out punctuation.
Then users will get around it with
I like it. the the the the the the the the
Then you will need to parse it for proper English grammer
Then no one will be able to post on your site becuase it has too many rules.
Better suggestion: Add comment moderation. Dumb posts get downvoted and go away. Good posts stay.
Check out the Akismet PHP5 class.
$WordPressAPIKey = 'KEYHERE';
$MyBlogURL = 'http://www.example.com/blog/';
$akismet = new Akismet($MyBlogURL ,$WordPressAPIKey);
$akismet->setCommentAuthor($name);
$akismet->setCommentAuthorEmail($email);
$akismet->setCommentAuthorURL($url);
$akismet->setCommentContent($comment);
$akismet->setPermalink('http://www.example.com/blog/alex/someurl/');
if($akismet->isCommentSpam()) {}
You can use a naive bayesian filter for this. http://www.paulgraham.com/better.html
There are probably existing libraries for this kind of thing. Check out spam assassin.
I'd do a simple check on consecutive consonants or vowels. If there are more than four of any in a row, than there is a high probability of nonsense. Furthermore, check for more than two repetitions of the same character. When looking at some nonsense text, I'm sure you'll find some pragmatic reciepes ;-)
Personally, I would say there's not much you can do about it. Even if you had a dictionary and parser, what if I were to leave a comment: "I like it. As do I like your car." Depending on what they're leaving a comment for, that could be complete nonsense. Best I can say is have an edit available for each comment so that you or a mod or whomever can edit it. Sorry that this isn't of any help.
I had this same issue when trying to create password restrictions. Words couldn't be used, so we needed to use a dictionary, but there is never a comprehensive dictionary. And the biggest thing was eliminating l33t speak. :)
Unfortunately not, your best bet is to modify something like this: Get Spelling Corrections From Google. When messages are close to the 80 character limit, you could look up each word individually and if it doesn't have a direct hit, boot out the input.
I need to create a 10 page quiz for a mobile browser. It is only a mobile webpage, so no considerations need to be taken for other browsers.
Here's the problem I'm having: I can't use JavaScript, because not every mobile browser supports it. I'm not very skilled in other languages, but I thought perhaps something could be done in PHP as it is server-side.
If my first URL is domain and I enter the correct quiz answer, the URL to the next page could be domain/?p=1. The URL doesn't need to do anything but hold a count of the number of correct results.
As for the actual code, I was thinking it could be included in the HTML itself, as I'm not very concerned about people viewing the source on their mobile phones.
Is it possible to write a line of code that increments the 'p=' attribute in the URL by one when clicked and only attach it to the correct answers?
Here's an image of what I mean: http://i.imgur.com/HbJ5U.jpg
And, what's to stop me from manually incrementing the "correct answer" counter in my address bar?
Do you not want to use a database because you don't have one available to you in your hosting, or because you don't know how?
I'm not a fan of the idea, but you can get the number of "correct answers" with the following code.
<?php
/* Gets current correct answer Count */
$answer_count = $_GET["p"];
/* checks to see if the submitted answer is the same as the correct answer */
if ($_POST["submitted-answer"] == "correct-answer") {
$answer_count++;
}
?>
Now, you just add the modified answer count to the link to the next question.
Next Question
If this is "just for fun" I don't see why you couldn't do it like this. It's definitely a simple way to solve the problem.
The standard way to do this is to store things in hidden form variables. Of course, if there is anything riding on this, that's a terrible way to do it, because it's really easy for the end user to put his own values in those hidden form values.
Aren't file-based sessions the obvious answer here?
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
What are some non-captcha methods for blocking spam on my comments?
In my experience the currently most effective methods are honeypot input fields that are made invisible to users via CSS (best use several different methods, such as visibility:hidden, setting a size of 0 pixels, and absolute positioning far outside the browser window); if they're filled anyway you can assume it's a spambot.
This blog describes a rather complex method that I've tried out myself (with 100% success so far), but I suspect that you could get the same result by skipping all the stuff with hashed field names and just add some simple honeypot fields.
1) Adding session-related information into the form Example:
<input type="hidden" name="sh" value="<?php echo dechex(crc32(session_id())); ?>" />
then at postback, check whether session is valid or not.
2) Javascript-only. Use Javascript injection at Submission. Example:
<input type="hidden" id="txtKey" name="key" value="" />
<input type="submit" value="Go" onclick="document.getElementById('txtKey').value = '<?php echo dechex(crc32(session_id())) ?>';" />
3) Time-limit per IP, User or Session. this is quite straightforward.
4) Randomizing field names:
<?php
$fieldkey = dechex(crc32(mt_rand().dechex(crc32(time()))));
$_SESSION['fieldkey'] = $fieldkey;
?>
<input type="text" name="name<?php echo $fieldkey; ?>" value="" />
<input type="text" name="address<?php echo $fieldkey; ?>" value="" />
Then you can check it over at the server side.
Akismet has an API. Someone wrote a wrapper class (BSD liscense) for it over at: http://cesars.users.phpclasses.org/browse/package/4401.html
There's also a Bayesian filter class (BSD Liscense as well)
http://cesars.users.phpclasses.org/browse/package/4236.html
This is simple trick to block spam bot or brute force attack without using captcha.
Put this in your form:
<input type="hidden" name="hash" value="<?php echo md5($secret_key.time()).','.time(); ?>" />
Put this in your php code
$human_typing_time = 5;/** page load (1s) + submit (1s) + typing time (3s) */
$vars = explode(',', $_POST['hash']);
if(md5($secret_key.$vars[1]) != $vars[0] || time() < $var[1] + $human_typing_time){
//bot?
exit();
}
Depend on weight of form you can increase or decrease $human_typing_time.
Naive Beyesian filters, of course:
http://blog.liip.ch/archive/2005/03/30/php-naive-bayesian-filter.html
There is the Honey Pot Theory as well. I enjoy coupling honey pots with other forms of spam reduction for best results.
http://www.projecthoneypot.org/
Another common approach is to give the user a simple question ("is fire hot or cold?" "what is 2 plus 7?" etc.). It is a little captcha-like, but it is more accessible to users with vision disabilities using screen readers. I think there must be a WordPress plugin that does this, because I see it very frequently on WordPress blogs.
As lot of people already proposed : use a honey pot input field. But there are two other things you need to do.
First, randomize the name / id of which input field is the honey pot. Store the state of usefull fields in session (as well as a form token, used against CSRF attacks). For exampe, you have these fields to get : name, email, message. In your form, you will have
"token" which is your token, "jzefkl46" which is name for this form, "ofdizhae" for email, "45sd4s2" for message and "fgdfg5qsd4" for honey pot.
In the user session, you can have something like
array("forms" => array("your-token-value" => array("jzefkl46" => "name",
"ofdizhae" => "email",
"45sd4s2" => "message",
"fgdfg5qsd4" => honey"));
You just have to re-associate it back when you get your form data.
Second thing, as the robot has lot of chances to avoid your honey pot field (25% chances), multiply the number of pots. With 10 or 20 of them, you add difficulty to the bots while not having too much overhead in your html.
Sblam! is an open-source filter similar to Akismet.
It uses naive bayesian filtering, checks sender's IP and links in multiple distributed blacklists, checks correctness of HTTP requests, and uses presence of JS as a hint (but not requirement).
Regular CAPTCHAs are spam-bot solvable now.
Consider instead "text CAPTCHAs" : a logic or common knowledge question, like "What's 1 + 1 ?" or "What color is General Custard's white horse?" The question can even be static (same question for every try).
(Taken from http://matthewhutchinson.net/2010/4/21/actsastextcaptcha )
I think Jeff Atwood even uses a validation like this on his blog. (Correct me if I'm wrong)
Some resources:
Text Captcha site & services : http://textcaptcha.com/demo
A plugin : http://matthewhutchinson.net/2010/4/21/actsastextcaptcha
More about text Captcha's with non-working code : http://www.thesamet.com/blog/2006/12/21/fighting-spam-on-phpbb-forums/
You could try looking at using a third party like Akismet. API keys are free for personal use. Also, The Zend Framework has a package for this.
Most bots simply fill out the whole form and send it to you. A simple trick that works is to create a normal field that you usually hide with the aid of javascript. On the server side just check whether this field has been filled. If so -- then it is spam for sure.
Disallow links. Without links, spam is useless.
[EDIT] As a middle way, only allow links to "good" sites (usually your own). There are only a handful of them, so you can either add them at the request of your users or hold a comment until you verified the link. When it's good, add it.
After a while, you can turn this off and automatically reject comments with links and wait for users to complain.
I have reduced about 99% of spam on my website through a simple mathematical question like the following:
What is 2+4 [TextBox]
The user will be able to submit the question/comment if they answer "6".
Works for me and similar solution works for Jeff Atwood from Coding Horror!
On my blog, I have a kind of compromise captcha: I only use a captcha if the post contains a link. I also use a honeypot input field. So far, this has been nearly 100% effective. Every now and then there will be a spammer that submits something to every form which contains no links (usually something like "nice site!"). I can only assume that these people think I will e-mail them to find out who they are (using the e-mail address that only I see).
along with using honey pot fields, we can ban there IP automatically (which don't work for dynamic IPs) and especially any links posted back by bots.
Akismet is a good alternative, they check your posts for spam and works very efficiently.
You just need to load their librabry.
http://akismet.com/development/
checkout some wp antispam plugins for examples and ideas
there're many nice antispam without using captcha.
some i'd recommend: hashcash, nospamnx, typepad antispam.
all these using different methods blocking spam and i use them all. hashcash+nospamnx block almost all spambot. and typepad antispam block most human typed spam.
these are also good ones: spambam, wp-spamfree, anti-captcha, bad-behaviour, httpbl, etc
also with simple .htaccess that block any bot direct POST that do not come from your own site (check referer)
or, simply outsource your comment system to disqus and sleep tight.