OpenBSD httpd CGI support

This first recommended step, to get CGI working, is to begin by getting basic HTTP requests functional. For details on how to do thatwiht OpenBSD's httpd, see configuring OpenBSD's httpd and other information available within the rest of the virtual machine: HTTP server section.

cpytobak /etc/httpd.conf
echo ${VISUAL}
sudoedit /etc/httpd.conf

As an example, the file starts with

chroot "/var/www/" # /var/www is the default.  Having this documents location.

And then, later, says:


server "example.org" \
{
listen on * port 80
listen on :: port 80
alias "www.example.org"
alias "*.example.org"
root "sites/exmplorg/"
directory auto index
directory index "index.htm"
}

Change that later section to look more like:


server "example.org" \
{
listen on * port 80
listen on :: port 80
alias "www.example.org"
alias "*.example.org"
root "sites/exmplorg/"
location "/cgi-bin/*" \
{
fastcgi
root "/sites/sitename/"
}
directory auto index
directory index "index.htm"
}

Verify that the configuration seems acceptable.

httpd -nf /etc/httpd.conf

e.g.:

$ httpd -nf /etc/httpd.conf
httpd: need root privileges
$ sudo httpd -nf /etc/httpd.conf
configuration OK
$ echo ${?}
0
$

Before making the changes effective, run the required “helper” program.

$ sudo slowcgi

Make some CGI content accessible.

This ought to be customized. This probably needs to be customized for every individual site that is having CGI enabled.

pwd
cd /var/www/sites/exmplorg/
sudo mkdir cgi-bin
sudo ln -s cgi-bin/ cgi-src
sudo ls -l ../../cgi-bin/[pt]*
for x in ../../cgi-bin/[pt]* ; do ls -l ${x} ; done
for x in ../../cgi-bin/[pt]* ; do sudo ln -s ../${x} cgi-bin/ ; done
cd ${OLDPWD}
pwd
ls -ld /var/www/sites/exmplorg/cgi-*

Get config to be effective:

$ sudo httpd -n
$ sudo pkill -HUP httpd

Make other changes. First, here's a sample of what it looks like:

$ ls -l /var/www/cgi-bin/
total ###
----------  1 root  bin  ###### MMM DD  YYYY bgplg
$ sudo mkdir /var/www/sites/$(hostname -s)/cgi-bin/
$ cd /var/www/sites/$(hostname -s)/cgi-bin/
$ pwd
/var/www/sites/sitename/cgi-bin
$ ls -l
(This could be blank. If this was a brand new directory,
it would be blank, so ls would have output nothing.)
$ sudo cp /var/www/cgi-bin/bgplg .
$ ls -l
total ###
----------  1 root  bin  ###### MMM DD  YYYY bgplg
$ sudo chmod 555 ./*
$ ls -l /var/www/cgi-bin/
total ###
-r-xr-xr-x  1 root  bin  ###### MMM DD  YYYY bgplg
$

Here is the first part of a list of just the commands:

ls -l /var/www/cgi-bin/
sudo mkdir /var/www/sites/$(hostname -s)/cgi-bin/
cd /var/www/sites/$(hostname -s)/cgi-bin/
pwd

That needed some customization. Here is the remaining part of the list of just the commands:

ls -l
sudo cp /var/www/cgi-bin/bgplg .
ls -l
sudo chmod 555 ./*
ls -l /var/www/cgi-bin/

One more piece needed to add CGI support:

sudo slowcgi

Have the web browser see some source code, by pointing it to:

http://localhost/cgi-bin/test-cgi

Post-Reboot Survivability
cpytobak /etc/rc.conf.local
echo slowcgi_flags=\"\"| sudo -n tee -a /etc/rc.conf.local
Further CGI testing/support
Supporting test-cgi
Background

This is based on test-cgi which can be obtained using upcoming details.

  • Warning:
    • Preliminary research into this file has suggested that people have deemed it to be insecure. (Perhaps the only significant threat was leaking the values of environment variables?) Still, out of an abundance of caution, the current recommendation is to not use this file except for temporary testing in a secured environment.
  • Credits:
Sample deployment
GTCGITST=http://cyberpillar.com/dirsver/1/mainsite/tutorial/bytoogam/multsvpj/vkidspri/kidvms/vmhttpsv/usecgi/cgiapach/cgiexmpl/
ftp -o ~/testcgi1.gz ${GTCGITST}/testcgi/testcgi1.gz
pwd
cd /var/www/sites/sitename/cgi-bin/
gzip -dc ~/testcgi.gz | sudo -n tee -a ./test-cgi
sudo chmod 555 ./test-cgi
ls -l
echo ${OLDPWD}

Does everything seem good? Nope. If you thought so, well, give it a try. The web browser will likely show an error result code of 500, blaming server misconfiguration.

Seeing a problem

To see why:

head -1 test-cgi

Example output:

$ head -2 test-cgi
#!/bin/sh

$

Ah, so this does seem customized compared to the original version:

$ head -2 test-cgi
#

# To permit this cgi, replace # on the first line above with the
# appropriate #!/path/to/sh shebang, and set this script executable
# with chmod 755.
#
# ***** !!! WARNING !!! *****
# This script echoes the server environment variables and therefore
# leaks information - so NEVER use it in a live server environment!
# It is provided only for testing purpose.
# Also note that it is subject to cross site scripting attacks on
# MS IE and any other browser which fails to honor RFC2616.

  • In the opinion of the author of this text, “ chmod 755 filename ” is more preferred than “ chmod 555 filename ”. The lower-numbered of these values will prevent the owning user from writing to the file unless permissions are changed. Granted, the amount of additional security is rather negligible, but this particular file shouldn't need customization after initial deployment. So there is no need to permit easy writing.
  • Microsoft Internet Explorer has been known to receive security improvements with newer versions, so perhaps it has become compliant after the quoted text has been written.
  • RFC 2616: Hypertext Transfer Protocol -- HTTP 1.1 is now marked as “obsoleted” by some newer RFCs.

So there is a file referenced by the version included with the OpenBSD package.

Fixing the issue
pwd
sudo cp /bin/sh /var/www/bin/
sudo ls -l ../bin/

Note that the specified bin/ directory is underneath the chroot directory, and is sharing the directory with all other websites that are served by this server. The location ought to be customizable by specifying a custom chroot value for an individual website. However, that may also affect logging. This guide is not showing how to accomplish that, because having one set of logs, combining the details for multiple sites, may be preferred (perhaps more commonly than wanting to have individual versions of executables).

Supporting PERL 5 and printenv
Background

This is based on printenv which can be obtained using upcoming details.

  • Warning:
    • Preliminary research into this file has suggested that people have deemed it to be insecure. (Perhaps the only significant threat was leaking the values of environment variables?) Still, out of an abundance of caution, the current recommendation is to not use this file except for temporary testing in a secured environment.
  • Credits:
Sample deployment
GTCGITST=http://cyberpillar.com/dirsver/1/mainsite/tutorial/bytoogam/multsvpj/vkidspri/kidvms/vmhttpsv/usecgi/cgiapach/cgiexmpl/
ftp -o ~/printenv.gz ${GTCGITST}/printenv/prntenv1.gz
pwd
cd /var/www/sites/sitename/cgi-bin/
gzip -dc ~/printenv.gz | sudo -n tee -a ./printenv
sudo chmod 555 ./printenv
ls -l
echo ${OLDPWD}

Does everything seem good? Nope. If you thought so, well, give it a try. The web browser will likely show an error result code of 500, blaming server misconfiguration.

Seeing a problem

To see why:

head -1 printenv

Example output:

$ cat printenv
#!/usr/bin/perl
##
##  printenv -- demo CGI program which just prints its environment
##

print "Content-type: text/plain\n\n";
foreach $var (sort(keys(%ENV))) {
    $var = $ENV{$var};
    $var =~ s|\n|\\n|g;
    $var =~ s|"|\\"|g;
    print "$var=\"${var}\"\n"
};

$

Ah, so this does seem customized compared to the original version:

#

# To permit this cgi, replace # on the first line above with the
# appropriate #!/path/to/perl shebang, and on Unix/Linux also
# set this script executable with chmod 755.
#
# ***** !!! WARNING !!! *****
# This script echoes the server environment variables and therefore
# leaks information - so NEVER use it in a live server environment!
# It is provided only for testing purpose.
# Also note that it is subject to cross site scripting attacks on
# MS IE and any other browser which fails to honor RFC2616.

##
##  printenv -- demo CGI program which just prints its environment
##
use strict;
use warnings;

print "Content-type: text/plain\n\n";
foreach $var (sort(keys(%ENV))) {
    $var = $ENV{$var};
    $var =~ s|\n|\\n|g;
    $var =~ s|"|\\"|g;
    print "$var=\"${var}\"\n"
};

  • In the opinion of the author of this text, “ chmod 755 filename ” is more preferred than “ chmod 555 filename ”. The lower-numbered of these values will prevent the owning user from writing to the file unless permissions are changed. Granted, the amount of additional security is rather negligible, but this particular file shouldn't need customization after initial deployment. So there is no need to permit easy writing.
  • Microsoft Internet Explorer has been known to receive security improvements with newer versions, so perhaps it has become compliant after the quoted text has been written.
  • RFC 2616: Hypertext Transfer Protocol -- HTTP 1.1 is now marked as “obsoleted” by some newer RFCs.

So there is a file referenced by the version included with the OpenBSD package.

Fixing the issue

First, some sample output:

$ ldd /usr/bin/perl
/usr/bin/perl:
Start            End              Type Open Ref GrpRef Name
00000########000 00000########000 exe  1    0   0      /usr/bin/perl
00000######00000 00000########000 rlib 1    0   0      /usr/lib/libpthre
ad.so.##.#
00000########000 00000########000 rlib 1    0   0      /usr/lib/libperl
so.##.#
00000########000 00000########000 rlib 1    0   0      /usr/lib/libm.so.
#.#
00000########000 00000########000 rlib 1    0   0      /usr/lib/libutil.
so.##.#
00000########000 00000########000 rlib 1    0   0      /usr/lib/libc.so.
##.#
00000######00000 00000######00000 rtld 1    0   0      /usr/libexec/ld.s
o
$ ldd /usr/bin/perl
  • (This sample format is shown from what was visible on an 80-column display.)
  • (Some digits in the values under Start and End may change. If the program is re-run instantly, then they'll be changed instantly.)

Here are some commands that might be uesful for copy-and-paste. However, do compare the following commands to the actual output shown by the previous command. It is very conceivable that there may be some necessary changes, and, therefore, need of customization.
sudo mkdir /var/www/usr/
sudo mkdir /var/www/usr/bin/
sudo cp /usr/bin/perl /var/www/usr/bin/
sudo mkdir /var/www/usr/lib/
sudo cp /usr/lib/libpthread.so.* /var/www/usr/lib/
sudo cp /usr/lib/libperl.so.*    /var/www/usr/lib/
sudo cp /usr/lib/libm.so.*       /var/www/usr/lib/
sudo cp /usr/lib/libutil.so.*    /var/www/usr/lib/
sudo cp /usr/lib/libc.so.*       /var/www/usr/lib/
sudo mkdir                   /var/www/usr/libexec/
sudo cp /usr/libexec/ld.so   /var/www/usr/libexec/

Note that the specified bin/ directory is underneath the chroot directory, and is sharing the directory with all other websites that are served by this server. The location ought to be customizable by specifying a custom chroot value for an individual website. However, that may also affect logging. This guide is not showing how to accomplish that, because having one set of logs, combining the details for multiple sites, may be preferred (perhaps more commonly than wanting to have individual versions of executables).

Follow-up: Securing things

Based on the comments from the files, they should not just be left remaining if the web server may have the potential to serve content to less trusted visitors.

pwd
sudo chmod o-r test-cgi
sudo chmod o-r printenv
echo ${OLDPWD}
cd ${OLDPWD}
Final thoughts

In theory, the chroot will protect the system from having visitors be able to modify the files outside of the chroot.

Another way that the chroot helps to protect the system's basic functionality is to limit how many tools exist within the chroot. Fewer available tools means that an attacker may have fewer easy options to launch an attack with. One of the prior examples showed adding one shell (/bin/sh), and the other example showed adding seven files to add support for the PERL 5.1 programming language. Having such tools may be required to support some specific content. Adding extra tools unnecessarily may provide attackers with more options, while not providing significant benefit. In short, adding files can have the effect of reducing one of the theoretical advantages that a chroot provides.

In other words, adding files is not recommended unless there is a specific need to add the files to achieve a specific benefit.