Existem alguns casos em que essa função de escape falhará. O mais óbvio é quando as aspas simples não são usadas:
string table= "\"" + table.Replace("'", "''") + "\""
string var= "`" + var.Replace("'", "''") + "`"
string index= " " + index.Replace("'", "''") + " "
string query = "select * from `"+table+"` where name=\""+var+"\" or id="+index
Neste caso, você pode "quebrar" usando aspas duplas, um back-tick. No último caso, não há nada para "quebrar", então você pode simplesmente escrever
1 union select password from users--
ou qualquer carga útil sql que o invasor desejar. A próxima condição em que esta função de escape falhará é se uma sub-string for obtida após a string ser escapada (e sim Eu encontrei vulnerabilidades como esta na natureza):
string userPassword= userPassword.Replace("'", "''")
string userName= userInput.Replace("'", "''")
userName = substr(userName,0,10)
string query = "select * from users where name='"+userName+"' and password='"+userPassword+"'";
Neste caso, um nome de usuário de
abcdefgji'
será transformado em abcdefgji''
pela função de escape e depois voltou para abcdefgji'
tomando a sub-string. Isso pode ser explorado definindo o valor da senha para qualquer instrução sql, neste caso or 1=1--
seria interpretado como sql e o nome de usuário seria interpretado como abcdefgji'' and password=
. A consulta resultante é a seguinte:select * from users where name='abcdefgji'' and password=' or 1=1--
T-SQL e outras técnicas avançadas de injeção de sql já foram mencionadas. Advanced SQL Injection In SQL Server Applications é um ótimo artigo e você deveria lê-lo se ainda não o leu.
A questão final são os ataques unicode. Essa classe de vulnerabilidades surge porque a função de escape não reconhece a codificação multibyte, e isso pode ser usado por um invasor para "consumir" o caractere de escape. Anexar um "N" à string não ajudará, pois isso não afeta o valor dos caracteres de vários bytes posteriormente na string. No entanto, esse tipo de ataque é muito incomum porque o banco de dados deve ser configurado para aceitar strings unicode GBK (e não tenho certeza de que o MS-SQL possa fazer isso).
A injeção de código de segunda ordem ainda é possível, esse padrão de ataque é criado confiando em fontes de dados controladas pelo invasor. O escape é usado para representar caracteres de controle como seu literal de caractere. Se o desenvolvedor esquecer de escapar de um valor obtido de um
select
e, em seguida, usa esse valor em outra consulta, em seguida, bam o invasor terá uma aspa simples literal de caractere à sua disposição. Teste tudo, não confie em nada.