Você está na página 1de 6

23/08/2016

InjeoSQL

Injeo SQL
SQL Server 2008 R2

Injeo SQL um ataque no qual um cdigo malintencionado inserido em cadeias de caracteres que so passadas posteriormente para uma instncia do SQL
Server para anlise e execuo. Qualquer procedimento que construa instrues SQL deve ser verificado quanto a vulnerabilidades de injeo porque o SQL Server
executar todas as consultas sintaticamente vlidas que receber. Mesmo dados com parmetros podem ser manipulados por um invasor qualificado e determinado.
A forma principal de injeo SQL consiste em insero direta de cdigo em variveis de entrada de usurio, concatenadas com comandos SQL e executadas. Um
ataque menos direto injeta cdigo malintencionado em cadeias de caracteres destinadas a armazenamento em uma tabela ou como metadados. Quando as
cadeias de caracteres armazenadas so concatenadas subseqentemente em um comando SQL dinmico, o cdigo malintencionado executado.
O processo de injeo 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 comentrio "". O
texto subseqente ignorado no momento da execuo.
O script a seguir mostra uma injeo SQL simples. O script cria uma consulta SQL concatenando cadeias de caracteres codificadas com uma cadeia de caracteres
inserida pelo usurio:

varShipcity;
ShipCity=Request.form("ShipCity");
varsql="select*fromOrdersTablewhereShipCity='"+ShipCity+"'";
O usurio solicitado a inserir o nome de uma cidade. Se ele inserir Redmond, a consulta criada pelo script ter a seguinte aparncia:
SELECT*FROMOrdersTableWHEREShipCity='Redmond'
No entanto, suponha que o usurio insira o seguinte:
Redmond';droptableOrdersTable
Nesse caso, a seguinte consulta gerada pelo script:
SELECT*FROMOrdersTableWHEREShipCity='Redmond';droptableOrdersTable'
O pontoevrgula ; denota o trmino de uma consulta e o incio de outra. O hfen duplo indica que o restante da linha atual um comentrio e deve ser
ignorado. Se o cdigo modificado estiver sintaticamente correto, ser executado pelo servidor. Quando o SQL Server processar essa instruo, o SQL Server
selecionar primeiro todos os registros em OrdersTable onde ShipCity Redmond. Em seguida, o SQL Server descartar OrdersTable.
Contanto que o cdigo SQL injetado esteja sintaticamente correto, a violao no poder ser detectada programaticamente. Portanto, necessrio validar todas as
entradas de usurio e verificar com cuidado o cdigo que executa comandos SQL construdos no servidor que voc est usando. Prticas recomendadas de
codificao so descritas nas sees seguintes deste tpico.

Valide todas as entradas


Sempre valide entrada de usurio testando tipo, comprimento, formato e intervalo. Quando voc estiver implementando precaues contra entrada mal
intencionada, considere os cenrios de arquitetura e implantao de seu aplicativo. Lembrese de que programas projetados para executar em um ambiente
seguro podem ser copiados para um ambiente sem segurana. As sugestes seguintes devem ser consideradas prticas recomendadas:
No faa suposies sobre o tamanho, o tipo ou o contedo dos dados recebidos pelo seu aplicativo. Por exemplo, voc deve fazer a seguinte avaliao:
Como seu aplicativo se comportar se um usurio errneo ou malintencionado inserir um arquivo MPEG de 10 megabytes onde seu aplicativo
espera um cdigo postal?
Como seu aplicativo se comportar se uma instruo 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 contedo de variveis de cadeia de caracteres e s aceite valores esperados. Rejeite entradas que contenham dados binrios, seqncias de
escape e caracteres de comentrio. Isso pode ajudar a impedir injeo de script e proteger contra exploraes de excesso de buffer.
Quando voc estiver trabalhando com documentos XML, valide todos os dados em seu esquema medida que so inseridos.
Nunca construa instrues TransactSQL diretamente da entrada do usurio.
Use procedimentos armazenados para validar entrada de usurio.
Em ambientes de vrias camadas, todos os dados devem ser validados antes de serem admitidos zona de confiana. Os dados que no passam pelo
processo de validao devem ser rejeitados e um erro deve ser retornado camada anterior.
Implemente vrias camadas de validao. Precaues tomadas contra usurios casualmente malintencionados podem ser ineficazes contra determinados
invasores. Uma prtica mais recomendada validar a entrada na interface do usurio e em todos os pontos subseqentes onde ele cruza um limite
confivel.

https://technet.microsoft.com/ptbr/library/ms161953(d=printer,v=sql.105).aspx

1/6

23/08/2016

InjeoSQL
Por exemplo, a validao de dados em um aplicativo cliente pode evitar injeo de script simples. No entanto, se a prxima camada assumir que sua
entrada j foi validada, qualquer usurio malintencionado que possa contornar um cliente poder ter acesso irrestrito ao sistema.
Nunca concatene entrada de usurio que no seja validada. A concatenao de cadeia de caracteres o ponto principal de entrada de injeo de script.
No aceite as seguintes cadeias de caracteres em campos dos quais nomes de arquivos podem ser construdos: AUX, CLOCK$, COM1 a COM8, CON,
CONFIG$, LPT1 a LPT8, NUL e PRN.

Sempre que puder, rejeite entrada que contenha os caracteres a seguir.

Caractere de entrada

Significado em TransactSQL

Delimitador de consulta.

'

Delimitador de cadeia de dados de caractere.

Delimitador de comentrio.

/* ... */

Delimitadores de comentrio. Texto entre / * e * / no avaliado pelo servidor.

xp_

Usado no incio do nome de procedimentos armazenados estendidos de catlogo, como xp_cmdshell.

Use parmetros SQL de tipo seguro


A coleo Parmetros no SQL Server fornece verificao de tipo e validao de comprimento. Se voc usar a coleo Parmetros, a entrada ser tratada como
um valor literal e no como cdigo executvel. Um benefcio adicional de usar a coleo Parmetros que voc pode impor verificaes de tipo e comprimento.
Valores fora do intervalo iro disparar uma exceo. O seguinte fragmento de cdigo mostra o uso da coleo Parmetros:

SqlDataAdaptermyCommand=newSqlDataAdapter("AuthorLogin",conn);
myCommand.SelectCommand.CommandType=CommandType.StoredProcedure;
SqlParameterparm=myCommand.SelectCommand.Parameters.Add("@au_id",
SqlDbType.VarChar,11);
parm.Value=Login.Text;
Nesse exemplo, o parmetro @au_id tratado como um valor literal e no como cdigo executvel. Esse valor verificado quanto ao tipo e comprimento. Se o
valor @au_id no estiver de acordo com o tipo especificado e as restries de comprimento, uma exceo ser gerada.

Use entrada com parmetros com procedimentos armazenados


Os procedimentos armazenados podero ser suscetveis a injeo SQL se usarem entrada no filtrada. Por exemplo, o cdigo seguinte vulnervel:

SqlDataAdaptermyCommand=
newSqlDataAdapter("LoginStoredProcedure'"+
Login.Text+"'",conn);
Se voc usar procedimentos armazenados, dever usar parmetros como entrada.

Use coleo de parmetros com SQL dinmico


Se voc no puder usar procedimentos armazenados, ainda poder usar parmetros, como mostrado no exemplo de cdigo seguinte:

SqlDataAdaptermyCommand=newSqlDataAdapter(
"SELECTau_lname,au_fnameFROMAuthorsWHEREau_id=@au_id",conn);
SQLParameterparm=myCommand.SelectCommand.Parameters.Add("@au_id",
SqlDbType.VarChar,11);
Parm.Value=Login.Text;

Filtrando a entrada
A filtragem de entrada tambm pode ser til para proteger contra injeo de SQL, removendo caracteres de escape. Porm, por causa do nmero grande de
caracteres que podem causar problemas, essa no uma defesa confivel. O exemplo a seguir procura o delimitador de cadeia de caracteres.

privatestringSafeSqlLiteral(stringinputSQL)
{
returninputSQL.Replace("'","''");
}

https://technet.microsoft.com/ptbr/library/ms161953(d=printer,v=sql.105).aspx

2/6

23/08/2016

InjeoSQL

Clusulas LIKE
Observe que se voc estiver usando uma clusula LIKE, os caracteres curinga ainda podero escapar:

s=s.Replace("[","[[]");
s=s.Replace("%","[%]");
s=s.Replace("_","[_]");

Revisando cdigo para injeo SQL


Voc deveria revisar todos os cdigos que chamam EXECUTE, EXEC ou sp_executesql. Voc pode usar consultas semelhantes que segue para ajudlo a
identificar procedimentos que contenham essas instrues. Essa consulta verifica se existem 1, 2, 3 ou 4 espaos aps as palavras EXECUTE ou EXEC.
SELECTobject_Name(id)FROMsyscomments
WHEREUPPER(text)LIKE'%EXECUTE (%'
ORUPPER(text)LIKE'%EXECUTE(%'
ORUPPER(text)LIKE'%EXECUTE(%'
ORUPPER(text)LIKE'%EXECUTE(%'
ORUPPER(text)LIKE'%EXEC(%'
ORUPPER(text)LIKE'%EXEC(%'
ORUPPER(text)LIKE'%EXEC(%'
ORUPPER(text)LIKE'%EXEC(%'
ORUPPER(text)LIKE'%SP_EXECUTESQL%'

Envolvendo parmetros com QUOTENAME e REPLACE


Em cada procedimento armazenado selecionado, verifique se todas as variveis usadas no TransactSQL dinmico esto sendo tratadas corretamente. Dados
oriundos de parmetros de entrada de procedimento armazenado ou que so lidos de uma tabela devem ser envolvidos em QUOTENAME ou REPLACE.
Lembrese de que o valor da @variable que passado para QUOTENAME sysname e tem um comprimento mximo de 128 caracteres.

@variable

Invlucro recomendado

Nome de um protegvel

QUOTENAME@variable

Cadeia de caracteres de 128 caracteres

QUOTENAME@variable, ''''

Cadeia de caracteres de > 128 caracteres

REPLACE@variable,'''', ''''''

Quando voc usa essa tcnica, uma instruo SET pode ser examinada como segue:
Before:
SET@temp=N'select*fromauthorswhereau_lname='''
+@au_lname+N''''
After:
SET@temp=N'select*fromauthorswhereau_lname='''
+REPLACE(@au_lname,'''','''''')+N''''

Injeo habilitada por truncamento de dados


Qualquer TransactSQL dinmico atribudo a uma varivel ser truncado se for maior do que o buffer alocado para aquela varivel. Um invasor que capaz de
impor truncamento de instruo ao passar cadeias de caracteres longas inesperadamente para um procedimento armazenado pode manipular o resultado. Por
exemplo, o procedimento armazenado criado pelo script a seguir vulnervel a injeo habilitada por truncamento.
CREATEPROCEDUREsp_MySetPassword
@loginnamesysname,
@oldsysname,
@newsysname

https://technet.microsoft.com/ptbr/library/ms161953(d=printer,v=sql.105).aspx

3/6

23/08/2016

InjeoSQL

AS
Declarevariable.
Notethatthebufferhereisonly200characterslong.
DECLARE@commandvarchar(200)
ConstructthedynamicTransactSQL.
Inthefollowingstatement,weneedatotalof154characters
tosetthepasswordof'sa'.
26forUPDATEstatement,16forWHEREclause,4for'sa',and2for
quotationmarkssurroundedbyQUOTENAME(@loginname):
200261642=154.
Butbecause@newisdeclaredasasysname,thisvariablecanonlyhold
128characters.
Wecanovercomethisbypassingsomesinglequotationmarksin@new.
SET@command='updateUserssetpassword='+QUOTENAME(@new,'''')+'whereusername='+QUOTENAME(@loginname,'''')+'AND
password='+QUOTENAME(@old,'''')

Executethecommand.
EXEC(@command)
GO
Ao passar 154 caracteres em um buffer de 128 caracteres, um invasor pode definir uma nova senha para sa sem conhecer a senha antiga.
EXECsp_MySetPassword'sa','dummy',
'123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012''''''''''''''''''''''''''
'''''''''''''''''''''''''
Por esse motivo, voc deve usar um buffer grande para uma varivel de comando ou executar diretamente o TransactSQL dinmico na instruo EXECUTE.

Truncamento quando QUOTENAME @ varivel, '''' e REPLACE so usados


Cadeias de caracteres retornadas por QUOTENAME e REPLACE sero silenciosamente truncadas se ultrapassarem o espao alocado. O procedimento
armazenado criado nos exemplos a seguir mostram o que pode acontecer.
CREATEPROCEDUREsp_MySetPassword
@loginnamesysname,
@oldsysname,
@newsysname
AS

Declarevariables.
DECLARE@loginsysname
DECLARE@newpasswordsysname
DECLARE@oldpasswordsysname
DECLARE@commandvarchar(2000)

Inthefollowingstatements,thedatastoredintempvariables
willbetruncatedbecausethebuffersizeof@login,@oldpassword,
and@newpasswordisonly128characters,butQUOTENAME()canreturn
upto258characters.

SET@login=QUOTENAME(@loginname,'''')
SET@oldpassword=QUOTENAME(@old,'''')

https://technet.microsoft.com/ptbr/library/ms161953(d=printer,v=sql.105).aspx

4/6

23/08/2016

InjeoSQL

SET@newpassword=QUOTENAME(@new,'''')

ConstructthedynamicTransactSQL.
If@newcontains128characters,then@newpasswordwillbe'123...n
wherenisthe127thcharacter.
BecausethestringreturnedbyQUOTENAME()willbetruncated,
itcanbemadetolooklikethefollowingstatement:
UPDATEUsersSETpassword='1234...[127]WHEREusername='otherstuffhere

SET@command='UPDATEUserssetpassword='+@newpassword
+'whereusername='+@login+'ANDpassword='+@oldpassword;

Executethecommand.
EXEC(@command)
GO
Portanto, a instruo a seguir definir as senhas de todos os usurios como o valor passado no cdigo anterior.
EXECsp_MyProc'','dummy',
'12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
'
Voc pode impor truncamento de cadeia de caracteres excedendo o espao do buffer alocado ao usar REPLACE. O procedimento armazenado criado nos
exemplos a seguir mostram o que pode acontecer.
CREATEPROCEDUREsp_MySetPassword
@loginnamesysname,
@oldsysname,
@newsysname
AS
Declarevariables.
DECLARE@loginsysname
DECLARE@newpasswordsysname
DECLARE@oldpasswordsysname
DECLARE@commandvarchar(2000)
Inthefollowingstatements,datawillbetruncatedbecause
thebuffersallocatedfor@login,@oldpasswordand@newpassword
canholdonly128characters,butQUOTENAME()canreturn
upto258characters.

SET@login=REPLACE(@loginname,'''','''''')
SET@oldpassword=REPLACE(@old,'''','''''')
SET@newpassword=REPLACE(@new,'''','''''')

ConstructthedynamicTransactSQL.
If@newcontains128characters,@newpasswordwillbe'123...n
wherenisthe127thcharacter.
BecausethestringreturnedbyQUOTENAME()willbetruncated,it
canbemadetolooklikethefollowingstatement:
UPDATEUsersSETpassword='1234[127]WHEREusername='otherstuffhere

https://technet.microsoft.com/ptbr/library/ms161953(d=printer,v=sql.105).aspx

5/6

23/08/2016

InjeoSQL

SET@command='updateUserssetpassword='''+@newpassword+'''whereusername='''
+@login+'''ANDpassword='''+@oldpassword+'''';

Executethecommand.
EXEC(@command)
GO
Assim como acontece com QUOTENAME, o truncamento da cadeia de caracteres por REPLACE pode ser evitado declarando variveis temporrias
suficientemente grandes para todos os casos. Quando possvel, voc deve chamar QUOTENAME ou REPLACE diretamente dentro do TransactSQL dinmico.
Caso contrrio, voc pode calcular o tamanho do buffer exigido como segue. Para @outbuffer=QUOTENAME(@input), o tamanho de @outbuffer deve ser 2*
(len(@input)+1).Quando voc usa REPLACE e aspas duplas, como no exemplo anterior, um buffer de 2*len(@input) suficiente.
O clculo seguinte cobre todos os casos:
Whilelen(@find_string)>0,requiredbuffersize=
round(len(@input)/len(@find_string),0)*len(@new_string)
+(len(@input)%len(@find_string))

Truncamento quando QUOTENAME@variable, ']' usado


Pode ocorrer truncamento quando o nome de um protegvel do SQL Server passado a instrues que usam a forma QUOTENAME(@variable,']'). O exemplo
a seguir mostra a isso.
CREATEPROCEDUREsp_MyProc
@schemanamesysname,
@tablenamesysname,
AS
Declareavariableassysname.Thevariablewillbe128characters.
But@objectnameactuallymustallowfor2*258+1characters.
DECLARE@objectnamesysname
SET@objectname=QUOTENAME(@schemaname)+'.'+QUOTENAME(@tablename)
Dosomeoperations.
GO
Quando voc est concatenando valores do tipo sysname, deve usar variveis temporrias suficientemente grandes para manter no mximo 128 caracteres por
valor. Se possvel, chame QUOTENAME diretamente no TransactSQLdinmico. Caso contrrio, voc pode calcular o tamanho do buffer exigido como explicado
na seo anterior.

Consulte tambm
Referncia

EXECUTE TransactSQL
REPLACE TransactSQL
QUOTENAME TransactSQL
sp_executesql TransactSQL

Conceitos

Protegendo o SQL Server


Usando sp_executesql

Contribuies da comunidade

2016 Microsoft

https://technet.microsoft.com/ptbr/library/ms161953(d=printer,v=sql.105).aspx

6/6