CGI: Obter parâmetros da url pelo bash

Eu nem deveria estar aqui escrevendo. Na verdade estou até o pescoço de coisas a fazer, mesmo já estando de férias…

Mas como fazia tempo que não postava algo relacionado ao Linux e como ultimamente estou muito envolvido com desenvolvimento para web (formulários! malditos formulários! rs), passei a pesquisar sobre coisas relacionadas a isso.

Quando se fala em desenvolver páginas dinâmicas, todo mundo pensa logo em PHP e Asp.NET, Ruby, Java, etc. Talvez estas sejam muito indicadas para isso, mas nada impede que você use a sua linguagem favorita. Quer criar páginas e só sabe programar em C? Ou só em Pascal? Ou só em shell-script (bash, zsn, csh, ksh, etc., etc., etc.)? Pois você pode sim :-)

Falei com um colega meu que em teoria você pode escrever páginas em qualquer linguagem e ele achou que eu estava louco. Tive que mostrar na prática. Mas em teoria é fácil de entender, já que só o que o servidor web faz é enviar textos para a saída padrão, no caso, o navegador do usuário, e aí este encarrega-se de montar o HTML. Assim qualquer linguagem de programação capaz de enviar dados para a saída padrão (stdout) pode ser utilizada para escrever páginas.

A resposta é CGI. Não vou falar muito sobre a coisa, já que pouco sei. Mas se quiser saber, dê uma pesquisada no Google.

Neste texto falo sobre como obter os parâmetros passados na url das páginas (via método GET), quando for um script em shell. Aqui uso o bash, mas você pode obter melhor desempenho com o dash ou o zsh. Costume de usar o bash mesmo :-)

É muito provável que alguém já use esta técnica, mas como nunca li nada a respeito e achei que esta maneira ficou interessante, decido compartilhar com meus coleguinhas de internet :-)

Primeiro é bom notar que num cgi em bash, a variável que guarda os parâmetros da url é a $QUERY_STRING. Ela é bem crua e deve ser tratada. Seu formato é “var1=valor1&var2=valor2” e assim em diante.

De início de comversa, vamos criar uma função que faz este tratamento. Ela se chamará extraiparams. Podemos até criar uma “biblioteca” com as funções que utilizamos com frequência. Eu costumo fazer isto :-)

extraiparams() {
local IFS=”&”
for i in $QUERY_STRING; do
eval $i
done
}

Esta é a primeira versão de nossa função. Ela funciona, mas tem várias falhas de segurança. O que ela faz exatamente?
IFS é uma variável que no bash define o separador de campos. Assim, quando a definimos como “&”, estamos dizendo que cada “coisa” limitada por este caractere será um elemento. No caso, um elemento do laço for. Assim, se  $QUERY_STRING for “var1=valor1&var2=valor2”, teremos duas iterações do for com o i valendo “var1=valor1” e “var2=valor2”.

Assim basta usar o comando eval, que executa uma string, no caso, atribuições, para termos nossas variáveis definidas. Teremos no final var2 com o conteúdo “valor1” e var2 com o conteúdo “valor2″. Perfeito. Ou não?

Acontece que o eval é um comando perigoso, pois pode executar não somente atribuições inofensivas, mas também comandos do sistema! Isso dá margem para que uma pessoa mal-intencionada danifique seu computador/servidor.

Vamos então a um melhor tratamento.

O que precisamos obter pela url? Variávels, oras! Qual é então o formato de uma atribução no bash? É variavel=conteúdo, onde o nome da variável deve começar com um caractere alfanumérico ou um caractere underscore (o sublinhado) seguido de uma sequencia de alphanuméricos, underscore ou numérico. Assim filtraremos o que recebemos na url com uma expressão regular bem simples. Aqui uso o grep, mas você pode usar o comando que achar melhor, sed, perl (sim, tenho um colega que usa perl para tudo!) ou o quer que seja.

A expressão para filtrar isso é: ^[[:alpha:]_][[:alnum:]_]*=

Destrinchando isso, significa: qualquer coisa que comece com uma letra ou undesrcore seguido de zero ou mais letras, underscore ou número. Ufa.

Vamos então reescrever nossa função:

extraiparams() {
local IFS=”&”
for i in $QUERY_STRING; do
if grep ‘^[[:alpha:]_][[:alnum:]_]*=’ <<< $i > /dev/null; then
eval $i
fi
done
}

Aqui, antes de executar o eval, verifico se o parâmetro se encaixa no meu padrão. Se encaixar, faz a atribuição. Senão, ignora. O redirecionamento para /dev/null serve para não jogar o conteúdo para o navegador, posi se você fizer isto antes de exibir o cabeçalho “content-type: text/html” seguido de uma linha vazia, vai dar pau no seu script e o servidor acusará erro!

Para usar a função, basta chamá-la sem quanquer parâmetros em qualquer ponto do seu script em cgi.

Podemos incrementá-la para que detecte tentativas de ataque e/ou guarde num array todos os parâmetros válidos (pra que isto seria útil?). Coloco aqui o script completo, como exemplo:

#!/bin/bash

extraiparams() {
local IFS=”&”
for i in $QUERY_STRING; do
if grep ‘^[[:alpha:]_][[:alnum:]_]*=’ <<< $i > /dev/null; then
VALID_PARAMS+=($i)
eval $i
else
INVALID_PARAMS+=($i)
fi
done
}

echo “content-type: text/html”
echo

echo “<html>”
echo “<body>”

extraiparams

if (( ${#INVALID_PARAMS[@]} > 0 )); then
echo -n “Tentando atacar este servidor com os comandos ”
for i in ${INVALID_PARAMS[@]}; do
echo -n ” <b>$i</b>,”
done
echo ” neh?”
fi

echo “<br><br>”

echo Paramametros validos:
echo “<ul>”
for i in ${VALID_PARAMS[@]}; do
echo “<li>$i</li>”
done
echo “</ul>”

echo “</body>”
echo “</html>”

Executando o script no servidor: http://localhost/~tenchi/cgi-bin/teste1.cgi?i=testa&ls&j=ornintorrinco&rm

E a saída será:

Se quiser saber mais sobre programação em shell-script, recomendo que acesse o site do Júlio Neves e do Aurélio:
http://www.aurelio.net
http://www.julioneves.com

E por hoje é isso pessoal. Eu estava sentindo falta das tais “pitadas nerds” neste blog.

6 Comments

  1. Posted julho 8, 2009 at 19:34 | Permalink

    WordPress fiodamãe! Mata toda a identação e substitui caracteres!

  2. Posted julho 8, 2009 at 19:40 | Permalink

    “O nerd de hoje é o cara rico de amanhã
    O nerd de hoje é o cara lindo de amanhã
    O nerd de hoje é o bom marido de amanhã
    Garota, escolha já seu nerd!”

    Eu já escolhi o meu.
    Te amo pessoa. =*

  3. Patola
    Posted julho 9, 2009 at 14:43 | Permalink

    O certo é “indentação” e “ornitorrinco”… :) Você escreveu “identação” e “ornintorrinco”.

  4. Posted julho 9, 2009 at 15:40 | Permalink

    Oh rly? hauahau
    É que meu corretor gramatical – ou ortográfico, não sei – não está configurado… :-)
    Mas valeu por ainda ser um leitor deste blog, mesmo que sempre achando defeitos nos textos e idéias.. hauah
    t+

  5. Posted agosto 6, 2009 at 11:58 | Permalink

    No 9° paragrafo há um erro também: “De início de comversa, vamos…”, sendo que a palavra “comversa” se escreve com “N” e não com “M”, pois “M” só é utilizado antes de “P” e “B”. Rsssss
    Te amo pessoa. =*

  6. Posted agosto 31, 2009 at 10:45 | Permalink

    ae mano vey……..te add no meu blog…..gostei da materia do beck………que fumou.
    Como te axei?Vc fez um comentario no blog
    http://eupodiatamatando.com/.
    Ae bem legal seu blog….
    Nerd ou não seu blog ficou massaroca.OTIMO.
    Ha uma dica para correção ortografico. WORD VARIAS VEZES O MESMO TEXTO.ISSO DÁ CERTO.
    VLW IRMAOZINHO

Comente

Required fields are marked *

*
*

%d blogueiros gostam disto: