Dostępność xmlrpc.php
ważność wysokamierzonysposób exposure
Czy xmlrpc.php przyjmuje wywołania (zapytanie POST o listę metod) zamiast być zablokowany. Wektor ataków brute-force i amplifikacji DDoS.
WIKI
artykuł z 16.09.2026 · źródeł 10Dostępność xmlrpc.php to parametr monitoringu stron WordPress, który sprawdza, czy plik /xmlrpc.php przyjmuje wywołania XML-RPC, zamiast je odrzucać. Pomiar polega na wysłaniu zapytania o listę metod i kończy się jednym z trzech wyników: serwer zwraca listę metod, odrzuca wywołanie albo nie odpowiada w wyznaczonym czasie. XML-RPC to interfejs WordPressa do zdalnej pracy z witryną, który zastąpił starsze interfejsy Blogger, MovableType i metaWeblog [1].
Jak działa
Serwer XML-RPC w WordPressie przyjmuje wyłącznie żądania POST. Na żądanie innego typu odpowiada kodem 405, nagłówkiem Allow: POST i komunikatem, że obsługuje tylko POST [3]. Zwykłe otwarcie pliku metodą GET nie mówi więc, czy interfejs działa. Lista metod obejmuje przestrzenie wp., blogger., metaWeblog., mt. i pingback., a filtr xmlrpc_methods pozwala metody dodawać i usuwać [4]. Do tej listy serwer zawsze dokłada trzy metody systemowe: system.getCapabilities, system.listMethods i system.multicall [3].
Metoda system.multicall wykonuje w pętli tablicę wywołań przekazaną w jednym żądaniu HTTP. Kod nie ogranicza liczby wywołań w tablicy, blokuje jedynie zagnieżdżanie system.multicall w samym sobie [3]. Metody wymagające uwierzytelnienia przyjmują login i hasło w każdym wywołaniu i sprawdzają je funkcją logowania serwera [4].
Wyłączenie interfejsu bywa rozumiane zbyt szeroko. Filtr xmlrpc_enabled, dostępny od wersji 3.5.0 i domyślnie ustawiony na true, steruje tylko metodami wymagającymi uwierzytelnienia, na przykład publikowaniem [2]. Dokumentacja zaznacza, że filtr nie decyduje o pingbackach ani o innych metodach bez uwierzytelnienia [2]. Po jego wyłączeniu logowanie przez XML-RPC kończy się błędem 405 z komunikatem „XML-RPC services are disabled on this site” [4], ale plik nadal przyjmuje wywołania.
Standardy i specyfikacje
- XML-RPC WordPress API opisuje interfejs jako następcę API Blogger, MovableType i metaWeblog, z grupami metod dla wpisów, taksonomii, mediów, komentarzy, opcji i użytkowników [1].
- Filtr
xmlrpc_enabled(od 3.5.0) włącza i wyłącza wyłącznie metody z uwierzytelnieniem [2]. - Serwer IXR w kodzie WordPressa odpowiada za obsługę tylko metody POST, metody systemowe i wykonywanie
system.multicall[3]. - Metoda
pingback.pingprzyjmuje adres strony źródłowej i docelowej. Sprawdza, czy cel jest wpisem tej witryny z otwartymi pingami, a potem pobiera stronę źródłową z limitem 10 s, bez przekierowań, do 150 KB, z nagłówkiemX-Pingback-Forwarded-Forzawierającym adres zlecającego [4].
Zagrożenia i skutki
Amplifikacja zgadywania haseł. W październiku 2015 roku Sucuri opisał ataki, w których jedno żądanie z system.multicall zawierało setki prób hasła. Trzy lub cztery żądania HTTP wystarczały na tysiące haseł i omijały narzędzia wykrywające zgadywanie haseł [5]. W większości ataków używano metody wp.getCategories, ale nadaje się do tego każda metoda wymagająca uwierzytelnienia [5]. Sucuri śledził te ataki od 10 września 2015 roku, a 7 października zanotował ok. 60 000 takich żądań [5]. Obecny kod rdzenia po pierwszym nieudanym uwierzytelnieniu oznacza instancję serwera i każdą kolejną próbę w tym samym żądaniu odrzuca bez sprawdzania hasła [4]. Jedno żądanie daje wtedy jedną próbę hasła, ale zgadywanie przez XML-RPC pojedynczymi żądaniami pozostaje możliwe.
Odbicie ruchu przez pingback. W marcu 2014 roku Sucuri naliczył ponad 162 000 legalnych stron WordPress, które w ciągu kilku godzin wzięły udział w ataku DDoS na jedną witrynę, generując setki żądań na sekundę [6]. Atakujący wysyłał do xmlrpc.php żądanie POST z metodą pingback.ping i adresem ofiary jako stroną źródłową, a strony pobierały ten adres [6]. W logach ofiary żądania miały w nagłówku User-Agent wersję WordPressa, a losowe parametry w adresie omijały pamięć podręczną [6]. Sucuri zaznaczył, że zachowanie nie zostanie poprawione, bo jest funkcją, z której korzystają wtyczki, i zalecił filtr usuwający pingback.ping z listy metod [6].
SSRF przez pingback. CVE-2013-0235 dotyczy WordPressa przed wersją 3.5.1: spreparowany adres źródłowy pingbacku pozwalał wysyłać żądania HTTP do serwerów w sieci wewnętrznej i skanować porty [7]. CVE-2022-3590 opisuje ślepy SSRF w pingbacku bez uwierzytelnienia: wyścig między walidacją adresu a żądaniem HTTP pozwala dotrzeć do wewnętrznych hostów, które walidacja miała wykluczyć; NVD ocenia go na 5,9 w skali CVSS [8].
Przykłady
XML-RPC ma legalnych użytkowników. Jetpack łączy się przez ten protokół z WordPress.com, a zablokowanie pliku zrywa to połączenie [9]. Jetpack nie przesyła przy tym loginu i hasła, tylko używa tokenów podobnych do OAuth [9]. Aplikacja mobilna wymaga dostępnego punktu końcowego XML-RPC; część firm hostingowych i wtyczek bezpieczeństwa go blokuje, a obejściem jest logowanie kontem WordPress.com, gdy strona ma połączony Jetpack [10].
| Konfiguracja | Odpowiedź na POST system.listMethods | Znaczenie |
|---|---|---|
| Instalacja domyślna [3] [4] | 200 z listą metod, w tym system.multicall i pingback.ping | pełny interfejs |
xmlrpc_enabled ustawione na false [2] | 200 z listą metod | logowanie odrzucane kodem 405, pingback działa [4] |
Filtr usuwający pingback.ping [6] | 200 z listą bez pingbacku | brak odbicia, logowanie działa |
| Żądanie GET zamiast POST [3] | 405 z Allow: POST | wynik bez znaczenia dla stanu interfejsu |
| Plik zablokowany przez hosting lub wtyczkę [10] | odmowa dostępu | Jetpack i aplikacja mobilna tracą połączenie [9] |
| WordPress przed 3.5.1 [7] | 200 z pingback.ping | SSRF do sieci wewnętrznej |
- [1] XML-RPC WordPress API · WordPress.org
- [2] Hook xmlrpc_enabled — Code Reference · WordPress.org
- [3] class-IXR-server.php — serwer XML-RPC w kodzie WordPressa · WordPress
- [4] class-wp-xmlrpc-server.php — metody XML-RPC WordPressa · WordPress
- [5] Brute Force Amplification Attacks Against WordPress XMLRPC · Sucuri
- [6] More Than 162,000 WordPress Sites Used for Distributed Denial of Service Attack · Sucuri
- [7] CVE-2013-0235 — rekord NVD · NIST NVD
- [8] CVE-2022-3590 — rekord NVD · NIST NVD
- [9] Jetpack and XML-RPC · Jetpack
- [10] Inaccessible XML-RPC Connection error · WordPress.com Apps
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.
- Przebiegów
- 33sposób exposure
- W 30 dni
- 0przebiegów
- Ostatni
- 19.09.2026start przebiegu
- Stron w przebiegach
- —33 przebiegów bez liczby stron
CARD
karta z kodu CREATO_PING, odczyt 22.09.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 (B10) |
|---|---|
| Workflow i częstotliwość | creato_ping_security_v2 · P3 działa na LAB247Skaner 2.0, rytm „p3” / „bezpieczenstwo”: premium co 6 h, reszta co 24 h (tier 1–3), co 9 dni (tier 4) · Dokładny skan. dns_integrity porównuje NS, MX, SPF i DMARC z wzorcem z poprzedniego przebiegu. |
| Sonda i helper | sposób exposure · CREATO_PING/helpers/exposure_check.py |
| Testy |
|
| Typ wyniku | 0 albo 1 ustalenie exposure_xmlrpc |
| Jednostka | brak — wynik jakościowy; w dowodzie groźne metody z listy |
| Próg i reguła | Timeout odpowiedzi 15 s, połączenia 5 s. 403, 404, 405, przekierowanie, błąd sieci i timeout = brak ustalenia. |
| Gdzie leżą pokrętła | CREATO_PING/helpers/exposure_check.py → PROBES (reguła xmlrpc_methods), _XMLRPC_LIST_METHODS, _XMLRPC_DANGEROUSCREATO_PING/helpers/config.py → TIMEOUTS["exposure"], TIMEOUTS["security_connect"]CREATO_PING/helpers/security_runner.py → do_writera (bramka gate z polityki; sito powagi zniknęło 18.09)CREATO_PING/config/incident_policy.toml → [finding] exposure_xmlrpc |
| 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`). Do LAB247 ten kanał nie idzie (do bazy serwisu jadą dziś tylko sprawdzenia dostępności), więc poza odczytem zostaje werdykt w tabeli `werdykty` i sprawa w tabeli `sprawy`. |
| Znane rozbieżności |
|
| Karta przepisana z | CREATO_PING/helpers/exposure_check.py · CREATO_PING/helpers/config.py · CREATO_PING/config/incident_policy.toml · CREATO_PING/helpers/security_runner.py · CREATO_PING/skaner/adapter_clickup.py · CREATO_PING/skaner/sprawy.py · CREATO_PING/skaner/usterki.toml · CREATO_PING/skaner/ocena.py · odczyt 22.09.2026 |
exposure_xmlrpc: bramka polityki otwarta (gate=true) → sprawa w skanerze → Otwarty xmlrpc.php — kanał logowania poza formularzem — waga 2 → ocena 3–4 (niebieski), status strony „niski”, dopóki sprawa jest otwarta. Osobno to higiena, ale w parze z ujawnionym loginem katalog widzi ŁAŃCUCH `przejecie_konta` (`exposure_xmlrpc` + `exposure_users_enum` albo `exposure_author_enum`): do zbioru usterek dochodzi jedna dodatkowa, o wadze 3 — „znany login i kanał do zgadywania haseł hurtem”. Składniki zostają, nie znikają.
| Kod | Finding | Severity | Pewność | Skutek | Finding / alarm | Waga → ocena | Co zrobić |
|---|---|---|---|---|---|---|---|
| B10.01 | Otwarty xmlrpc.phpexposure_xmlrpc | Wysoka | Ewidentne | otwarta podatność | tak / nie | waga 2 → ocena 3–4 (niebieski) | Zablokuj xmlrpc.php, jeśli nie używasz aplikacji mobilnej lub Jetpacka. |
| Kod i klucz | B10.01 · exposure_xmlrpc · w tabeli typów |
|---|---|
| Co znaczy | xmlrpc.php przyjmuje żądania — wektor brute-force (multicall) i amplifikacji DDoS. |
| Kiedy powstaje | POST /xmlrpc.php z treścią system.listMethods (Content-Type text/xml). Zapala się przy statusie 200, gdy treść zawiera '<methodResponse', NIE pasuje do regexu '<int>\s*-32601\s*</int>' (fault) i zawiera 'system.' albo 'wp.'.Body :76-79, ocena :223-230. W evidence methods= to lista znalezionych spośród system.multicall, pingback.ping i wp.getUsersBlogs (:276-278). |
| Severity · pewność | Wysoka · Ewidentne |
| Skutek dla strony | otwarta podatność · zakłada Finding · alarm nie |
| Waga → ocena | waga 2 → ocena 3–4 (niebieski) |
| Klasyfikacja | CWE: CWE-307 (Improper Restriction of Excessive Authentication Attempts)OWASP Top 10:2025: A07:2025 Authentication FailuresMITRE ATT&CK 19.2: T1110 Brute Force (warunek)OWASP ASVS 5.0.0: 6.3.4OCSF 1.9.0: Vulnerability Finding (class_uid 2002) |
| Rekord OCSF | finding_info.analytic.uid = "B10.01" · analytic.name = "exposure_xmlrpc" · finding_info.types = ["B10 Dostępność xmlrpc.php"] |
| Co zrobić | Zablokuj xmlrpc.php, jeśli nie używasz aplikacji mobilnej lub Jetpacka. |
| Wersje typu |
|
LOOP
pętli: 3Trafnoś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.
Sygnał: Tarcze antybotowe hostingu, strony parkingowe i serwery catch-all odpowiadają 200 na każdą ścieżkę, więc sondy oparte na kodzie 200 dawały „wystawiony” wszędzie. Równocześnie sondy na wolnych hostingach odpowiadały po około 15 s, a limit 5 s ucinał je bez śladu. · dotyczy też: Ekspozycja .env, Kopie wp-config.php, Ekspozycja .htaccess.bak, REST API: enumeracja użytkowników, Ekspozycja .git/HEAD, Dostępność readme.html, Dostępność wp-cron.php, Ekspozycja kopii zapasowych, Ekspozycja zrzutu bazy, Ekspozycja manifestów dev, Ekspozycja .DS_Store
- 1. Zbiórkaręcznieodczyt z nocnego skanu, bez zapisu per strona
- 2. Werdyktręcznieprzegląd skanera: 200 na wszystko i ciche timeouty to fałszywe wyniki
- 3. Miarabrakliczników trafności wtedy nie było
- 4. Kartabrakkarta parametru powstała 2026-09-16
- 5. Zmianazrobionestrażnik ścieżki, 15 s, logowanie błędów
- 6. Replaybrakbrak zapisanych odczytów do replayu
| Data | Zmiana | Powód | Wpływ na system | Commit · replay |
|---|---|---|---|---|
| 2026-09-05 | Przed sondami GET losowej, nieistniejącej ścieżki; odpowiedź 200 z treścią = zero sond i jedno ustalenie exposure_scan_unreliable (niska powaga, bez subtaska).helpers/exposure_check.py · config/incident_policy.toml | Odpowiedź 200 na losową ścieżkę dowodzi, że kod 200 na tym serwerze nic nie znaczy; dalsze sondowanie tarczy grozi banem IP monitoringu. | cały system Obejmuje wszystkie sondy ekspozycji naraz i wprowadza typ „nie dało się sprawdzić”; tę samą konwencję dostało wykrywanie wtyczek. Ustalenie ma niską powagę, więc filtr przebiegu je odrzuca i w produkcji nie zostawia śladu. | b0fc77cbez replayubez zapisu zatwierdzenia |
| 2026-09-05 | Limit odpowiedzi z 5 s na 15 s i połączenia z 2 s na 5 s, przeniesione do config.py; błąd sieci sondy logowany zamiast cichego pustego wyniku; do 4 sond naraz na stronę.helpers/config.py · helpers/exposure_check.py · helpers/html_fetch.py · helpers/wp_fingerprint.py | Wolne hostingi odpowiadały po około 15 s, a pusty wynik po timeoucie był nieodróżnialny od „sprawdzone, czysto”. | cały system Limit połączenia 5 s przejęło wspólne pobieranie HTML całego skanu bezpieczeństwa i wykrywanie wersji — strony z wolnym TLS przestały wypadać z całego skanu. | b0fc77cbez replayubez zapisu zatwierdzenia |
Sygnał: Brak pamięci podczas skanu: publiczny debug.log jednej ze stron był bardzo duży, a klient HTTP buforował całą odpowiedź. · dotyczy też: Sitemap.xml, Kopie wp-config.php, Ekspozycja .env, Ekspozycja .htaccess.bak, REST API: enumeracja użytkowników, Ekspozycja .git/HEAD, Dostępność readme.html, Dostępność wp-cron.php, Ekspozycja kopii zapasowych, Ekspozycja zrzutu bazy, Ekspozycja manifestów dev, Ekspozycja .DS_Store
- 1. Zbiórkaręcznieodczyt z nocnego skanu, bez zapisu per strona
- 2. Werdyktręcznieawaria procesu przypisana ścieżce debug.log
- 3. Miarabrakliczników trafności wtedy nie było
- 4. Kartabrakkarta parametru powstała 2026-09-16
- 5. Zmianazrobionestrumień z limitem 64 KB
- 6. Replaybrakbrak zapisanych odczytów do replayu
| Data | Zmiana | Powód | Wpływ na system | Commit · replay |
|---|---|---|---|---|
| 2026-07-19 | Odpowiedź sondy czytana strumieniem do 64 KB; do oceny idzie pierwsze 5000 znaków.helpers/exposure_check.py · helpers/html_fetch.py · helpers/sitemap_check.py | Do rozpoznania ekspozycji wystarcza początek pliku; zmiana dotyczy sposobu czytania, nie werdyktu. | cały system Brak pamięci w helperze zatrzymywał cały proces skanu bezpieczeństwa partii stron; ten sam limit dostało sprawdzenie sitemap. | 343b699bez replayubez zapisu zatwierdzenia |
Sygnał: Audyt AI strony klienta znalazł otwarty xmlrpc.php (POST zwracał listę metod z system.multicall i pingback.ping), którego sonda nie widziała: na GET xmlrpc.php odpowiada 405, a reguła wymagała 200.
- 1. Zbiórkaręcznieaudyt AI jednej strony, nie nocny skan
- 2. Werdyktręcznieaudyt AI potwierdził otwarty endpoint żądaniem POST
- 3. Miarabrakliczników trafności wtedy nie było
- 4. Kartabrakkarta parametru powstała 2026-09-16
- 5. Zmianazrobionesonda POST system.listMethods
- 6. Replaybrakbrak zapisanych odczytów do replayu
| Data | Zmiana | Powód | Wpływ na system | Commit · replay |
|---|---|---|---|---|
| 2026-09-05 | POST /xmlrpc.php z system.listMethods; ustalenie przy kodzie 200, odpowiedzi methodResponse bez błędu -32601 i metodach system. albo wp.; w dowodzie groźne metody.helpers/exposure_check.py | GET dostaje 405 także przy otwartym xmlrpc; nadużycia (multicall, pingback) idą wyłącznie przez POST. | tylko ten parametr | b0fc77cbez replayubez zapisu zatwierdzenia |