Standardy, dobre praktyki a bezpieczeństwo- czyli jak tu żyć?

1

Przykład z życia wzięty. Jeśli chce się być purystą, lub przynajmniej w miarę spełniać jakieś standardy, to implementując serwis RESTowy wypadało by (a może nie?) aby endpoint odpowiadający za zwracanie jakichś danych, ale nie modyfikujący nic, przyjmował polecenia GET. Ponieważ do **wyszukania **odpowiednich danych potrzebne są pewne dane wejściowe, te przekazujemy za pomocą query parameters, np:

https://mysite.com/search?filterOne=something&filterTwo=somethingelse

Wszystko ładnie i pięknie. Rzecz w tym że mieliśmy audyt bezpieczeństwa aplikacji i to właśnie query parameters zostały wymienione jako jedno z największych potencjalnych zagrożeń, ponieważ zawierają one poufne dane (imię, nazwisko, pewne unikalne identyfikatory takie jak VIN pojazdu). Co za tym idzie zostało zarekomendowane aby do takich zapytań stosować POST, i przekazywać dane wejściowe jako payload. Oczywiście query parameters również są szyfrowane przy transporcie przez HTTPS, ale powodem wymienionym było to że całe URL wraz z parametrami może znaleźć się w logach przeglądarki, serwera i aplikacji.

Stąd też moja dywagacja- czy jeśli ktoś chciałby mieć "czysto" RESTowy serwis, to musiałby porzucić pewne kwestie bezpieczeństwa? Jak to pogodzić?

Temat do luźnej dyskusji, nie oczekuję żadnej "jedynej i słusznej" odpowiedzi.

2

Kiedyś byłem zmuszony do przerzucenia parametrów do POSTa, ponieważ Internet Explorer nie wspierał tak długiego query stringa, i ucinał query co powodowało błędy :) Więc kolejna rzecz, którą tam czasami trzeba (teraz już może rzadziej) mieć na uwadze.

1

No to pozostaje szyfrować query string i deszyfrować na backendzie. Wydaje mi się to lepsze niż pchanie tego POSTem. Swoją drogą całkiem ciekawy temat.

0

Payloada też mogę logować, wiec argument trochę z czapy. Przerabialiśmy taki problem i po prostu był filtr przed logowaniem żeby tego jednego konkretnego parametru nie logować.

@dargenn 255 znaków w URLu czy jest już więcej dozwolone?

0

@KamilAdam: chyba głównym zmartwieniem jest to że serwer (w sensie system hostujacy aplikację) może sam takie rzeczy logować. Jeśli chodzi o logowanie payloadu to też miałem takie odczucia.

@UglyMan no właśnie, tylko że jest i druga strona medalu gdzie ktoś może stwierdzić że to przerost formy nad treścią, niepotrzebna logika w imię nadmiernych dogmatów.

2

@Aventus: jest bardzo dużo prostszych metod do wyciągania danych osobowych niż parsowanie przypadkowych quert stringów. Z drugiej strony takie kodowanie pozwala też zabezpieczyć api przed próbą wyciągnięcia wszystkich danych. Oczywiście jest to akademicki poziom dyskusji.

Ostatnio szukałem i standard nie mówi nic wysyłaniu body w GET. To qs można wsadzić tam - dla mnie to trochę dziwne, ale można.

1

Ostatnio szukałem i standard nie mówi nic wysyłaniu body w GET. To qs można wsadzić tam - dla mnie to trochę dziwne, ale można.

Można, ale znów będzie to łamać "czysty" REST:

https://datatracker.ietf.org/doc/html/rfc2616#section-9.3

The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI.

Wysyłając payload, identyfikuję dane do zwrotu nie za pomocą URI a właśnie paylod'u. No i puryści płaczą...

Już z chyba z dwojga złego wolę POST bo nie będzie wprowadzał programistów w konsternację.

0

Ten wątek to trolling?

2
666 napisał(a):

Ten wątek to trolling?

Czemu troling? Spotkałem się z oboma wymienionymi tu problemami z GETem:

  • tajne dane w urlu
  • przekroczenie długości urla

No ale można założyć że ja tez jestem tropem :p

3

Kolejny przykład to potwierdzanie w mailu, które musi** iść GETem i ewentualnie musi być przepakowane na UI w POST/PATCH/PUT.

Generalnie spotkałem się z takimi problemami, zwłaszcza po audytach security. Tam gdzie problem dotyczył logowania/tokenów/2FA/uprawnień zawsze stawiałem security ponad wszystko. Podobną kwestię miałem względem RODO/GDPR i właśnie danych osobowych, które przez to, że latały w URLach odkładały się w ogromnej liczbie logów i w przypadku prośby o czyszczenie było to niemal niewykonalne. Można ewentualnie zapytania encodować ale realnie to wciąż plain string.

Tak długo jak jestem w stanie trzymać pure RESTa to to robie, ale jeśli muszę go złamać ze względu na ograniczenia:

  • bezpieczeństwa
  • prawne
  • techniczne

to po prostu pragmatycznie to robię.

** inject js'a to tragiczny pomysł

3

Zacznijmy od tego że GET jest kulawy bo max wielkość payloadu to 2K (to się zmienia, ale 2k to bezpieczna wartość), czyli jak masz więcej danych to i tak pójdzie POSTem.

Rozważmy sytuację, dziewczyna korzysta z kompa chłopaka żeby wyliczyć np. OC swojej "mydelniczki". Chłopak potem sprawdza historię przeglądarki a tam zapisały się różne url'e z poufnymi danymi. Jest też taki toolik: https://www.nirsoft.net/utils/chrome_cache_view.html Sam się w to nigdy nie bawiłem więc nie wiem jak dużo da radę wyciągnąć, ale potencjał jest. HTTPS przed tym nie chroni.

Dostępne opcje:

  • Manglowanie URLa np. szyfrowanie parametrów przekazywanych w urlach jakimś kluczem per sesja
  • Zrobienie POSTa jak sugerują, opcja którą również polecam
  • Zmiana domeny tak żeby dane poufne zapisały się POST'em a potem korzystanie tylko z ich IDków

Widać też że dla chcącego jest 1000 opcji.

REST to nie świętość, Uncle Bob to nie papież, DDD to nie jedyna właściwa droga.

3

Zapewne chodzi o logi usług dodatkowych, jak Proxy, Reverse Proxy itp.
Te w logach zapewne gromadzą url path query i są to usługi zupełnie niezależne od logiki aplikacje (ergo same z siebie nie będą w stanie odfiltrować danych wrażliwych).
Sam miałem kiedyś zadanie wyczyścić logi z danych wrażliwych w aplikacji desktop.

Pytanie co dla klienta jest ważniejsze RODO czy książkowy REST.
Za naruszenie tylko jednego są konsekwencje prawne.

0

@KamilAdam:

Payloada też mogę logować, wiec argument trochę z czapy.

Według mnie to jest właśnie ta cała trickiness związana z security

no bo z jednej strony masz rację, a z drugiej zastanówmy się nad praktyką - czy przypadkiem servery HTTP by default nie logują właśnie urli, a payloady to tylko jak sobie ustawisz?

Tutaj przykład logów czystego Nginxa

... - - [29/Sep/202152:37 +0000] "POST ///* HTTP/1.1" 404 143 "http://*:80/admin/login.asp" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:71.0) Gecko/20100101 Firefox/71.0"

3

Rozważmy sytuację, dziewczyna korzysta z kompa chłopaka żeby wyliczyć np. OC swojej "mydelniczki". Chłopak potem sprawdza historię przeglądarki a tam zapisały się różne url'e z poufnymi danymi.

O ile ma to sens w przypadku tradycyjnych stron, to w naszym przypadku jest to nietrafiony przykład bo mamy SPA i takie requesty lecą AJAXem, bezpośrednio to web API. A więc nie pojawiają się w historii przeglądarki jako odwiedzone strony, a i laik użytkownik nic z tym nie zrobi. Zresztą jeśli ktoś niepowołany miałby dostęp do tego na poziomie przeglądarki, to te query params byłyby najmniejszym problemem.

1

Bo GET:

  • zostaje w historii przeglądarki,
  • zapisuje się w całości w logach serwera

i to chyba te kluczowe aspekty.
O limicie długości 2k pisał już @0xmarcin ale do tego dochodzą jeszcze różne kodowani a urli, które też dają różne możliwości sprawniejszym hakjerom...
Oczywiście POST'y też można logować ale nie jest to działanie "domyślne" ani w przeglądarce ani po stronie serwera stąd prawdopodobieństwo przechwycenia poufnych danych jest mniejsze.
Z mojego punktu widzenia faktycznie przekazywanie loginu i hasła w GET/URL to słaby pomysł. Lepiej już oprogramować osobny endpoint do logowania tak aby przekazywał dane w post i zamiast otwartego hasła jakiś hash z solą a następnie zwrócić token na czas działania sesji lub inaczej ograniczony czasowo i dalej nim się posługiwać.

1

@katakrowa:

zostaje w historii przeglądarki

GET wysłany AJAXem zostaje w historii przeglądarki? Pytam serio.

Z mojego punktu widzenia faktycznie przekazywanie loginu i hasła w GET/URL to słaby pomysł.

Nikt tutaj nie mówi (chyba że coś przeoczyłem) o wysyłaniu loginu i hasła w query params.

EDIT
Jeszcze odnośnie RODO które było wcześniej wspomniane. Co ciekawe w tym systemie niczym takim nie musimy się przejmować, bo system operuje w Stanach, i to na razie tych które prawa ochrony danych mają w zasadzie zerowe z perspektywy programistycznej. Oczywiście nie oznacza to że nie mamy różnych mechanizmów chroniących te dane ;)

2

@UglyMan

Niestety GET z Body jest jakiś taki wątpliwy z perspektywy RFC, aczkolwiek servery HTTP pewnie respektują

screenshot-20210930200917.png

0
WeiXiao napisał(a):

@UglyMan

Niestety GET z Body jest jakiś taki wątpliwy z perspektywy RFC, aczkolwiek servery HTTP pewnie respektują

screenshot-20210930200917.png

Nie mówię że nie jest. Ale nie jest zabroniony a co nie jest zabronione jest dozwolon:)

0

Skoro to AXAJ GET to sprawa się komplikuje. Weź lepiej zapytaj na Discord https://gynvael.coldwind.pl/ to Ci odpowiedzą fachowcy od sec'a.

Być może firma co to testowała pojechała jakimś automatem i do jednego wora wrzuciła AJAXy i zwykłe GETy. AJAX po HTTPS powinien być bezpieczny +/- to logowanie URLy na proxy itp. Generalnie danych wrażliwych w logach należy również unikać.

1

Pytać nie muszę bo wybór koniec końców padł na wysyłanie tego POSTem. Ja nie mam zamiaru być za to odpowiedzialny gdyby coś wyciekło, a mamy oficjalnie udokumentowaną rekomendację żeby te GETy zamienić na POST.

Tak jak napisałem w pierwszym poście, temat założyłem bardziej do ogólnej dyskusji i tym że czasem chyba nie ma wyjścia i trzeba wybierać między standardami/dogmatami a bezpieczeństwem.

2

Fragment logów z Apache:
screenshot-20210930203614.png![screenshot-20210930203614.png]

Nie ma znaczenia czy ajax czy nie ajax bo serwer i tak tego nie rozróżnia.

3

Mam dokładnie tak samo. W bankach to standard. (GET nie może zawierać danych "biznesowych/identyfikujacych).

I nie mam z tym problemu.
Czysty REST to bzdurka, którą nie warto sobie zawracać głowy - jak można i model oraz security pasuje to spoko, ale żadnego wahania przed łamaniem nie miej. To i tak czysto utpijna koncepcja (REST). Świat działa na więcej niż 4 czasownikach (czy tam ośmiu).

Samo uzasadnienie security (że może stać serwer i logować) jest średnie, ale zawsze jakieś to jest i nie da się do końca argumentu ubić. Co prawda POSTy też mozna logować, a logowanie GETów wyłaczyć, ale domyślne konfiguracje są takie, jakie są i trzeba to wziąc pod uwagę.

3

Gościu, weź sobie przeczytaj specyfikację http i wszystko Ci się wyjaśni, gwarantuję: https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html

Jeśli mówisz, że GET niebezpieczny, bo przeglądarki logują url (czyli część requestu), to to nie HTTP jest niebezpieczny tylko te przeglądarki.

Jeśli mówisz że serwery logują, cachują, trzymają jakiś element requestu, to nie GET jest niebezpieczny tylko te serwery.

Jeśli klient lub serwer coś loguje, to choćbyś wsadził te dane do headera X-Dupa to zarówno klient jak i serwer mogą go sobie zalogować i zrobić z nim co chcą.

GET i POST w HTTP się różnią tym że w jednym paramsy lecą w pierwszej linijce requestu, a w post lecą po headerach, tzw body. Jeśli wysyłasz request bez headerów, to różnicą byłby pojedynczy znak nowej linii. Także mówienie że różnią się czymś więcej jest absurdem. Różnica jest tylko w położeniu parametrów w requescie o semantyce (że GET powinien odczytać zasób a post zapisać).

0

To może nagłówek http i tam podawać parametry do query? Nagłówek customowy np, tylko nie pamiętam jaki tam jest limit długości.

[edit]
Chociaż, @TomRiddle dobrze pisze

2

@TomRiddle

Jeśli mówisz, że GET niebezpieczny, bo przeglądarki logują url (czyli część requestu), to to nie HTTP jest niebezpieczny tylko te przeglądarki.
Jeśli mówisz że serwery logują, cachują, trzymają jakiś element requestu, to nie GET jest niebezpieczny tylko te serwery.

ale kogo to obchodzi z pratical standpoint czy to tak właściwie HTTP czy przeglądarka? :P

Są 2 czy tam 3 enginy przeglądarek, 2 czy tam 3 servery HTTP i jeżeli one tak robią, no to pod nich trzeba się dostosować bo mają cały marketshare

GET i POST w HTTP się różnią tym że w jednym paramsy lecą w pierwszej linijce requestu, a w post lecą po headerach, tzw body. Jeśli wysyłasz request bez headerów, to różnicą byłby pojedynczy znak nowej linii. Także mówienie że różnią się czymś więcej jest absurdem. Różnica jest tylko w położeniu parametrów w requescie o semantyce (że GET powinien odczytać zasób a post zapisać).

jasne, możesz samemu sobie parsować jak to tam chcesz, ale nie po to mamy RFC i standardy aby robić jak się komu podoba

0
WeiXiao napisał(a):

@TomRiddle

Jeśli mówisz, że GET niebezpieczny, bo przeglądarki logują url (czyli część requestu), to to nie HTTP jest niebezpieczny tylko te przeglądarki.
Jeśli mówisz że serwery logują, cachują, trzymają jakiś element requestu, to nie GET jest niebezpieczny tylko te serwery.

ale kogo to obchodzi z pratical standpoint czy to tak właściwie HTTP czy przeglądarka? :P

Są 2 czy tam 3 enginy przeglądarek, 2 czy tam 3 servery HTTP i jeżeli one tak robią, no to pod nich trzeba się dostosować bo mają cały marketshare

Czyli używasz serwera w którym nie możesz go dostosować do swoich wymagań, do tego stopnia że musisz zmienić API (np post na get)? :) jeśli tak, to masz duży problem i logowanie URLI to Twój najmniejszy kłopot

3
TomRiddle napisał(a):

Czyli używasz serwera w którym nie możesz go dostosować do swoich wymagań, do tego stopnia że musisz zmienić API (np post na get)? :) jeśli tak, to masz duży problem i logowanie URLI to Twój najmniejszy kłopot

@TomRiddle: autor tematu nie pisze na jakim serwerze będzie to stawiał więc warto w takiej sytuacji brać pod uwagę konfiguracje domyśle popularnych rozwiązań, a te są w znaczącej części takie, że całego get logują... To raczej rozsądne podejście, którego celem nie jest 100% zabezpieczenie ale zmniejszenie prawdopodobieństwa włamu / wycieku daych.

0
katakrowa napisał(a):
TomRiddle napisał(a):

Czyli używasz serwera w którym nie możesz go dostosować do swoich wymagań, do tego stopnia że musisz zmienić API (np post na get)? :) jeśli tak, to masz duży problem i logowanie URLI to Twój najmniejszy kłopot

@TomRiddle: autor tematu nie pisze na jakim serwerze będzie to stawiał więc warto w takiej sytuacji brać pod uwagę konfiguracje domyśle popularnych rozwiązań, a te są w znaczącej części takie, że całego get logują... To raczej rozsądne podejście, którego celem nie jest 100% zabezpieczenie ale zmniejszenie prawdopodobieństwa włamu / wycieku daych.

Sure, warto być świadomym domyślnych konfiguracji.

Ale będąc zaalarmowanym logowaniem rzeczy, pierwszą rzeczą jaką powinieneś zrobić jest edycja ustawień, a nie zmiana swojego API.

1
TomRiddle napisał(a):
katakrowa napisał(a):
TomRiddle napisał(a):

Czyli używasz serwera w którym nie możesz go dostosować do swoich wymagań, do tego stopnia że musisz zmienić API (np post na get)? :) jeśli tak, to masz duży problem i logowanie URLI to Twój najmniejszy kłopot

@TomRiddle: autor tematu nie pisze na jakim serwerze będzie to stawiał więc warto w takiej sytuacji brać pod uwagę konfiguracje domyśle popularnych rozwiązań, a te są w znaczącej części takie, że całego get logują... To raczej rozsądne podejście, którego celem nie jest 100% zabezpieczenie ale zmniejszenie prawdopodobieństwa włamu / wycieku daych.

Sure, warto być świadomym domyślnych konfiguracji.

Ale będąc zaalarmowanym logowaniem rzeczy, pierwszą rzeczą jaką powinieneś zrobić jest edycja ustawień, a nie zmiana swojego API.

A co jak ruch leci przez serwery do których nie masz dostępu?

0

@UglyMan

Masz na myśli np CloudFlare i ukrywanie IPka twojego servera? bo to chyba byłby najpopularniejszy usecase?

1 użytkowników online, w tym zalogowanych: 0, gości: 1