DevStart Blogi Napisano Grudzień 12, 2015 Zgłoś Udostępnij Napisano Grudzień 12, 2015 Czasami w widoku wywołujemy funkcję JavaScript z parametrami, które są przekazane za pomocą ViewModel z kontrolera. Załóżmy, że nasza metoda w kontrolerze wygląda następująco: public ActionResult Index() { return View(new FooModel("Hello World!")); } ViewModel z kolei zawiera jedną właściwość: public class FooModel { public string Text { get; set; } public FooModel(string text) { Text = text; } } Następnie zdefiniujmy jakąkolwiek funkcję JS przyjmującą parametry: <script type="text/javascript"> function doSomethingInJs(text) { $('#sampleContainer').html(text); } </script> Błędne wywołanie funkcji w razor wygląda z kolei następująco: <script type="text/javascript"> doSomethingInJs('@Model.Text'); </script> Jest to nic innego, jak klasyczny przykład wstrzyknięcia złośliwego kodu. Dotyczy to wszystkich pól typu string. Nawet jeśli spodziewamy się tylko imienia czy nazwiska, nigdy nie wiadomo jakie dane zawiera view model. Zwykle dane pochodzą z bazy danych. Co jeśli w jakiś sposób, baza danych zawiera już złośliwy kod? Aplikacja powinna traktować wszystkie dane, jako potencjalne zagrożenie. Co jeśli, następująca treść zostanie przekazana? public ActionResult Index() { return View(new FooModel("<script>alert('Hello World')</script>")); } Na szczęście powyższy kod jest bezpieczny, ponieważ Razor zamieni <script> na znaczniki HTML: <script type="text/javascript"> $(function() { doSomethingInJs('<script>alert('Hello World')</script>'); }); </script> Innymi słowy, kod zostanie wyświetlony jak zwykły tekst. Za każdym razem, jak wywołujemy @Model, zawartość jest enkodowana. Co jednak stanie się, jeśli treść zostanie przekazana jako ASCII HEX? public ActionResult Index() { var text = "\\x3c\\x73\\x63\\x72\\x69\\x70\\x74\\x3e\\x61\\x6c\\x65\\x72\\x74\\x28\\x27\\x48\\x65\\x6c\\x6c\\x6f\\x20\\x57\\x6f\\x72\\x6c\\x64\\x27\\x29\\x3c\\x2f\\x73\\x63\\x72\\x69\\x70\\x74\\x3e"; return View(new FooModel(text)); } Razor nie zakoduje treści ponieważ jest to zwykły tekst (brak znaczników HTML). Javascript z kolei, rozpoznaje ASCII w postaci hex (za pomocą \x). Efekt będzie taki, że kod javascript wykona się i wyświetli alert. W tej chwili, jeśli zajrzymy do źródła strony, zobaczymy: <script type="text/javascript"> $(function() { doSomethingInJs('\x3c\x73\x63\x72\x69\x70\x74\x3e\x61\x6c\x65\x72\x74\x28\x27\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x27\x29\x3c\x2f\x73\x63\x72\x69\x70\x74\x3e'); }); </script> Rozwiązaniem jest endkodowanie parametrów funkcji JavaScript za pomocą HttpUtility.JavaScriptStringEncode: <script type="text/javascript"> $(function() { doSomethingInJs('@HttpUtility.JavaScriptStringEncode(Model.Text)'); }); </script> Efektem będzie: <script type="text/javascript"> $(function() { doSomethingInJs('\\x3c\\x73\\x63\\x72\\x69\\x70\\x74\\x3e\\x61\\x6c\\x65\\x72\\x74\\x28\\x27\\x48\\x65\\x6c\\x6c\\x6f\\x20\\x57\\x6f\\x72\\x6c\\x64\\x27\\x29\\x3c\\x2f\\x73\\x63\\x72\\x69\\x70\\x74\\x3e'); }); </script> Widzimy, że każdy kod ascii, zostały poprzedzony dodatkowym znakiem ‘\’. Generalnie połączenie jQuery + mieszanie C# z JavaScript jest nie tylko złą praktyką z punktu widzenia bezpieczeństwa, ale również nie jest to zbyt czysty kod. Nie powinno mieszać się kodu inline z szablonami razor. Te dwie warstwy powinny rozwijać się niezależnie. Da nam to nie tylko łatwiejszy w utrzymaniu kod, ale również jak widać powyżej, łatwiej będzie uniknąć luk w bezpieczeństwie. Wyświetl pełny artykuł Cytuj Link do komentarza Udostępnij na innych stronach More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.