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

    Firefox 37.0 - Fast, safe Web browser. (...
    Firefox offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals and casual... Read more
    Arq 4.11 - Online backup to Google Drive...
    Arq is super-easy online backup for the Mac. Back up to your own Google Drive storage (15GB free storage), your own Amazon Glacier ($.01/GB per month storage) or S3, or any SFTP server. Arq backs up... Read more
    MacFamilyTree 7.3.4 - Create and explore...
    MacFamilyTree gives genealogy a facelift: it's modern, interactive, incredibly fast, and easy to use. We're convinced that generations of chroniclers would have loved to trade in their genealogy... Read more
    Yummy FTP 1.10.2 - FTP/SFTP/FTPS client...
    Yummy FTP is an FTP + SFTP + FTPS file transfer client which focuses on speed, reliability and productivity. Whether you need to transfer a few files or a few thousand, schedule automatic backups, or... Read more
    VueScan 9.5.08 - Scanner software with a...
    VueScan is a scanning program that works with most high-quality flatbed and film scanners to produce scans that have excellent color fidelity and color balance. VueScan is easy to use, and has... Read more
    Iridient Developer 3.0.1 - Powerful imag...
    Iridient Developer (was RAW Developer) is a powerful image conversion application designed specifically for OS X. Iridient Developer gives advanced photographers total control over every aspect of... Read more
    Air Video Server HD 2.1.0 - Stream video...
    Air Video Server HD streams videos instantly from your computer on your iPhone, iPad, iPod touch or Apple TV. No need to worry about converting or transferring files. We took everything that was... Read more
    Duplicate Annihilator 5.7.5 - Find and d...
    Duplicate Annihilator takes on the time-consuming task of comparing the images in your iPhoto library using effective algorithms to make sure that no duplicate escapes. Duplicate Annihilator... Read more
    BusyContacts 1.0.2 - Fast, efficient con...
    BusyContacts is a contact manager for OS X that makes creating, finding, and managing contacts faster and more efficient. It brings to contact management the same power, flexibility, and sharing... Read more
    Capture One Pro 8.2.0.82 - RAW workflow...
    Capture One Pro 8 is a professional RAW converter offering you ultimate image quality with accurate colors and incredible detail from more than 300 high-end cameras -- straight out of the box. It... Read more

    2K Announces WWE 2K, Mobile's First...
    It seems like this month has been pretty big for wrestling. First Wrestlemania, then 2K has announces that they're releasing  WWE 2K for iOS. It's a simulation-based WWE game where you'll get to play with several WWE superstars such as John Cena, ... | Read more »
    How the Apple Watch Could Change the Fac...
    The Apple Watch is still a ways out, but my previous musings on the wearable’s various features got me thinking: what might it be like a year after launch? Two years? Five years? What if it becomes a symbiotic part of the iOS framework to the point... | Read more »
    Pie In The Sky: A Pizza Odyssey (Games)
    Pie In The Sky: A Pizza Odyssey 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: A game about delivering pizza. In space. | Read more »
    Chosen Gives Hopeful Singers, Songwriter...
    If YouTube videos and reality TV shows like The Voice have taught us one thing, it’s that there are a lot of people out there who are anxious to show the world their talents. And if they’ve taught us a second thing, it’s that there’s an almost... | Read more »
    Android's Popular OfficeSuite Now A...
    Once only available for Android devices, OfficeSuite has finally landed on the app store. The Mobile Systems app lets you view, edit, create, and share Word, Excel, and PowerPoint documents as well as convert them to/from PDFs. It's touted as being... | Read more »
    Warhammer: Arcane Magic is Coming Soon,...
    Turbo Tape Games has announced that they're joining forces with Games Workshop to bring the turn-based strategy board game, Warhammer: Arcane Magic, to life on the iOS. | Read more »
    Fast & Furious: Legacy's Creati...
    | Read more »
    N-Fusion and 505's Ember is Totally...
    | Read more »
    These are All the Apple Watch Apps and G...
    The Apple Watch is less than a month from hitting store shelves, and once you get your hands on it you're probably going to want some apps and games to install. Fear not! We've compiled a list of all the Apple Watch apps and games we've been able to... | Read more »
    Appy to Have Known You - Lee Hamlet Look...
    Being at 148Apps these past 2 years has been an awesome experience that has taught me a great deal, and working with such a great team has been a privilege. Thank you to Rob Rich, and to both Rob LeFebvre and Jeff Scott before him, for helping me... | Read more »

    Price Scanner via MacPrices.net

    13-inch 2.4GHz Retina MacBook Pro available f...
    MacMall has the 2013 13″ 2.4GHz/128GB Retina MacBook Pro available for $949.99 for a limited time. Shipping is free. Their price is $350 off original MSRP, and it’s the only sub-$1000 new Retina... Read more
    Adobe Brings Powerful Layout-Design Capabilit...
    Adobe today announced the availability of Adobe Comp CC, a free iPad app that enables rapid creation of layout concepts for mobile, Web and print projects. With Comp CC, designers can rough out and... Read more
    13-inch 2.6GHz/256GB Retina MacBook Pro avail...
    Best Buy has clearance 2014 13″ 2.6GHz/256GB Retina MacBook Pros available for $1199.99 including free shipping. Their price is $300 off original MSRP, and it’s the lowest price for this model.... Read more
    Updated Mac Price Trackers
    We’ve updated our Mac Price Trackers with the latest information on prices, bundles, and availability on systems from Apple’s authorized internet/catalog resellers: - 15″ MacBook Pros - 13″ MacBook... Read more
    21-inch 1.4GHz iMac on sale for $999, save $1...
    Best Buy has the 21″ 1.4GHz iMac on sale for $999.99 on their online store. Choose free shipping or free local store pick up. Price is for online orders only, in-store prices may vary. Their price is... Read more
    2.6GHz Mac mini on sale for $649, save $50
    Amazon has the 2.6GHz Mac mini on sale for $649.99 including free shipping. Their price is $50 off MSRP, and it’s the lowest price available for this model. Read more
    Textkraft Professional 3.2 Powerful iPad Text...
    Finally it’s springtime, at least theoretically in my neck of the woods, where we’re still navigating canyons between towering snowbanks with temperatures well below freezing in winter weather that... Read more
    Apple offering refurbished 27-inch 5K iMacs f...
    The Apple Store is offering Apple Certified Refurbished 27″ 3.5GHz 5K iMacs for $2119 including free shipping. Their price is $380 off the price of new models, and it’s the lowest price available for... Read more
    16GB iPad mini on sale for $199, save $50
    Walmart has 16GB iPad minis (1st generation) available for $199.99 on their online store, including free shipping. Their price is $50 off MSRP. Online orders only. Read more
    New 128GB MacBook Airs on sale for $50 off MS...
     B&H Photo has 128GB 11″ and 13″ 2015 MacBook Airs on sale today for $50 off MSRP including free shipping plus NY sales tax only: - 11″ 1.6GHz/128GB MacBook Air (Model #MJVM2LL/A): $849 $50 off... Read more

    Jobs Board

    DevOps Software Engineer - *Apple* Pay, iOS...
    **Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring 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
    Sr. Technical Services Consultant, *Apple*...
    **Job Summary** Apple Professional Services (APS) has an opening for a senior technical position that contributes to Apple 's efforts for strategic and transactional Read more
    Lead *Apple* Solutions Consultant - Retail...
    **Job Summary** Job Summary The Lead ASC is an Apple employee who serves as the Apple business manager and influencer in a hyper-business critical Reseller's store Read more
    *Apple* Pay - Site Reliability Engineer - Ap...
    **Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
    All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.