Tutor NumaBoaCUIDADO COM A SEGURANÇA
Tutorial Perl CGI - 4
Silício NumaBoa


As 4 estapas iniciais dos fluxogramas A e B são iguais: localizar o interpretador, estabelecer variáveis configuráveis, estabelecer as variáveis do script e tratar os parâmetros recebidos. As três primeiras etapas já foram discutidas no módulo 3 - As primeiras linhas.

A quarta etapa do fluxograma, o fracionamento e depuração dos parâmetros recebidos, é de vital importância para nosso script pois se refere à segurança de rede.



7. Rotina Principal do Script
36 # #############################
37 # Script
38 # #############################
39
40 &pegaInput;
41 $topico = $campo{'topico'};
42 $topico =~ s/%20/ /g;
43
44 if ($ENV{'REQUEST_METHOD'} eq 'GET') {
45    &fazMaster();
46 }
47
48 if ($ENV{'REQUEST_METHOD'} eq 'POST') {
49    &mandaMaster;
50 }
51

7.1. Identificando e depurando os parâmetros recebidos

Quando o script é acionado recebendo parâmetros deve-se SEMPRE OBSERVAR MEDIDAS DE SEGURANÇA para que o processamento de parâmetros viciados seja impedido. Para evitar que comandos ou fragmentos de código sejam transferidos ao nosso script por pessoas mal intencionadas (os crackers), utilizamo-nos das expressões regulares. Estas farão as substituições necessárias "limpando" os parâmetros que serão utilizados no processamento.

A criação de uma subrotina específica para este procedimento não é necessária, porém facilita manutenções posteriores além de deixar o texto mais claro.

A subrotina criada para tal fim foi denominada pegaInput e é chamada logo no começo do script através de &pegaInput, conforme a linha (40).



7.2. A subrotina pegaInput
52 sub pegaInput {
53    (*fval) = @_ if @_ ;
54    local ($buf);
55    if ($ENV{'REQUEST_METHOD'} eq 'POST') {
56       read(STDIN,$buf,$ENV{'CONTENT_LENGTH'});
57    } else {
58       $buf=$ENV{'QUERY_STRING'};
59    }
60    if ($buf eq "") {
61       return 0 ;
62    } else {
63       @fval=split(/&/,$buf);
64       foreach $i (0 .. $#fval) {
65          ($nome,$valor)=split(/=/,$fval[$i],2);
66          $valor =~ tr/+/ /;
67          $valor =~ s/%(..)/pack("c",hex($1))/ge;
68          $valor =~ s/<!--#[^>]+>//g;
69          $valor =~ s/!.+>//g;
70          $valor =~ s/<\w.+?>|<\/\w.+?>//g;
71          $valor =~ s/<\w?>|<\/\w?>//g;
72          $valor =~ s/\s-\w.+//g;
73          $valor =~ s/system\(.+//g;
74          $valor =~ s/grep//g;
75          $valor =~ s/\srm\s//g;
76          $valor =~ s/\srf\s//g;
77          $valor =~ s/\.\.([\/\:]|$)//g;
78          $valor =~ s/< *((SCRIPT)|(APPLET)|(EMBED))[^>]+>//ig;
79
80          $nome =~ tr/+/ /;
81          $nome =~ s/%(..)/pack("c",hex($1))/ge;
82          $nome =~ s/<!--#[^>]+>//g;
83          $nome =~ s/!.+>//g;
84          $nome =~ s/<\w.+?>|<\/\w.+?>//g;
85          $nome =~ s/<\w?>|<\/\w?>//g;
86          $nome =~ s/\s-\w.+//g;
87          $nome =~ s/system\(.+//g;
88          $nome =~ s/grep//g;
89          $nome =~ s/\srm\s//g;
90          $nome =~ s/\srf\s//g;
91          $nome =~ s/\.\.([\/\:]|$)//g;
92          $nome =~ s/< *((SCRIPT)|(APPLET)|(EMBED))[^>]+>//ig;
93
94          if (!defined($campo{$nome})) {
95             $campo{$nome}=$valor;
96          } else {
97             $campo{$nome} .= ",$valor";
98          }
99       }
100  }
101  return 1;
102 }

Vamos apenas comentar os principais aspectos da subrotina pegaInput. Para entender e ampliar seus conhecimentos, siga os links indicados no texto.

Na linha (54) definimos uma variável local denominada $buf. Esta variável será utilizada para guardar as variáveis de contexto de acordo com o método utilizado para chamar o script.

Na linha (55) testamos a variável de contexto $REQUEST_METHOD (request method = método de requisição ou chamada) do array $ENV (environment = contexto) e comparamos seu valor através de uma expressão condicional: if ($ENV{'REQUEST_METHOD'} eq 'POST'). Caso o método seja POST, atribui-se a $buf o valor do request_method através de uma leitura da entrada padrão, conforme a linha (56). Caso o método não seja POST (portanto, o método utilizado foi um GET), atribuimos a $buf o valor da variável de contexto query_string, conforme a linha (58).

Tendo atribuído um valor à variável $buf, podemos trabalhar com a mesma. Se $buf estiver vazia (linhas 60 e 61), a subrotina é interrompida e devolve o valor 0 (ou falso). Se $buf tiver conteúdo, isolamos cada uma das partes que compõe a string de $buf utilizando a função split e guardando o resultado no array @fval. Vejamos como:

Suponha que a chamada ao script tenha ocorrido através de um link que contenha uma query do tipo ../diretorio/mailMan.cgi?enviar=webmaster&topico=Humor. O método utilizado foi um GET e $buf recebe inicialmente a string da query, ou seja, $buf = "enviar=webmaster&topico=Humor" (linha 59). Como sabemos que os campos da query estão separados através do caracter &, praticamos um primeiro split e guardamos o resultado no array @fval (linha 64). Dessa forma, $fval[0] contém "enviar=webmaster" e $fval[1] é igual a "topico=Humor".

Estamos quase lá... agora podemos submeter cada um dos elementos do array @fval a um novo split, tendo como separador o caracter =. Na linha (64), usando um loop foreach, armazenamos o resultado do split em duas variáveis, $nome e $valor. Na primeira passada do loop, $nome é igual a "enviar" e $valor é igual a "webmaster"; na segunda (e última), $nome="topico" e $valor="Humor. Pronto, agora é só fazer a crítica dos conteúdos de $nome e $valor para evitar dores de cabeça.

Nas linhas seguintes, linhas (65 a 92), aplicamos expressões regulares às variáveis $nome e $valor por medida de segurança. Queremos substituir quaisquer caracteres que possam representar um perigo de invasão do sistema, por exemplo, uma sequência de valores hexadecimais, system, grep, applets, scripts, etc. Expressões regulares localizam e substituem sequências de caracteres de uma string e seguem o padrão $variável =~ s/procurar/substituir por/ [opções]. Note que, ao eliminar notações hexadecimais, em "substituir por" é usada a função pack e como opções temos ge - onde g força a busca/substituição de todas as ocorrências encontradas (linha 67 e linha 81).

Note que não apenas o $valor é depurado, também a variável $nome é criticada e depurada. O seguro morreu de velho...

Finalmente, nas linhas (94 a 97), caso a variável $campo{$nome} não tenha ainda sido definida, define-se e atribui-se a ela o valor $valor; caso já tenha sido definida, adiciona-se o respectivo valor. Se tudo ocorreu conforme o previsto, a subrotina retorna com valor 1 (verdadeiro) e estamos prontos para a próxima etapa do nosso script.

Logo após a chamada à subrotina pegaInput, na linha (40), inicializamos a variável $topico e lhe atribuímos o valor de $campo{'topico'}. Na verdade, não é absolutamente necessário criar esta nova variável, porém é mais cômodo referenciá-la adiante apenas como $topico. Na linha (42), através de uma expressão regular, substituímos todas as ocorrências de "%20" (caracter especial para espaço, que alguns editores de HTML incluem automaticamente) por um espaço em branco. Exemplo: topico="Humor%20Negro" é transformado em "Humor Negro".

Em seguida, faz-se a verificação do método de chamada para direcionar o script para o fluxograma A ou B - Veja no próximo módulo.



Todos os scripts CGI deste site são "made in Aldeia". As linguagens utilizadas são principalmente PHP e alguma coisa em Perl. Faça contato: tire dúvidas, solicite matérias, critique e contribua.





@ Tutorial Perl CGI | Dicas | Um script | Primeiras linhas | Segurança | Formulário | Enviar e-mail | Checar | Script completo |

| AAAA | Página Inicial | Mapa do Site | Novidades | Busca | Indique esta página | Mestre da Teia | Voltar |
| Localizador || @ Info NumaBoa > Tutoriais > Perl + CGI - Cuidado com a segurança
Créditos: vovó Vicki

webdesign sobMedida by vickiSoft - /informatica/tutor/cgiPerl/cgiScript4.php (20.10.00) versão 1.1 de 21.07.03
Licença Creative Commons 1998-2006 Aldeia NumaBoa
Exceto onde especificamente declarado, todo material deste site é disponibilizado de acordo com a Licença Creative Commons.