logo
Apache Lounge
Webmasters

 


About

Forum Index Downloads Search Register Log in  RSS Apache Lounge
 



Keep Server Online

If you find the Apache Lounge, the downloads and overall help useful, please express your satisfaction with a donation.

or

Bitcoin

A donation makes a contribution towards the costs, the time and effort that's going in this site and building.

Thank You! Steffen

Apache Lounge is not sponsored.

Your donations will help to keep this site alive and well, and continuing building binaries.



human reason validation?

 
Post new topic   Reply to topic    Apache Forum Index -> Coding & Scripting Corner



View previous topic :: View next topic  
Author Message
Doug22



Joined: 02 Jun 2013
Posts: 44
Location: Houston TX

PostPosted: Wed 03 Jun '15 20:14    Post subject: human reason validation? Reply with quote

I'd like to protect a web PAGE from bots and the like. I don't want to go through password protection, with usernames and passwords. I'd just like to present the person trying to see the page with a simple human reason question prompt like "What year is it?", and if they type in the right number, they get to proceed and see the page. Even simpler than a captcha.

How do I do that? I'm sure this is a standard procedure, but I'm not even sure what that strategy is called, so I can't research it.
Back to top
glsmith
Moderator


Joined: 16 Oct 2007
Posts: 2101
Location: Sun Diego, USA

PostPosted: Thu 04 Jun '15 11:40    Post subject: Reply with quote

As far as I know it's called a human test. Done with a scripting language of your choice. Present a form, compare the input given, if it is correct, print out the info. If not, then tell them/it "Sorry Charlie."

http://page.of.buggycode.info:88/
Back to top
Doug22



Joined: 02 Jun 2013
Posts: 44
Location: Houston TX

PostPosted: Thu 04 Jun '15 16:49    Post subject: Reply with quote

Many thanks. That's *exactly* what I'm looking for. As I use a Mac for a server, this page gives pretty complete instructions for how to use that script.

http://www.cgi101.com/book/connect/mac.html
Back to top
Doug22



Joined: 02 Jun 2013
Posts: 44
Location: Houston TX

PostPosted: Thu 04 Jun '15 17:33    Post subject: Reply with quote

Well, that test works fine. I go to that page, which I have called first.cgi, and I am verified as human after I input the year.

But that doesn't quite complete the job.

What I want it to do is after verifying that I am human, go straight to the page -- myprotectedpage.html (say, instead of confirming that I am established to be human).

How do I make that script do that?

My apologies, but I am very much NOT a cgi programmer.
Back to top
glsmith
Moderator


Joined: 16 Oct 2007
Posts: 2101
Location: Sun Diego, USA

PostPosted: Thu 04 Jun '15 22:22    Post subject: Reply with quote

http://apaste.info/GBw

You do need to actually protect the html file somehow. You could put it outside the DocumentRoot provided where you put it is readable by Apache or simply put an .htaccess file in there to deny access to the html file.

Not that when you use htaccess files you must have the AllowOverride for the directory set properly. If it's Apache 2.2 then it must include Limit. If 2.4 then it's AuthConfig.

I'm assuming reading your cgi101 link you'll be doing this in your user file, ted.conf in the example.

Code:
# .htaccess
# Protect the actual html file from direct viewing.
<Files "myprotectedpage.html">
#
# Uncomment next line if you use Apache 2.4.x
# Require all denied

# Uncomment next line if you use Apache 2.2.x
# Deny from all
#
</Files>
Back to top
Doug22



Joined: 02 Jun 2013
Posts: 44
Location: Houston TX

PostPosted: Thu 04 Jun '15 23:13    Post subject: Reply with quote

Yes, I understand that the file itself needs to be put away where it isn't directly accessible. But my question is what command I put in my cgi file to redirect to that protected file once humanity is established.

That is, after determining the humanity of the accessor, how do I redirect to that file? Presumably that redirection happens in the cgi script.

I tried putting

Code:
print $q->redirect('http://myserver/myprotectedfile.htm');


All that did was print the command on the screen! No redirection happened. My browser wasn't sent to myprotectedfile.htm.

I'm confused.
Back to top
glsmith
Moderator


Joined: 16 Oct 2007
Posts: 2101
Location: Sun Diego, USA

PostPosted: Thu 04 Jun '15 23:19    Post subject: Reply with quote

print $q->redirect('http://myserver/myprotectedfile.htm');

Do this before printing out the content-type. I have not seen your script but assuming you're using cgi.pm, before
print $q->header

But, and this is a BIG BUT, you do not want to allow direct access to the html, and by redirecting the visitor is directly accessing the html file. If the html file is protected, they will get a 403 Forbidden. If it's not protected, they could just as easily go to http://myserver/myprotectedfile.htm and not have to be tested if they are human or not.

Look at the apaste link at the top my prior post. Use, modify, steal ideas/code from it all you want. But the script reads in the html file and then prints out it's contents, it does not redirect the visitor to the html file itself.
Back to top
Doug22



Joined: 02 Jun 2013
Posts: 44
Location: Houston TX

PostPosted: Fri 05 Jun '15 1:00    Post subject: Reply with quote

Thank you, and your apaste link looks really handy. Actually, I'm just trying to protect the file from bots, so if someone is clever enough to go directly to the page, that won't bother me, as long as they don't advertise that link to the web bots. Of course, that will probably happen one way or another.

Now, my cgi script looks like this.

Code:
#!/usr/bin/perl
#!c:/perl/bin/perl
##################################################################
print "Content-type: text/html\n\n";
print "<html><head><title>human test</title></head><body>\n";
if ($ENV{'CONTENT_LENGTH'}) {
  (@LocalTime) = localtime(time);
  $year = ($LocalTime[5]+1900);
  &parse_content;
  &error if $FORM{'answer'}=~/\D/;
  if ($FORM{'answer'} == $year) {
    print "<pre>\n\n\n\n\n\n</pre>\n";
    print "<center><h1>Yes, you are human!</h1>";
    print $q->redirect('http://myserver/myprotectedfile.htm');
}
  else {
  print "<pre>\n\n\n\n\n\n</pre>\n";
    print "<center><h1>Nope!<br/>You must not be a human :(</h1>";
    print '<img src="robot.png" border="0" alt="Human"/><br /><a href="/">Try Again</a></center>'."\n";
  }
}
else {
    print "<pre>\n\n\n\n\n\n</pre>\n";
    print "<center><h1>Prove you are not a bot.</h1>";
    print "<center>Sorry, but we need to repel bots.";
    print "<pre>\n</pre>";
    print '<form method="POST">What year is it?&nbsp; <input type="text" name="answer" size="5" maxlength="4"/><br/><input type="submit" value="I am human!"/></form></center>'."\n";
}
print "</body></html>\n";
exit 0;

sub error {
  print "<h3>Invalid Input</h3>\n";
  print "</body></html>\n";
  exit 0;
}

sub parse_content {

   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
   @pairs = split(/&/, $buffer);
    if ($iswitch) { @pairs = split(/&/, $ENV{'QUERY_STRING'}); }
    foreach $pair (@pairs) {
      ($name, $value) = split(/=/, $pair);
      $value =~ tr/+/ /;
      $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
      $value =~ s/\#exec/ /g;
      $FORM{$name} = $value;
   }
} #end


You can see where I put my redirect statement. But I don't understand why that redirect statement doesn't work at all. In fact, as I said, it just prints the command to the screen instead of executing it.

How can I put it before where I print the content type? Doesn't that content type printing have to be done before I ask for the human test? I have to put the redirect command after that test.

Aaargh!
Back to top
glsmith
Moderator


Joined: 16 Oct 2007
Posts: 2101
Location: Sun Diego, USA

PostPosted: Fri 05 Jun '15 4:45    Post subject: Reply with quote

Doug22 wrote:
How can I put it before where I print the content type? Doesn't that content type printing have to be done before I ask for the human test?

Most certainly, but once they press the button it is an all new request, and if you are not going to print out anything but the redirect, no need for a content-type.

I wasn't using cgi.pm in this script however (no big need to) so $q->redirect doesn't exist. This does what you want, just change the 4th line to the proper url.

Code:
#!/usr/bin/perl
##################################################################
# Change this below to the actual url of the html file.
$htmlpage = "http://httpd.apache.org";

if ($ENV{'CONTENT_LENGTH'}) {
  (@LocalTime) = localtime(time);
  $year = ($LocalTime[5]+1900);
  &parse_content;
  &error if $FORM{'answer'}=~/\D/;
  if ($FORM{'answer'} == $year) {
    print "Location: ".$htmlpage."\n\n";
  }
  else {
    &header;
    print "<pre>\n\n\n\n\n\n</pre>\n";
    print "<center><h1>Nope!<br/>You must not be a human :(</h1>";
    print '<img src="robot.png" border="0" alt="Human"/><br /><a href="/">Try Again</a></center>'."\n";
  }
}
else {
    &header;
    print "<pre>\n\n\n\n\n\n</pre>\n";
    print "<center><h1>Prove you are not a bot.</h1>";
    print "<center>Sorry, but we need to repel bots.";
    print "<pre>\n</pre>";
    print '<form method="POST">What year is it?&nbsp; <input type="text" name="answer" size="5" maxlength="4"/><br/><input type="submit" value="I am human!"/></form></center>'."\n";
}
print "</body></html>\n";
exit 0;

sub error {
  print "<h3>Invalid Input</h3>\n";
  print "</body></html>\n";
  exit 0;
}

sub header {
  print "Content-type: text/html\n\n";
  print "<html><head><title>human test</title></head><body>\n";
}

sub parse_content {

   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
   @pairs = split(/&/, $buffer);
    if ($iswitch) { @pairs = split(/&/, $ENV{'QUERY_STRING'}); }
    foreach $pair (@pairs) {
      ($name, $value) = split(/=/, $pair);
      $value =~ tr/+/ /;
      $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
      $value =~ s/\#exec/ /g;
      $FORM{$name} = $value;
   }
} #end
Back to top
Doug22



Joined: 02 Jun 2013
Posts: 44
Location: Houston TX

PostPosted: Fri 05 Jun '15 5:14    Post subject: Reply with quote

Awesome! That works beautifully. Thank you!!

One slight complication is that the original file I wanted to protect from bots was myprotectedfile.htm.

So if I want everyone who has bookmarked that file to keep that bookmark, I have to give my cgi script that same name and change the name of the one I want to protect. But that cgi script is not an htm file, and funny things happen if I change the name of that cgi file to myprotectedfile.htm.

I guess I could just redirect myprotectedfile.htm to the cgi script in my .htaccess. But is there a more elegant way?
Back to top
glsmith
Moderator


Joined: 16 Oct 2007
Posts: 2101
Location: Sun Diego, USA

PostPosted: Fri 05 Jun '15 18:28    Post subject: Reply with quote

Doug22 wrote:
I guess I could just redirect myprotectedfile.htm to the cgi script in my .htaccess. But is there a more elegant way?


Yes but, you will have to rename the protected file to something else, or the redirect will go into an endless loop.

bookmarked myprotectedfile.htm -> cgi script -> myprotectedfile.htm -> cgi script -> myprotectedfile.htm -> on and on and on
Back to top
Doug22



Joined: 02 Jun 2013
Posts: 44
Location: Houston TX

PostPosted: Fri 05 Jun '15 20:52    Post subject: Reply with quote

OK, the cgi script that you listed below works great, and I can do a human test before I reach my page myprotectedpage.html.
But now I'm trying to implement your protection script that prevents one from going to that page directly, without going through the human test.

You outlined that above.

I put, in my .htaccess file, the following script (I'm using Apache 2.2.24)...

Code:
AllowOverride Limit
# Protect the actual html file from direct viewing.
<Files "myprotectedpage.html">
Deny from all
</Files>


... and nothing works. I get errors whether I am trying to go directly to that page (which I guess is correct), but also if I go to my cgi script. In fact, I can't get to anything.

What am I doing wrong?
Back to top
glsmith
Moderator


Joined: 16 Oct 2007
Posts: 2101
Location: Sun Diego, USA

PostPosted: Fri 05 Jun '15 21:47    Post subject: Reply with quote

Sigh, yes, and I tried to tell you that, kind of loudly even.
glsmith wrote:
But, and this is a BIG BUT, you do not want to allow direct access to the html, and by redirecting the visitor is directly accessing the html file. If the html file is protected, they will get a 403 Forbidden. If it's not protected, they could just as easily go to http://myserver/myprotectedfile.htm and not have to be tested if they are human or not.


If you want to protect that page, and only show it after they have passed through the check, you have to have the script read in the contents of the page and then have the script print the contents it read in out to the user.

http://apaste.info/GBw

That one did just that but you were already set on the redirect and not understanding why it did not work. My not saying "just use this" didn't help matters much either to be honest.
Back to top
glsmith
Moderator


Joined: 16 Oct 2007
Posts: 2101
Location: Sun Diego, USA

PostPosted: Fri 05 Jun '15 22:06    Post subject: Reply with quote

Doug22 wrote:
Code:
AllowOverride Limit
# Protect the actual html file from direct viewing.
<Files "myprotectedpage.html">
Deny from all
</Files>


OK, let's first see if this is even allowed because I don't think AllowOverride is allowed in .htaccess. Nope, it's only allowed in the <Directory> container in the main config.

See "Context",
http://httpd.apache.org/docs/2.2/mod/core.html#allowoverride

Description of Context
http://httpd.apache.org/docs/2.2/mod/directive-dict.html#Context

This tells you where a directive is allowed to be used. If you're going to use Apache, you might as well look things up as needed, and before you follow advise, it could be incomplete, or worse bad advise Smile The docs are massive, often confusing but they are your friend.

You might already have Limit as an AllowOveride in your httpd.conf or vhosts.conf or wherever this host is configured at in that machine. Not all are alike, no one but you can know, or at minimum check.
Back to top
Doug22



Joined: 02 Jun 2013
Posts: 44
Location: Houston TX

PostPosted: Sat 06 Jun '15 0:13    Post subject: Reply with quote

Do I understand that your apaste.info script does *everything* that I'm looking for? That is, it not only does a human test, but also reads the protected file? If so, my apologies. I didn't understand that.

But I'm still trying to understand how to protect that file. What I need to do is make it so that only I can read it directly. Where does that protection script that you wrote go? In .htaccess? But then the AllowOverride command goes in httpd.conf?
Back to top
Doug22



Joined: 02 Jun 2013
Posts: 44
Location: Houston TX

PostPosted: Sat 06 Jun '15 3:22    Post subject: Reply with quote

OK, I tried you apaste.info script, and it simply doesn't work. I get an Internal Server Error message when I call it up.
Back to top
Doug22



Joined: 02 Jun 2013
Posts: 44
Location: Houston TX

PostPosted: Sat 06 Jun '15 3:53    Post subject: Reply with quote

Yes yes yes yes yes yes yes!

I didn't have execute permission on your apaste.info script. Now that I do, it works.

And

I pointed it at myprotectedpage.html which was not in the public area. I'm using my own server, so I have access to that root directory.

So it's all done. It works. That page is accessible through the cgi script, but is inaccessible directly.

Now I just redirect the page name to the cgi script, so anyone using the bookmarked old name will get shunted immediately to that script.

Thank you!
Back to top


Post new topic   Reply to topic    Apache Forum Index -> Coding & Scripting Corner
Page 1 of 1