TweetFollow Us on Twitter

Enabling CGI Scripts, The Second

Volume Number: 19 (2003)
Issue Number: 10
Column Tag: Programming

Untangling the Web

Enabling CGI Scripts, The Second

by Kevin Hemenway

You've enabled CGI, but how do you know it's good?

In the last issue, we learned about CGI scripts: what they are, what they can do, how they're already enabled within Apache, and how to tweak that configuration to be more URL friendly. What we didn't do is teach you anything for the future: at most, we brought a wide-eyed wonder-boy to a patch of poison ivy, and backed away slowly. Will he rub it on his skinned knee? Pin it to little Susie's dress as a token of his affection? Roll around in it like catnip? Where is the inbred fear necessary for every child's survival?

Insert transitional one-liner here!

Dissection--Similarities

Before we can understand, be aware, and watch for the security ramifications of running CGI scripts from unknown and untrusted third parties, we need to see how they're coded, how poorly written ones can ruin our mornings, and how to look for some semblance of quality. The quickest way to get a general feel is with the two sample scripts already installed with Apache: /Library/WebServer/CGI-Executables/printenv and /Library/WebServer/CGI-Executables/printenv/test-cgi. If you looked at their source code last month, you may have noticed they're written in two different languages.

The smaller of the two scripts, test-cgi, starts with #!/bin/sh, whereas printenv instead uses #!/usr/bin/perl -T. These lines, specifically the #! prefix, are often called the "shebang", and tell us which interpreter will execute the programming instructions that follow. The interpreter located at /bin/sh, rarely seen in production CGI, indicates that the rest of the code is written in the shell scripting language. Any CGI script you deploy will need to have some sort of shebang--whether it's /bin/sh, /usr/bin/perl, /usr/bin/python or something else entirely, it's absolutely required. Not only is it necessary, it also has to be accurate: if your only Perl is /sw/bin/perl, then the shebang should point there instead. Shebangs can also contain command line arguments: in printenv, -T is passed directly to the /usr/bin/perl interpreter (where it means something we'll cover a bit later).

Another similar difference between our two scripts is the printing of something called a Content-type (Listing 1), which tell the requesting user-agent (your visitor's browser) what sort of data it's about to receive (an image to render, text to display, XML to parse, etc.). The Content-type will never actually be shown in your final output--it's hidden pixie dust for the browser's benefit only (if you're curious, Mozilla allows you to view the Content-type by getting the "Page Info" of the current URL). Without this crucial bit of contextual magic (and the two required newlines), Apache will fail your CGI scripts with an "Internal Server Error". This error is never a satisfying explanation--you'll need to check Apache's /var/log/httpd/error_log for the exact reasoning.

Listing 1: Printing the Content-type in Shell and Perl

From the sample CGI scripts printenv and test-cgi

# content type display from test-cgi
# note that echo spits out a newline,
# 2 echo's for the 2 required newlines.
echo Content-type: text/plain
echo
# and the similar entry from printenv
print "Content-type: text/html\n\n";

The values of our Content-types (text/plain and text/html) didn't just appear out of thin air--they're MIME types, and most any file you've ever worked with has one. You can find a large listing of MIME types, based on their common file extensions, by perusing the /etc/httpd/mime.types file. For example, the matching MIME types for JPEG, XHTML, Quicktime, and Microsoft Word files are:

image/jpeg                      jpeg jpg jpe
application/xhtml+xml           xhtml xht
video/quicktime                 qt mov
application/msword              doc

If you can't find the matching MIME type for the data you're interested in serving (either because it's not in the mime.types file or Google has spurned your search request), you can use the "some sort of data" MIME type of application/octet-stream. This has already been explicitly assigned to a number of files, including Apple disk images:

application/octet-stream   dms lha lzh exe class so dll dmg

Dissection--Why The Perl Script Is Arguably Stronger

All CGI scripts, regardless of what they're programmed in, can be run from the command line--whether they actually do anything useful is a case-by-case basis. This is a surprisingly useful bit of information: since troubleshooting and debugging happens best when unfrilled by complication, removing Apache from the process can prove helpful. Running your CGI scripts on the command line can preemptively weed out problems like missing Content-type's, file permission errors, invalid syntax problems, missing language extensions, and so forth.

Both the test-cgi and printenv scripts run "successfully" at the command line, although only the first gives any useful output (Figure 1). Compare this to the regular browser-based output we demonstrated in the last MacTech (or simply re-access http://127.0.0.1/cgi-bin/test-cgi). The first line is that dastardly Content-type and, as mentioned before, is normally processed by the browser and removed from the final display. Since we're running the script without the benefit of a web server or browser, the Content-type is viewable without extra effort. This becomes a handy barometer: if you run your CGI script from the command line and there's no Content-type, it'll never run correctly under Apache.


Figure 1: The slightly undefined test-cgi, when run in the Terminal

But wait... there's no Content-type if we try to run printenv (in fact, there's nothing at all), so why does it work when we access it by URL (http://127.0.0.1/cgi-bin/printenv)? In actuality, this is one of the "strengths" of the Perl version. If you check the source code, the next line after our required shebang (ignoring comments) is:

exit unless ($ENV{'REQUEST_METHOD'} eq "GET");

This terminates the script unless it was invoked via a GET request. Generically speaking, unless it is a POST, every request a web browser makes is a GET with or without key/value pairs. Since the shell isn't a web browser, no GET is issued and the script terminates. If we wanted to get fancy, we could fake the required method by running setenv REQUEST_METHOD GET && ./printenv (if you're using the tsch shell; REQUEST_METHOD=GET ./printenv if you prefer bash). As a result, we get a Terminal full of HTML listing the environment variables. We can redirect this mass of HTML to a file by adding > output.html to our previous command line; Figure 2 shows the generated file.


Figure 2: Shell output of our tricked printenv script

Figure 2 also gives us another reason why the Perl script is stronger: it doesn't pretend to know what the environment is going to look like. test-cgi, hard-coded to display the values of known variables (SERVER_SOFTWARE, SERVER_NAME, GATEWAY_INTERFACE, etc.), shows nothing but undefined values when run from the Terminal (Figure 1), where those specific entries don't normally exist.

Three Ways Perl CGI Scripts Can Be Improved

The bulk of the code within the printenv script caters to creating a pretty HTML page, something not important to the true purpose of generating a list of the current environment. To make our upcoming improvements more clearly, we'll base our changes on the Perl script shown in Listing 2, which does the exact same thing as printenv, only without the HTML. For all intents and purposes, this is a working CGI script: it's got the shebang pointing to the correct Perl interpreter, and it prints a plain-text Content-type before any other data.

Note that even though we're talking specifically about CGI scripts, the following improvements can, and should, be made in most any Perl script, especially those to be used in production environments. Security should never be a feature.

Listing 2: Printing the environment more simply

Our base.pl script could use some improvements.

#!/usr/bin/perl
print "Content-type: text/plain\n\n";
foreach $var (keys %ENV) {
   print "$var = $ENV{$var}\n";
}

Save this file as base.pl and run it from the command line; my output is in Figure 3. None of our upcoming improvements will change this display and, as you can see by comparing it to Figure 2, it's identical save for the loss of HTML (and the differences between Safari and the Terminal's interpretation of TERMCAP).


Figure 3: Our rewritten script's (base.pl) output

Our improvements to the script are quite minimal additions, but they ensure that user data has been properly checked for dangerous input, warnings have been enabled for common mistakes or typos that don't necessarily stop a script from running, and a stricter development environment has been used to encourage stronger coding and careful variable declaration. The revised script is shown in Listing 3.

Listing 3: Printing the environment more strongly

Our revised script is three times stronger than before.

#!/usr/bin/perl -wT
use strict;
print "Content-type: text/plain\n\n";
foreach my $var (keys %ENV) {
   print "$var = $ENV{$var}\n";
}
  • Use warnings: The first change, adding -w to the shebang, turns on Perl's warnings pragma, which spits a list of optional, non-fatal warnings to STDERR (which becomes Apache's error_log when run as a CGI). Technically, you don't have to address any of the messages since the script will continue on regardless, but they'll alert you to typos, uninitialized values, deprecated functions, and a slew of other mishaps that can eventually escalate into full-blown bugs. Typically, the messages are terse enough to be useful for seasoned Perl programmers, but you can increase their verbosity by adding use diagnostics; within the body of your code.

  • Use strict: Our third and fourth changes complement our warnings. Perl's strict pragma should be used in any script that is more than "casual", and ensures that every variable is pre-declared and localized, and that other "unsafe constructs" are detected and addressed. Unlike warnings, any error that triggers strict will stop your script from continuing further. You'll notice that we've localized our $var variable with the my() function. The first time you use strict, it'll feel like an unwieldy and overly doting mother, but scripts that compile cleanly benefit from an attention to detail that strengthens their quality immensely.

  • Use taint: Even though it is "strongly recommended", very few Perl or CGI scripts use taint mode, which is what the -T on the shebang enables. Under this mode, any outside data received by your code is considered highly dangerous, and will cause script errors until it has been checked for safety. These safety checks can be as simple as ensuring that a command line argument only contains alphanumerics, or that the process you're spawning isn't being handed potentially damaging shell metacharacters. While taint mode will force you to focus more strongly about the evils of the outside world and exactly what data you expect, programmers who misunderstand how to "untaint" data may inadvertently do so incorrectly, creating a false sense of security.

These programming additions aren't the ultimately panacea, but merely a placebo. Yes, your code will be stronger with them, but that doesn't mean crucial bugs won't creep in and ruin your day. Serious coders and sysadmins should take a look at the following sampling of Perl and CGI security links:

  • The Perl Security manpage, accessible by typing man perlsec in your Terminal, can also be read online at http://www.perldoc.com/perl5.6.1/pod/perlsec.html

  • "Avoiding security holes when developing an application", a six part series from LinuxFocus.org: http://www.linuxfocus.org/English/November2001/article203.shtml

  • SecureProgramming (http://www.secureprogramming.com/) offers a huge collection of links to over 50 articles, books, recipes to learn from and adapt, and more.

  • RFP's "Perl CGI problems", which appeared in an old issue of the seminal Phrack magazine, still remains relevant: http://www.wiretrip.net/rfp/txt/phrack55.txt

  • CERT's "How To Remove Meta-characters From User-Supplied Data In CGI Scripts", in both Perl and C: http://www.cert.org/tech_tips/cgi_metacharacters.html. Handy for when you're looking to untaint some data.

  • The "Securing Programming for Linux and Unix HOWTO", available from http://en.tldp.org/HOWTO/Secure-Programs-HOWTO/. Similar articles like "The Hack FAQ" (http://www.nmrc.org/pub/faq/hackfaq/index.html), and the "WWW Security FAQ" (http://www.w3.org/Security/Faq/www-security-faq.html) will also prove insightful.

    Choosing a CGI Script for Deployment

    The above programming suggestions are fine if you're solely looking at the code quality of a potential CGI script, but there are few more areas to investigate before you can consider a program worthy of being installed on your server:

    • Check the Bugtraq archives (http://securityfocus.com/archive/1). Anyone interested in security should be reading Bugtraq, where a large community of hackers, white hats, sysadmins, and professionals regularly post bugs, exploits, and warnings for insecure products. Occasionally, you'll also see new whitepapers concerning various aspects of security and programming. Before installing new scripts, comb the archives to see if any advisories have been posted. If so, ensure they've been fixed before using the code.

    • Googling for problems can prove illuminating, as you'll often find common tech support problems, heaps of praise or scorn for the code or author, and occasionally, other web hosts who offer the script for their own customer base.

    • Check the dates: When was the script last updated? Is it so long ago that no one will give a darn if you have a problem? Just because a script doesn't have any reported problems in Bugtraq doesn't mean that it isn't susceptible to relatively new exploits like cross-site scripting attacks (http://www.cgisecurity.com/articles/xss-faq.shtml). Code that has been updated recently has a better chance of good turnaround time for crucial fixes, updates, and support.

    • Got logfiles? Most CGI scripts don't have any logging capability, primarily because they only do one small thing (like email forms, add one to a number, display a calendar, etc.) Some complicated scripts, however, can benefit from logging, especially those with built-in user authentication ("who is using my site?") or flaw tracking ("a bug occurred at [time], and things turned awry [like this]"). Scripts can use their own logfiles or Perl's Sys::Syslog module to log directly to /var/log/system.log.

      Homework Malignments

      In our next column, we'll move on to configuring PHP, as well as explain the up- and downsides between forking processes (like CGI) and embedded modules (like mod_php). We'll explore the default configuration of PHP, the non-existent configuration file (php.ini) and, if we have time, how to install MySQL and do a few integration tests. For now, students may contact the teacher at morbus@disobey.com.

    • Besides -w, you can also enable Perl's warning pragma with use warnings; (similar to use strict;). Subtle differences exist between the two--research them and find out which satisfies your programming needs better.

    • Any Perl script with logging may eventually run up against a perceived "buffering" problem, the sordid details of which are explained in Mark Jason Dominus' "Suffering from Buffering?" (http://perl.plover.com/FAQs/Buffering.html).

    • If you're looking to brush up on your Perl knowledge, you can't go wrong with O'Reilly's Learning Perl, The Perl Cookbook (which just received an impressive Second Edition update), and the recent Learning Perl Objects, References, & Modules. You can read sample chapters from all the books at http://www.oreilly.com/.


      Kevin Hemenway, coauthor of Mac OS X Hacks and Spidering Hacks, is better known as Morbus Iff, the creator of disobey.com, which bills itself as "content for the discontented." Publisher and developer of more home cooking than you could ever imagine (like the popular open-sourced aggregator AmphetaDesk, the best-kept gaming secret Gamegrene.com, the ever ignorable Nonsense Network), he's twirling his hair and trying not to cheerlead. Contact him at morbus@disobey.com.

  •  

    Community Search:
    MacTech Search:

    Software Updates via MacUpdate

    OmniOutliner Pro 4.2 - Pro version of th...
    OmniOutliner Pro is a flexible program for creating, collecting, and organizing information. Give your creativity a kick start by using an application that's actually designed to help you think. It's... Read more
    VLC Media Player 2.2.1 - Popular multime...
    VLC Media Player is a highly portable multimedia player for various audio and video formats (MPEG-1, MPEG-2, MPEG-4, DivX, MP3, OGG, ...) as well as DVDs, VCDs, and various streaming protocols. It... Read more
    Nisus Writer Pro 2.1.1 - Multilingual wo...
    Nisus Writer Pro is a powerful multilingual word processor, similar to its entry level products, but brings new features such as table of contents, indexing, bookmarks, widow and orphan control,... Read more
    Tinderbox 6.2.0 - Store and organize you...
    Tinderbox is a personal content management assistant. It stores your notes, ideas, and plans. It can help you organize and understand them. And Tinderbox helps you share ideas through Web journals... Read more
    OmniOutliner 4.2 - Organize your ideas,...
    OmniOutliner is a flexible program for creating, collecting, and organizing information. Give your creativity a kick start by using an application that's actually designed to help you think. It's... Read more
    Things 2.5.4 - Elegant personal task man...
    Things is a task management solution that helps to organize your tasks in an elegant and intuitive way. Things combines powerful features with simplicity through the use of tags and its intelligent... Read more
    NeoOffice 2014.10 - Mac-tailored, OpenOf...
    NeoOffice is a complete office suite for OS X. With NeoOffice, users can view, edit, and save OpenOffice documents, PDF files, and most Microsoft Word, Excel, and PowerPoint documents. NeoOffice 3.x... Read more
    iPhoto Library Manager 4.2 - Manage mult...
    iPhoto Library Manager allows you to organize your photos among multiple iPhoto libraries, rather than having to store all of your photos in one giant library. You can browse the photos in all your... Read more
    Web Snapper 3.3.8 - Capture entire Web p...
    Web Snapper lets you capture Web pages exactly as they appear in your browser. You can send them to a file as images or vector-based, multi-page PDFs. It captures the whole Web page - eliminating the... Read more
    TeamViewer 10.0.41404 - Establish remote...
    TeamViewer gives you remote control of any computer or Mac over the Internet within seconds, or can be used for online meetings. Find out why more than 200 million users trust TeamViewer! Free for... Read more

    Chainsaw Warrior: Lords of the Night has...
    It's time to put the Darkness back in its place now that Chainsaw Warrior: Lords of the Night has officially made it to iOS. | Read more »
    A World of Ice and Fire Lets You Stalk 2...
    George R. R. Martin’s A World of Ice and Fire, by Random House, is a mobile guide to the epic series. The new update gives you the Journeys map feture that will let you track the movements of 25 different characters. But don't worry, you can protect... | Read more »
    Gameloft Announces Battle Odyssey, a New...
    Battle Odyssey, Gameloft's newest puzzle RPG, is coming to the App Store next week. Set in the world of Pondera, you will need to control the power of the elements to defend the world from evil. You'll be able to entlist over 500 allies to aid you... | Read more »
    Fusion - HDR Camera (Photography)
    Fusion - HDR Camera 1.0.0 Device: iOS Universal Category: Photography Price: $1.99, Version: 1.0.0 (iTunes) Description: Fusion creates HDR (high dynamic range) photos by capturing different exposures and then combining them into one... | Read more »
    Sago Mini Toolbox (Education)
    Sago Mini Toolbox 1.1 Device: iOS Universal Category: Education Price: $2.99, Version: 1.1 (iTunes) Description: Come build with the Sago Mini friends! Use a wrench, try a saw, or hammer some nails. From sewing hand puppets to... | Read more »
    You Should Probably Grab Hitman GO While...
    Hitman GO is a surprisingly cool (yet also incredibly drastic) departure from the Hitman series. It's well worth playing for any puzzle game fans out there, and at the moment you can get your hands - or garrotte if you will - on it for a mere $0.99... | Read more »
    IFTTT is Bringing Do Button and Do Note...
    IFTTT has announced Do Button and Do Note for the Apple Watch. Do Button lets you make your own personalized button that can connect to things like your Google Drive, control the temperature in your home with Nest Thermostat, or turn the lights on... | Read more »
    How Many Days, Hours, and Minutes Are Le...
    Countdown, by Yves Tscherry, is now available on the App Store. The app keeps track of countdowns to your favorite things such as someones birthday or days till the New Year. You can display the time in seconds, minutes, hours, days, weeks, months,... | Read more »
    The All-New Misfit 2.0 App is Available...
    Misfit has just given their app a complete overhaul. Misfit 2.0 now has a brand new interface with a sleek design and is easier to navigate. You'll be able to sync your Misfit device and look up health and fitness information faster than ever before... | Read more »
    Halo: Spartan Strike (Games)
    Halo: Spartan Strike 1.0 Device: iOS Universal Category: Games Price: $5.99, Version: 1.0 (iTunes) Description: Delve into 30 challenging missions through cities and jungles using a devastating arsenal of weapons, abilities and... | Read more »

    Price Scanner via MacPrices.net

    TigerText Introduces First Secure Enterprise...
    TigerText, a provider of secure, real-time messaging for the enterprise, has announced the launch of TigerText for the Apple Watch. TigerText for the Apple Watch enables users to securely send and... Read more
    The Conservation Fund Partners with Apple To...
    The Conservation Fund has announced that it will partner with Apple to help protect working forests in the United States. The Apple initiative will conserve more than 36,000 acres of working... Read more
    Clearance 13-inch 2.6GHz Retina MacBook Pro a...
    B&H Photo has clearance 2014 13″ 2.6GHz/128GB Retina MacBook Pros now available for $1099, or $200 off original MSRP. Shipping is free, and B&H charges NY sales tax only. Read more
    Apple refurbished 2014 13-inch Retina MacBook...
    The Apple Store has Apple Certified Refurbished 2014 13″ Retina MacBook Pros available for up to $400 off original MSRP, starting at $979. An Apple one-year warranty is included with each model, and... Read more
    iMacs on sale for up to $205 off MSRP, NY tax...
    B&H Photo has 21″ and 27″ iMacs on sale for up to $205 off MSRP including free shipping plus NY sales tax only: - 21″ 1.4GHz iMac: $1019 $80 off - 21″ 2.7GHz iMac: $1189 $110 off - 21″ 2.9GHz... Read more
    Sale! 16GB iPhone 5S for $1 with service
    Best Buy is offering 16GB iPhone 5Ss for $1.00 with 2-year activation at a participating cellular provider. Choose free home shipping and activation, or buy online and activate during in-store pickup... Read more
    Apple refurbished 2014 MacBook Airs available...
    The Apple Store has Apple Certified Refurbished 2014 MacBook Airs available starting at $679. An Apple one-year warranty is included with each MacBook, and shipping is free. These are currently the... Read more
    27-inch 3.5GHz 5K iMac on sale for $2349, sav...
     Adorama has the 27″ 3.5GHz 5K iMac in stock today and on sale for $2349 including free shipping plus NY & NJ sales tax only. Their price is $150 off MSRP. For a limited time, Adorama will... Read more
    Save up to $380 on an iMac with Apple refurbi...
    The Apple Store has Apple Certified Refurbished iMacs available for up to $380 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free: - 27″ 3.5GHz 5K iMac – $2119 $... Read more
    iFixIt Teardown Awards 12-IInch Retina MacBoo...
    iFixIt has posted its illustrated teardown of the new 12-inch MacBook Retina. They note that this new MacBook is less than half the thickness of the last Apple notebook called just “MacBook” back in... Read more

    Jobs Board

    *Apple* Watch SW Application Project Manager...
    **Job Summary** The Apple Watch software team is looking for an Application Engineering Project Manager to work on new projects for Apple . The successful candidate Read more
    *Apple* Solutions Consultant - Retail Sales...
    **Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail Read more
    *Apple* Retail - Multiple Positions (US) - A...
    Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
    Technical Project Manager - *Apple* Pay - A...
    **Job Summary** Apple Pay is seeking an experienced technical PM to…manage the on boarding of new merchants for the Apple Pay platform in the US Within this role you Read more
    Senior Identity Architect - *Apple* Pay - A...
    **Job Summary** Apple , Inc. is looking for a highly motivated, innovative and hands-on senior identity architect to join the Apple Pay Engineering team. You will Read more
    All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.