Skrypty z domen wygasłych
ważność wysokamierzonysposób skrypty_domeny
Zewnętrzny script src z domeny, która wygasła. Kto ją odkupi, wstrzykuje dowolny kod na stronę klienta.
Wdrożony 01.10 (badanie profilem): domena rejestrowalna każdego zewnętrznego skryptu strony głównej sprawdzana w DNS; NXDOMAIN = do wzięcia.
WIKI
artykuł z 16.09.2026 · źródeł 7Skrypty z domen wygasłych to parametr monitoringu stron internetowych, który zestawia adresy skryptów JavaScript ładowanych z cudzych domen ze stanem rejestracji tych domen. Pomiar kończy się jednym z trzech wyników: wszystkie domeny są zarejestrowane, co najmniej jedna wygasła, jest wolna albo ma świeżą rejestrację, lub stanu nie dało się ustalić. Strona, która dołącza skrypt z zewnętrznego serwera, zwykle nie ma gwarancji, że kod pod tym adresem pozostanie taki, jaki widzieli jej twórcy i testerzy [1].
Jak działa
Bibliotekę można skopiować na własny serwer albo kazać przeglądarce pobierać ją bezpośrednio od dostawcy. W drugim wariancie dostawca ma pełną kontrolę nad kodem, który trafia do użytkownika, i może na przykład podmienić wygląd strony albo przechwycić dane logowania przez modyfikację DOM lub odczyt ciasteczek [2]. Gdy domena dostawcy wygaśnie, a właściciel strony tego nie zauważy, dołączenie staje się „nieaktualne”: ktoś może zarejestrować zwolnioną nazwę i odsyłać złośliwy kod na każde żądanie. Atak nie wymaga kontaktu z ofiarą, więc autorzy badania porównują go do trwałego XSS [2].
Pomiar składa się z czterech kroków, a każdy wymaga innych danych. Pierwszy to lista skryptów: atrybuty src wskazujące inny host, zebrane z HTML strony głównej i podstron. Ta lista jest niepełna, bo biblioteka może w czasie działania doładowywać kolejny kod z innych serwerów [2]. Drugi krok sprowadza nazwę hosta do domeny, którą da się zarejestrować. Służy do tego Public Suffix List, spis sufiksów, pod którymi użytkownicy mogą rejestrować nazwy [7]. Trzeci krok to DNS: w badaniu z 2012 roku sprawdzano, które domeny nie rozwiązują się na adres IP, potem szukano ich w bazie WHOIS, a przy braku wyniku próbowano je zarejestrować [2]. Czwarty to RDAP, w którym tablica events zawiera zdarzenia registration, last changed i expiration [6]. Data rejestracji późniejsza niż dzień dodania skryptu do strony wskazuje nowego właściciela, dlatego pomiar potrzebuje też historii: od kiedy dany skrypt jest na stronie. Szczegóły RDAP opisuje artykuł Wygaśnięcie domeny.
Standardy i specyfikacje
- Subresource Integrity (W3C) pozwala przeglądarce sprawdzić, czy pobrany zasób dotarł bez nieoczekiwanej modyfikacji [4]. Atrybut
integrityzawiera skrót pliku; przeglądarka musi obsługiwać SHA-256, SHA-384 i SHA-512 [4]. Odpowiedź niezgodna ze skrótem nie zostanie wykonana, a żądanie kończy się błędem sieci [4]. Zasoby z innej domeny wymagają przy tym CORS [4]. - Content Security Policy Level 3 kontroluje, jakie zasoby strona może pobrać lub wykonać, i jest pomyślana jako obrona w głąb, a nie pierwsza linia [5]. Lista dozwolonych hostów nie pomoże, gdy zmienił się właściciel samego hosta. CSP3 pozwala jednak dopuszczać skrypty zewnętrzne po skrócie, jeśli element
scriptma metadane integralności wymienione w polityce [5]. Więcej w artykule Content Security Policy. - RFC 9083 definiuje zdarzenia obiektu RDAP;
expirationoznacza, że obiekt został albo zostanie usunięty z rejestru w ustalonym terminie [6]. - OWASP zaleca Subresource Integrity, kopię skryptu na własnym serwerze oraz umieszczanie kodu dostawcy w ramce
iframez innej domeny, która odcina go od DOM i ciasteczek strony [1].
Zagrożenia i skutki
Przejęcie wygasłej domeny. Badacze przeszukali ponad 3,3 mln stron z 10 000 najpopularniejszych serwisów. Znaleźli 56 domen dostarczających skrypty, wolnych do rejestracji i dołączanych przez 47 z tych serwisów; 6 z nich było literówkami w nazwie [2]. Zarejestrowali dwie takie domeny i przez 15 dni odpowiadali stroną błędu 404. Jedna z nich odebrała 80 466 wizyt z 84 podstron w 24 domenach [2].
Zmiana właściciela bez wygaśnięcia. W lutym 2024 roku firma kupiła domenę polyfill.io wraz z kontem projektu w GitHub. Skrypt osadzało ponad 100 000 stron, a nowy kod przekierowywał użytkowników urządzeń mobilnych na strony hazardowe [3]. Nie uruchamiał się przy wykryciu administratora i opóźniał działanie, gdy znalazł usługę analityki [3]. Domena nie wygasła, więc sama data expiration takiej zmiany nie pokaże.
Kompromitacja serwera dostawcy. OWASP wskazuje przejęcie serwera z kodem zewnętrznym jako największe ryzyko [1]. W 2011 roku przez lukę w WordPressie przejęto domenę popularnej wtyczki jQuery, a zmodyfikowana biblioteka była rozpowszechniana przez 33 dni [2]. Pokrewne zjawiska opisuje artykuł Infekcja.
Przykłady
| Sytuacja | Co widać w danych | Czy SRI zatrzyma obcy kod |
|---|---|---|
| Domena skryptu wygasła, nikt jej nie kupił [2] | nazwa nie rozwiązuje się w DNS | nie ma obcego kodu, skrypt nie działa |
| Wolną domenę zarejestrował ktoś inny [2] | nowa data registration w RDAP [6] | tak, gdy jest integrity [4] |
| Domenę sprzedano razem z projektem [3] | rejestracja ciągła, bez wygaśnięcia | tak, jeśli plik ma stały skrót [4] |
| Literówka w nazwie domeny [2] | domena wolna albo cudza | tak, gdy jest integrity [4] |
| Przejęty serwer dostawcy [1] | brak zmian w rejestrze | tak, gdy jest integrity [4] |
| Kod doładowany w czasie działania [2] | adresu nie ma w HTML | zależy od skryptu ładującego |
- [1] Third Party JavaScript Management Cheat Sheet · OWASP
- [2] Nikiforakis i in. — You Are What You Include: Large-scale Evaluation of Remote JavaScript Inclusions (ACM CCS 2012) · ACM CCS 2012
- [3] Polyfill supply chain attack hits 100K+ sites · Sansec
- [4] Subresource Integrity · W3C
- [5] Content Security Policy Level 3 · W3C
- [6] RFC 9083 — JSON Responses for the Registration Data Access Protocol (RDAP) · IETF
- [7] Public Suffix List · Mozilla / Public Suffix List
STATS
wyniki z systemu · tylko liczby zbiorczeTen parametr nie zapisuje odczytu per strona — przebieg zostawia tylko ustalenia, więc liczby sprawdzonych stron i wyników „ok” system nie ma. Pojawią się po wdrożeniu zapisu przebiegów per strona per parametr.
Ten parametr nie otworzył jeszcze żadnego ustalenia w bazie LAB247. Pusto nie znaczy „czysto” — znaczy, że nic nie przekroczyło reguły.
Harmonogram nie zapisał jeszcze przebiegu ze sposobem „skrypty_domeny”. Zapis przebiegów z n8n działa od 2026-09-14.
CARD
karta z kodu CREATO_PING, odczyt 01.10.2026Jak ten parametr trafia do ClickUpa: wynik sondy to linia w subtasku 2. Pomiar, a usterka, którą otwiera — linia w subtasku 1. Podsumowanie (z identyfikatorem CWE i kategorią OWASP), skąd liczy się wskaźnik zagrożenia i status strony. Projekcja z bazy skanera odświeża oba subtaski co godzinę. Do 22.09 każde ustalenie dostawało własny subtask i status ze starego słownika (PODATNA, WARNING…) — te słowa zostały jeszcze w części opisów pomiaru niżej jako język wewnętrzny sond.
| Obszar i ważność | Bezpieczeństwo · wysoka (B34) |
|---|---|
| Workflow i częstotliwość | skaner_badanie działa na LAB247Skaner 2.0, badanie kohorty: premium co 12 h, reszta co 24–48 h · Od 2026-10-01 zestawy kohort (premium_pelny, tani_ciezki, tani_lekki) mają tury higiena, serwer, sklep, kasa i strony (wyciek ścieżek B41, CMS po EOL B44, kluczowe podstrony S08, odnośniki kontaktowe D10); nocny pomiar wydajności (trend, waga, od 01.10 też metryki pasma W01–W04 i W07) tylko premium — u reszty prośba o pomiar zagłodziłaby nocny plan. Sklep: strona bez WooCommerce = „nie dotyczy”. |
| Sonda i helper | sposób skrypty_domeny · CREATO_PING/helpers/higiena_check.py |
| Testy |
|
| Typ wyniku | ok z liczbą domen zewnętrznych skryptów, listą domen (do 40) i listą domen z niepewną odpowiedzią DNS; po jednym ustaleniu exposure_script_domain_unregistered na każdą domenę bez wpisu w DNS; nie_dalo_sie_sprawdzic (`zrodlo_nie_odpowiada`, `blokada`) |
| Jednostka | liczba domen rejestrowalnych zewnętrznych skryptów; wynik jakościowy |
| Próg i reguła | Reguła: NXDOMAIN domeny rejestrowalnej zewnętrznego skryptu = exposure_script_domain_unregistered (powaga wysoka; w dowodzie domena i do 5 adresów skryptów). Limit 8,0 s na pobranie i na zapytanie DNS (TIMEOUT_S). |
| Gdzie leżą pokrętła | CREATO_PING/helpers/higiena_check.py → skrypty_domeny, _SKRYPT, domena_rejestrowalna, TIMEOUT_SCREATO_PING/config/public_suffix_list.dat (ta sama lista co w partial_availability_check)CREATO_PING/config/incident_policy.toml → [finding] exposure_script_domain_unregistered |
| Retencja odczytów | Surowy pomiar jako NIEZMIENNY wiersz tabeli `odczyty` w bazie skanera (wejście, wyjście, dowody, sha karty sondy i helpera, commit kodu) — trigger odrzuca każdą zmianę. Okno retencji z kohorty: 90 dni premium, 30 dni reszta; poza oknem zostają odczyty z werdyktem problemu, akcją albo etykietą, bo replay reguł ich potrzebuje (`skaner/retencja.py`). Poza odczytem zostaje werdykt w tabeli `werdykty`; sprawy nie ma, bo badanie jej nie zakłada. Panel klienta LAB247 czyta najnowszy odczyt na żądanie (`GET /latest-readings`). |
| Znane rozbieżności |
|
| Karta przepisana z | CREATO_PING/helpers/higiena_check.py · CREATO_PING/helpers/partial_availability_check.py · CREATO_PING/helpers/security_testy.py · CREATO_PING/skaner/strona.py · CREATO_PING/skaner/worker.py · CREATO_PING/skaner/scenariusze/premium_pelny.toml · CREATO_PING/skaner/scenariusze/tani_ciezki.toml · CREATO_PING/skaner/scenariusze/tani_lekki.toml · CREATO_PING/skaner/scenariusze/ecommerce.toml · CREATO_PING/config/incident_policy.toml · CREATO_PING/skaner/usterki.toml · CREATO_PING/skaner/ocena.py · odczyt 01.10.2026 |
exposure_script_domain_unregistered: bramka polityki otwarta (gate=true) → sprawa w skanerze → Skrypt ze strony pochodzi z wolnej domeny — do przejęcia — waga 3 → ocena 5–6 (żółty), status strony „sredni”, dopóki sprawa jest otwarta. Ten test chodzi wyłącznie w badaniu kohort, a sprawy zakłada worker tylko dla zleceń z harmonogramu (`skaner/worker.py` → ZRODLA_PRODUKCJI): w badaniu droga kończy się na werdykcie i usterce przebiegu, która podnosi wskaźnik tego badania (`skaner/strona.py` → usterki_przebiegu). Sprawa nie powstaje, więc wskaźnik strony liczony ze spraw się nie zmienia.
| Kod | Finding | Severity | Pewność | Skutek | Finding / alarm | Waga → ocena | Co zrobić |
|---|---|---|---|---|---|---|---|
| B34.01 | Skrypt ze strony pochodzi z wolnej domeny — do przejęciaexposure_script_domain_unregistered | Wysoka | — | otwarta podatność | tak / — | waga 3 → ocena 5–6 (żółty) | — |
| Kod i klucz | B34.01 · exposure_script_domain_unregistered · w tabeli typów |
|---|---|
| Co znaczy | opis do opracowania |
| Kiedy powstaje | GET / (follow_redirects, nagłówki przeglądarki, timeout 8 s); przy statusie >= 400 wynik to nie_dalo_sie. Z pierwszych 3 000 000 znaków brane są src z <script src=...>, rozwiązywane względem końcowego URL; zostają te, których domena rejestrowalna (PSL) różni się od domeny strony. Dla każdej takiej domeny zapytanie DNS NS: NXDOMAIN daje Finding; NoAnswer = domena istnieje; NoNameservers albo Timeout trafia tylko do dns_niepewne bez Findingu.Emisja :238, regex :51, domena rejestrowalna :196-202. security_runner go nie woła (security_testy.py:57-60, :297-301). |
| Severity · pewność | Wysoka |
| Skutek dla strony | otwarta podatność · zakłada Finding |
| Waga → ocena | waga 3 → ocena 5–6 (żółty) |
| Klasyfikacja | CWE: CWE-829 (Inclusion of Functionality from Untrusted Control Sphere)OWASP Top 10:2025: A08:2025 Software or Data Integrity FailuresOCSF 1.9.0: Detection Finding (class_uid 2004) |
| Rekord OCSF | finding_info.analytic.uid = "B34.01" · analytic.name = "exposure_script_domain_unregistered" · finding_info.types = ["B34 Skrypty z domen wygasłych"] |
| Co zrobić | — |
| Wersje typu |
|
LOOP
bez pętliTrafności jeszcze nie liczymy: zamknięcie subtaska nie niesie dziś werdyktu (prawdziwy / fałszywy / nie dało się sprawdzić). Cztery liczby pojawią się, gdy każde zamknięcie dostanie werdykt — to warunek startu pętli 1.
Ten parametr nie przeszedł jeszcze żadnej pętli. Kolejność po pierwszych pięciu grupach ustali miara trafności.