Poznámka: články jsou již mnoho let staré, doba se posunula, mnoho věcí v nich doporučovaných je již dnes překonané - berte s rezervou!


Proč není v ASP.NET funkce addslashes? A jak tedy chránit databázi před Sql-injection?

Jak je známo, textům zadaným uživatelem nelze věřit a je třeba uživatelské vstupy kontrolovat. Jazyk PHP obsahuje několik funkcí pro ošetření uživatelských vstupů.

Do první skupiny patří funkce, které ošetřují vypisování uživatelem zadaného textu do těla stránky (a chrání tak před Cross Site Scripting) - jsou to funkce htmlentities a htmlspecialchars a možná nějaké další. Ty zakódují speciální HTML do jim odpovídajících HTML entit (tedy především znak < se zakóduje na &lt; a > na &gt;.

Další skupina ošetřuje vstupy před uložením do databáze. Tam je potřeba dávat pozor na znaky jednoduchých a dvojitých uvozovek a zpětného lomítka, které mají speciální význam v jazyce SQL. Některé servery s PHP mají zapnuté tzv. Magic Quotes, které toto ošetření dělají automaticky, pokud zapnuté nejsou je třeba použít funkci addslashes. Tyto prostředky chrání před tzv. Sql-injection.

V ASP.NET je třeba samozřejmě vstupy ošetřovat taktéž. K funkci htmlentities z PHP existuje ekvivalentní metoda HtmlEncode. Navíc pokud nedůvěryhodný text vypisujete v komponentě GridView, stačí danému sloupci nastavit vlastnost HtmlEncode na true a dosáhnete téhož. Viz upravený příklad z MSDN:

<h3>BoundField Example</h3> <asp:gridview id="CustomersGridView" datasourceid="CustomersSqlDataSource" autogeneratecolumns="false" allowpaging="true" runat="server"> <columns> <asp:boundfield datafield="CustomerID" readonly="true" headertext="Customer ID"/> <asp:boundfield datafield="Address" htmlencode="true" headertext="Address"/> <asp:boundfield datafield="City" htmlencode="true" headertext="City"/> </columns> </asp:gridview>

Co se týče ochrany vstupů ukládaných do databáze, žádnou funkci jako je addslashes v PHP v ASP.NET nenajedete - jednoduše proto, že není potřeba.

Databázi se totiž neposílají příkazy přímo, ale pomocí objektu SqlCommand. Vlastonst SqlCommand.CommandText určuje, jaký příkaz bude proveden a je typu string. Nedoporučuje se ale CommandText nastavovat nějakým řetězcem, který vznikl sčítáním řetězců určených programátorem spolu s řetězci uživatelského vstupu. Nikdy byste tak neměli napsat něco takového:

SqlCommand sqlcomm = new SqlCommand(); sqlcom.CommandText = "Select * from Products where productId = '" + pid + "'";

Je sice pravda, že byste mohli napsat nějakou vlastní funkci, která třeba pomocí regulárních výrazů a nahrazování podřetězců provoede to, co dělá addslashes v PHP, ale i tak, jeden nikdy neví, navíc existuje mnohem čistší přístup - použít parametrizovaný dotaz. Předešlý kód upravíme takhle:

SqlCommand sqlcomm = new SqlCommand(); sqlcomm.CommandText = "Select * from Products where productId = @pid"; sqlcomm.Parameters.AddWithValue("@pid", pid);

I když v kódu přímo explicitně žádné escapování neprovádíme, o veškerou bezpečnost se již postará objekt SqlCommand, hodnotu parametru před provedením příkazu sám upraví tak, aby neobsahoval žádné nebezepečné sekvence znaků.

Ohodnoťte prosím užitečnost článku




16
 
9
 
7
 
8
 
0
 
 
Vložit komentář:
 

 



 

 

Nepoužívejte žádné html ani texy značky, odřádkování se zachová. Pokud uvádíte zdrojový kód, můžete ho vložit mezi značky
<syntax jazyk="PHP">...</syntax>,
bude potom zformátován. Jako atribut můžete uvést PHP, C#, HTML, CSS a mnoho dalších.


opiste cislo Opište číslo:

 

13. 6. 2006 22:44:47
[1] (hamster (donaldduck(at)zoznam.sk))
otazka odpovědět
Dobry den, viem ze moja otazka bude trochu mimo rozoberanej temy ale aspon skusim :-) V asp som uplny zaciatocnik a rad by som sa opytal ci je mozne v dotaze na databazu pouzit namiesto nazvu tabulky premennu. Myslim nieco taketo:

dim DA as OleDbDataAdapter = new OleDbDataAdapter("Select * from (NejakaPremenna)",connectionString)

Ak mi s tym niekto bude vediet pomoct napiste mi pls na e-mail donaldduck@zoznam.sk
14. 6. 2006 11:47:01
[2] (Trupík (jakub.maly(at)atlas.cz))
Re: otazka odpovědět
Doufám, že se bavíme o asp.net a ne o asp. Ale v tomto případě to asi nehraje roli, protože tento dotaz se týká databáze a ta je pro obojí stejná.

Vytvořit parametrizovaný dotaz, kde parametr je jméno tabulky nejde.
(pokus o něco takovéhleho skončí na sql serveru chybou:
SELECT * FROM @table;).
Celkem to i chápu a nikdy mi podobná funkce nechyběla - pokud skutečně v závislosti na kódu potřebujete rozhodnout, ze které tabulky vybíráte, je to možná špatný návrh. Ale pokud to potřebujete skutečně nutně, můžete použít ono sčítání řetězců, proti kterému článek brojí.
Takže napsat
string _query;
_query = "SELECT * FROM " + NejakaPremenna";
OleDbaDataAdapter DA = new OleDbDataAdapter(_query, connectionString)