Zabezpieczanie Breeze na serwerze, aby zapobiec złośliwym aktualizacjom kluczy obcych

Problem

Próbuję tylko ustalić, ile z własnego bezpieczeństwa muszę zaimplementować po stronie serwera podczas zapisywania zmian w Breeze. W szczególności myślę o tym, jak złośliwy użytkownik może ręcznie włamać się do żądania SaveChanges lub włamać javascript do klienta, aby ominąć moje normalne reguły biznesowe - na przykład, aby złośliwie zmienić identyfikatory kluczy obcych w moich jednostkach.

Chcę dokładnie zrozumieć, gdzie muszę skoncentrować swoje wysiłki bezpieczeństwa; Nie chcę tracić czasu na wdrażanie warstw zabezpieczeń, które nie są wymagane.

Używam Breeze z .net i Entity Framework po stronie serwera.

Przykład

Oto trywialny przykład.ObjectA ma odniesienie doObjectB, iObjectA jest własnością konkretnegoUser. Moja baza danych wygląda tak:

ObjectA:

Id    ObjectB_Id    SomeField          User_Id
1     1             Alice's ObjectA    1
2     2             Bob's ObjectA      2

ObjectB:

Id    SomeOtherField
1     Foo
2     Bar

User:

Id    Name
1     Alice
2     Bob

Z tego modelu mam problemy związane z bezpieczeństwem:

Nie chcę, aby nieuwierzytelnieni użytkownicy zmienili jakiekolwiek daneNie chcę, żeby Bob mógł dokonywać jakichkolwiek zmian w AlicjiObjectANie chcę, żeby Alice próbowała ją wskazaćObjectA u BobaObjectB.Nie chcę, żeby Bob próbował zmienićUser_Id na jegoObjectA być Alice.

Rozwiązanie dla (1) jest banalne; Zapewnię, że moja metoda SaveChanges ma[Authorize] atrybut.

Mogę łatwo użyć Fiddlera do zbudowania żądania SaveChanges w celu odtworzenia problemów od 2 do 4 - na przykład mogę zbudować żądanie, które się zmieniaAlicejest ObjectA wskazujący na BobaObjectB. Oto jak może wyglądać treść wiadomości:

"entities":
[
    {
        "Id":1,
        "ObjectB_Id":2,
        "SomeField":"Alice's ObjectA",
        "User_Id":1,
        "entityAspect":
        {
            "entityTypeName":"ObjectA:#MyNamespace",
            "defaultResourceName":"ObjectAs",
            "entityState":"Modified",
            "originalValuesMap":
            {
                "ObjectB_Id":"1"
            },
            "autoGeneratedKey":
            {
                "propertyName":"Id",
                "autoGeneratedKeyType":"Identity"
            }
        }
    }
],

Tak jak się spodziewałem, gdy żadne zabezpieczenia nie są implementowane po stronie serwera, utrzymuje się zaktualizowana wartość dlaObjectB_Id do bazy danych.

Jednak potwierdziłem to również, jeśli nie ma wpisuObjectB_Id woriginalValuesMap, a nawet jeśli zmienię wartość dlaObjectB_Id w głównej części wiadomości NIE jest aktualizowany w bazie danych.

Główne zasady?

Myślę, że oznacza to, że ogólne zasady bezpieczeństwa, których muszę przestrzegać na serwerze, to:

[Edytowane 4 lipca 2013 r. - przepisane dla większej przejrzystości]

Ogólnie:

Nic w wiadomości nie może być zaufane: ani wartości w originalValuesMap, ani rzekomo „niezmienione” wartościJedynym wyjątkiem jest tożsamość podmiotu, którą możemy założyć, że jest poprawna.Podobno „niezmienione” właściwości mogły zostać naruszone, nawet jeśli nie znajdują się w originalValuesMap

Dla właściwości „niezmienionych” (właściwości, które nie znajdują się również w originalValuesMap):

Kiedy „używamy” dowolnej „niezmienionej” właściwości, NIE wolno nam używać wartości z komunikatu; musimy pobrać obiekt z bazy danych i użyć wartości z tego.na przykład podczas sprawdzania własności obiektu w celu upewnienia się, że użytkownik może go zmienić, nie możemy ufać identyfikatorowi użytkownika w wiadomości; musimy pobrać obiekt z bazy danych i użyć wartości UserId z tegoDla każdej innej „niezmienionej” właściwości, której nie używamy w żaden sposób, nie musimy się martwić, jeśli została naruszona, ponieważ nawet jeśli tak, zmieniona wartość nie zostanie utrwalona w bazie danych

Dla zmienionych właściwości (właściwości, które znajdują się również w originalValuesMap):

Reguły biznesowe mogą uniemożliwiać zmianę określonych właściwości. Jeśli tak jest, powinniśmy wdrożyć kontrolę dla każdej takiej reguły.

Jeśli dozwolona jest zmiana wartości i jest to klucz obcy, prawdopodobnie powinniśmy przeprowadzić kontrolę bezpieczeństwa, aby upewnić się, że nowa wartość może być używana przez tożsamość sesji

Nie możemy używać żadnych oryginalnych wartości w originalValuesMap, ponieważ mogły one zostać naruszone

[Koniec edycji]

Wdrażanie zasad

Zakładając, że te zasady są poprawne, myślę, że istnieje kilka opcji implementacji zabezpieczeń wokół zmienionych kluczy obcych:

Jeśli reguły biznesowe nie zezwalają na zmiany w określonym polu, odrzucę żądanie SaveChangesJeśli reguły biznesowe zezwalają na zmiany w określonym polu, sprawdzę, czy nowa wartość jest dozwolona. Robiąc to, NIE MOŻNA użyćoriginalValuesMap; Muszę przejść do bazy danych (lub innego zaufanego źródła, np. Sesji Cookie)

Zastosowanie tych zasad do obaw dotyczących bezpieczeństwa, które podałem powyżej,

problem bezpieczeństwa (2). Będę musiał sprawdzić tożsamość użytkownika w sesji przeciwkoUser_ID naObjectA który jest obecnie w bazie danych. Dzieje się tak, ponieważ nie mogę ufać ID_użytkownika na żądanie, nawet jeśli nie ma go woriginalValuesMap.

problem bezpieczeństwa (3). Jeśli reguły biznesowe pozwalają na zmianęObjectB, Muszę sprawdzić, kto jest właścicielem nowej wartościObjectB_Id; Zrobię to, pobierając określony obiekt B z bazy danych. Jeśli toObjectB nie jest własnościąObjectAwłaściciela, prawdopodobnie chcę odrzucić zmiany.

problem bezpieczeństwa (4). Jeśli reguły biznesowe pozwalają na zmianęUser, jest to już objęte (2).

pytania

Tak więc, naprawdę szukam potwierdzenia, że ​​myślę zgodnie z właściwą linią.

Czy moje ogólne zasady są prawidłowe?Czy moje wdrożenie zasad brzmi rozsądnie?Czy coś mi brakuje?Czyżbym komplikował rzeczy?

questionAnswers(2)

yourAnswerToTheQuestion