Arquivo de junho 2008

SQL Injection ou injeção de SQL é uma técnica de invasão de sistemas que se tornou famosa na Internet, mas pode ser utilizada em qualquer linguagem de programação. No entanto, na Internet temos uma combinação explosiva:

  • A aplicação está acessível para toda internet que possui milhares de usuários dispostos a quebrar seu sistema;
  • O uso de linguagens de script fracamente tipadas em conjunto com com tipos de dados fracamente tipados ajuda a abrir algumas brexas de segurança.
  • O protocolo HTTP tem peculiaridades que quando mal utilizadas podem tornar uma aplicação web mais vulnerável como o uso de parâmetros GET.

O exemplo clássico é o login de um usuário da aplicação. Você pede o nome e senha do usuário numa tela e depois envia um SQL com esta característica:

SELECT TRUE WHERE nome = 'telles' AND senha = 'abizi'

Na tela de login o usuário pode digitar no lugar da senha algo mais ou menos assim:

USUÁRIO: admin
SENHA: ‘ OR 1=1 –

Ao substituir as variáveis o seu SQL ficaria assim:

SELECT TRUE WHERE nome = 'admin' AND senha = '' OR 1=1 --'

Segurança contra o SQL Injection

Regra no mínimo privilégio

Veja que há uma série de problemas a serem analisados aqui. A primeira questão que qualquer sistema deve se preocupar em analisar é saber qual o potencial de destruição que o usuário vai ter se ele conseguir um ataque bem sucedido. Se o usuário que se conecta na aplicação é dono de objetos no banco de dados, como muitas aplicações gostam de fazer por uma questão de comodidade, você verá que o seu usuário terá permissões plenas sobre os seus objetos. Utilizando SQL Injection, ele poderá realizar operações como DROP, TRUNCATE, ALTER além do DELETE, INSERT, UPDATE e SELECT.

Então a primeira regra que deve SEMPRE ser seguida a risca é que:

“O USUÁRIO QUE A APLICAÇÃO UTILIZA PARA SE CONECTAR NO BANCO DE DADOS JAMAIS DEVE SER O DONO DOS OBJETOS CRIADOS NO BANCO DE DADOS”

Alguns artigos que tratam sobre SQL Injection ignoram solenemente esta recomendação. Alguns ficam desempregados inesperadamente. Então, precauções especiais devem ser tomadas em aplicações onde cada usuário da aplicação não tem seu próprio usuário criado no banco de dados - o que é comum em aplicações web com milhares de usuários que surgem sem controle do DBA. Você deve ter pelo menos 4 usuários para cada aplicação com este perfil:

  1. Um usuário que é dono dos objetos criados no banco de dados. Este usuário deve estar sob controle somente e tão somente do DBA, tanto no ambiente de testes como em produção. Lembre-se que este usuário tem poderes plenos sobre estes objetos do banco de dados.
  2. Um usuário ou grupo de usuários destinado aos desenvolvedores com poderes específicos para as suas tarefas. Pode-se determinar que no ambiente de produção ele tenha permissão de SELECT em todas tabelas e sequências e no ambiente de produção tenha poderes de SELECT, INSERT, UPDATE e DELETE.
  3. Um usuário ou grupo de usuários destinado aos administradores da aplicação, que terão poderes específicos na aplicação como deletar registros ou atualizar valores em tabelas. Este usuário deve se conectar a partir de outro executável que não o utilizado pelos usuários normais. A aplicação utilizada para fins administrativos deve ter acesso restrito ao acesso local por exemplo. Este usuário terá permissões de DELETE, UPDATE e INSERT em tabelas que um usuário normal não terá permissão. Portanto, este usuário jamais deve ser utilizado em operações de rotina.
  4. Um usuário para os usuários normais da aplicação. Este usuário deve seguir a risca a regra no menor privilégio. Ele deve apenas as permissões para acessar os objetos estritamente necessários. Privilégios de UPDATE e DELETE devem ser concedidos com muita cautela. Operações deste tipo quando executadas sem uma clausula WHERE adequada podem ser desatrosas. É este usuário que será alvo de ataques de SQL Injection. Se você for rigoroso com as permissões para este usuário, limitará muito a dimensão dos estragos que podem acontecer no caso de um ataque bem sucedido.

Use criptografia, visões e funções

Feito isso, você já terá um ambiente muito mais seguro, com certeza. A próxima parte do nosso trabalho será realizar um tratamento dedicado às informações mais sensíveis do seu sistema. Identifique estes objetos com cuidado. Existem dados sigilosos que podem ser alvo de criptografia. Senhas jamais devem ser armazenados sem criptografia. Use uma função como MD5 para isso. Lembre-se que você não poderá saber qual é a senha armazenada no campo, apenas poderá verificar se uma senha é igual a que está armazenada. No entanto, se apenas um grupo específico precisa ter acesso a estas informações você deve restringir o acesso a elas. Quando você quer restringir o acesso a apenas uma coluna ou grupo de columas de uma tabela a melhor alternativa é criar uma visão com apenas as colunas que o usuário vai precisar. De permissão ao usuário acessar esta visão não permita que ele leia a tabela diretamente.

Há casos em que a pessoa precisa alterar ou ler registros, mas você não quer que limitar a possibilidade de que o usuário altere todos os registros da tabela. Para isso, você pode criar funções que encapsulem toda a operação. Você passa para a função os parâmetros a serem alterados, a função checa a validade destes dados, faz todas as alterações em todas tabelas necessárias e retorna se realizou a operação com sucesso ou não, ou ainda retorna um valor desejado como se fosse um SELECT. O resultado disso é que você só precisa dar permissão ao usuário para executar a função e não precisa dar nenhum acesso a qualquer um dos objetos envolvidos na transação. Isto significa que o usuário só poderá realizar aquela transação especificada pela função, que se for bem codificada, evitará definitivamente qualquer chance de acesso indevido.

Procedimentos preparados

A terceira etapa é utilizar os procedimentos preparados ou “prepared statements’. Este procedimentos fazem com que você passe como parâmetros os valores a serem substituídos num comando SQL qualquer. As pessoas evitam utilizar este procedimento pois ele requer que você o execute em duas etapas: preparar o procedimento e executar o procedimento. Quando executado com freqüência, os procedimentos preparados não só são mais seguros, como também apresentam um ganho de performance.

Dollar Quoting

A quarta etapa que você pode utilizar é peculiar ao PostgreSQL, e chama-se “dollar quoting“. Ao invés colocar strings de caractere entre aspas simples em expressões SQL, você pode usar o $$ como em:

SELECT TRUE FROM users WHERE name = $$$$ AND senha = $$abizi$$;

Você ainda pode fazer coisas como:

SELECT TRUE FROM users WHERE name = $name$telles$name$ AND senha = $senha$abizi$senha$;

Note que você pode colocar suas strings entre $$, $nome$, $senha$ ou qualquer outra coisa, tendo somente que começar e terminar com a mesma marca. Usar este tipo de notação no código SQL pode parecer um tanto grotesco inicialmente, mas quando você for escrever funções, ela pode tornar a sua vida muito mais simples, pois você não terá situações bizarras como um grupo de várias aspas simples ou contra barras. Com o dollar quoting, você não precisa se preocupar com as aspas simples.

Checar o tipo de dados

A próxima barreira de defesa na luta contra a injeção de SQL é checar o tipo de dados utilizado. Um tipo comum de ataque é por exemplo ingetar código em parâmetros GET do protocolo http. Se você espera um número, tenha certeza de que ele é um número antes de substituir a sua variável no seu código SQL. Uma forma eficiente de fazer isso é utilizar a função ‘printf’. Quase toda linguagem de programação possui um comando semelhante ao printf da linguagem C. A nossa string SQL utilizando printf ficaria alguma coisa assim:

SQL = printf('SELECT TRUE FROM users WHERE nome = %s AND senha = %s', nome, senha)

A questão aqui é que a função printf vai forçar o uso do tipo de dados correto na função SQL. Não é uma solução perfeita, mas pode evitar alguns problemas além de evitar a conversão implícita de tipos de dados, fonte de muitas dores de cabeça no banco de dados.

Escapar as strings

A barreira mais conhecida na proteção contra a injeção de SQL é o uso de funções que escapem as strings. Hoje a maioria das linguagens de programação possuem funções para escapar caracteres como aspas simples em strings. Veja que uma aspa simples pode fazer parte de uma string como em “database’s security”. Para que uma string deste tipo seja aceita, é preciso escrevê-la desta forma numa expressão SQL:

INSERT INTO titulo VALUES ('database''s security');

Note que existem duas aspas simples e não uma aspas dupla. Esta é a única forma de se adicionar aspas simples numa string em banco de dados. Você deve esperar que o seu usuário por qualquer motivo digite uma aspa simples em qualquer string. A não ser que você remova explicitamente as aspas simples da sua string antes de construir o seu comando SQL, você deverá sempre escapa-las. Se a sua linguagem de programação possuir uma função de escape de strings específica para o seu banco de dados, utilize-a no lugar de uma função genérica.

Conclusão

Os problemas de segurança em geral são criados por profissionais mal informados ou por desenvolvedores que acreditam que segurança é um fator supérfluo e que implementar todas as barreiras necessárias é muito trabalhoso. O descuido com a segurança chega num ponto onde muitos servidores web exibem suas mensagens de erro diretamente na tela do usuário, no ambiente de produção. O uso de técnicas de SQL Injection em ambiente que não implantaram todas as barreiras citadas e ainda oferecem de bandeja os erros da aplicação na tela é absolutamente devastador. O usuário consegue descobrir o nome de todas as tabelas e colunas da sua aplicação, alterar qualquer registro ou mesmo apagar todas as informações de todas tabelas. Não é incomum encontrarmos aplicações de grande porte com furos homéricos de segurança. Não é incomum sites famosos e grandes corporações sofrerem com o vazamento de informações, fraudes e perda de dados. O prejuízo é sempre maior do que o custo de implementar a segurança de forma correta na aplicação.

Quando pensar novamente em segurança, lembre-se que a tarefa é de todos. Os ataques de SQL injections são muito simples de executar, a pondo de criarem a expressão “Script kiddie” para designar pessoas com pouco conhecimento técnico que utilizam receitas simples e eficientes para invadir sistemas. Não adiante a rede, o servidor e o banco de dados adotarem condutas rigorosas de segurança se você lança mão de aplicações (desenvolvidas por você ou por terceiros) que não tomam este tipo de precaução.

Tags: , , ,

Comments 3 comentários »

A tarefa é trivial, mas não é algo que você faz todo dia. Então resolvi documentar aqui para facilitar a minha vida. Há várias formas diferentes de se rearranjar tablespaces. Com a popularização dos RAIDs, não é mais tão comum ficar dividindo tablespaces através de discos isolados, mas ainda assim, há bons motivos para você criar todos os objetos em apenas um tablespace:

  • O backup on-line pode ser feito um tablespace por vez, diminuindo a quantidade de logs gerados durante o backup;
  • Você pode transportar tablespaces entre bases (teste e produção por exemplo) sem ter que exportar e importar todos os dados;
  • Você pode utilizar diferentes parâmetros de storage, particionamento, etc;
  • Fica mais fácil monitorar o crescimento da base com várias aplicações se cada aplicação possuir suas próprias tablespaces;
  • Separar índices de tabelas ainda é uma boa política, especialmente porquê os índices podem ser reconstruídos e as tabelas não;
  • Objetos especiais como LOBs e dados estáticos são bons candidatos a terem seu próprio tablespace;

Assim sendo, é comum você pegar uma tabela que cresceu muito e alocar um tablespace só para ela e coisas do tipo. Particularmente, quando os desenvolvedores tem a liberdade de criar objetos no ambiente de testes (sim, isso é polêmico e fonte para outra conversa), é comum ter que ajustar os parâmetros de storage antes de colocar os objetos no ambiente de homologação ou produção. Seja qual for o motivo da movimentação, você terá que fazer a migração em 3 etapas:

  • Migrar tabelas com o comando:
ALTER TABLE nome_da_tabela MOVE TABLESPACE nome_do_novo_tablespace
;
  • Migrar índices com o comando:
ALTER INDEX nome_do_indice REBUILD TABLESPACE nome_do_novo_tablespace
;
  • Migrar LOBs com o comando:
ALTER TABLE nome_da_tabela MOVE LOB(nome_da_coluna_lob)
    STORE AS (nome_do_novo_tablespace);

Note tabelas que contem LOBs, possuem um índice que aparece na tabela DBA_INDEXES com data_type do tipo LOB. Se você tentar reconstruir estes índices em outro tablespace você terá um erro do tipo: “ORA-02327: cannot create index on expression with datatype LOB”. Por isso é importante a etapa de migração dos LOBs.

Segue aqui um script para fazer isso rapidamente num para todos objetos de um determinado esquema:

SELECT 'ALTER TABLE nome_do_esquema.' || table_name || ' MOVE TABLESPACE nome_do_novo_tablespace;'
  FROM dba_tables
  WHERE
    owner = 'nome_do_esquema';
 
SELECT 'ALTER INDEX nome_do_esquema.' || index_name || ' REBUILD TABLESPACE nome_do_novo_tablespace;'
  FROM dba_indexes
  WHERE
    owner = 'nome_do_esquema' AND
    index_type != 'LOB';
 
SELECT
  'ALTER TABLE nome_do_esquema.' || table_name ||
  ' MOVE LOB( ' || COLUMN_NAME ||
  ' ) STORE AS (TABLESPACE nome_do_novo_tablespace);'
  FROM dba_tab_columns
  WHERE
    owner = 'nome_do_esquema' AND
    data_type LIKE '%LOB';
Tags: , ,

Comments Nenhum comentário »

Já faz tempo que algumas idéias me incomodam profundamente, isto não é segredo para os que já me conhecem. Há tempos atrás assisti há um filme interessante. Chama-se “O Segredo”. Uma amiga comentou, mas não falou exatamente sobre o que o filme se tratava e mediante a uma séria indecisão ao passar na locadora acabei levando. Sim, a curiosidade matou o gato.

Bom, a primeira questão é que o filme não conta história alguma. Não há algo emocionante que é revelado no final. O filme é uma sucessão de falas de narradores que prosperaram graças ao “segredo”. Todos os que assistiram ao filme ou viram o livro sabem do que eu estou falando. Sim, trata-se de auto ajuda. Mas há de se dar um bom crédito a sucessão de fatos e idéias apresentadas:

  • Sim, existe o fator placebo. Pessoas que acreditam que estão sendo curadas apresentam melhora natural, mesmo que não estejam de fato recebendo tratamento algum. O efeito placebo é considerado em toda pesquisa científica na área da medicina;
  • Sim, energias positivas atraem energias positivas e vice-versa. Se você está deprimido, as pessoas se afastam naturalmente de você pois não gostam de ficar em companhia de pessoas deprimidas. Se você está sempre feliz, você atrairá as pessoas pois elas acharão a sua companhia agradável.
  • Planejar o futuro, criar metas e traçar planos são estratégias inteligentes para se atingir objetivos. Não se trata apenas esperar as coisas acontecerem. As pessoas que tomam atitudes certamente se aproximam mais da realização do que aqueles que ficam apenas esperando que as coisas aconteçam.

Não preciso entrar no mérito da religião, energias cósmicas, poderes ocultos do cérebro humano ou outras questões polêmicas para dizer que uma pessoa com depressão pode extrair lições valiosas do filme. Mas… sim, é claro que há um mas… e vejamos bem, não é apenas um, são vários.

A primeira questão que eu gostaria de levantar é a questão da fé. Nunca me esqueço de um discurso proferido por um dado representante de uma dada religião (realmente não vem ao caso qual). ao se pronunciar num ato junto aos seus seguidores relacionou a miséria humana com a falta de fé. É simples, as pessoas pobres são aquelas que não tem fé em XYZ ícone da religião em questão. Então eu vejo aqueles milhares de pessoas que se massacram em sua fé, com esperanças de que tudo irá melhorar, ou então de que este é o caminho da salvação, ou ainda de que está sofrendo uma provação ou castigo divino. Não é fácil dizer quem é pobre e quem tem fé exatamente. Então esta associação é fraca, passível de contraargumentação. Mas é uma pista.

É claro que você pode dizer que se a pessoa tem uma “fé equivocada”, se acredita na religião errada, está condenado a miséria humana. Mas se você é destas pessoas que acreditam que somente uma religião está correta e todas as outras estão erradas, por favor, pare de ler aqui. Você não vai concordar comigo adiante e eu nunca vou concordar com você então não perca o seu tempo, e não desperdice o meu.

Mas deixando de vez a questão da fé, há alguém que começou a trabalhar os males que afetam o indivíduo de forma diferente e trouxe profundo impacto e debate nos meios acadêmicos. Esta pessoa conduziu uma investigação científica sobre o suicídio. Ela descobriu que apesar de haverem fatores psicológicos que levam cada um a se suicidar, existem tendências de as pessoas fazê-lo em maior ou menor frequência dependendo do local e época onde vive. A questão é que o suicídio é também uma questão social e não apenas individual. Há fatores sociais, coletivos, não individuais, que influenciam o comportamento das pessoas. É por isso que psicólogos e sociólogos para sempre duelarão no campo das ciências e eventualmente nos bares e congressos por aí. Mas há um fato inegável. A sociedade oferece uma coerção que influencia na sua forma de agir. Esta coerção pode ser um olhar de desaprovação, uma carta de demissão ou mesmo a repreensão policial. Ela existe.

O que isso tem haver com “O Segredo”? Bom, em primeiro lugar, foram estes estudos que levaram a conclusão de que existem vários fatores que levam as pessoas a pobreza. Você pode até interpretar a ira divina na forma de desastres naturais como a evidência da religião na questão… mas existem outros fatores muito importantes também. E surgem outras explicações mirabolantes. Uma que está na moda hoje em dia é o da falta de escolarização, por exemplo. Hum… faça um exercício, pegue o número de vagas disponíveis que exigem alta escolarização na Grande São Paulo. Agora imagine que por intervenção divina (não vai achar que algum país bom samaritano vai fazer isso, vai?) venha e pegue todos os pobres da cidade e mande-os por 10 anos para as melhores universidades e escolas do planeta. Alimente-os adequadamente, dê formação integral, tudo do bom e do melhor. Traga-os de volta para a Grande São Paulo… tente arrumar emprego para eles… adivinha o que vai acontecer? Vão ficar desempregados e vai haver uma queda nos salários das pessoas que estão bem empregadas devido ao aumento na oferta de mão-de-obra especializada.

Veja, não é falta de estudo ou fé que faz um país inteiro miserável. As pessoas daquele lugar não são más por natureza. Os pigmeus da Africa, quando bem alimentados cresciam normalmente. Eu imagino o povo de “O Segredo” indo para países miseráveis ensinando suas lições valiosas e o tudo mudando em poucos anos… será? Bom, os miseráveis não costumam comprar livros nem ingressos de cinema.

Note que no tom de harmonia celestial do filme, não há mais luta… basta desejar. Você é compelido no filme a não reclamar das coisas. Reclamar vai lhe atrair energias negativas. Não existem mais escolhas, apenas desejos, não exitem direita e esquerda, proletários e capitalistas. Tudo isso some no filme. Basta desejar. O Sr. Charles Wright Mills já se preocupava muito com isso no final da II Guerra Mundial, afinal, a paz e o conformismo chegaram para ficar. Sua preocupação era com as estruturas de poder no mundo. Estruturas que mudam o tempo todo com o passar dos séculos. Mas por incrível que pareça, nós nos conformamos com ela como se ela sempre existisse, e fosse eterna e imutável e não uma construção social, construída por seres humanos de carne e osso como nós. Quando olhamos ao longo dos séculos vemos inúmeras lutas, avanços e reveses no nosso processo civilizatório. Seja qual for o futuro da nossa moderna “civilização”, a questão é que o poder e a dominação, econômica, militar e cultural existe, e a forma de entender o mundo pode e deve ser visto conforme a sua posição nestas cadeias de poder. Entender esta situação, traz a tona um emaranhado de conseqüências capazes de desvendar inúmeros discursos e opiniões sobre a nossa sociedade. Resumindo, existem 4 posições:

  • Os reacionários que já estiveram no poder e cobiçam resgata-lo. São aqueles que glorificam os bons tempos passados. O exemplo clássico são os nobres em suas monarquias que foram substituídos por repúblicas. Os reacionários não são velhos e insignificantes. Eles muitas vezes retomam o poder pois acumularam muita força durante seu período de glória. Também não é verdade que eles são obrigatoriamente melhores ou piores que os conservadores. São os que estavam no poder antes e foram depostos por algum motivo histórico.
  • Os conservadores são os que estão no poder hoje. Para eles a história acabou. Não existe futuro nem passado e nada deve sair do lugar. A sociedade é como um corpo que deve funcionar de forma saudável e regular. Toda e qualquer disfunção que tente modificar o estado de coisas deve ser tratado como uma infecção a ser combatida e eliminada. Assim os que estão no cérebro e comandam os demais. Comandam os glóbulos brancos, a distribuição dos alimentos e dizem qual é a forma correta de agir para todos os demais;
  • Os reformistas, são aqueles que acham que a sociedade não é justa, mas é possível melhorar ela gradualmente até que ela chegue num estado ótimo. Basta que se realizem os ajustes corretos e tudo entrará nos eixos e todos seremos mais felizes. Os reformistas se auto denominam como pessoas de bom censo, pois são um ponto de equilíbrio na sociedade entre os conservadores e os revolucionários. Na verdade se equilibra entre a possibilidade ascenção e o risco de desabar para a pobreza;
  • Os revolucionários são aqueles dispostos a dinamitar a sociedade e reconstruí-la pedra por pedra novamente, custe o que custar. Eles sabem que a sociedade é injusta e não acreditam ser possível reformar a sociedade sem mudanças radicais. Os revolucionários são o contra-peso da sociedade que fazem denúncias constantes sobre atual da injustiça social.

Veja que a sociedade oscila entre estas posições, e vão de um lado para outro conforme suas posições no tabuleiro mudam. Este é o real segredo dos discursos na humanidade. A luta pelo poder jamais sumiu do mapa e ela rege a nossa vida de forma avassaladora. Wright Mills se preocupava sobre como as pessoas deixaram de se preocupar com isso e passaram a resolver seus problemas no divã ou na religião. A riqueza e a pobreza não podem ser vistas apenas no plano individual. São fenômenos coletivos e construídos historicamente. Não importa o quanto você pague ao seu analista ou quanto você se penitencie, estas forças continuarão atuando sobre você. Vender livro de auto-ajuda é fácil, mas acabar com a miséria humana não. Há pessoas lutando para manter o seu poder sobre as demais e há multidões tentando não serem esmagadas. Enquanto você fica apenas desejando a abundância e a prosperidade… alguém está pensando em como as engrenagens da sociedade funcionam.

Alguém aí já pensou se realmente é possível prover com abundância tudo aquilo que desejamos para todos? Imagine por exemplo quais são os bens mínimos que uma família moderna precisa para sobreviver? Uma casa com um fogão e uma geladeira? Não haveria reservas de metal suficiente para produzir os milhões de geladeiras e fogões para todas as famílias do planeta. Não haveria eletricidade e gaz para alimenta-los. Veja o desastre ambiental provocado pelo aumento de consumo na China. Os recursos naturais são escaços, não há o suficiente para todos. A única saída está realmente no coletivo e não no indivíduo. É o transporte público, o restaurante comunitário, o não consumismo e o fim dos bens descartáveis.

Será que é isso que você deseja? O fim de todo o conforto sonhado? Bom, se você pensa no conforto possível para todos, talvez estas sejam as únicas alternativas viáveis. Mas será que as pessoas que já desfrutam de muitas das comodidades modernas como o carro, o microondas, os produtos eletrônicos, a comida pelo telefone e outras tantas coisas que gostaríamos de ter e não estão tão longe dos nossos dedos estão dispostas a abrir mão delas? É claro que não. Mas a questão ambiental pode ser facilmente contornável se apenas alguns tiverem acesso a estes bens…

Onde você está? Como você pensa? Você acredita em auto-ajuda? Até onde? É possível uma sociedade melhor? Para todos ou só para alguns? Como esta sociedade seria? Será mesmo vivendo num dos países com maior desigualdade social do mundo nós conseguimos ficar indiferente a tudo isso? Basta colocar mais policiais nas ruas para que pessoas como o Luciano Huck não tenham seu relógio rolex roubado? O mundo vai acabar amanhã? Você fará o que for preciso se prometerem não acabar com a cerveja no planeta? Deixe seu comentário… a porta está aberta!

Comments 6 comentários »

Não qual vai ser o impacto na Internet neste dia…

Se isso ajudar as pessoas a usarem menos o IE…

Eu fico feliz.

E aí… está esperando o que?

Download Day

Tags:

Comments 1 comentário »

Agora é a sua vez de mandar uma proposta de palestra para o PGCon Brasil 2008. A chamada já foi publicada e se encerra no dia 22/06. Portanto não perca tempo e mande logo a sua proposta. Está em dúvida sobre qual palestra submeter??? Mande mais de uma! :-)

Está esperando o que??? Ah… você conhece uma pessoa que é fera em PostgreSQL? Convide-o a participar também! E não deixe de divulgar o evento!

Tags: ,

Comments Nenhum comentário »