ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

sqlmap dbwire 模块解析:零依赖的数据库直连(-d)Wire 协议回退客户端

sqlmap dbwire 模块解析:零依赖的数据库直连(-d)Wire 协议回退客户端 sqlmap dbwire 模块解析零依赖的数据库直连-dWire 协议回退客户端【免费下载链接】sqlmapAutomatic SQL injection and database takeover tool项目地址: https://gitcode.com/gh_mirrors/sq/sqlmap导读当 sqlmap 以-d参数直连数据库服务器而非通过注入点时通常依赖原生驱动psycopg2、pymysql、pymssql等或 SQLAlchemy。本文详解仓库 extra/dbwire 提供的第三级回退方案一组仅使用 Python 标准库实现的、跨产品家族的数据库 wire protocol 客户端让-d模式在没有安装任何第三方库的环境下依然开箱即用。读完本文你将掌握 dbwire 的覆盖范围、DB-API 接口约定、各协议的认证支持与边界限制以及它如何在 sqlmap 的 connector 三级体系中自动兜底。背景为什么需要一套纯标准库的直连客户端sqlmap 的-d模式绕过 HTTP 注入点直接与数据库服务器建立连接并执行查询。正常情况下它按以下优先级选择连接器原生驱动psycopg2、pymysql、pymssql、oracledb、firebirdsql等SQLAlchemy当原生驱动缺失但 SQLAlchemy 支持对应 dialect 时dbwire当两者都不可用时作为零依赖的兜底。这一结论在原文档中有明确描述同时可以在 lib/core/dicts.py 和 lib/controller/handler.py 的源码中得到印证——后者的连接建立逻辑在原生驱动与 SQLAlchemy 均失败触发NameError时会检查目标 DBMS 是否在DBWIRE_MODULES映射中若在则切换为DbwireConnector并重试连接。dbwire 的每个模块都是针对数据库**wire protocol线协议**编写的纯 Python 实现只依赖标准库中的socket、struct、hashlib、hmac、base64、urllib没有任何第三方依赖且源码在 Python 2.7 与 Python 3 下均可不加修改直接运行见各模块模块头注释如 extra/dbwire/postgres.py。覆盖矩阵一个协议客户端服务整个产品家族wire protocol 通常由整族产品共享因此 dbwire 的一个模块往往可以服务多个数据库引擎。原文档给出了完整对照表整理如下模块协议覆盖引擎postgres.pyPostgreSQL v3PostgreSQL、CockroachDB、CrateDB、Redshift、Greenplum、Verticamysql.pyMySQL client/serverMySQL、MariaDB、TiDB、Aurora (MySQL)、Perconatds.pyTDS 7.xMicrosoft SQL Serversybase.pyTDS 5.0Sybase / SAP ASEfirebird.pyFirebird wireFirebird 3 / 4 / 5cubrid.pyCUBRID CASCUBRIDclickhouse.pyHTTP (TabSeparated)ClickHouse 及 HTTP 兼容分支monetdb.pyMAPIMonetDBpresto.pyHTTP/REST (JSON)Presto、TrinoDBMS 到模块的映射集中定义在 lib/core/dicts.py 的DBWIRE_MODULES字典中。其中有两个值得注意的设计细节CrateDB 映射到postgresCrateDB 对外讲 PostgreSQL wire protocolVertica 映射到postgresVertica 使用 PostgreSQL v3 衍生协议支持 trust/cleartext/md5 认证Sybase 独立映射到sybaseSAP ASE 保留的是 TDS 5.0与微软 7.x 的登录与 token 方言不同因此必须单独实现一个模块。也就是说dbwire 的模块划分粒度是协议而不是产品同一协议家族的成员共享同一个客户端只有在协议分叉处如 TDS 5.0 vs 7.x才拆分模块。接口约定PEP 249DB-API 2.0子集每个 dbwire 模块对外暴露一个精简的 DB-API 2.0 子集原文档明确指出遵循 PEP 249 规范本文按仓库事实转述其接口不再引用外部链接connect(host, port, user, password, database, connect_timeout, ...)→ConnectionConnection.cursor()、.commit()、.rollback()、.close()Cursor.execute(query)、.fetchall()、.fetchone()、.close()、.description、.rowcount共享的异常层级定义在 extra/dbwire/init.pyError→InterfaceError/DatabaseError→OperationalError/DataError/IntegrityError/ProgrammingError/InternalError/NotSupportedError。__init__.py还声明了apilevel 2.0、threadsafety 1、paramstyle pyformat等模块级属性让调用方可以按标准方式探测驱动能力。值得注意的是虽然声明了paramstyle但 dbwire 刻意不实现参数绑定见下文设计决策execute()只接受完整拼装好的查询字符串。面向读取的设计决策原文档明确说明dbwire 是为 sqlmap 的使用场景刻意设计为只读导向的具体体现为三条约定execute()只接受完整查询字符串不做参数绑定调用方传入的 SQL 原样发给服务器语句自动提交每个语句执行后即提交无需显式commit()二进制列值以bytes返回这样 sqlmap 可以将其渲染为十六进制形式与原生驱动的行为保持一致。这一点在 extra/dbwire/postgres.py 的Cursor与Connection._simple_query实现中可以得到充分印证execute()若收到params参数会直接抛出NotSupportedError(parameter binding is not supported...)commit()与rollback()均为空实现因为简单查询协议simple query protocol会对每条语句隐式提交bytea类型的列值OID 17会被_decode_bytea解码为bytes该函数同时处理新版\xHEX文本格式与旧版八进制 escape 格式见 postgres.py。对 PostgreSQL 而言这种简单查询 自动提交的设计还有一个额外好处由于每一条语句都在自己的隐式事务中完成天然规避了有状态原生驱动常见的中止事务污染aborted-transaction poisoning与先提交再取数commit-before-fetch两类陷阱见 postgres.py 模块头注释。各协议认证支持与边界结合源码原文档分协议给出了认证能力与限制下面结合对应源码模块逐一展开。PostgreSQLpostgres.py支持trust、cleartext、MD5、SCRAM-SHA-256 四种认证见 postgres.py 的_authenticate函数。其中 SCRAM 实现值得关注客户端随机生成 nonce并严格按照 RFC 5802 校验服务器 nonce 必须以客户端 nonce 开头且追加了自己的材料否则判定为rogue serverpostgres.py校验迭代次数不低于 4096防止过低的迭代次数弱化离线攻击成本postgres.py最后校验server-final中的服务器签名v字段使整个握手成为双向认证——服务器也必须证明自己持有存储凭据postgres.py若 Python 版本过低hashlib.pbkdf2_hmac不可用即早于 2.7.8会抛出清晰的NotSupportedError。此外当服务器发送CopyInResponse等待客户端COPY FROM STDIN数据时客户端会主动发送CopyFail拒绝避免与服务器互相等待造成死锁postgres.py。MySQLmysql.py支持mysql_native_password以及caching_sha2_password的快速路径。完整的caching_sha2_password认证在明文连接上需要 RSA/TLS而标准库不提供 RSA因此该场景会抛出干净的NotSupportedError原文档给出的实操建议是为依赖零依赖路径的账号配置mysql_native_passwordMariaDB / TiDB 默认如此。实现层面还包含能力标志协商_CLIENT_PROTOCOL_41、_CLIENT_PLUGIN_AUTH等见 mysql.py并对二进制列做了精细区分只有BLOB/BINARY/VARBINARY/GEOMETRY族charset 63 且字段类型在_BINARY_TYPES集合内才以bytes返回数值与时间列虽然也上报 charset 63但携带的是文本形式必须解码为字符串——否则-d会把整数12345错误地十六进制化成3132333435mysql.py。TDS 7.x / TDS 5.0tds.py/sybase.pytds.py微软 SQL Server仅支持明文登录。服务器强制加密的场景如 Azure SQL Database需要 TLSdbwire 不支持应回退到原生驱动或 SQLAlchemy 层。LOGIN7 是微软的 TDS 7.x 方言不会到达 Sybase。sybase.pySybase / SAP ASE使用明文 LOGINREC 登录。客户端不声明可选能力因此服务器会把date/time/bigdatetime等扩展类型在发送前降级为基线类型数据包大小由登录协商决定收发均按 UTF-8 处理因此运行任何字符集的服务器都能被正确解码。Firebirdfirebird.pyFirebird 3 及以后版本默认强制SRP-256及 SRP认证并配套 ChaCha20 或 RC4 线加密dbwire 均予以实现旧式 pre-SRP 认证不在支持范围内。CUBRIDcubrid.py通过 CAS broker 协议明文登录。大对象BLOB/CLOB不会内联取回而是返回其原始 locator 句柄。统一的失败语义当遇到不支持的情况时各模块一律抛出语义明确的NotSupportedError而不是返回错误数据上层捕获后-d可以干净地继续尝试下一级 connector见 lib/controller/handler.py 的回退逻辑。这是保证三级回退可靠性的关键设计宁可明确失败也不静默产出错误结果。连接生命周期超时、保活与粘包处理extra/dbwire/init.py 中还有一组被各模块共享的连接管理工具体现了相当细致的工程考量http_origin(host, port)拼装http://host:port对字面量 IPv6 地址按 RFC 3986 加方括号避免冒号被解析为端口分隔符init.pyconnection_lost(ex)把裸socket.error/OSError包装为 DB-API 层级中的OperationalError确保只按Error及其子类捕获异常的 PEP 249 调用方拿到的是可处理的连接失败而不是未捕获的 tracebackinit.pyhandshake_done(sock)登录交换完成后解除connect_timeout截止时间。设计要点是超时必须覆盖整个握手过程而不只是 TCP 连接——一个接受连接后沉默的对端错误端口、静默代理、丢弃流量的防火墙在 keepalive 看来是完全存活的若无界等待登录读取会永远挂起init.pykeepalive(sock)启用SO_KEEPALIVE并尝试设置TCP_KEEPIDLE60、TCP_KEEPINTVL10、TCP_KEEPCNT5让内核探测无 FIN 而死的对端。它刻意不是读超时大表上的合法查询可能耗时数分钟固定截止时间会误杀慢查询keepalive 区分的是死对端与慢对端。选项不可移植时静默降级init.pyrecvn(sock, n)精确读取 n 字节短读即抛出异常——因为所有 wire protocol 都是定帧的短读意味着流已失步而非消息更短。该函数被五处重复的 recv 循环收敛为一份实现保证修复只需落地一次init.py。与 sqlmap 的集成方式dbwire 通过两个关键点接入 sqlmap 主流程依赖检查豁免在 lib/core/common.py 的驱动检查中当原生驱动缺失、SQLAlchemy 也不可用时只要目标 DBMS 出现在DBWIRE_MODULES中检查即通过不再报缺少第三方库错误否则才会抛出SqlmapMissingDependence并建议安装驱动或python-sqlalchemy。连接器适配lib/utils/dbwire.py 中的Connector类继承自plugins.generic.connector.Connector通过importlib.import_module(extra.dbwire.%s % module)动态加载对应协议模块把 dbwire 的connect/execute/fetchall/select包装成 sqlmap 的标准 connector 接口dbwire 异常统一转换为SqlmapConnectionException远程错误信息则按conf.dbmsHandler是否启用决定以 WARN 还是 DEBUG 级别记录。触发入口在 lib/controller/handler.py。测试验证无网络的协议转录测试仓库为 dbwire 提供了专门的测试文件 tests/test_dbwire.py其设计思路同样值得关注网络无关用FakeSocket类回放预录的服务器转录transcript并记录客户端写出的所有字节从而可以在无网络环境下精确表达恶意或畸形对端test_dbwire.py覆盖的场景都是对真实服务器难以触达的用例不知道密码的 rogue server、永不结束消息的对端、缺失强制能力的服务器等见模块头注释 test_dbwire.py具体覆盖点包括PostgreSQL SCRAM 服务器签名验证含伪造签名场景test_dbwire.py、MySQL 能力协商、TDS 帧与受影响行数、Trino 会话状态以及共享的 DB-API 异常与 URL 辅助函数仅依赖unittest无 pytest / 无 pip 依赖同样兼容 Python 2.7 与 3.x。总结与适用前提dbwire 是 sqlmap 直连模式的三级保障中最轻量的一环零第三方依赖、Python 2.7/3 双兼容、按协议家族覆盖九类主流引擎、严格遵循 PEP 249 子集。它的定位是-d的回退方案而非通用驱动刻意不做参数绑定、预处理语句、批量加载/COPY与 TLS遇到能力边界时以清晰的NotSupportedError失败并让上层继续回退而不是返回错误数据。使用时的两条实用建议其一涉及 MySQL 且需要零依赖路径时为账号选择mysql_native_password认证其二面向 Azure SQL Database 等强制 TLS 加密的服务器应依靠原生驱动或 SQLAlchemy 层级而非依赖 dbwire。若你希望在最小化环境中让-d开箱即用dbwire 正是仓库为你准备好的那层保障。【免费下载链接】sqlmapAutomatic SQL injection and database takeover tool项目地址: https://gitcode.com/gh_mirrors/sq/sqlmap创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表