To LUGNET HomepageTo LUGNET News HomepageTo LUGNET Guide Homepage
 Help on Searching
 
Post new message to lugnet.admin.generalOpen lugnet.admin.general in your NNTP NewsreaderTo LUGNET News Traffic PageSign In (Members)
 Administrative / General / 1794
1793  |  1795
Subject: 
Re: Cracking down on unauthorized image links
Newsgroups: 
lugnet.admin.general
Date: 
Wed, 9 Jun 1999 17:33:10 GMT
Viewed: 
2094 times
  
In lugnet.admin.general, Horst_Lehner@bb.maus.de (Horst Lehner) writes:
The robust, long-term solution is to serve the JPEG images selectively
to on-site pages and reject them to off-site pages, using an Apache
webserver module called "mod_rewrite" and looking at the HTTP referrer
field on-the-fly; or invoking a CGI script whenever an image is
requested, and optionally doing more advanced filtering.

Looks like you already have that cgi script in place now -- would you
mind to share it with less skilled web authors like me?

Horst,
Here it is (attached below).  Note that there are four lines in it that
you'll need to redefine with your own server-specific stuff:

1. The path to perl (top of the file)
2. The directory where your images are stored (top of the code)
3. The regex for matching allowable domain names (middle of the code)
4. The URL of your "oops" image (bottom of the code/file)

I'm placing this file/program/script into the public domain (no copyright
or license) but in return please send along any modifications you may make
which others may find useful.

--Todd




#!/path/to/perl
#------------------------------------------------------------------------------
#
#  GENERAL IMAGE CONDUIT
#
#  This quick & dirty script return a single graphic image -- as long it isn't
#  requested directly by an unauthorized offsite link.  This is intended to
#  keep people from linking directly to images, which unfairly gobbles up
#  system bandwidth and resources.  For more background:
#
#     http://www.lugnet.com/news/display.cgi?lugnet.admin.general:1740
#
#  Input to this script is the URI fragment of an image, encoded in standard
#  CGI format, for example:
#
#     http://www.lugnet.com/img.cgi?foo/bar/gonk/blorp17.jpg
#
#  The URI is relative to a base directory in the local file system.  The URI,
#  of course, doesn't need to be the actual URI of the image on the webserver;
#  in fact, it should not be -- otherwise clever users could munge the URI into
#  a well-formed URL and access the images that way.  Rather, the images should
#  be located in a special directory outside of the webserver's root directory
#  but still accessible by this CGI script.
#
#  Note:  There are at least three weak points here:  This algorithm relies on
#  browser to set the referring page correctly and honestly, and some browsers
#  (certainly in the minority, however) do not set the HTTP referrer field
#  when requesting a new URL.  Therefore, images must be served when the HTTP
#  referrer is undefined, which means that (1) direct off-site image links will
#  be silently honored for browsers which do not set the HTTP referrer,
#  including even modern browsers which by design do not set it when they are
#  switching access methods, for example from "file://" to "http://"; that (2)
#  if a user can figure out a way to invoke an arbitrary URL in the browser
#  without setting the HTTP referrer, this mechanism will be defeated in that
#  case; and that (3) if ever the mechanism is defeated, it is unlikely to be
#  readily detectable.  Nevertheless, although this algorithm is imperfect,
#  it is the canonical way to prevent image link exploiting, and in practice
#  serves well to reduce direct linking problems dramatically.  The script
#  also runs extremely fast on systems with efficient forking and I/O.
#
#  Legal Notice:  This file of code has been placed into the public domain by
#  its author.  There is therefore no copyright.  This code contained herein
#  also carries no warranty of any kind.  Use at your own risk.
#
#  Todd Lehman, 2 Jun 1999
#

use strict; $^W = 1;


# Directories and filenames...

my $basedir = "/usr/home/lugnet/www_images";
my $filename = "$basedir/$ENV{QUERY_STRING}";  # Image requested by client


# Only allow HTTP methods of GET and HEAD (disallows POST, DELETE, etc.)...

Forbidden() if ($ENV{REQUEST_METHOD}||'') !~ m/^(?:GET|HEAD)$/;


# Weed out a few known robots (they shouldn't be invoking CGI scripts!)...

my $robots = "Crawl|Robot|Slurp|Snoop|Spider|Teleport Pro|WebCopy|LWP::Simple";
Forbidden() if ($ENV{HTTP_USER_AGENT}||'') =~ m/$robots/;


# Determine content type and filter out requests for non-images.

my %content = ('gif'=>'image/gif', 'jpg'=>'image/jpeg', 'jpeg'=>'image/jpeg');
my ($type) = ($filename =~ m/\.([^\.]+)$/);
$type = lc($type);
Forbidden() if !$content{$type};


# Filter filename to prevent shell-trickery and directory snooping...

Forbidden() if $filename =~ m/[^a-zA-Z0-9_\-\+\.\/]/;  # stop trickery
Forbidden() if $filename =~ m/\.\./;  # stop directory snooping
Forbidden() if !-r $filename;


# Filter out bad referrers (unauthorized off-site links)...

my $domain = "(?:www\.)?foo\.bar\.gonk";
Oops() if $ENV{HTTP_REFERER} && $ENV{HTTP_REFERER} !~ m{^http://$domain}i;


# Now it is safe to "slurp & burp" the file...

open IMAGE, "<$filename" or die;
print "Content-type: $content{$type}\n",
      "Content-length: @{[ (stat(IMAGE))[7] ]}\n",
      "\n";
local $/;  # Slurp entire file with <IMAGE> rather than line-by-line.
print <IMAGE> unless $ENV{REQUEST_METHOD} eq 'HEAD';
close IMAGE;
exit 0;


# Not all browsers may support the 'Status:' header, but this will definitely
# result in a broken-image link on all browsers.

sub Forbidden()
{
   print "Status: 403 Forbidden\n\n";
   exit 0;
}


# Redirect the browser to the default image file, which should contain a bit of
# of additional information (such as a URL) embedded in it.  The redirection
# causes an extra HTTP request to occur, but at least the default image will be
# cached this way, which may result in fewer requests overall.

sub Oops()
{
   print "Location: http://foo.bar.gonk/oops.gif\n\n";
   exit 0;
}



Message is in Reply To:
  Re: Cracking down on unauthorized image links
 
Hi Todd, (...) Even though I have to admit that I have used direct image links (but with credit for the source) in some of my eBay auctions, I have to agree with this argument, and will copy images in the future. (...) Looks like you already have (...) (25 years ago, 9-Jun-99, to lugnet.admin.general)

41 Messages in This Thread:

















Entire Thread on One Page:
Nested:  All | Brief | Compact | Dots
Linear:  All | Brief | Compact
    

Custom Search

©2005 LUGNET. All rights reserved. - hosted by steinbruch.info GbR