Pożegnanie lata z sekurakiem. Tniemy ceny do 70%
NOWOŚĆ! Szkolenie AI w pracy admina
Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!
Pożegnanie lata z sekurakiem. Tniemy ceny do 70%
NOWOŚĆ! Szkolenie AI w pracy admina
Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!
Badacze z Noma Labs odkryli krytyczną (ocenioną na 10 w skali CVSS) podatność w Ruflo, platformie open source do zarządzania agentami AI (ponad 67 tys. gwiazdek na GitHub i 2. miejsce na MCPMarket). Narzędzie dostarcza interfejs czatu, trwałą pamięć oraz narzędzia oparte na MCP. I to ten ostatni komponent okazał się problematyczny.
Choć platforma Ruflo działa jako interfejs użytkownika, zawiera także wbudowany MCP Bridge, będący serwerem Express.js obsługującym wywołania narzędzi. Udostępnia on 233 narzędzia obejmujące dostęp do powłoki, operacje na bazach danych, zarządzanie agentami oraz przechowywanie pamięci, dzięki czemu przechodzą przez niego wywołania narzędzi wykonywane przez agentów.
Badacze odkryli, że wspomniany MCP Bridge udostępniał narzędzia bez żadnego uwierzytelniania. Badaczom udało się wykorzystać jedno z nich do wykonania dowolnego polecenia powłoki. Pojedyncze żądanie HTTP POST na port 3001 dawało możliwość wykonywania komend wewnątrz kontenera. Serwer nie wymagał żadnego tokenu czy klucza API.
Ruflo jest często utrzymywany w modelu self-hosted. Programista klonuje repozytorium, dodaje swoje klucze API do usług LLM, uruchamia kontener Dockera i otrzymuje działającą platformę AI. Problem polega na tym, że plik docker-compose.yml domyślnie mapuje port 3001 na 0.0.0.0, wystawiając bridge dla wszystkich interfejsów sieciowych. Oczywiście wciąż istotne są reguły firewalla i segmentacji sieci, ale w wielu przypadkach instancje Ruflo wystawione do internetu są podatne na wykorzystanie błędu.
Endpoint POST /mcp implementuje protokół MCP JSON-RPC. Akceptuje wywołania narzędzi i przekazuje je bezpośrednio do executeTool() bez żadnej warstwy uwierzytelniania:

Istnieje co prawda lista zablokowanych poleceń (AUTOPILOT_BLOCKED_PATTERNS), która ogranicza niebezpieczne operacje, ale działa ona wyłącznie w ramach funkcji autopilota. Endpoint /mcp całkowicie ją omija. Wśród 233 dostępnych narzędzi znajduje się ruflo__terminal_execute, które wykonuje dowolne polecenia powłoki wewnątrz kontenera.
Do zdalnego wykonania kodu na podatnej instancji Ruflo wystarczyło jedno żądanie:
| curl -s -X POST https://<target>:3001/mcp -H “Content-Type: application/json” -d ‘{“jsonrpc”:”2.0″,”id”:1,”method”:”tools/call”,”params”:{“name”:”ruflo__terminal_execute”,”arguments”:{“command”:”id && hostname”}}}’ |
Listing 1 – żądanie wykonujące kod na instancji, źródło: noma.security
Polecenie wykona się wewnątrz kontenera z jego uprawnieniami (UID 1000), ale nie przeszkadza to w wykradzeniu danych uwierzytelniających, dostępu API agentów czy bazy danych.
Mając możliwość wykonywania poleceń, osiągnięcie pełnego przejęcia jest tylko kwestią połączenia kolejnych requestów do tego samego endpointu. Badacze pokazali, że podatność ta pozwalała przejść od prostego dostępu do MCP Bridge do pełnego przejęcia środowiska Ruflo.
Najpierw wykorzystali dostęp do endpointu, aby zidentyfikować wszystkie dostępne narzędzia, a następnie uzyskali zdalne wykonanie kodu przez terminal_execute. W kolejnym kroku pozyskali klucze API dostawców LLM przechowywane w zmiennych środowiskowych, wykorzystali je do tworzenia kontrolowanych przez siebie agentów. Następnie uzyskali dostęp do historii rozmów przechowywanych w MongoDB, ustanowili trwały backdoor w kontenerze i wykorzystali mechanizm restartu Dockera do utrzymania dostępu. Na koniec usunęli ślady po wykonywanych poleceniach z historii powłoki.
Reakcja Ruflo była wzorowa. Badacze zgłosili podatność, a po kilku godzinach była już poprawka i opublikowany biuletyn bezpieczeństwa. Poprawki wyeliminowały każdy z wektorów ataku w łańcuchu – MCP bridge wymaga MCP_AUTH_TOKEN, jeśli usługa wystawiona jest dla wszystkich interfejsów sieciowych. Dodatkowo narzędzie terminal_execute działa jedynie, gdy włączono opcję MCP_ENABLE_TERMINAL (domyślnie jest ona wyłączona). Oprócz tego dodano konfigurację CORS.
Użytkownikom utrzymującym swoje instancje Ruflo polecamy aktualizację do najnowszej wersji, a długofalowo także wdrożenie firewalla i odblokowywanie tylko tych portów, które mają być dostępne publicznie (jeśli jeszcze tego nie robicie ;-)) – najlepiej przez jakieś reverse proxy pozwalające na dodatkową kontrolę nad przychodzącymi zapytaniami.
Źródło: noma.security
~Tymoteusz Jóźwiak