Wątek przeniesiony 2023-09-18 10:19 z JavaScript przez Riddle.

Jak ze strony internetowej wczytać dane z innego serwisu?

0

Zakładam, że problem jest banalny ale nie potrafię tego obejść.

Potrzebuję pobrać dane z API biznes.gov.pl

async function fetchData()
{
    const url = 'https://dane.biznes.gov.pl/api/ceidg/v2/firmy?nip=772111222';

const response = await fetch(url, {
    headers: {
        'Authorization': 'Bearer {token}',
    },
});

const text = await response.text();

Jeśli uruchomię ten plik js przez node otrzymuję poprawną odpowiedź

Jeśli jednak uruchamiam to przez przeglądarkę mam komunikat:

Access to fetch at 'https://dane.biznes.gov.pl/api/ceidg/v2/firmy?nip=772111222/' from origin 'https://dev.pl' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I teraz jeśli dodam no-cors otrzymuję komunikat 401 o braku autoryzacji

3

Wydaje mi się, że jeżeli to nie jest Twoja strona to nie możesz tak o sobie z poziomu przeglądarki do niej wołać. W innym przypadku wchodząc na losową stronę, ktoś mógłby javascriptem uderzyć do np. twojego facebooka, banku itd.

3

jak pisze @anonimowy . Po to jest cors zebys nie mogl zrobic tego co chcesz zrobic. Jedyne rozwiazanie to proxowac to przez wlasny backend, np node

1
KamilAdam napisał(a):

jak pisze @anonimowy . Po to jest cors zebys nie mogl zrobic tego co chcesz zrobic. Jedyne rozwiazanie to proxowac to przez wlasny backend, np node

Ale jak testowo wywołuję sobie to API z tej strony https://reqbin.com/ to wszystko działa poprawnie.

Bo rozumiem, że po to jest API wystawione, żeby z niego korzystać z każdej strony

0

Być może ta strona działa przez backend. Sprawdź w konsoli sobie. Czyli tak samo jakbyś sobie lokalnie postmanem to zrobił a potem wystawił wynik.

Dodatkowo umieszczanie prywatnego (z headera) tokena po stronie klienta też nie jest dobrym pomysłem

0

Nie dodali nagłówka twojej domeny do odpowiedzi serwera. Musisz do nich napisać żeby to zrobili. Wtedy będziesz mógł pobierać dane z ich API. :) Albo zrób własny serwer i z niego odpytuj ich bazę. Dodatkowo dodaj sobie cache odpowiedzi bo ich API ma limity.

0
mamrzeczy.pl napisał(a):

Nie dodali nagłówka twojej domeny do odpowiedzi serwera. Musisz do nich napisać żeby to zrobili. Wtedy będziesz mógł pobierać dane z ich API. :) Albo zrób własny serwer i z niego odpytuj ich bazę. Dodatkowo dodaj sobie cache odpowiedzi bo ich API ma limity.

Nie chcę mi się wierzyć, że na tej stronie gdzie testowałem to API jest dodana ich domena. Zresztą zapytania przez curl albo poprzez wywołanie pliku js z node działa poprawnie.

8

Temat poruszany milion razy na forum.

Wszystko się rozbija o zabezpieczenie użytkownika przeglądarki. Wyobraź sobie, że wchodzisz na stronę hacker.com, i ta strona robi fetcha do Twojego fejsubka albo konta w banku (np robi fetch('facebook.com/messages') albo fetch('mbank.com/transaction-history'). Wtedy wchodząc na losową stronę, ta strona mogłaby robić żądania do Twoich innych prywatnych stron, i one by się udały, bo jesteś na nich zalogowany w przeglądarce. Potem kod na takiej stronie może przesłać Twoje prywatne dane do takiego hackera.

Dlatego przeglądarki mają wbudowane zabezpieczenie, takie, że jeśli akurat otwarta strona (w tym wypadku ta, którą Ty napisałeś), próbuje wczytać dane z innej strony (w tym wypadku dane.biznes.gov.pl), to ta strona myśli "a co jeśli akurat otwarta strona jest hackerem, i próbuje wczytać wrażliwe dane mojego użytkownika z dane.biznes.gov.pl?. Dochodzi do wniosku że nie można tego wykluczyć, więc blokuje taki ruch.

Dodanie no-cors do Twojej strony nic nie zmieni - adresowana strona nadal nie ufa Twojej witrynie (więcej o tej opcji napisał @obscurity w poście niżej).

Napisałeś:

Wojciech Koperski napisał(a):

Jeśli uruchomię ten plik js przez node otrzymuję poprawną odpowiedź

Jeśli jednak uruchamiam to przez przeglądarkę mam komunikat:

Wojciech Koperski napisał(a):

Zresztą zapytania przez curl albo poprzez wywołanie pliku js z node działa poprawnie.

No i dokładnie to jest serce Twojego problemu.

Jak strzelasz z node, to robisz sobie po prostu request HTTP, który normalnie możesz zrobić - nikt Ci tego nie zabroni. Również uda się z curl, z pythona czy z dowolnego innego klienta - bo odpalasz to żądanie z Twojego komputera, z Twoją sesją, z Twoimi cookiesami, z Twojej sieci z Twoim IP. Zrobisz krzywdę najwyżej sobie.

Ale w przeglądarce użytkownika sytuacja jest już inna. Jeśli zamieścisz ten kod w skrypcie w witrynie internetowej, i odpala ją użytkownik, to już nie jest Twój komputer/sesja/ip/cookies/sieć; tylko komputer i sesja Twojego użytkownika. Żądanie zostanie wysłane z jego komputera wraz z jego sesją, jego cookiesami, jego danymi, z jego sieci z jego IP. Użytkownik wtedy świadczy i ryzukuje swoimi danymi. Nie możesz go tak łatwo zmusić do tego żeby jego cookiesami i sesją strzelić do jakiegoś serwera. Kiedy użytkownik otwiera Twoją stronę, to pozwala na uruchomienie Twojego (potencjalnie szkodliwego) kodu na swojej maszynie, w swojej przeglądarce, ze swoimi cookiesami, sesją i danymi, ze swojego IP ze swojej sieci. Po prostu jesteś w stanie wtedy wykonać arbitralny kod na komputerze Twojej "ofiary" (ofiary w cudzysłowie), i np posługując się jego sesją, cookiesami i adresem, możesz np wysłać albo wczytać wrażliwe dane tego użytkownika. Mając dostęp do jego danych, i mogą robić fetch()e z jego sesją jesteś w stanie mu wyrządzić szkodę.

Mówisz, że:

Wojciech Koperski napisał(a):

Nie chcę mi się wierzyć, że na tej stronie gdzie testowałem to API jest dodana ich domena. Zresztą zapytania przez curl albo poprzez wywołanie pliku js z node działa poprawnie.

Oprócz jawnego wpisania domeny w nagłówkach CORS, można jeszcze dodać wildcard: Access-Control-Allow-Origin: *, i wtedy z takiej strony mogą wczytywać strony wszystkich hackerów i serverów na całym świecie. Jest to rzadko stosowane, bo jest to bardzo niebezpieczne. Wtedy użytkownik wchodząc na dowolną stronę, jest w stanie wykraść informacje z tej domeny bardzo prosto.

Działa to mniej więcej tak:

Scenariusz #1

  • Użytkownik wchodzi na stronę hacker.com
  • Skrypt wczytany z tej strony próbuje wczytać Twoje wrażliwe dane, i robi np fetch('facebook.com/messages')
  • Twoja przeglądarka nie ufa skryptowi na stronie hacker.com, więc strzela do facebook.com i pyta o CORS.
  • facebook.com odsyła CORS, z której wynika że facebook.com nie ufa hacker.com.
  • Przeglądarka odrzuca żądanie HTTP ze strony hacker.com do facebook.com

Scenariusz #2

  • Użytkownik wchodzi na Twoją stronę
  • Skrypt wczytany z tej strony próbuje wczytać dane, i robi np fetch('https://reqbin.com/echo/get/json')
  • Twoja przeglądarka strzela pod ten adres, i pyta o Access-Control-Allow-Origin
  • Strona reqbin.com odpowiada nagłówkiem Access-Control-Allow-Origin: *
  • Przeglądarka uznaje że reqbin.com ufa każdej stronie, i dlatego pozwala skryptowi wczytanemu z Twojej strony na wykonanie żądania

tl;dr;

Przeglądarki mają wbudowane zabezpieczenie, które reguluje z jakiej innej witryny ktoś może się dostać do danej domeny. Czyli:

  • Żądanie do strony siema-elo.com można wysłać z przeglądarki, tylko ze skryptu wczytanego ze strony siema-elo.com (same-origin)
  • Żądanie do strony siema-elo.com można wysłać z przeglądarki, tylko ze skryptu wczytanego ze strony która jest wyróżniona w Access-Control-Allow-Origin zwróconego z siema-elo.com.
  • Żądanie do strony siema-elo.com można wysłać z przeglądarki ze skryptu wczytanego z dowolnej domeny, jeśli siema-elo.com zwróciła nagłówek Access-Control-Allow-Origin: *

Oczywiście te zabezpieczenia dotyczą skryptów z przeglądarki - bo tam operujemy sesją i cookiesami odwiedzających użytkoników. Dysponując swoją sesją (np z curl, postman, python, node'a), możemy robić requesty zawsze i wszędzie.

0
Wojciech Koperski napisał(a):
mamrzeczy.pl napisał(a):

Nie dodali nagłówka twojej domeny do odpowiedzi serwera. Musisz do nich napisać żeby to zrobili. Wtedy będziesz mógł pobierać dane z ich API. :) Albo zrób własny serwer i z niego odpytuj ich bazę. Dodatkowo dodaj sobie cache odpowiedzi bo ich API ma limity.

Nie chcę mi się wierzyć, że na tej stronie gdzie testowałem to API jest dodana ich domena. Zresztą zapytania przez curl albo poprzez wywołanie pliku js z node działa poprawnie.

Napisałem Ci przecież, że ta strona używa backendu do strzelania do ich API. Ta strona nie robi requesta do tej strony przez twoją przeglądarkę tylko przez swój serwer

0

Dziękuję wszystkim za bogate odpowiedzi. Teraz mam wszystko jasne, wiem co było robione źle i co trzeba poprawić.
Raz jeszcze dziękuję wszystkich, za wyczerpujące odpowiedzi.

1
KamilAdam napisał(a):

po to jest cors zebys nie mogl zrobic tego co chcesz zrobic

Riddle napisał(a):

CORS to jest zabezpieczenie użytkownika przeglądarki.

Znowu siejecie dezinformację i znowu muszę to pisać.
Po to jest CORS żebyś mógł zrobić to co chcesz zrobić (za pozwoleniem drugiej strony).

Zabezpieczenie przeglądarki o którym piszecie to same-origin policy i było wprowadzone niemal od początku wraz z Netscape Navigator 2.0 w 1995 roku.
CORS to Cross-origin Resource Sharing - mechanizm wprowadzony dużo później pozwalający na poluzowanie zabezpieczeń origin policy wprowadzony dopiero w 2014 roku w Chrome a wcześniej jako customowy nagłówek "XDomainRequest" w Internet Explorer 8.
CORS to nie zabezpieczenie. CORS nie wprowadza blokad i nie sprawia że czegoś nie możesz tylko wręcz przeciwnie - pozwala na ustalenie wyjątków i sprawia że możesz zrobić coś co było zawsze zakazane (zapytania cross origin).

Tryb no-cors został wprowadzony w 2015 ale już wcześniej można było wykonywać tego typu zapytania. Wystarczyło dodać obrazek <img src="dowolnyURL"> żeby przeglądarka zrobiła GET na danym resourcie i można było zrobić <form action="dowolnyURL" method="POST"> a potem wysłać taki formularz z javascript. W ten sposób można było wysłać dowolne żądanie POST lub GET na dowolny adres bez reguł CORS ale za to bez możliwości obejrzenia rezultatu, co jest w miarę bezpieczne bo nie możemy w ten sposób dostać się do żadnych danych użytkownika. Metoda no-cors upraszcza to że nie musimy używać tego typu sztuczek żeby wysłać takie zapytanie. Przez to że takie żądania były zawsze możliwe powstały anti-CSRF tokens czyli tokeny bez których nie możemy poprosić o np wylogowanie z serwisu czy zapostowanie na forum bez wiedzy użytkownika. Dzięki temu że w trybie "no-cors" nie możemy czytać odpowiedzi to nie jesteśmy w stanie dostać się do potrzebnego tokena i wykonywać akcje w tle w imieniu usera.

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