Apache e il CGI

Cos'è il CGI

Il CGI ( Common Gateway Interface, http://hoohoo.ncsa.uiuc.edu/cgi ) è uno standard per interfacciare applicazioni esterne con un Web Server, creando pagine HTML in modo dinamico. Tipiche applicazioni sono query di un database o registrazioni di moduli compilati tramite Web cioè form HTML ( per esempio questionari o registrazioni per accedere a qualche servizio offerto).

L'applicazione CGI può essere fatta in un qualsiasi linguaggio di programmazione che supporti delle librerie CGI contenenti funzioni per interpretare dati mandati al Server Web tramite i metodi HTML GET o POST.

I dati vengono inviati al Server Web dove c'è l'applicazione CGI installata, il quale eseguirà l'applicazione CGI interessata che genererà a sua volta un output, che il Server manderà come risposta al richiedente. Più avanti si farà un esempio che chiarirà meglio il discorso fatto.

Come configurare Apache per gestire richieste di esecuzione di script CGI

Per poter eseguire programmi CGI essenzialmente bisogna impostare la directory dove sono contenuti i vari scripts. Quando si esegue una GET/POST, per esempio nella pagina WEB da dove arriva la richiesta, si indica quasi sempre " cgi-bin/nome_eseguibile " dove "/cgi-bin/" è il nome simbolico ( alias) che viene attribuito a tale directory. Apache quindi può essere configurato a piacere.

Aprendo il file httpd.conf ( il noto file di configurazione ) con un editor di testi a piacere si noteranno la ripetizione di righe con prima parola la direttiva Alias, questa serve per assegnare ad un nome simbolico una reale directory. In generale il comando setta le directory di sistema, per esempio con alias /icons/ si abbina la directory dove sono contenute le immagini che rappresentano le directory di files e non pagine HTML. Per assegnare invece directory contenenti script eseguibili si usa il comando ScriptAlias. Detto questo se per esempio le applicazioni CGI sono nella cartella /usr/local/apache2/cgi-bin/ si può impostare la directory così

ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/"

Con Apache è anche possibile stabilire un comportamento particolare in base all'estensione di un file, con il comando AddHandler. Questo comando è sconsigliato usarlo nel caso di programmi CGI perchè permetterebbe l'uso ed esecuzione di essi al di fuori della directory precedentemente settata. Quindi per questi motivi commentate ( se non è già commentata ) la riga ..

#AddHandler cgi-script .cgi

questo supposto che gli eseguibili nel sistema abbiano estensione .cgi ma la cosa si può estendere ad altri tipi di eseguibili associati ad altri tipi di script. Sempre per questioni di sicurezza è consigliabile aggiungere ulteriori controlli sull'accesso alla directory. Infatti un malintezionato utilizzando SSI ( Server Side Include ), direttive che permettono all'HTML statico di essere interpretato al volo dal Server Web per determinati output al browser del richiedente, potrebbe con un comando tipo: <!--#exec cgi="cgi-bin/nome_eseguibile"--> ( nel codice html creato da lui ), sfruttare informazioni che per noi erano importanti per altri scopi. Per evitare questo si "blinda" la directory con una serie di direttive di sicurezza di Apache.

Normalmente l'accesso ad una directory da parte di un utente viene controllata con un file nella directory stessa, il file nascosto è .htaccess ( il nome settato con AccessFileName ), in caso di intrusioni potrebbe essere modificato e la nostra configurazione col file httpd.conf non sarebbe più valida. Per evitare questo si usa la direttiva AllowOverride None , dove il None indica che l'accesso viene controllato invece che da un file, dalle impostazioni date da questo comando ( None = nessun file ).

Le possibilità di configurazione sono:

None --> Impedisce che qualunque direttiva venga scavalcata.

All --> Permette che siano scavalcate tutte le direttive.

Options --> Permette l'uso di:

FollowSymLinks --> Abilita l'uso di collegamenti simbolici

SymLinksIfOwnerMatch --> Abilita l'uso di collegamenti simbolici solo se il proprietario coincide.

ExecCGI --> Permette l'esecuzione dei programmi CGI

Indexes --> Permette di ottenere il listato del contenuto

Includes --> SSI èpermesso

IncludesNOEXEC --> SSI èpermesso in parte

Limit --> Permette l'uso di direttive di controllo sugli accessi.

AuthConfig --> Permette l'uso di direttive di autorizzazione.

FileInfo --> Permette l'uso di direttive di controllo del tipo di documento.

Indexes --> Permette l'uso di direttive di controllo sul listato delle directory

combinate con queste direttive

Require --> Utenti che possono accedere attraverso autenticazione

Deny --> Specifica i nodi a cui viene negato l'accesso

Allow --> Specifica i nodi a cui viene concesso l'accesso

Order --> Ordine di valutazione delle direttive deny e allow

AuthName --> Nome o descrizione di una zona soggetta ad autenticazione

AuthType --> Definizione del tipo di autenticazione.

quindi si può settare la directory per gli eseguibili CGI in questo modo

<Directory "/usr/local/apache2/cgi-bin">

AllowOverride None

Options ExecCGI

Order deny,allow

Allow from all

</Directory>

L'ultima cosa da settare per motivi di sicurezza, è la pagina di errore. Essa viene generata al momento di un eventuale problema nella fase di esecuzione di un programma CGI oppure in una ricerca azzardata di un malintenzionato. Se da un browser viene digitata la stringa "http://nomesito/cgi-bin/" normalmente viene generata una pagina di errore ( non avendo i permessi, da estraneo ) ma che svela la versione di Apache utilizzata. Sapendo la versione, sempre un malintenzionato, potrebbe cercare eventuali bugs conosciuti e non ancora coperti dall'amministratore del sito.

Quindi èsempre importante aggiornare il Server Web che si è installato. Per rendere difficile la vita dell'eventuale intrusore è consigliabile modificare la pagina in questo modo.

ErrorDocument 403 "Forbidden: You don't have permission to access /cgi-bin/ on this server."

infatti con la direttiva ErrorDocument e il numero dell'errore si può settare la risposta da dare, in formato testo o pagina html, quindi per i discorsi fatti prima si possono cambiare a piacimento le pagine di errore o crarne alcune in modo dinamico con script CGI.

ErrorDocument 404 /missing.html

Esempi di pagine di errori si possono trovare nella cartella /usr/local/apache2/error .

Esempio di script-CGI

Un veloce esempio di script CGI potrebbe essere l'implementazione di una login da semplice pagina Web, con la compilazione di un form ( user, password ), passarli come parametri all'applicazione CGI e aver come risultato la stampa di ciò che si èintrodotto. L'esempio svolto è uno script-CGI fatto in C, normalmente questi script vengono fatti in PERL, essendo un linguaggio interpretato dove la compilazione è al volo, ma per miglior completezza si è preferito farlo in C.

Partendo dal form in html si ha:

<meta http-equiv="content-type"
content="text/html; charset=ISO-8859-1">
<title>login</title>
</head><body>
<h1>Prova di una login: </h1>
<form action="/cgi-bin/login.cgi" enctype="multipart/form-data" method="post"> <h3> Nome: &nbsp; &nbsp;&nbsp; </h3>
<input type="text" name="nome"> <h3> Password: </h3>
<input type="password" name="password"> <br><br>
&nbsp; &nbsp; &nbsp; &nbsp;<input type="submit" value="ok"><input type="reset" value="cancella"></form><br>
</body></html>

non entrando troppo nel dettaglio ( per saperne di più sull'HTML http://www.w3.org/TR/html4/ ) si può notare l'inizio del form ( form action ), notare il file eseguibile chiamato "/cgi-bin/login.cgi". Un'altra cosa da notare sono gli oggetti di input, input type="text" e input type="password" , i loro nomi sono i nomi dei parametri da verificare. Ora si dia una occhiata alllo script-cgi scritto in C

#include <stdio.h>
#include "cgic.h"
#include <string.h>
#include <stdlib.h>

void HandleSubmit();
void ShowForm();
void CookieSet();
void Name();
void Address();
void Hungry();
void Temperature();
void Frogs();
void Color();
void Flavors();
void NonExButtons();
void RadioButtons();
void File();
void Entries();
void Cookies();
void LoadEnvironment();
void SaveEnvironment();

int cgiMain() {

char **array;
char result[256];

/* RISCRIVI COME HEADER LO STESSO DELLA PAGINA DI RICHIESTA*/

cgiHeaderContentType("text/html");

/*TITOLO PAGINA*/

fprintf(cgiOut, "<HTML><HEAD>\n");
fprintf(cgiOut, "<TITLE>Risultato login:</TITLE></HEAD>\n");

/* VERIFICA DEL CORRETTO PASSAGGIO DEI PARAMETRI */

if (cgiFormEntries(&array) != cgiFormSuccess)
{ return 0; }

/* ELABORAZIONE PARAMETRI ( STAMPO SOLO ) */

cgiFormString("nome",result,256);

if (strlen(result)==0) fprintf(cgiOut, "<BODY><H1>Manca il nome</H1><br>");

else fprintf(cgiOut, "<BODY><H1>Nome:%s</H1><br>",result);

cgiFormString("password",result,256);

if (strlen(result)==0) fprintf(cgiOut, "<BODY><H1>Manca la password</H1><br>");

else

fprintf(cgiOut,"<BODY><H1>La password è:%s</H1><br>",result);

/* CHIUSURA CODICE HTML */

cgiStringArrayFree(array);
fprintf(cgiOut, "</BODY></HTML>\n");
return 0;

}

Inanzitutto per compilare lo script si deve possedere il file cgic.h ( scaricabile da http://www.boutell.com/cgic/ ) e il file cgic.c contenente tutte le funzioni che servono per gestire i parametri ( anche per l'attivazione di eventuali cookie, ecc.. ) . Ora come si può notare con la funzione cgiFormEntries, si controllano i parametri esistenti, in questo caso esisteranno sempre ma per altri oggetti di input ( come i check box ) non èdetto che ci siano. Altra funzione importante è la cgiFormString, dal nome del parametro si ricava il valore, nella variabile result. Infine si libera la memoria allocata nella variabile array ( usata per il controllo dei parametri ) con la funzione cgiStringArrayFree. Si può notare, in base ai parametri introdotti, la stampa sullo standar di output cgiOut usando la funzione printf. Apache, invierà il tutto al browser client richiedente. La funzione cgiHeaderContentType, meno importante delle altre, mette come intestazione di risposta lo stesso header della pagina richiedente.

Per compilare il file C, chiamato per esempio login.cgi.c , e si desidera che crei il file eseguibile login.cgi nella directory con il file cgic.c e cgic.h, si deve eseguire il comando da shell

gcc -o login.cgi login.cgi.c cgic.c

ora conservando i file sorgenti in un posto sicuro, va copiato il file eseguibile login.cgi nella directory /usr/local/apache2/cgi-bin . La pagina Web HTML la si può creare copiando il testo descritto sopra in un nuovo file di testo, rinominarlo come file .html per esempio, e copiarlo all'interno della directory delle pagine HTML del Server Web . Con un browser provare a visualizzare la pagina e vederne il funzionamento.