Buscar

ATPS Desenvolvimento de Software Seguro - Etapa 3

Prévia do material em texto

FACULDADE ANHANGUERA – UNIDADE CAMPINAS I
TECNOLOGIA EM ANÁLISE E DESENVOLVIMENTO DE SISTEMAS
DESENVOLVIMENTO DE SOFTWARE SEGURO – ETAPA 03
ALUNO RA
QUEMUEL SANTOS DE AQUINO 8309737322
PAULO VICTOR DE MENEZES 2848233367
SIDMAR PORFÍRIO 7989711257
LEONARDO CUENCAS 7700620660
ATIVIDADE PRÁTICA SUPERVISIONADA (ATPS)
TUTOR: PROF. RICARDO AUGUSTO DA SILVA
CAMPINAS, 27 DE MAIO DE 2015.
SUMÁRIO
INTRODUÇÃO .........................................................................................................................................3
O RISCO DE ATAQUES PELA WEB ...........................................................................................................3
UTILIZANDO OS OPERADORES DE CONCATENAÇÃO ..............................................................................8
ATAQUES SQL INJECTION UTILIZANDO LINGUAGENS DINÂMICAS ......................................................22
RELATÓRIO 1 – EVITANDO ATAQUES SQL INJECTION ..........................................................................38
REFERÊNCIAS BIBLIOGRÁFICAS ............................................................................................................40
2
INTRODUÇÃO
Esta atividade é importante para que possamos compreender alguns métodos de entrada de
dados mal-intencionados e formas de acesso indevido a bancos de dados.
Trataremos neste documento sobre codificações abreviadas, mais conhecidas como
shortcodes, além de mostrarmos alguns exemplos de sua utilização. Além disso, trataremos
também da utilização de códigos dinâmicos. Neste segundo momento, poderemos avaliar a
sua utilização em casos que precisamos escrever códigos T-SQL que criam códigos T-SQL
mais específicos.
O RISCO DE ATAQUES PELA WEB
Aplicações web são o principal alvo de ataques de Agentes Maliciosos (hackers ilegais e
crackers), devido à possibilidade de alcance rápido de altos ganhos, e ao baixo risco de
exposição do criminoso.
Dados de cartões de crédito, informações de clientes e de operações da empresa, roubos de
identidades e outros dados sigilosos, informações sobre a infraestrutura de dados e vários
outros podem ser usados para compor cenários de ataques com alto impacto.
Segundo o Instituto Gartner (2009), mais de 75% dos problemas com segurança na internet
são devidos a falhas exploráveis a partir das aplicações web.
A maior parte das páginas web são naturalmente vulneráveis devido às tecnologias adotadas
em sua concepção, à forma como são desenhadas e desenvolvidas, e ao uso de vários objetos
e recursos, além da integração de outros sistemas, na medida em que são priorizados os
aspectos funcionais que atendem a área de negócios, enquanto os requisitos de segurança
ficam em segundo plano.
3
Os ataques podem causar problemas de variados níveis de impacto, como por exemplo:
- Interrupção ou queda de desempenho do serviço;
- Acesso não autorizado a dados confidenciais e estratégicos;
- Roubo de informações cadastrais de Clientes;
- Fraudes e modificação de dados no fluxo das operações;
- Perdas financeiras diretas e indiretas;
- Prejuízos à imagem da marca da empresa;
- Perda da lealdade dos Clientes;
- Gastos extraordinários com incidentes de segurança;
Os riscos de ataques mais comuns são mundialmente conhecidos e podem ser previstos com
antecedência, pois são listados pela Open Web Application Security Project (OWASP), e
dentre eles, os 3 principais são:
1- SQL Injection;
2- Cross Site scripit;
3- Broken Authentication and Session Management;
Mas ataques importantes não são apenas aqueles que causam impacto de imagem, vazamento
de informações, ou que afetam a disponibilidade ou desempenho de serviços, pois estes são
rapidamente percebidos e provocam imediata reação das áreas de segurança para restaurar a
integridade dos sistemas.
Os ataques mais graves são aqueles que, quando realizados sobre brechas no ambiente da
aplicação web, não serão percebidos de imediato e resultam no acesso a dados sigilosos do
negócio, da sua infraestrutura, ou de seus clientes, e que podem ser posteriormente
organizados para compor um ataque de impacto mais relevante, ou uma fraude.
Considere que da perspectiva da empresa não há como exercer controle total sobre a
incidência de todos os fatores que conduzem ao risco, como a identificação prévia do Agente
Malicioso, ou do momento do ataque, ou a forma como ele se dará se houver uma
vulnerabilidade explorável.
4
Por este motivo, se o fator “vulnerabilidade explorável” for eliminado o quanto antes deste
cenário, o ambiente de negócios estará mais seguro e o risco de ataques será minimizado.
Este fator pode ser rapidamente administrado a partir da adoção de um processo de
Gerenciamento de vulnerabilidades com a metodologia proposta pelo Sistema RedeSegura.
- SQL Injection
Injeção SQL é um ataque no qual um código mal-intencionado é inserido em cadeias de
caracteres que são passadas posteriormente para uma instância do SQL Server para análise e
execução. Qualquer procedimento que construa instruções SQL deve ser verificado quanto a
vulnerabilidades de injeção porque o SQL Server executará todas as consultas sintaticamente
válidas que receber. Mesmo dados com parâmetros podem ser manipulados por um invasor
qualificado e determinado.
A forma principal de injeção SQL consiste em inserção direta de código em variáveis de
entrada de usuário, concatenadas com comandos SQL e executadas. Um ataque menos direto
injeta código mal-intencionado em cadeias de caracteres destinadas a armazenamento em uma
tabela ou como metadados. Quando as cadeias de caracteres armazenadas são concatenadas
subseqüentemente em um comando SQL dinâmico, o código mal-intencionado é executado.
O processo de injeção funciona encerrando prematuramente uma cadeia de caracteres de texto
e anexando um novo comando. Como o comando inserido pode ter cadeias de caracteres
adicionais anexadas a ele antes de ser executado, o malfeitor encerra a cadeia de caracteres
injetada com uma marca de comentário "--". O texto subseqüente é ignorado no momento da
execução.
O script a seguir mostra uma injeção SQL simples. O script cria uma consulta SQL
concatenando cadeias de caracteres codificadas com uma cadeia de caracteres inserida pelo
usuário:
var Shipcity;
ShipCity = Request.form ("ShipCity");
var sql = "select * from OrdersTable where ShipCity = '" + ShipCity + "'";
5
O usuário é solicitado a inserir o nome de uma cidade. Se ele inserir Redmond, a consulta
criada pelo script terá a seguinte aparência:
SELECT * FROM OrdersTable WHERE ShipCity = 'Redmond'
No entanto, suponha que o usuário insira o seguinte:
Redmond'; drop table OrdersTable--
Nesse caso, a seguinte consulta é gerada pelo script:
SELECT * FROM OrdersTable WHERE ShipCity = 'Redmond';drop table OrdersTable--'
O ponto-e-vírgula (;) denota o término de uma consulta e o início de outra. O hífen duplo (--)
indica que o restante da linha atual é um comentário e deve ser ignorado. Se o código
modificado estiver sintaticamente correto, será executado pelo servidor. Quando o SQL
Server processar essa instrução, o SQL Server selecionará primeiro todos os registros em
OrdersTable onde ShipCity é Redmond. Em seguida, o SQL Server descartará OrdersTable.
Contanto que o código SQL injetado esteja sintaticamente correto, a violação não poderá ser
detectada programaticamente. Portanto, é necessário validar todas as entradas de usuário e
verificar com cuidado o código que executa comandos SQL construídos no servidor que você
está usando. Práticas recomendadas de codificação são descritas nas seções seguintes destetópico.
- Dicas de Segurança
Sempre valide entrada de usuário testando tipo, comprimento, formato e intervalo. Quando
você estiver implementando precauções contra entrada mal-intencionada, considere os
cenários de arquitetura e implantação de seu aplicativo. Lembre-se de que programas
projetados para executar em um ambiente seguro podem ser copiados para um ambiente sem
segurança. As sugestões seguintes devem ser consideradas práticas recomendadas:
6
- Não faça suposições sobre o tamanho, o tipo ou o conteúdo dos dados recebidos pelo seu
aplicativo. Por exemplo, você deve fazer a seguinte avaliação:
- Como seu aplicativo se comportará se um usuário errôneo ou mal-intencionado inserir um
arquivo MPEG de 10 megabytes onde seu aplicativo espera um código postal?
- Como seu aplicativo se comportará se uma instrução DROP TABLE for incorporada em um
campo de texto? 
- Teste o tamanho e tipo de dados de entrada e imponha limites apropriados. Isso pode ajudar
a impedir excesso deliberado de buffer.
- Teste o conteúdo de variáveis de cadeia de caracteres e só aceite valores esperados. Rejeite
entradas que contenham dados binários, seqüências de escape e caracteres de comentário. Isso
pode ajudar a impedir injeção de script e proteger contra explorações de excesso de buffer.
- Quando você estiver trabalhando com documentos XML, valide todos os dados em seu
esquema à medida que são inseridos.
- Nunca construa instruções Transact-SQL diretamente da entrada do usuário.
- Use procedimentos armazenados para validar entrada de usuário.
- Em ambientes de várias camadas, todos os dados devem ser validados antes de serem
admitidos à zona de confiança. Os dados que não passam pelo processo de validação devem
ser rejeitados e um erro deve ser retornado à camada anterior.
- Implemente várias camadas de validação. Precauções tomadas contra usuários casualmente
mal-intencionados podem ser ineficazes contra determinados invasores. Uma prática mais
recomendada é validar a entrada na interface do usuário e em todos os pontos subseqüentes
onde ele cruza um limite confiável.
7
Por exemplo, a validação de dados em um aplicativo cliente pode evitar injeção de script
simples. No entanto, se a próxima camada assumir que sua entrada já foi validada, qualquer
usuário mal-intencionado que possa contornar um cliente poderá ter acesso irrestrito ao
sistema.
- Nunca concatene entrada de usuário que não seja validada. A concatenação de cadeia de
caracteres é o ponto principal de entrada de injeção de script.
- Não aceite as seguintes cadeias de caracteres em campos dos quais nomes de arquivos
podem ser construídos: AUX, CLOCK$, COM1 a COM8, CON, CONFIG$, LPT1 a LPT8,
NUL e PRN.
UTILIZANDO OS OPERADORES DE CONCATENAÇÃO
A utilização dos operadores de concatenação podem parecer um recurso simples, mas
garantem uma maior facilidade de leitura do código e também uma redução aceitável de
código. Primeiramente, vejamos com relação a sintaxe para a concatenação que utiliza o
operador de adição, em seguida, apresentaremos a sintaxe de utilização do operador de
subtração que é bastante semelhante a sintaxe de adição. Estas operações não são encontradas
apenas no T-SQL, mas sim em muitas das linguagens de programação conhecidas do
mercado, como é o caso do PHP, C, C++, C# ou o próprio Java.
- Sintaxe de concatenação com o operador de adição.
Expressão += Expressão
Ao analisarmos a sintaxe acima, podemos observar que temos duas expressões separadas pela
junção dos sinais de adição e de igualdade (+=). Isto é onde a semelhança destes dois
operadores termina. O operador de concatenação de Strings é usado para concatenar valores
de cadeia. As expressões em que o operador concatenação podem ser de qualquer tipo de
dados válido. O valor concatenado que será retornado pela operação de concatenação irá
conter o tipo de dados da expressão com a maior precedência. Assim como o suplemento é
8
igual à primeira expressão (do lado esquerdo) que deve ser variável, e é a variável que conterá
o resultado final da operação de concatenação.
O operador += exige que cada expressão a ser analisada seja de um tipo de dado numérico,
exceto BIT. Este operador assume o valor de cada expressão e o adiciona, retornando um
valor numérico da operação de adição em que o tipo de dados do resultado tem um tipo de
dados que a expressão com a maior precedência. 
A expressão do lado esquerdo do operador += tem de ser uma variável. Como dito
anteriormente, a operação de subtração concatenada será apresentada a sguir, a qual apresenta
a sua semelhança.
- Sintaxe de concatenação com o operador de subtração.
Expressão -= Expressão
Assim como a operação utilizando o operador de adição, a string de concatenação com o
operador de subtração também possui as duas expressões. Assim como na expressão anterior,
ambas as expressões precisam ser de tipos numéricos diferente de BIT. Assim como o
operador de +=, o operador de -= assume o valor de cada expressão e subtrai o segundo termo
a partir do primeiro e, em seguida, retorna um valor numérico, onde o tipo de dado tem que
ser um tipo de dado com a maior precedência. Assim como o operador de +=, o operador de
-= requer uma variável para a expressão no lado esquerdo do operador que é igual a
subtração, e é esta variável que ficará com o valor resultante da operação.
Talvez tenhamos complicado um pouco na teoria com relação ao assunto, mas vamos
começar agora com alguns exemplos para um melhor entendimento com relação ao uso desses
operadores. Para nossos exemplos estaremos utilizando o SQL SERVER 2014, caso tenham
interesse em criar os exemplos, vocês podem baixar através do site
http://msdn.microsoft.com/pt-br/evalcenter/dn434042.aspx
9
- Utilizando o operador de concatenação +=
Começaremos então com um exemplo simples utilizando o operador de adição, onde
setaremos duas strings e em seguida, faremos a sua concatenação, o código que estaremos
apresentando será de acordo com o apresentado acima.
- Utilização simples da concatenação de strings com o operador +.
-- Concatenação com shortcodes
DECLARE @String varchar(100);
 SET @String = 'Edson';
 SET @String += ' Dionisio';
 SELECT @String;
GO
-- Concatenação sem Shortcode
 DECLARE @String varchar(100);
 SET @String = 'Edson';
 SET @String = @String + ' Dionisio'
 SELECT @String;
 GO
Perceba que no código apresentado temos dois exemplos diferentes de como podemos
concatenar duas strings juntas. No primeiro conjunto de declarações usamos o nosso atalho
(digamos dessa forma) que é o operador de concatenação de String, enquanto que no segundo
conjunto de declarações, usamos o operador "+" para concatenar duas strings, de forma bem
simples. 
Como podemos observar, no primeiro conjunto de declarações, só tínhamos especificado a
@String uma vez. Ela foi especificada apenas no lado esquerdo do operador +=.
Considerando que, no segundo conjunto de instruções, temos a variável @String especificada
em ambos os lados do operador de igualdade (=). Esses conjuntos de instruções realizam a
mesma operação de concatenação. Mas perceba que utilizando o atalho, +=, 
10
reduzimos a quantidade de código escrito e tivemos o mesmo resultado, numa forma mais
limpa.
- Setando um valor numérico para controle de um loop.
No exemplo abaixo vamos mudar um pouco o contexto de strings para valores numéricos e
apresentaremos a utilização dos nossos atalhos para incrementar e decrementar valores
numéricos.
DECLARE @I int =1;
 WHILE @I < 20
 BEGIN
 SELECT 'O valor da variável @I é ' + CAST(@I as char(1));
 SET @I += 1;
 END
Ao olharmos para o código apresentado acima, podemos perceber que incrementamos o valor
da variável @I de 1 cada vez que ele passa no while usando o operador de +=. Somar e
subtrair valor a uma variável é algo comum quando estamos escrevendo código no nosso dia a
dia. Com a adição dos operadores += e -=, esta operação se torna mais fácil de implementar. É
isso que ocorre no nosso exemplo, onde temos nossa variável iniciando em 1 e que vai ser
concatenada daí em diante até chegar ao valor esperado que é o 20. 
- Outra maneira de incrementar valores no loop.
O código abaixo é equivalente ao código apresentado acima, mas não usa o nosso atalho +=.
DECLARE @I int = 1;
 WHILE @I < 20
 BEGIN
 SELECT 'O valor da variável @I é ' + CAST(@I as char(1));
 SET @I = @I + 1;
 END
11
Ao compararmos os códigos apresentados neste tópico e no anterior, podemos ver que no
tópico anterior usamos menos atalhos para incrementar a variável @I. o operador de -= pode
ser usado apenas como o operador +=. 
- Exemplo de utilização do operador -=.
No exemplo abaixo contém um código que diminui o valor da variável de controle do loop
WHILE usando o operador de subtração.
DECLARE @I int = 10;
 WHILE @I > 0
 BEGIN
 SELECT 'O valor da variável @I é ' + CAST(@I as char(2));
 SET @I -= 1;
 END
Em todos os nossos exemplos até este momento usamos uma constante com os operadores de
adição ou subtração para aumentar ou diminuir o conjunto da variável. Além disso, também é
possível usar as variáveis ou mesmo fórmulas no lado direito destes de ambos os operadores.
- Usando uma formula com o operador +=.
DECLARE @I int = 3;
 DECLARE @X int = 15;
 DECLARE @Y int = 2;
 SET @I += @X * @Y
 SELECT @I
Se observarmos o código acima, veremos que temos uma formula matemática, sendo esta
apresentada com as variáveis X, Y e I, onde realizamos a multiplicação das variáveis @X e
@Y e em seguida somamos o valor da variável @I, o que nos dá um resultado de 33 pra @I.
12
- Porquê utilizar T-SQL dinâmicas?
Agora que vimos com relação a utilização dos operadores de concatenação, chegou a hora de
tratarmos da utilização de T-SQL dinâmicas, saber o porquê de utilizá-las, o porquê de sua
importância.
A primeira pergunta que surge a nossa mente é: o que são as T-SQL dinâmicas? Por que é
necessário utilizá-las? Bem, um T-SQL dinâmico é o código que é potencialmente diferente a
cada vez que nós o executamos. Ele é um conjunto de instruções T-SQL que é gerado e
executado em tempo de execução. Este código é criado com base em algumas condições ou
mesmo parâmetros no bloco de instruções. Quando as "condições ou parâmetros" são
diferentes do código T-SQL, ele produz uma T-SQL diferente para ser executada.
Geralmente usamos a T-SQL dinâmica quando queremos determinar programaticamente o T-
SQL que precisamos com base em parâmetros e/ou com base em dados armazenados em
tabelas de banco de dados. Os usos para a T-SQL dinâmica são infinitas. Aqui apresentamos
dois exemplos de quando podemos usar uma T-SQL dinâmica, que são quando:
- Queremos que o usuário selecione alguns critérios de uma lista suspensa que podem realizar
uma consulta para executar de formas diferentes, como uma ordem de classificação.
- Sua aplicação não sabe o nome da tabela que poderá ser usada em tempo de execução.
Para um melhor entendimento com relação as T-SQL dinâmicas, apresentaremos alguns
exemplos a partir desse momento.
- Criando uma T-SQL dinâmica simples
Para o nosso primeiro exemplo de criação de T-SQL’s dinâmicas, consideremos a seguinte
situação: Suponhamos que nós temos uma aplicação onde a interface com o usuário permite
que o usuário selecione a tabela que deseja ler a partir de uma lista suspensa. Com isso,
podemos ver de início que cada usuário poderá acessar a tabela que quiser para retornar os
dados existentes. 
13
Para darmos continuidade a esses exemplos, vamos supor que este usuário exiba informações
da tabela do banco de dados AdventureWorks2012_database e o mesmo escolha a tabela de 
dventureWorks2012.Sales.SalesOrderDetail. 
O código que será apresentado abaixo nos mostra um método de utilizar o código T-SQL
dinâmico para retornar os 10 registros da tabela
AdventureWorks2012.Sales.SalesOrderDetail.
- Exemplo de utilização de uma T-SQL dinâmica simples.
-- Declaramos aqui a variável que terá o código da T-SQL dinâmica
 DECLARE @COMANDO nvarchar(1000);
 -- Declarando o nome da tabela para leitura
 DECLARE @Tabela nvarchar(125);
 SET @Tabela = 'AdventureWorks2012.Sales.SalesOrderDetail';
 -- construindo dinamicamente a declaração da T-SQL
 SET @COMANDO = 'SELECT TOP 10 * FROM ' + @Tabela;
 -- executando a declaração da T-SQL dinâmica
 EXECUTE (@COMANDO);
O código apresentado acima, disponibiliza a declaração da variável chamada @COMANDO
que é para armazenar a instrução SELECT dinamicamente que vai construir a @Table que é
para manter o nome da tabela. Então, definiremos a @Table para
AdventureWorks2012.Sales.SalesOrderDetail. 
Para construirmos a nossa declaração T-SQL de forma dinâmica, usamos uma instrução SET.
Esta declaração define a @COMANDO para o valor da cadeia concatenada que contém uma
instrução SELECT e o valor da @TABLE. 
Agora que temos a nossa declaração definida, executemos a nossa declaração T-SQL
dinâmica que está contida na @COMANDO.
14
Para realizarmos um outro teste com a T-SQL dinâmica, podemos substituir a tabela utilizada
por uma tabela diferente no código, alterando apenas a instrução "SET @ Table =" para
usarmos a tabela de AdventureWorks2012.Sales.Sales.OrderHeader.
- Código dinâmico para exclusão de tabelas
Há momentos em que precisamos escrever alguns códigos T-SQL dinâmicos mais
complicados. Seja DBA ou programador com privilégios de DBA, nos encontramos em uma
daquelas situações em que precisamos gerar um código para executarmos algum tipo de
manutenção de banco de dados. O que fazer? O que podemos fazer é construir uma T-SQL
dinâmica para fins de manutenção de banco de dados que serão aplicados da seguinte
maneira: temos uma visão (view) do sistema e, em seguida, geramos um script que seria
executado. 
Suponhamos então que assumimos a manutenção de um banco de dados e que desejamos
excluir várias tabelas de teste que foram criadas em uma determinada base de dados. As
tabelas possuem nomes que começam com o prefixo "Teste", como uma boa prática. 
Para demonstrarmos, vamos ler a view sys.tables e gerar as instruções DELETE apropriadas.
-- Criando a base e as tabelas de exemplo
 USE master;
 GO
 CREATE DATABASE QSASOLUCOES;
 GO
 USE QSASOLUCOES; 
 GO
 CREATE TABLE Dados1 (Id int, DataDesc varchar(100));
 CREATE TABLE Dados2 (Id int, DataDesc varchar(100));
 CREATE TABLE TesteDados1 (Id int, DataDesc varchar(100));
 CREATE TABLE TesteDados2 (Id int, DataDesc varchar(100));
 GO
15
 -- código T-SQL dinâmico para deletar as tabelas
 USE QSASOLUCOES;
 GO
 DECLARE @TabelaNome varchar(100);
 DECLARE @CMD varchar(1000);
 SELECT TOP 1 @TabelaNome = nome FROM sys.tables
 WHERE nome like 'Teste%'
 ORDER BY nome;
 WHILE @@ROWCOUNT > 0
 BEGIN
 SELECT @COMAND = 'DROP TABLE ' + @TabelaNome + ';';
 PRINT @ COMAND
 EXECUTE(@COMAND);
 SELECT TOP 1 @TabelaNome = nome FROM sys.tables
 WHERE nome like 'Teste%' andnome > @TabelaNome
 ORDER BY nome;
 END
 -- Limpeza profunda! 
 USE master;
 GO
 DROP DATABASE QSASOLUCOES;
De acordo com o código apresentado acima, temos três seções diferentes. Na primeira seção,
criamos um banco de dados chamado QSASOLUCOES, e em seguida criamos quatro tabelas
diferentes, duas das quais começam com "Teste". Estas duas tabelas são as tabelas que
desejamos apagar com código T-SQL dinamicamente. Na segunda seção apresentada do
código está o nosso T-SQL dinâmico. E por fim, na terceira seção do código, limpamos o
banco de dados de teste que criamos.
Se analisarmos o código apresentado pela segunda seção, encontraremos o código T-SQL
dinâmico que primeiro imprime as instruções de DELETE que será executada, em seguida,
exclui as tabelas de teste que criamos na primeira parte, onde fazemos o processamento em
um loop while para ver as diferentes tabelas que começam com a cadeia de caracteres "Teste".
16
Para cada tabela que começar com "Teste", construímos um comando DELETE que é
armazenado no @COMAND. Daí, apresentamos a declaração DELETE usando uma instrução
PRINT, imediatamente seguido da execução da instrução usando a instrução EXECUTE. Na
última seção, realizamos a limpeza, deixando o banco de dados que criamos.
Para testarmos este código, sugerimos que a execução seja realizada a cada seção comentada
de forma independente, a fim de iniciarmos a partir de primeira seção. Após executar esta
seção, verificamos que existem quatro tabelas no banco de dados QSASOLUCOES. 
No próximo bloco de código, quando executado, visualizamos duas mensagens sendo
exibidas na guia mensagem na janela de Query Analyzer. As duas declarações são mostradas
com as duas instruções DELETE que foram geradas e executadas de forma dinâmica. Uma
vez que isso é feito, executamos o código da segunda seção, e voltamos a ver as tabelas no
nosso banco de dados QSASOLUCOES. Se o Pesquisador de Objetos no SQL Server
Management Studio estiver ativo, não esqueçam de atualizar. 
Alternativamente, podemos selecionar apenas do ponto de vista sys.tables. Agora devemos
observar que existem apenas duas tabelas, e as duas tabelas excluídas são aquelas que
começam com "Teste". Após essa verificação ter sido realizada, executamos o código
presente na terceira seção que é responsável pela limpeza. Este é um exemplo muito simples
de como examinar as linhas de metadados e gerarmos a T-SQL dinâmica. 
Agora o que podemos fazer em casos de sql injection? podemos em algum momento, ter
obtido a informação de que uma TSQL dinâmica é ruim, onde a parte ruim da T-SQL
dinâmica é que ela abre possibilidades para um ataque de SQL Injection. 
O SQL Injection é uma técnica de hacking que usuários mal intencionados tentam explorar o
uso de um campo de entrada de dados de forma livre. Esses usuários mal intencionados
tentam inserir um código T-SQL adicional em um campo de entrada de dados de uma forma
diferente de como o campo de entrada de dados foi originalmente destinado a ser utilizado.
Através da inserção de códigos T-SQL que podem enganar o sistema e retornar dados que
originalmente não deveriam ser obtidos, ou poderiam ainda mais, executar comandos
17
adicionais T-SQL contra seu banco de dados SQL Server. Dependendo das permissões que o
aplicativo tenha executado sob um ataque de injeção de SQL, isso pode inserir dados em suas
tabelas de banco de dados, excluir uma tabela, ou pior ainda configurar um novo login com
direitos sysadmin diferentes.
- Base de dados e tabela criadas para teste de sql injection.
Para demonstrarmos agora como uma T-SQL dinâmica pode estar sujeita a um ataque de SQL
Injection, criaremos uma nova base de dados e uma nova tabela, com o intuito de demonstrar
como uma T-SQL dinâmica pode ser vulnerável a um ataque de desse tipo.
USE master;
 GO
 CREATE DATABASE QSASOLUCOES2;
 GO
 USE QSASOLUCOES2;
 GO
 CREATE TABLE Produto(ID int, Nome_produto varchar(100), Preco money);
 INSERT INTO Produto VALUES (1, boneco lego vermelho', 12.99),(2, 'Boneco Hulk vermelho',
23.18), (2, 'Carrinho de fricção', 7.59), (2, 'Drone', 177.76);
O código que acabamos de apresentar cria o nosso banco de dados chamado de
QSASOLUCOES2 e, em seguida, criamos e preenchemos uma tabela que chamamos de
produto com quatro linhas de dados. 
- Código da stored procedure GetProdutos.
Suponhamos que a nossa aplicação tenha uma tela de seleção de dados, onde o usuário poderá
inserir uma cadeia de caracteres que está contido em um nome_produto e, em seguida, a
aplicação retorne todos os registros da tabela de produtos que contenham a sequência de texto
digitado. Após isso, esta sequência de caracteres é processada por uma stored procedure,
chamada de GetProdutos, que tem a finalidade de selecionar os dados de acordo com o padrão
estabelecido, e, em seguida, estes dados são retornados pela stored procedure e são exibidos
para este usuário. 
18
 CREATE PROC GetProdutos 
 (@pesquisa varchar (100))
 AS 
 DECLARE @COMAND varchar(255);
 SET @COMAND = 'SELECT nome_produto, Preco ' + 
 'FROM [QSASOLUCOES2].[dbo].Produto ' +
 'WHERE nome_produto LIKE ''%' + 
 @ pesquisa + '%''';
 PRINT @ COMAND
 EXEC (@COMAND);
Ao analisarmos nossa procedure GetProdutos presente, podemos observar que esta stored
procedure aceita um único parâmetro que é o @pesquisa. Este parâmetro é então usado para
criar dinamicamente uma instrução T-SQL que é armazenada na varável @COMAND. Para
demonstrarmos como usar a nossa stored procedure, vamos então executá-la.
- Executando a stored procedure GetProdutos.
EXEC GetProdutos 'vermelho';
Ao executarmos essa procedure, obtemos o retorno de duas linhas em nossa consulta que
contém o termo “vermelho” contido nelas. Como o código presente em nossa stored
procedure GetProdutos tem um parâmetro do tipo varchar e gera a variável @COMAND, isso
deixa a stored procedure propícia a um ataque de SQL Injection. Podemos demonstrar isso
através da execução da stored procedure GetProdutos com o código apresentado abaixo.
- Código que mostra como a stored procedure está vulnerável
EXEC GetProdutos 'vermelho%'' and ID = 1 --';
Se pararmos para analisar o código acima, veremos que foi passada uma série de outros
termos adicionais para a string "vermelho" ao nosso GetProdutos. Esses termos adicionais que
foram passados, nos permitem restringir a consulta para retornar somente os produtos que
19
possuem "vermelho" na coluna nome_produto e que possui um valor de ID de 1. Ao
permitirmos que o stored procedure possa usar o texto no parâmetro @pesquisa, permitimos a
injeção de caracteres adicionais em que o parâmetro pode fazer com que o código execute
outras ações que não foram originalmente destinados a realizar no stored procedure
GetProdutos.
Até o momento, mostramos um ataque de SQL Injection não destrutivo usando a nossa T-
SQL dinâmica com a stored procedure GetProdutos. A maioria dos ataques de SQL Injection
busca obter dados adicionais dos nossos sistemas, ou apenas corromper nossos bancos de
dados. Para mais informações, vamos explorar um pouco mais através do tópico abaixo.
- SQL injection para retornar dados adicionais.
EXEC GetProdutos 'vermelho'' ;SELECT * FROM [QSASOLUCOES2].[dbo].Produto;--';
Ao executarmos este código, ele irá gerar os dois conjuntos de resultados, onde o primeiro
tem zero linhas e o segundo retorna os registros cadastrados na base anteriormente.
Se formos comparar osresultados de uma execução normal da stored procedure GetProdutos
encontrada nos resultados com os resultados encontrados da nossa última execução, veremos
que o código acima gerou algumas colunas de saída adicionais que nossa stored procedure
não foi originalmente preparada para exibir, mas que acabou exibindo devido a um ataque de
SQL Injection.
Nosso exemplo ainda não era um uso destrutivo de SQL Injection, mas deu brecha para
explorarmos o parâmetro @pesquisa de nossa stored procedure getProdutos para retornar
dados de todas as colunas da tabela. Para conseguir isso adicionamos o "'; Select * from
[QSASOLUCOES].[dbo].produtos; -". Uma observação a se fazer é com relação a adição de
dois traços ("-") no fim de nossa string. Isso nos permite comentar o que quer que o código
que nossa stored procedure possa ter incluído após o parâmetro. 
20
- Código destrutivo de sql injection.
Para finalizarmos o exemplo, faremos agora um ataque destrutivo T-SQL.
EXEC GetProdutos 'vermelho'' ;DROP TABLE [QSASOLUCOES2].[dbo].Produto;--'; 
Ao executarmos agora nossa instrução, apagamos a nossa tabela! Esse é um tipo de sql
injection destrutivo. Vejamos como podemos combater sql injections. Ninguém quer ter seu
código comprometido por um ataque de SQL Injection. Então, para combatermos contra estes
ataques de SQL, devemos considerar alguns pontos ao desenvolver o código do aplicativo T-
SQL, que são:
- Não usar SQL dinâmico;
- Editar os parâmetros que o usuário passou para caracteres especiais como o ponto e vírgula e
comentários;
- Ter parâmetros apenas enquanto for necessário para manter os dados digitados pelo usuário.
- Caso devamos usar SQL dinâmico, devemos em seguida usar T-SQL parametrizado que
utilize sp_execute sql para executar nossas T-SQL dinâmica, ao invés de usar o EXEC.
- Se realmente for necessário a construção do código que contenha T-SQL dinâmico, usar
uma T-SQL parametrizada é uma boa maneira de combater o SQL Injection. 
- Usando parametrizações no T-SQL.
ALTER PROC GetProdutos 
 (@pesquisa varchar (100))
 AS 
 DECLARE @COMAND nvarchar(1000);
 DECLARE @ParametroCoringa varchar(102);
21
 SET @COMAND = 'SELECT Nome_produto, Preco ' + 
 'FROM [QSASOLUCOES2].[dbo].Produto ' +
 'WHERE Nome_produto LIKE @pesquisa';
 SET @ParametroCoringa = '%' + @pesquisa + '%';
 EXEC sp_executesql @COMAND,N'@pesquisa varchar(100)',@pesquisa=@ParametroCoringa;
Ao fazermos estas alterações, o usuário não poderá mais tentar injetar código T-SQL
adicional em nosso stored procedure.
ATAQUES SQL INJECTION UTILIZANDO LINGUAGENS DINÂMICAS
- Evitando injection em formulário web com PHP
Interações entre formulários web e usuários deixam uma porta aberta para inserção de
qualquer tipo de dado. Essa possibilidade pode ser ao mesmo tempo o céu ou inferno de um
desenvolvedor. Formulários que não possuem controle de dados de entrada correm o sério
risco de serem manipulados indevidamente, prejudicando a segurança do sistema.
Injections são uma forma de manipulações mal intencionadas de formulários web e podem
atingir desde funções em linguagem de programação até manipulações em banco de dados,
correndo o risco de danificar o sistema ou expor dados privados.
Uma maneira de contornar este problema é tratar todos os dados de entrada, independente de
qual tipo de componente de formulário ele teve origem.
Como as passagens de dados de uma página para outra é feita através de vetores (POST, GET,
SESSION, COOKIE) todos estes vetores devem ser verificados antes dos seus dados serem
utilizados.
O primeiro passo é definir uma função que elimine toda entrada de formulário considerada
maliciosa, que de uma forma ou de outra poderia prejudicar o sistema. As entradas mais
comuns são espaços vazios, configuração de cabeçalho de e-mail como Content-Type e bcc,
tags HTML como os sinais de maior e menor, e aspas. 
22
Para contornar este problema criamos a seguinte função:
/**
 * @abstract Tratamento de injections em formulários.
 * @return string
 */ 
function antiInjection($str) 
{
 # Remove palavras suspeitas de injection.
 $str = preg_replace(sql_regcase("/(\n|\r|%0a|%0d|Content-Type:|bcc:|to:|cc:|Autoreply:|from|
select|
insert|delete|where|drop table|show tables|#|\*|--|\\\\)/"), "", $str);
 $str = trim($str); # Remove espaços vazios.
 $str = strip_tags($str); # Remove tags HTML e PHP.
 $str = addslashes($str); # Adiciona barras invertidas à uma string.
 return $str;
}
Esta função remove possíveis entradas de dados maliciosas. Tem como parâmetro de entrada
um vetor, podendo ser qualquer vetor, desde vetores criados pelo próprio desenvolvedor até
vetores próprios da linguagem, como POST, GET, COOKIE e SESSION.
Com a função de tratamento de injection criada, caímos em outro problema: pode haver
vetores dentro de vetores. Um exemplo disto seria um select multiple ou um vetor de
checkbox. Para tratar isto criamos outra função:
/**
 * @abstract Antes de tratar os injections, verifica se é vetor ou não.
 */ 
function validaParametro($vetor)
{
 if (is_array($vetor))
 {
 foreach ($vetor as $chave => $valor) 
23
 {
 if (is_array($valor)) 
 {
 $vetor[$chave] = validaParametro($valor); 
 } else $vetor[$chave] = antiInjection($valor);
 }
 } else $vetor[$chave] = validaParametro($valor);
 return $vetor;
}
Dessa forma, antes de tratar possíveis injections, verifica se o parâmetro passado é um vetor
ou não, caso seja um vetor, a função validaParametro() é chamada recursivamente passando o
novo vetor como parâmetro, caso não seja um vetor, chama a mesma função passando a string
a ser tratada. A chamada à função ficaria da seguinte forma:
$_POST = validaParametro($_POST);
$_GET = validaParametro($_GET);
Lembrando que qualquer vetor pode ser verificado.
- Prevenindo SQL Injection no ASP.NET
A SQL - Structured Query Language - é largamente usada para interagir com banco de dados
relacionais. Se você considerar que 90% das aplicações utilizam banco de dados com suporte
a SQL vai concluir que o uso da SQL é quase uma unanimidade por ser prática , fácil e
portátil.
Em se falando de aplicações Web temos uma grande utilização de banco de dados para
armazenar as mais diversas informações : endereços e documentos pessoais , contas e valores
financeiros , números de cartões de crédito , dados empresariais , etc.
Ao colocar sua aplicação na Web você a esta expondo a um acesso mais amplo e
indiscriminado. Afinal qualquer um que tenha acesso a url do site terá acesso a sua aplicação
e aos dados que ela disponibiliza. 
24
Pensando na segurança de suas informações as empresas investem pesado em firewalls ,
certificação digital e outros recursos , com o objetivo de se proteger de invasores.
Para que o controlar o acesso as informações normalmente restringe-se o acesso aos usuários
cadastrados usando um nome e senha para identificação ; estes dados são colhidos através de
um formulário de login e são então verificados com as informações armazenadas em um
banco de dados dos usuários cadastrados; se estiverem corretas o acesso é permitido caso
contrário o acesso é negado.
É assim que funciona o home banking na internet e uma infinidade de outras aplicações web
na qual o acesso é restrito.
Você pode ter o aparato mais moderno em termos de tecnologia de segurança protegendo o
seu site de um ataque hacker e nem se dar conta de que a vulnerabilidade da sua aplicação
esta ali naquele formulário de login. Ele pode ser a porta de entrada para ataques maliciosos
atravésda injeção de SQL.
A injeção SQL ocorre quando um invasor consegue inserir comandos SQL na instrução SQL
que você usa no seu script de modo a burlar a restrição e ter acesso ou danificar as
informações armazenadas no seu banco de dados.
Neste artigo eu vou mostrar como a injeção de SQL ocorre e falar sobre algumas das medidas
que você pode tomar para evitá-la. Embora as informações sejam focadas em páginas ASP e
banco de dados SQL Server /Access elas se aplicam a qualquer script e banco de dados que
usam um dialeto SQL.
- Como ocorre a injeção SQL
Se você acha que não deve levar a sério a injeção SQL veja esta notícia da INFO:
Segundo o Sans Institute Storm Center, SISC, os ataques atingiram sites de entidades, de
empresas e até páginas de governo. “Esse tipo de injeção esvazia o conceito de site
‘confiável’ ou ‘seguro’ ”, diz o pesquisador Donald Smith, do SISC.
25
500 mil sites sofrem injeção de SQL
Sexta-feira, 25 de abril de 2008 – 12h54
SÃO PAULO – 500 mil sites foram afetados por uma injeção de SQL que propaga um cavalo-de-tróia
ladrão de senhas.
Os sites comprometidos com essa injeção de SQL são invadidos por um código que redireciona o
browser para outro site, no qual um cavalo-de-tróia ladrão de senhas tenta se instalar na máquina do
usuário.
O SISC recomenda que as empresas bloqueiem em seus firewalls de borda o acesso ao endereço
hxxp:/www.nihaorr1.com e também ao IP a ele associado, 219DOT153DOT46DOT28
veja também esta notícia: http://www.linhadefensiva.org/2008/05/ataques-de-sql-injection-atingem-
sites-brasileiros/
500 mil sites !!!! Você gostaria que o seu estive entre um deles ??? 
Abaixo temos um típico formulário de login :
<form name="frmLogin" action="login.asp" method="post">
 Nome : <input type="text" name="nomeUsuario">
 Senha: <input type="text" name="senhaUsuario">
 <input type="Enviar">
</form>
Geralmente quando o usuário clicar no botão - Enviar - o script login.asp será executado para
efetuar a validação dos dados informados. Abaixo temos um script típico para um arquivo de
validação de informações:
<%
dim nomeUsuario, senhaUsuario, consulta
dim conn, rS
nomeUsuario = Request.Form("nomeUsuario")
senhaUsuario = Request.Form("senhaUsuario")
set conn = server.createObject("ADODB.Connection")
set rs = server.createObject("ADODB.Recordset")
26
consulta = "select count(*) from usuarios where nomeUsuario='" & nomeUsuario & "' and
senhaUsuario='" & 
senhaUsuario & "'"
conn.Open "Provider=SQLOLEDB; Data Source=(local);Initial Catalog=myDB; User Id=sa;
senhaUsuario="
rs.activeConnection = conn
rs.open consulta
if not rs.eof then
 response.write "Acesso Concedido"
else
 response.write "Acesso Negado"
end if
%>
Vamos analisar o que ocorre quando um usuário tenta se autenticar. Vamos supor que ele é
usuário cadastrado com nome QSASOLUCOES e senha 123456 (só suposição). Ao informar
o nome e a senha e clicar no botão Enviar o script do arquivo login.asp será executado.
Vamos ver como ficou a instrução SQL montada neste caso :
select count(*) from usuarios where nomeUsuario='qsasolucoes' and senhaUsuario='123456'
Neste caso o usuário qsasolucoes, senha 123456 será autenticado e terá acesso ao sistema.
Tubo bem ?
Não , se você usa este tipo de instrução SQL nada esta bem pois o texto final da consulta
SQL depende inteiramente do conteúdo das variáveis , e , se o conteúdo destas variáveis não
for validado e tratado o texto final concatenado poderá ser um SQL adulterado através de uma
injeção SQL.
27
Quer ver ? Vou começar pegando leve. Vamos supor que um hacker decidiu invadir sua
página. Uma das primeiras coisas que ele pode fazer é tentar uma injeção SQL , e, vai
começar verificando se você esta tratando o apóstrofe (aspa simples: '). Se você não sabe a
presença de um caractere de apóstrofe (') no conteúdo de uma variável concatenada no SQL é
usada para delimitar strings de texto. Então suponha que ele digite os seguintes dados nos
campos nome e senha:
nome = tes'te
senha =
Se você não tratar o apóstrofe vai ocorrer um erro de SQL (incorrect Sintax) ,e , vendo isto o
hacker vai ficar mais animado...
Agora vou pegar pesado. Suponha então que a seguir ele digite os seguintes dados
nome = ' ; drop table users--
senha =
Este comando irá excluir a tabela users (se ela existir). E se você pensa que é muito difícil o
hacker adivinhar o nome da sua tabela vou mostrar mais abaixo que ele pode fazer isto de
uma maneira simples. Isto é possível pois o caractere (;) indica o fim de uma consulta e o
começo de outra em T-SQL , e , o caractere (--) no final da linha faz com que o scrpt ASP
seja executada sem erro.
Continuando o ataque , ele pode também informar o seguinte :
nome = admin
senha = ' or 1=1--
veja como vai ficar a consulta SQL montada:
select count(*) from usuarios where nomeUsuario='admin' and senhaUsuario='' or 1=1--'
28
Aqui a consulta irá verificar se o nome do usuário é admin e se senha é vazio ou 1 for igual a
1 ( o que é verdade) ; bingo, se existir um usuário admin ele entrou no seu sistema.
Ele pode também tentar o seguinte :
nome = ' or 1=1--
senha =
a consulta SQL montada será :
select count(*) from usuarios where nomeUsuario='' or 1=1 --' and senhaUsuario=''
e bingo, ele burlou o seu sistema.
O hacker pode também tentar o seguinte:
nome = ' OR "='
senha = ' OR "='
e a consulta SQL montada será :
select count(*) from usuarios where nomeUsuario='' OR "=" AND senhaUsuario='' OR "="
a consulta agora esta fazendo a comparação : OR "=" que é sempre verdadeira. Bingo ele
entrou no seu site.
Para saber o nome das tabelas e campos o hacker pode fazer o seguinte :
nome = ' having 1=1--
senha =
isto pode causar o seguinte erro:
29
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft] [ODBC SQL Server Driver] [SQL Server] Column 'usuarios.codigo' is invalid in
the select list because it is not contained in an aggregate function and there is no GROUP BY
clause.
/login.asp , line 28
e bingo , o hacker agora sabe que o nome da tabela é usuarios e o nome do campo relacionado
no formulário como nome é codigo.
E então , o que você acha que ele vai fazer ? Fazer a mesma coisa para o campo senha e então
ele vai saber o nome da tabela e dos campos relacionados ao formulário. Imagine o estrago
que ele não será capaz de fazer agora...
Pensa que ele pode ficar somente nisto. Já conhecendo o nome da tabela e das colunas se o
hacker quiser saber o tipo de dados do campo ele pode fazer o seguinte :
nome = ' UNION SELECT SUM(nomeUsuario) FROM usuarios--
senha =
Como o SQL Server vai tentar aplicar a cláusula SUM antes de determinar se o número dos
campos nas duas colunas é igual. Ao tentar fazer um SUM em um campo texto o sistema pode
emitir a seguinte mensagem de erro:
Microsoft OLE DB Provider for ODBC Drivers error '80040e7'
[Microsoft] [ODBC SQL Server Driver] [SQL Server] The Sum or average aggregate
operation cannot take a varchar data type as na argument.
/login.asp , line 109
e bingo de novo, ele agora sabe o tipo de dado do campo nomeUsuario.
Agora sabe o que ele vai fazer ? Vai inserir um usuário com nome senha para se logar, assim:
30
nome = ' ; INSERT INTO usuarios VALUES('hacker','111111')--
senha =
E... bingo , ele vai se logar como hacker e senha 111111.
Acho que com estes exemplos já deu para você perceber que você tem que cuidar com muito
mais cuidado das suas instruções SQL .Tenha certeza de uma coisa : as possibilidades do
hacker são muitas.
- Como evitar uma ataque de injeção SQL
A seguir algumas orientações de como vocêpode evitar um ataque de injeção SQL :
1- Estabeleça uma política de segurança rígida e criteriosa limitando o acesso dos seus
usuários. Isto quer dizer que você deve dar somente os poderes necessários aos seus usuários.
Não de acesso de escrita a tabelas e dê somente acesso as tabelas que o usuário vai precisar.
2- Faça a validação da entrada de dados no formulário e não permita os caracteres inválidos
como : (') , (--) e (;) nem de palavras maliciosas como insert , drop , delete, xp_ . Abaixo
algumas funções que você pode usar:
- Substituindo o apóstrofe(') pelo duplo apóstrofe ('')
<%
Function ExpurgaApostrofe(texto)
 ExpurgaApostrofe = replace( texto , "'" , "''")
End function
%>
31
- Substituindo os caracteres e palavras maliciosas por vazio("").
<%
Function LimpaLixo( input )
 dim lixo
 dim textoOK
 lixo = array ( "select" , "drop" , ";" , "--" , "insert" , "delete" , "xp_")
 textoOK = input
 for i = 0 to uBound(lixo)
 textoOK = replace( textoOK , lixo(i) , "")
 next
 LimpaLixo = textoOK
end Function
%>
- Rejeitando os dados maliciosos:
<%
Function ValidaDados( input )
 lixo = array ( "select" , "insert" , "update" , "delete" , "drop" , "--" , "'")
 ValidaDados = true
 for i = lBound (lixo) to ubound(llixo)
 if ( instr(1 , input , lixo(i) , vbtextcompare ) <> 0 ) then
 ValidaDados = False
 exit function}
 end if
32
 next
end function
%>
Sempre que puder, rejeite entrada que contenha os caracteres a seguir.
Caractere de entrada Significado em Transact-SQL
 ; Delimitador de consulta.
 ' Delimitador de cadeia de dados de caractere.
 -- Delimitador de comentário.
 /* ... */ Delimitadores de comentário. Texto entre / * e * / não é avaliado pelo servidor.
 xp_ Usado no início do nome de procedimentos armazenados estendidos de catálogo,
como xp_cmdshell.
- Limite a entrada de texto para o usuário no formulário de entrada de dados
Se o campo nome deve ter somente 10 caracteres restrinja a isto a entrada de dados no
formulário. O mesmo vale para a senha;
- Faça o tratamento adequado de erros não permitindo que mensagens de erros exponham
informações sobre a estrutura dos seus dados;
- Faça um log para auditoria dos erros ocorridos e das operações mais importantes da
aplicação;
- Sempre valide entrada de usuário testando tipo, comprimento, formato e intervalo;
- Nunca construa instruções SQL ou Transact-SQL diretamente da entrada do usuário;
- Use procedimentos armazenados (stored Procedures) para validar entrada de usuário;
- Nunca concatene entrada de usuário que não seja validada. A concatenação de cadeia de
caracteres é o ponto principal de entrada de injeção de script;
33
- Teste o conteúdo de variáveis de cadeia de caracteres e só aceite valores esperados. Rejeite
entradas que contenham dados binários, seqüências de escape e caracteres de comentário. Isso
pode ajudar a impedir injeção de script e proteger contra explorações de excesso de buffer;
A Microsoft lançou um kit de ferramentas que pretende auxiliar desenvolvedores e
administradores de websites a bloquear e erradicar a recente onda de ataques de SQL
Injection (Injeção SQL).
As ferramentas, que são voltadas para desenvolvedores web e administradores de TI, buscam
auxiliar a identificação de pontos frágeis em scripts ASP que poderiam ser explorados em um
ataque de injeção SQL.
As ferramentas são:
Scrawlr - Examina os arquivos do site e simultaneamente analisa os parâmetros usados em
cada página buscando por vulnerabilidades do injeção SQL.
Microsoft Source Code Analyzer for SQL Injection - Chamada de MSCASI, esta é uma
ferramenta de análise estática para análise dos códigos em ASP. Para executá-la é necessário
ter acesso ao código fonte da página.
URLScan 3.1 - Esta ferramenta restringe os tipos de solicitações HTTP que o IIS (Internet
Information Services) irá processar. Ao bloquear alguns tipos específicos de solicitações, a
ferramenta pode prevenir certos ataques.
Segurança é coisa séria e vale a pena tomar todas as precauções ao nosso alcance para
preservar nossos dados e nossos empregos.
- Evitando Ataques em JSP
Esta classe de ataques, muito comum em ambientes web, consiste na inserção de comandos
nos dados passados como entrada para a aplicação de forma que estes comandos sejam
executados pela ou através da aplicação. As subclasses mais comuns são SQL injection e
Shell Command Injection. Injeção de SQL, ou SQL Injection, consiste em inserir comandos
SQL nos dados enviados para a aplicação de modo a acessar o banco de dados subjacente. Por
34
exemplo, suponhamos que uma aplicação web esteja vulnerável e contenha uma sentença
SQL: "SELECT Login, Nome FROM Usuario WHERE Login = '" + sParam + "'". Se o
adversário passar para esta aplicação a string "zé' OR '2'='2'", o resultado será: "SELECT
Login, Nome FROM Usuario WHERE Login = 'zé' OR '2'='2'". Esta sentença SQL retornará a
lista de todos os usuários da aplicação, que poderá ser usada posteriormente como subsídio
para outros ataques. O adversário poderia também inserir comandos visando alterar ou apagar
dados do banco, causando estragos ainda maiores. A injeção de comandos shell acontece de
forma similar se a aplicação acessa o sistema operacional através de um interpretador de
comandos.
A maneira mais simples de proteger uma aplicação contra injeção de comandos é evitar o uso
de interpretadores externos, como um interpretador SQL ou um shell. Para evitar o uso de
comandos de shell, devemos usar as bibliotecas do sistema que realizem as funções
específicas necessárias.
Nos casos em que não há alternativa, tais como as chamadas a interpretadores SQL de bancos
de dados, devemos validar criteriosamente os dados recebidos e certificar que estes dados não
incluam nenhum comando ou conteúdo potencialmente nocivo. Devemos também estruturar
as requisições de maneira que os parâmetros recebidos sejam efetivamente tratados como
dados e não como comandos. No caso de Java, pode-se empregar também stored procedures e
prepared statements (representados em Java pelas classes CallableStatement, quando são
usadas stored procedures, e PreparedStatement, quando se usa SQL) para aumentar o nível de 
proteção à informação.
O exemplo abaixo ilustra o uso incorreto de PreparedStatement, pois insere os dados
recebidos pela aplicação diretamente no comando SQL que será enviado para o banco de
dados.
String name = request.getParameter("name");
PreparedStatement pstmt = conn.prepareStatement("insert into EMP (ENAME) values ('" + name +
"')");
pstmt.execute();
pstmt.close();
35
A maneira correta seria:
PreparedStatement pstmt = conn.prepareStatement ("insert into
EMP (ENAME) values (?)");
String name = request.getParameter("name");
pstmt.setString (1, name);
pstmt.execute();
pstmt.close();
No segundo exemplo, o parâmetro name é tratado exclusivamente como dado (mais
especificamente uma string), o que protege a aplicação contra a tentativa de injeção de código
SQL.
Abaixo, temos um trecho de código onde o CallableStatement é usado de forma incorreta:
String name = request.getParameter("name");
String sql = "begin ? := GetPostalCode('" + name + "'); end;";
CallableStatement cs = conn.prepareCall(sql);
cs.registerOutParameter(1, Types.CHAR);
cs.executeUpdate();
String result = cs.getString(1);
cs.close();
No código acima, há a possibilidade que o código SQL enviado ao servidor seja (o texto em
vermelho correspondeao suposto conteúdo do parâmetro name):
begin ? := GetPostalCode(''); delete from users; commit; dummy(''); end;
A maneira correta de usar o CallableStatement está mostrada abaixo. É possível perceber que
há o registro do parâmetro name, como dado contendo caracteres.
String name = request.getParameter("name");
CallableStatement cs = conn.prepareCall ("begin ? :=
36
GetStatePostalCode(?); end;");
cs.registerOutParameter(1,Types.CHAR);
cs.setString(2, name);
cs.executeUpdate();
String result = cs.getString(1);
cs.close();
Nos casos em que é usado o framework Hibernate, as manipulações de dados mais simples ou
corriqueiras são tratadas diretamente pelo framework. No entanto, o Hibernate disponibiliza a
linguagem HQL (ou Hibernate Query Language) para que os programadores possam definir
consultas ou manipulações complexas dos dados da aplicação. Embora o HQL apresente
algumas restrições no conteúdo dos comandos que diminuam o risco de ataques de injeção de
comandos, os riscos não são totalmente eliminados. Assim, são necessários os mesmos
cuidados que no caso do uso direto de SQL para acesso à base de dados.
O exemplo a seguir apresenta um comando HQL passível de ser atacado por injeção de
código, através do parâmetro paymentIds:
Payment payment = (Payment) session.find("from com.example.Payment as payment where
payment.id = " + paymentIds.get(i));
O mesmo trecho pode ser reescrito usando outras versões da função session.find que
permitem definir explicitamente os tipos dos dados a serem passados para a base de dados.
Desta forma, o risco de ataques por injeção de comandos é bastante reduzido, conforme
demonstra o exemplo abaixo:
String pId = paymentIds.get(i);
TsPayment payment = (TsPayment) session.find("from com.example.Payment as payment where
payment.id = ?", pId, StringType);
37
RELATÓRIO 1 - EVITANDO ATAQUES SQL INJECTION
O usuário com que o SGBD é executado dentro do sistema operacional também é um ponto a
ser observado. 
Utilização de usuários como root (UNIX) e administrator (Windows) fazem com que
eventuais comandos executados maliciosamente no sistema operacional através de uma
injeção de SQL rodem com privilégios irrestritos no sistema. 
O grande vilão responsável pela imensa maioria das vulnerabilidades de injeção de SQL é,
sem sombra de dúvidas a concatenação de strings para montagem de comandos SQL. No
entanto, é perfeitamente viável a construção de consultas dinâmicas sem a concatenação
direta dos parâmetros à string principal. 
A API JDBC, por exemplo permite a utilização de prepared statements para execução de
acessos ao SGBD. 
Um prepared statement é uma instrução SQL pré-processada pela API do SGBD, que recebe
os parâmetros separadamente da string de consulta principal. Na string principal, os
parâmetros constam como marcadores que serão, posteriormente, substituídos pelo SGBD
pelos seus respectivos valores durante a execução da consulta. SELECT nome FROM
funcionario WHERE departamento = ?
Parâmetro 1: nomeDepartamento Neste exemplo, o valor da variável nomeDepartamento
será utilizado exclusivamente como critério de comparação com a coluna departamento.
Caso seja recebido como valor de nomeDepartamento a string “ '' OR 1 = 1”, o resultado será
a busca de um registro cujo valor de departamento seja a string “ '' OR 1 = 1”, garantindo
assim o sentido original da consulta. 
Evidentemente, é claro, as APIs e mecanismos dos SGBDs que fornecem
funcionalidades como os prepared statements citados acima necessitam, internamente, serem
seguras contra a injeção de SQL. A implementação insegura das camadas de acesso a
38
dados pode tornar uma aplicação que as utilize completamente insegura, mesmo que esta
tenha sido construída sob os mais criteriosos preceitos de programação segura. 
A utilização de sistemas de bancos de dados como repositórios de informações é padrão na
imensa maioria dos sistemas de informações existentes hoje, inclusive naqueles acessíveis
via web. Na mesma medida em que benefícios são adquiridos pela sua utilização, também os
riscos de ataques como a injeção de SQL são trazidos à tona. 
Há um grande foco de atenção na área de segurança computacional em torno de algoritmos de
criptografia e verificações de vulnerabilidades em sistemas operacionais, SGBDs e servidores
de aplicações. No entanto, as grandes brechas de segurança que viabilizam a injeção de SQL
estão presentes no código da própria aplicação, e não nos softwares de infra-estrutura que esta
utiliza. 
É imprescindível, portanto, que o mesmo rigor com que são avaliados os aspectos de
segurança dos softwares acessórios à aplicação quanto à sua segurança, seja aplicado também
na avaliação da própria aplicação. 
É fato que as boas práticas de programação que restringem imensamente o potencial de
ocorrência de um ataque de injeção de SQL são em linhas gerais bastante simples de serem
aplicadas, mas também é fato que, a existência de um único ponto do código de uma
aplicação construído de forma insegura torna a aplicação insegura como um todo. 
Faz-se de suma importância neste cenário, que seja incluído no currículo de todos os cursos
formadores de mão-de-obra especializada no desenvolvimento de sistemas computacionais,
a compreensão da natureza deste tipo de ataque, como ele é possível e as práticas adotadas
no dia-a-dia da construção de sistemas para evitá-los. Neste sentido, este trabalho espera
dar sua contribuição, através da demonstração das formas de ataque como motivadores de
conscientização da imprescindibilidade da adoção de práticas seguras de construção e
configuração de sistemas aqui relatadas. 
39
REFERÊNCIAS BIBLIOGRÁFICAS
[1] ANLEY, C. (more) Advanced SQL Injection, 2002. Disponível em 
<www.ngssoftware.com/papers/more_advanced_sql_injection.pdf>. Acesso em Nov 2009. 
[2] BAMBNEK, J. SQL Injection Worm on the Loose, 2008. Disponível em 
<http://isc.sans.org/diary.html?storyid=4393>. Acesso em Nov 2009. 
[3] BEAULIEU, A; TRESELER, M. E. Learning SQL. 2ª ed. Sebastapol, CA, EUA:
O'Reilly, 2009. 
[4] BLINDFOLDED SQL Injection, 2009. Disponível em 
<http://www.imperva.com/download.asp?id=4>. Acesso em Nov 2009. 
[5] CHAPPLE, M. Testing For SQL Injection Vulnerabilities, 2008. Disponível em 
<http://databases.about.com/od/security/a/sql_inject_test.htm>. Acesso em Nov 2009. 
[6] CLARKE, J. SQL Injection Attacks and Defense. 1ª ed. [S.l.]: Syngress, 2009. 
[7] CUMMING, A.; RUSSEL, G. SQL Hacks. 1ª ed. [S.l.]: O'Reilly Media, 2006. 
[8] DATE, C. J. Introdução a Sistemas de Banco de Dados. Rio de Janeiro: Campus, 2000. 
[9] HOWARD, M.; LEBLANC, D. Writing secure code, 2nd ed. Redmond, 2003. 
[10] LEMONIAS, N. Introduction to Buffer Overflows, 2009. Disponível em 
<http://www.packetstormsecurity.org/papers/attack/Memory_Exploitation_Res_Publication.p
df>. Acesso em Nov 
2009. 
[11] MEEK, B. L.; HEATH, P. Guide to Good Programming Practice. 1ª ed. [S.l.]: Ellis
Horwood Ltd, 1980. 
40
[12] MEIER J. D. et al. Improving Web Application Security: Threats and
Countermeasures, 1ª ed. 
Microsoft Press. Redmond, 2003. 
[13] ORACLE/PLSQL: Oracle System Tables, 2009. Disponível em 
<http://www.techonthenet.com/oracle/sys_tables/index.php>. Acesso em Nov 2009. 
[14] SCHLICHTING, D. SQL Server 2005 System Tables and Views, 2005. Disponível em 
<http://www.databasejournal.com/features/mssql/article.php/3508881/SQL-Server-2005-System-Tables-and-
Views.htm>. Acesso em Nov 2009. 
41
	SUMÁRIO
	O RISCO DE ATAQUES PELA WEB

Continue navegando