Czy jest coś jeszcze, co kod musi zrobić, aby oddzielić dane identyfikacyjne (tabela, widok, kolumna), inne niż zawijanie ich w cudzysłowy i podwójny cudzysłów znaki obecne w nazwie identyfikatora? Referencje byłyby mile widziane.Prawidłowe usuwanie identyfikatorów rozdzielonych w programie SQL Server bez użycia QUOTENAME
Odziedziczyłem bazę kodu, która ma niestandardowy system mapowania obiektowo-relacyjnego (ORM). SQL nie może być zapisany w aplikacji, ale ORM musi ostatecznie wygenerować SQL do wysłania do SQL Server. Wszystkie identyfikatory są cytowane podwójnymi cudzysłowami.
string QuoteName(string identifier)
{
return "\"" + identifier.Replace("\"", "\"\"") + "\"";
}
Gdybym budowy tego dynamicznego SQL w SQL, chciałbym skorzystać z wbudowanej funkcji SQL Server QUOTENAME:
declare @identifier nvarchar(128);
set @identifier = N'Client"; DROP TABLE [dbo].Client; --';
declare @delimitedIdentifier nvarchar(258);
set @delimitedIdentifier = QUOTENAME(@identifier, '"');
print @delimitedIdentifier;
-- "Client""; DROP TABLE [dbo].Client; --"
nie znalazłem żadnej ostatecznej dokumentacji na temat sposobu ukryte identyfikatory w SQL Server. Znalazłem Delimited Identifiers (Database Engine) i widziałem także this stackoverflow question o sanityzacji.
Jeśli musiałaby wywoływać funkcję QUOTENAME tylko po to, aby podawać identyfikatory o dużym natężeniu ruchu do SQL Server, które nie powinny być potrzebne.
ORM wydaje się być całkiem dobrze przemyślany pod względem SQL Injection. Jest w języku C# i poprzedza port nHibernate i Entity Framework itd. Wszystkie dane wejściowe użytkownika są wysyłane za pomocą obiektów SqlParameter ADO.NET, jest to tylko nazwa identyfikatora, o którą się martwię w tym pytaniu. To musi działać na SQL Server 2005 i 2008.
Aktualizacja 2010-03-31
Choć aplikacja nie ma umożliwić wejście użytkownika nazw identyfikatorów w zapytaniach, ORM czyni poprzez składnia zapytania, którą ma dla odczytów w stylu ORM i niestandardowych zapytań. To ORM staram się ostatecznie zapobiec wszystkim możliwym atakom SQL Injection, ponieważ jest to bardzo mały i łatwy do zweryfikowania w przeciwieństwie do całego kodu aplikacji.
Prostym przykładem interfejsu zapytań:
session.Query(new TableReference("Client")
.Restrict(new FieldReference("city") == "Springfield")
.DropAllBut(new FieldReference("first_name"));
ADO.NET wysyła w ciągu tego zapytania:
exec sp_executesql N'SELECT "T1"."first_name"
FROM "dbo"."Client" AS "T1"
WHERE "T1"."city" = @p1;',
N'@p1 nvarchar(30)',
N'Springfield';
Może to pomoże, aby myśleć o tym, jak coś podobnego mogłoby to wyglądać w NHibernate Query Język (HQL):
using (ISession session = NHibernateHelper.OpenSession())
{
Client client = session
.CreateCriteria(typeof(Client)) \\ <-- TableReference in example above
.Add(Restrictions.Eq("city", "Springfield")) \\ <-- FieldReference above
.UniqueResult<Client>();
return client;
}
Może powinienem zobaczyć i zobaczyć, jak nHibernate chroni wprowadził.
Myślę, że masz na myśli, że powinienem wymagać długości wejścia do mojej funkcji to <= 128 znaków. To ma sens. Parametr funkcji TOTAL QUOTENAME to nvarchar (128) i zwraca nvarchar (258). Nie widzę, aby mógł kiedykolwiek zwrócić więcej niż 258 znaków ze 128-znakowego wejścia, ponieważ wydaje się, że co najwyżej każdy znak byłby podwojony (256), a także początkowy i końcowy ogranicznik. Czy mógłbyś podać przykład, kiedy QUOTENAME zostałby obcięty? wybrać len (quotename (replikacji (']', 128))), len (quotename (replikacji (']', 129))) powraca: 258, null –
Dokładnie, czynność musi potwierdzić, że wejście jest <= 128 znaków. Funkcja T-SQL QUOTENAME nigdy się nie skraca - obcięcie, na które trzeba uważać, przypisuje wartość zwracaną przez funkcję C# QuoteName do zmiennej nvarchar (258) w (dynamicznym) języku SQL. Tak długo, jak funkcja C# QuoteName wymaga, aby dane wejściowe było <= 128 znaków, tzn. Zachowuje się podobnie do funkcji T-SQL QUOTENAME, nie musisz się martwić. –