Solved

How do I do basic CGI file security?

Posted on 2002-06-23
16
297 Views
Last Modified: 2013-12-25
I would like to write CGI files that can be called from server-side (PHP) code in my site's Web pages, but that cannot be browsed to by the remote user's browser or by Web pages the remote user might write.

The problem I'm trying to solve is illustrated by this example:

Let's say I want to write '/cgi-bin/counter.pl', a hit counter. It will access data file 'count.dat' also located in the cgi-bin dir. I want to increment the hit count by calling counter.pl from PHP (server-side) code in my home page (possibly sending GET or POST arguments to counter.pl), but I don't want the remote user to be able to call counter.pl and mess up the count.

That is, I want counter.pl to be callable from my Web site but not from anyone else's Web site.

Normally, of course, the user can browse to any CGI file. This will execute or interpret the file and send its output back to the user's browser. I would like this default behavior to continue for all CGI files except counter.pl.

I'm sure I'm missing something very basic indeed. It would be wonderful if someone can enlighten me, or point me to a good tutorial.

Thanks,
David
0
Comment
Question by:dspector
  • 6
  • 4
  • 3
  • +2
16 Comments
 
LVL 15

Expert Comment

by:samri
Comment Utility
David,

It all depends on your webserver platform.

If using Apache;

I would be possible to examine the HTTP_REFERER env variable in the CGI program itself.

If you counter-pl is called from your PHP scripts, then the HTTP_FERERER="http://yoursite/yourphp.php", otherwise, it will be something else, or undefined maybe.

So it is possible to construct the couter.pl in such a way to update the counter.dat if the HTTP_REFERER is valid.  The env var would be $ENV{HTTP_REFERER}.

Apache has a FAQ on this.  Not directly related, but can be applied to you requirement.

http://httpd.apache.org/docs/misc/FAQ.html#image-theft


good luck.
0
 
LVL 15

Expert Comment

by:samri
Comment Utility
David,

There is one discussion already in PAQ.  The question is directly about preventing image theft, but should be workable for you liking (still Apache centric).
PAQ: http://www.experts-exchange.com/apache/Q_20255627.html

There are several suggestion that I proposed, but this one is claimed to be the one chosen:

The info from the link you provided worked.  Thanks.
http://www.chaosreigns.com/adventures/entry.php?date=2001-11-28&num=1

cheers.
0
 
LVL 11

Expert Comment

by:mouatts
Comment Utility
Its got absolutely nothing to do with using Apache all browsers send HTTP_REFERER unless blocked by a firewall and as an HTTP header all servers will present it as a server variable.

The basic idea of using this to check that the counter was called from the right place is fine, although be aware that spoofing the referer is simple if some one wants to stuff things up. But then why should they?

Steve


0
 
LVL 51

Expert Comment

by:ahoffmann
Comment Utility
> .. all browsers send HTTP_REFERER ..
NO.
Some old ones (Netscape 2.x for example) don't do.
Probably not of interest nowerdays, but there are such browsers.
0
 
LVL 11

Expert Comment

by:mouatts
Comment Utility
ahoffman - true but we are talking very old browsers now (looking at the stats from a very high hit site netscape 2 makes up 0.0% of users!).

The point I was making was that it has absolutley nothing to do with the web server involved as Samri had suggested.

Steve
0
 
LVL 6

Expert Comment

by:andreif
Comment Utility
HTTP_REFERER: you should be very careful with using this

reason 1: some browsers do not support this header and some allow to switch it off
reason 2: I have evidence that some firewalls kill this header!
reason 3: it's very easy to overwrite this header's value. So, I'd recomend do not use HTTP_REFERER where you need secure and 100% working solution.
0
 
LVL 11

Expert Comment

by:mouatts
Comment Utility
andreif: I think we already said all that.

(Forget evidence about firewalls - Norton Personal Firewall has this as one of its privacy settings - case proved).
0
 
LVL 15

Expert Comment

by:samri
Comment Utility
it's kinda of funny.

The original question is about the protecting the counter, and David is looking for ways to get it to work.

HTTP_REFERRER approach is one option that I put up with.  It may not be the only option, and neither the best.

I would be happy if somebody could at least suggest something different rather than killing the HTTP_REFERRER options.

it's like saying a product is crappy, and not sugessting any alternative.

cheers.
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 11

Expert Comment

by:mouatts
Comment Utility
Read what I originally said carefully and you will see I wasn't rubbishing the idea justing pointing out the potential problems (which I don't think are major) and correcting what you said about apache etc.

To be honest using the refer is the best way in my opinion, its not perfect but it is as good as you are going to get.

Steve
0
 
LVL 6

Expert Comment

by:andreif
Comment Utility
2 mouatts: Sorry if I repeated things which has been already said.

2 samri: I said "I'd recomend do not use HTTP_REFERER where you need secure and 100% working solution."

But I should say that I can't suggest easy & effective solution for a BASIC protection.  Please, read my comment as warning only.
0
 
LVL 1

Author Comment

by:dspector
Comment Utility
Hi, all. I was planning to pick the best answer and close the question today, but it is not yet clear that the discussion is over. I appreciate all the helpful comments.

I've done some experiments:

I'm using Apache/Unix. I'm using a "printenv" Perl in my cgi-bin dir. This cgi program shows the value of %ENV for each key.

I'm doing three tests with this printenv.pl:

1. Calling it directly as a browser URL.
2. Calling it from a page on the same site in javascript as "location.href = '...';".
3. Calling it from a page on the same site using the server-side preprocessing language PHP as "readfile(...);".

The result: The HTTP_REFERER variable does not appear in the output for any of the tests.

I repeated the tests in my local development environment (Apache/Windows), and there is also no HTTP_REFERER variable.

David
0
 
LVL 11

Expert Comment

by:mouatts
Comment Utility
Yep they are three occasions when there is no referer, not because it is being suppress but because there geuninly no referer.

The referer is only present when it is called directly from a link or form within a page.

However as you wan to prevent people frigging your counter is this a problem in that if no referer is present then you don't increment the count.
0
 
LVL 1

Author Comment

by:dspector
Comment Utility
Unfortunately, since I want to be able to use protected data files in various ways (not just a counter--that was an example), I cannot be limited to calling from HTML (link or form).

I got some helpful suggestions from another forum on the Web. I will give them here in case anyone finds them interesting.

The first method is to call the CGI program or the PHP code that accesses the data with a URI arg containing a password. Both the page sending the URI and the receiver are visible only on the server, not to users' browsers.

The second method is to use an .htaccess file (Apache-specific) to deny access to all files (the data files) contained in its dir from all IP addresses except the one hosting my pages.

Thanks all for your suggestions. I'm not sure that I can accept any as the answer, but I will wait a day or two just in case.

David
0
 
LVL 11

Accepted Solution

by:
mouatts earned 200 total points
Comment Utility
Well that puts a completely different slant on the question!

As I understand your description the second solution won't work.

If you are say there is a public page (ie your page) that has a link in eg
<A HREF="/securearea/myfile.dat">Click here</a>

and that the securearea is only accessible using the IP address of your webserver. The no-one will ever see the file unless they happen to be surfing from that machine.

When someone clicks on that link the only IP address that will be passed to your server will be the address of the client. Not the IP address of server that originally served the page that the link was in. HTTP just doesn't work like that.

Again if I understand your description of the first solution that won't work either .

If PageA has the link to the CGI, that then accesses the secure area and passes the data back then all someone needs to do is call the CGI independently.

Basically if there is any way throught to the file then someone can independently get to it.

However I do have one suggestion for you that should handle this situation without using the referer etc.

Assume that PageA contains a link to PageB.
PageB contains a link to the file that you want to protect.

PageB should actually be generated by a CGI. This CGI should store the incoming IP address and time to a database or file along with a randomly generated number to be used as a key. The key should be passed as a parameter to the link that you output in PageB.

PageB is a second CGI which looks up using the incoming record the previsouly stored values and compare the new incoming IP address and the time (with some leeway given obvisouly). If they match then the file can be passed back, if not reject the request.

Its not totally impossible to beat but it is certainly beyond the ability of most people.

Incidentally you can still use the original first suggestion to protect the actual data file although the easier method is simply to store the file outside the accessible paths or the webserver.

Steve




0
 
LVL 1

Author Comment

by:dspector
Comment Utility
Steve, Thank you for your thoughtful and interesting ideas.

After thinking about several approaches, and wanting a generalized solution to other similar problems, I have decided to go with a different approach, one that has no easy security holes.

I put all my data files in a new directory (rather unimaginatively called "data") and added an .htaccess file (my server runs Apache/Unix, my development server runs Apache/Windows) with the following content:

<Files ~ ".*">
     Order allow,deny
     Allow from 127.0.0.1 <--- Replace with your IP
     Satisfy All
</Files>

This tells the server to disallow any references to files in "data" except those that directly come from the server. That means that the files can only be accessed in server-side code (CGI files, ASP, PHP, etc.).

Thanks,
David
0
 
LVL 1

Author Comment

by:dspector
Comment Utility
I am awarding you the points because you seem to have contributed most to the discussion. I also appreciate samri's contributions.

David
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Preface In the first article: A Better Website Login System (http://www.experts-exchange.com/A_2902.html) I introduced the EE Collaborative Login System and its intended purpose. In this article I will discuss some of the design consideratio…
Preface This is the third article about the EE Collaborative Login Project. A Better Website Login System (http://www.experts-exchange.com/A_2902.html) introduces the Login System and shows how to implement a login page. The EE Collaborative Logi…
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now