Ενεργό περιεχόμενο με CGI

Προγράμματα CGI (Common Gateway Interface) επικοινωνούν με τον εξυπηρετητή Web για να εκτελέσουν κάποιες λειτουργίες που ζητά ο πελάτης, ή/και να δημιουργήσουν ενεργό περιεχόμενο.

Το πρόγραμμα CGI δέχεται από τον εξυπηρετητή τις παραμέτρους που καθόρισε ο χρήστης μέσω μεταβλητών του περιβάλλοντος (environment variables). Τυπικό δείγμα των μεταβλητών που μεταφέρονται στο πρόγραμμα CGI είναι το παρακάτω:

SERVER_SOFTWARE=Apache/1.2.5
GATEWAY_INTERFACE=CGI/1.1
DOCUMENT_ROOT=/home/www/htdocs
REMOTE_ADDR=192.168.135.5
SERVER_PROTOCOL=HTTP/1.0
REQUEST_METHOD=GET
REMOTE_HOST=staffpc15.aegean.gr
QUERY_STRING=
HTTP_USER_AGENT=Mozilla/3.01 (Win95; I)
PATH=/bin:/usr/bin:
HTTP_CONNECTION=Keep-Alive
HTTP_ACCEPT=image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
REMOTE_PORT=1124
SCRIPT_NAME=/cgi-bin/pe
SCRIPT_FILENAME=/home/www//cgi-bin/pe
SERVER_NAME=www.aegean.gr
REQUEST_URI=/cgi-bin/pe
SERVER_PORT=80
HTTP_HOST=www.aegean.gr
SERVER_ADMIN=webmaster@aegean.gr
Αφού το πρόγραμμα επεξεργαστεί τις παραμέτρους που όρισε ο χρήστης στη φόρμα (που περιέχονται κωδικοποιημένες στη μεταβλητή QUERY_STRING) δημιουργεί μια πλήρη απάντηση σύμφωνα με το πρωτόκολλο HTTP (επικεφαλίδα και δεδομένα). Για παράδειγμα, η εκτύπωση των πιο πάνω μεταβλητών έγινε από το εξής πρόγραμμα σε Perl:
#!/usr/bin/perl
print "Content-Type: text/plain\n\n";
for $key (keys %ENV) {
        print "$key=$ENV{$key}\n";
}
Σχετιζόμενα προβλήματα ασφάλειας είναι τα παρακάτω: Παρόμοια προβλήματα μπορούν να εμφανίσουν και τα server side includes που εκτελούν κώδικα.

Παράδειγμα

Το παρακάτω λανθασμένο και ανασφαλές πρόγραμμα σε Perl τρέχει την εντολή finger σε σύστημα Unix για το χρήστη που έχει ζητήσει κάποιος στο πεδίο USER μιας φόρμας HTML.
#!/usr/bin/perl
$query = $ENV{'QUERY_STRING'};
@pairs = split(/\&/, $query);
for (@pairs) {
        ($field, $val) = split(/=/);
        $field =~ s/\+/ /g;
        $field =~ s/\%(\w\w)/sprintf("%c", hex($1))/eg;
        $val =~ s/\+/ /g;
        $val =~ s/\%(\w\w)/sprintf("%c", hex($1))/eg;
        $field{$field} = $val;
}
$|=1;
print "Content-Type: text/plain\n\n";
system "finger $field{USER}\n";  
Αν το εκτελέσουμε με την παράμετρο USER να έχει την τιμή dds
http://www.senanet.com/cgi-bin/pe?USER=dds
θα εμφανιστεί το παρακάτω αποτέλεσμα:
Login: dds                              Name: Diomidis Spinellis
Directory: /home/dds                    Shell: /bin/bash
On since Wed Jun 30 12:18 (EET) on ttyp0
   5 minutes 49 seconds idle
Αν όμως προσθέσουμε στο τέλος του URI ένα ερωτηματικό (που διαχωρίζει τις εντολές στο φλοιό του Unix) και την εντολή cat /etc/passwd
http://www.senanet.com/cgi-bin/pe?USER=dds;cat%20/etc/passwd
θα λάβουμε και το περιεχόμενο του αρχείου passwd (περιέχει τους κωδικοποιημένους κωδικούς χρηστών σε ορισμένες εκδόσεις του Unix) στο τέλος της απάντησης:
Login: dds                              Name: Diomidis Spinellis
Directory: /home/dds                    Shell: /bin/bash
On since Wed Jun 30 12:18 (EET) on ttyp0
   5 minutes 49 seconds idle

root:XXXXXXXXXXXXX:0:0:Charlie Root:/root:/bin/bash
bin:*:1:1:bin:/bin:
daemon:*:2:2:The Devil Himself:/sbin:
adm:*:3:4:adm:/var/adm:
lp:*:4:7:lp:/var/spool/lpd:
...
Για να αποφεύγουμε τέτοια προβλήματα πρέπει: