CORS - pytanie od dummiego

0

Cześć,

Jestem programistą, ale nie webdev. Moje pytanie dotyczy podstaw webdevu.
Wiem, że dałbym radę to rozkminić po 4-8 godzinach szukania w necie. Poświęciłem już 1h i ... nic nie znalazłem.
Nie chcę poświęcać więcej czasu, bo nie mam ku temu ogromnej motywacji. Nie potrzebuję tej wiedzy do żadnego taska w pracy. Pytam z czystej ciekawości.
Lubię rozumieć, jak działa świat.

Pytanie.
Mamy te całe CORS. Czyli, że API będzie odpowiadało tylko na zapytania pochodzące z whitelisty.
Tylko, że ...
... większość zapytań będzie przecież przychodziła z przeglądarek. Liczba IP-ków, które potrzebuję wpisać do tej whitelisty jest zatem ogromna.
Co gorzej, zmienia się dynamicznie (bo klienci się zmieniają).

Czy tak to się właśnie implementuje? Whitelista zmienia się dynamicznie? Czy jest ona naprawdę tak długa i zawiera w dowolnym momencie kilkaset tysięcy adresów?

3

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

Przeczytaj, popatrz na diagramy i Ci się rozjaśni, ze nie chodzi o whitelistowanie IPkow.

2

Nie.

Większość stron ma domyślne ustawienie zamkniętych CORS, czyli że przeglądarka zezwoli skryptowi na stronie kontakt tylko z hostem z którego została zaservowana i niczym innym.

Drugi najpopularniejszy, to kiedy ludzie wyłączają CORS całkiem, tak że strona może się dobić wszędzie (co jest oczywiście groźnie, bo strona wtedy może wysłać nasze dane do innych stron).

Jakiś odsetek stron to jest podanie konkretnych hostów, ale ich jest zazwyczaj kilka.

0
TomRiddle napisał(a):

Drugi najpopularniejszy, to kiedy ludzie wyłączają CORS całkiem, tak że strona może się dobić wszędzie (co jest oczywiście groźnie, bo strona wtedy może wysłać nasze dane do innych stron).

Dlaczego groźne? Jeśli nasz frontend może się dobić wszędzie, to na czym tak naprawdę tracimy? Przecież my sami piszemy ten frontend (sami decydujemy, co gdzie wysyłamy). Ja widzę tu raczej profit niż zagrożenie.
@TomRiddle: dlaczego groźne?

2
dedicated napisał(a):
TomRiddle napisał(a):

Drugi najpopularniejszy, to kiedy ludzie wyłączają CORS całkiem, tak że strona może się dobić wszędzie (co jest oczywiście groźnie, bo strona wtedy może wysłać nasze dane do innych stron).

Dlaczego groźne? Jeśli nasz frontend może się dobić wszędzie, to na czym tak naprawdę tracimy? Przecież my sami piszemy ten frontend (sami decydujemy, co gdzie wysyłamy). Ja widzę tu raczej profit niż zagrożenie.
@TomRiddle: dlaczego groźne?

Bo gdybyś miał groźny skrypt przez pomyłkę uruchomiony na Twojej stronie, to on nic nie zrobi z Twoimi danymi. Jak odblokujesz CORS to może je wysłać w świat.

1

@dedicated: nie masz kontroli nad każdą linijką kodu z bibliotek, których używasz. Poczytaj o XSS

13

@dedicated obawiam sie że mylisz tu kilka pojęć takich jak:

  • origin
  • domain name
  • IP

To są zupełnie oderwane od siebie elementy. CORS działa na bazie nagłówka Origin który zawiera domenę ustawianą przez przeglądarkę. Czyli jesteś na stronie a.bc i ta strona wysyła jakiś AJAXowy request do innej domeny (inny port to tez już inna domena) i w takiej sytuacji przeglądarka dokłada nagłówek Origin: a.bc do takiego requestu. IP użytkownika nie ma żadnego znaczenia. Docelowa aplikacja może teraz sprawdzić sobie czy ma na whiteliście domenę a.bc i na tej podstawie zdecydować co zrobić z takim requestem

Żeby wyjaśnić problem z CORS może zacznijmy od tego po co?. Gdyby mozna było ot tak wysłać request do dowolnego adresu, to mógłbyś np. wejść na stronkę ze śmiesznymi kotami, a ta stronka mogłaby zaczać wysyłać requesty z twojej przeglądarki do innych serwisów.
Z jednej strony to problem bo do takiego requestu mogą zostać dołożone cookies, czyli jesteś zalogowany do banku a ktoś wysyła z twojej przeglądarki request żeby zrobić sobie przelew, albo pobiera informacje o stanie twojego konta.
Z drugiej strony możesz być np. w jakimś VPNie i twoja przeglądarka widzi jakieś hosty "intranetowe", np. jakieś firmowe wewnętrzne systemy i skrypty na stronce ze śmiesznymi kotami mogą zacząć "klikać" po tych systemach proxując się przez twoją przeglądarkę.

Żeby temu zapobiegać wprowadzono SOP - single origin policy, które mówi, że skrypt odpalony z domeny X może sobie ot tak stukać tylko po adresach z tejże domeny, a jeśli spróbuje stuknąć w coś innego to dochodzi header Origin i requesty są oznaczone jako cross-origin. W odpowiedzi na taki request backend zwraca header Access-Control-Allow-Origin i informuje przeglądarkę jakie originy są ok i na tej podstawie przeglądarka decyduje czy skrypt który wysłał request może odczytać odpowiedź.

Warto wiedzieć, że te zabezpieczenia nie są idealne. Da się ominąć SOP bez triggerowania CORS. Dzieje sie tak, dlatego że ten cały mechanizm bazuje na domenach a nie na adresach IP. Jeśli wejdziesz na moją stronę śmiesznekoty.pl a ja teraz zmienie wpis DNS i sprawie że moje śmiesznekoty.pl teraz pokazują na IP 192.168.X.X to skrypty na tej mojej stronie mogą stukać na swoją domenę śmiesznekoty.pl (czyli CORS tego nie łapie bo jest single origin) ale teraz ta domena rozwiązuje sie do jakiegoś lokalnego adresu i pozwala na komunikacje z intranetowymi aplikacjami. To nazywa sie DNS rebinding. Przeglądarki maja pewne mechanizmy które próbują temu zapobiegać, cachując sobie na jakis czas IP do których rozwiązują się domeny, ale nie da się tego całkiem wyeliminować, bo dziś wszystko stoi na jakichś cloudach za load balancerami i to że w tej chwili facebook.com rozwiązuje ci się do jakiegoś IP nie znaczy ze za chwilę ten IP nie będzie już niedostępny.

@TomRiddle chyba coś pokręciłeś, bo CORS ustawia się po stornie "odbiorcy" requestu (backend) a nie po stronie klienta który request wysyła. Problem stanowi to, że jak "wyłączysz" CORS to każdy może do twojego backendu wysłać request w imieniu użytkownika.

1
Shalom napisał(a):

@TomRiddle chyba coś pokręciłeś, bo CORS ustawia się po stornie "odbiorcy" requestu (backend) a nie po stronie klienta który request wysyła. Problem stanowi to, że jak "wyłączysz" CORS to każdy może do twojego backendu wysłać request w imieniu użytkownika.

Włączyć tak. Ale sprawdzać - nie.

Mógłbym napisać klienta HTTP który całkowicie olewa CORS i wtedy headery z backendu są nic nie warte. Całe bezpieczeństwo CORS polega na zaufaniu przeglądarce że je bloknie.

0

Mógłbym napisać klienta HTTP który całkowicie olewa CORS i wtedy headery z backendu są nic nie warte. Całe bezpieczeństwo CORS polega na zaufaniu przeglądarce że je bloknie.

No mógłbyś i większość klientów tak właśnie robi przecież, tylko to bez znaczenia bo problem stanowią requesty z przeglądarki a nie manualnie wysyłane curle. Problem jest w tym, że przeglądarka może dołożyć do requestu cookies i że pozwala "bez wiedzy użytkownika" wysyłać requesty z jego maszyny do innych miejsc.

1
Shalom napisał(a):

Mógłbym napisać klienta HTTP który całkowicie olewa CORS i wtedy headery z backendu są nic nie warte. Całe bezpieczeństwo CORS polega na zaufaniu przeglądarce że je bloknie.

No mógłbyś i większość klientów tak właśnie robi przecież, tylko to bez znaczenia bo problem stanowią requesty z przeglądarki a nie manualnie wysyłane curle. Problem jest w tym, że przeglądarka może dołożyć do requestu cookies i że pozwala "bez wiedzy użytkownika" wysyłać requesty z jego maszyny do innych miejsc.

No, czyli przeglądarka sprawdza to czy CORS nie są złamane. Server tylko wysyła headery.

0

@TomRiddle: oczywiście że tak, ale to ty pisałes jakieś bzdury że ludzie wyłączają CORS całkiem, tak że strona może się dobić wszędzie. Strona zawsze sie moze dobić wszędzie i wysyłać requesty gdzie chce i CORS nijak się do tego ma.

1
Shalom napisał(a):

@TomRiddle: oczywiście że tak, ale to ty pisałes jakieś bzdury że ludzie wyłączają CORS całkiem, tak że strona może się dobić wszędzie. Strona zawsze sie moze dobić wszędzie i wysyłać requesty gdzie chce i CORS nijak się do tego ma.

Czyli jak zrobię na stronie z włączonymi CORS fetch("https://google.com") to zadziała? :> Mówiąc "strona może się dobić" miałem na myśli AJAX z tej strony.

Shalom napisał(a):

Strona zawsze sie moze dobić wszędzie i wysyłać requesty gdzie chce i CORS nijak się do tego ma.

Ty mówisz o froncie strony? Że JavaScript który się odpala na wczytanej stronie?

1

Czyli jak zrobię na stronie z włączonymi CORS

Co to w ogóle niby znaczy? Gdzie ty niby "włączasz" albo "wyłączasz" CORS na stronie? o_O CORS jest ustawiony w backendzie, więc w twoim przykładzie to google decyduje co zrobić z tym requestem. Jak zrobisz to swoje fetch("https://google.com") to do google.com poleci request z dodanym headerem Origin i to google.com zdecyduje co zrobić z twoim requestem i jaki header wysłać w odpowiedzi. Google może ci odesłać jakieś Access-Control-Allow-Origin: dupa.com i na tej podstawie twoja przeglądarka zdecyduje czy twój javascript moze odczytac odpowiedź czy też nie.

1
Shalom napisał(a):

Czyli jak zrobię na stronie z włączonymi CORS

Co to w ogóle niby znaczy? Gdzie ty niby "włączasz" albo "wyłączasz" CORS na stronie?

No że ustawię na backendzie z jakich originów się można dobić. Ja tak mówię "wyłączyć CORS", bo mnie luj strzela jak widzę że ktoś robi Allow-Access-Control-Origin: *.

o_O CORS jest ustawiony w backendzie, więc w twoim przykładzie to google decyduje co zrobić z tym requestem. Jak zrobisz to swoje fetch("https://google.com") to do google.com poleci request z dodanym headerem Origin i to google.com zdecyduje co zrobić z twoim requestem i jaki header wysłać w odpowiedzi. Google może ci odesłać jakieś Access-Control-Allow-Origin: dupa.com i na tej podstawie twoja przeglądarka zdecyduje czy twój javascript moze odczytac odpowiedź czy też nie.

No tak. Sam to napisałeś i na tej podstawie twoja przeglądarka zdecyduje. Przeglądarka sprawdza CORS. Gdybym siedział na własnej customowej przeglądarce którą nauczę olewać CORS to ona by przepuściła taki request. Co jest sytuacją oczywiście potencjalnie groźną, bo mogą mi wyciec dane.

Rozumiem że mogłeś pomyśleć, z jakiegoś powodu, że nie rozumiem CORS i chciałeś mi wbić szpileczkę. Może innym razem się uda.

0

No że ustawię na backendzie z jakich originów się można dobić

Nie no gubisz się coś w zeznaniach bo przed chwilą pisałeś:

Czyli jak zrobię na stronie z włączonymi CORS fetch("https://google.com")

Jeszcze raz pytam: co to znaczy na stronie z włączonymi CORS? Bo backendem tutaj jest google.com przecież.

Rozumiem że mogłeś pomyśleć, z jakiegoś powodu, że nie rozumiem CORS i chciałeś mi wbić szpileczkę. Może innym razem się uda.

Dowody świadczą na twoją niekorzyść.

Pisałeś przecież:

Bo gdybyś miał groźny skrypt przez pomyłkę uruchomiony na Twojej stronie, to on nic nie zrobi z Twoimi danymi. Jak odblokujesz CORS to może je wysłać w świat.

Co jest bzdurą bo taki groźny skrypt na twojej strone zawsze może wysłać dane w świat i CORS nijak się do tego ma.

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

@TomRiddle: oczywiście że tak, ale to ty pisałes jakieś bzdury że ludzie wyłączają CORS całkiem, tak że strona może się dobić wszędzie. Strona zawsze sie moze dobić wszędzie i wysyłać requesty gdzie chce i CORS nijak się do tego ma.

Czyli jak zrobię na stronie z włączonymi CORS fetch("https://google.com") to zadziała? :>

Jeśli to zrobisz z przeglądarki, która nie egzekwuje CORSów to tak, bo "strona" nie ma tu nic do gadania, tylko przeglądarka. Możesz odpalić Chrome z flagą --disable-web-security i wtedy z każdej strony możesz walić requesty do każdego serwera.

4
TomRiddle napisał(a):

Większość stron ma domyślne ustawienie zamkniętych CORS, czyli że przeglądarka zezwoli skryptowi na stronie kontakt tylko z hostem z którego została zaservowana i niczym innym.

Drugi najpopularniejszy, to kiedy ludzie wyłączają CORS całkiem, tak że strona może się dobić wszędzie (co jest oczywiście groźnie, bo strona wtedy może wysłać nasze dane do innych stron).

Wygląda że zupełnie nie rozumiesz tematu i co gorsze udzielasz się siejąc dezinformację.
Po pierwsze - każda strona może wysłać dane wszędzie i to od zawsze - POST/GET przez ukryty formularz, GET przez choćby ładowanie obrazka.
CORS tylko zezwala na poluzowanie Same Origin Policy i pozwala na czytanie odpowiedzi / ładowanie resource'ów (domyślnie odczytywanie danych z cudzych domen jest zablokowane).
Ustalasz przez nagłówki wysyłane na swoim serwerze które domeny mogą czytać dane z Twojej strony, nie które mogą do niej wysyłać dane, ani nie do których stron twoje skrypty mogą się "dobić".
To zabezpieczenie przed pozyskiwaniem danych z Twojej domeny z domen trzecich a nie przed wysyłaniem danych.

To ma chronić użytkowników przed tym że jak wejdą na stronę xyz.com to strona nie może sobie przeczytać twojego walla na facebooku i danych karty kredytowej z banku w którym jesteś teraz zalogowany. Jak piszesz własną aplikację to wiadomo że może sobie ona robić co tylko jej każesz, tylko zmuszenie do odpalenia tej twojej aplikacji (zwanej dalej: malware) jest trudniejsze niż skłonienie do otworzenia zwykłego linka.

Shalom napisał(a):

@TomRiddle chyba coś pokręciłeś, bo CORS ustawia się po stornie "odbiorcy" requestu (backend) a nie po stronie klienta który request wysyła. Problem stanowi to, że jak "wyłączysz" CORS to każdy może do twojego backendu wysłać request w imieniu użytkownika.

I tak może. Przed tym nie chroni Same Origin Policy. Do tego służy CSRF token (po stronie serwera ofiary).

Do zapobiegania przed atakami wychodzącymi od nas i wyciekającymi danymi (to o czym pisał TomRiddle) przez np XSS służy CSP i atrybut nonce.

0

Według mnie, podstawowym zadaniem CORS jest zablokowanie dostępu do sieci prywatnej:

  • Robisz sobie jakieś tam OPA
  • Użytkownik ładuje tę aplikację w swojej przeglądarce
  • Skoro aplikacja jest uruchomiona WEWNĄTRZ sieci, to ma dostęp do wszystkiego co w tej sieci jest udostępnione.

Żeby zablokować taki scenariusz ataku wprowadzone jest zabezpieczenie CORS, czyli

  • strona origin.com jest ładowana

  • strona żąda zasobu z INNEJ DOMENY niż ta z której została załadowana np. resource.com

  • przeglądarka przed obsłużeniem żądania http odpytuje serwer do którego kierowane jest zapytanie o to, czy zezwala na taką akcję, czyli wykonuje żądanie CORS do resource.com informując, że żądanie pochodzi ze strony origin.com

  • jeżeli przeglądarka zostanie poinformowana o tym, że zasób jest dostępny dla żądań pochodzących origin.com wykonuje takie żądanie, jeżeli taki zasób nie jest na white, pardon, allow-list, nie wykonuje.

    W praktyce najczęściej była konieczność ustawiania tego w przypadku kiedy z jednej domeny szły statyczne pliki, a uruchomiony kod odwoływał się do backendu w innej domenie.

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