Nmap识别MongoDB 6.0指纹

Nmap识别MongoDB 6.0指纹

朋友反馈一个问题,说使用Nmap扫描MongoDB服务时对于6.0以上的版本默认无法识别到服务版本信息。

如上图所示,对应的VERSION信息是空的,在提示信息中可以看到,官方推荐将指纹信息上传以帮助更新服务指纹,又或者可以通过Nmap的默认脚本mongodb-info来做版本识别。前一种方式需要等待官方做指纹文件更新或产品版本更新,后者使用脚本又会影响到扫描速度。如果想在当前的Nmap版本下不使用脚本来识别MongoDB 6.0以上版本,唯一的办法是使用Nmap内置的服务指纹将MongoDB 6.0服务版本识别出来。

Nmap服务指纹解析

Nmap默认的服务指纹文件位于/usr/share/nmap目录下,文件名是nmap-service-probes,根据默认端口27017可以找到Nmap识别MongoDB服务的内容:

上图中的匹配规则用到了四个指令:

  • Probe:为识别服务发送的字符串信息;
  • rarity:1-9范围的数字,是服务识别和可靠性的概率,数字越大,扫描概率越小,返回信息价值越低;
  • ports:服务识别常用的端口,效果与nmap的-p参数相同;
  • match:根据Probe指令发送字符串返回的信息,匹配服务指纹规则;

上图中用于识别MongoDB服务,通过TCP协议发送到服务端的字符串是:

\x41\0\0\0\x3a\x30\0\0\xff\xff\xff\xff\xd4\x07\0\0\0\0\0\0test.$cmd\0\0\0\0\0\xff\xff\xff\xff\x1b\0\0\0\x01serverStatus\0\0\0\0\0\0\0\xf0\x3f\0

match指令的格式包括:

  • 服务名称(service)
  • 匹配规则(pattern)
  • 版本信息(versioninfo)

以第一行的match指令为例:

match mongodb m|^.*version.....([\.\d]+)|s p/MongoDB/ v/$1/ cpe:/a:mongodb:mongodb:$1/
  • 服务名称:MongoDB
  • 匹配规则:m|^.*version.....([\.\d]+)|s,采用Perl格式的正则表达式,s表示包含换行符;
  • 版本信息:p/MongoDB/ v/$1/ cpe:/a:mongodb:mongodb:$1/,其中p指的是厂商信息,v指的是版本信息,这里引用自匹配规则里匹配的参数,cpe指的CPE(Common Platform Enumeration)格式,用于识别服务、操作系统和硬件;

CPE的格式如下:

cpe:/<part>:<vendor>:<product>:<version>:<update>:<edition>:<language>

除了v指令之外,CPE的第4个值也是产品版本信息,因此上图匹配规则中,只有第一行的规则可以用于识别MongoDB服务版本,通过匹配返回信息中的version信息来显示MongoDB版本。

MongoDB 5.0.1指纹解析

以MongoDB 5.0.1版本为例,当使用nmap对目标的27017端口进行扫描时:

nmap会发送上文中的Probe指令:

MongoDB响应数据包中可以匹配上文中第一条match指令:

因为在Nmap的扫描结果中,可以看到version(版本号)是p指令+指令,即“MongoDB v5.0.1”。

MongoDB有线协议

MongoDB有线协议(Wire Protocol)是请求/响应形式的TCP/IP的Socket,客户端和服务端通过该协议进行通讯,服务端实例(mongod和mongos)的默认端口是27017。

以MongoDB 6.0为例,客户端和服务端在通讯时的消息格式采用的是OP_MSG操作符,即采用以下格式对消息进行编码:

OP_MSG {MsgHeader header;           // standard message headeruint32 flagBits;            // message flagsSections[] sections;        // data sectionsoptional<uint32> checksum;  // optional CRC-32C checksum
}

其中,MsgHeader是标准信息头,客户端与服务端来往的消息都包含标准信息头(在SSL/TLS连接时没有checksum字段),其后才是消息内容(如OP_MSG结构中sections数组,数组每一项由Kind值开头,后接载体数据),标准信息头的结构如下:

struct MsgHeader {int32   messageLength; // total message size, including thisint32   requestID;     // identifier for this messageint32   responseTo;    // requestID from the original request//   (used in responses from the database)int32   opCode;        // message type
}

MsgHeader中opCode消息类型会决定OP_MSG的结构,以OP_QUERY为例:

struct OP_QUERY {MsgHeader header;                 // standard message headerint32     flags;                  // bit values of query options.  See below for details.cstring   fullCollectionName ;    // "dbname.collectionname"int32     numberToSkip;           // number of documents to skipint32     numberToReturn;         // number of documents to return//  in the first OP_REPLY batchdocument  query;                  // query object.  See below for details.[ document  returnFieldsSelector; ] // Optional. Selector indicating the fields//  to return.  See below for details.
}

OP_QUERY类型用于查询数据库中的集合,也是Nmap进行指纹识别时发送的请求消息类型,即上文图中的Probe指令。

但在MongoDB 5.1版本之后,OP_QUERY等消息类型已被淘汰,而相应的Nmap的服务指纹文件和NSE脚本中的服务识别脚本都未更新MongoDB的OP_MSG消息格式,因此无法正确识别出MongoDB的版本信息。

MongoDB 6.0指纹识别

知道MongoDB 5.0.1版本的指纹识别方式,以及MongoDB的OP_MSG消息格式,便可以通过抓取MongoDB 6.0的版本信息请求的流量,修改Nmap的服务探针文件nmap-service-probe来识别服务版本。

首先写一段Python代码作为客户端向MongoDB服务端发起版本信息的请求:

#!/bin/env pythonimport pymongoclient = pymongo.MongoClient("mongodb://192.168.168.133:27017")
server_status = client.admin.command("serverStatus")
print(server_status["version"])

同时,在脚本执行的同一环境下使用TCPDump抓取流量包

sudo tcpdump -i eth0 host 192.168.168.133 -w mongo.pcap

基于抓取的流量包进行分析,可以看到获得最终版本信息的请求头:

从/0x5f/0x00/0x00/0x00开始的便是Python脚本发送给MongoDB服务端的OP_MSG消息头,使用该十六进制字符串替换/usr/share/nmap/nmap-service-probes文件中的Probe指令,由于响应消息中的version匹配格式与原match指令中相同,所以不用变更match指令,这样即可实现对于MongoDB 6.0版本的识别。

但现在的识别仅是相当于流量重放的结果,不一定能够识别所有MongoDB 6.0的指纹,因此需要解析上面流量的OP_MSG消息,剥离出通用版本的OP_MSG请求。

根据6.0版本的OP_MSG格式,可以得知上图中的十六进制字符串的构成:

\x5f\x00\x00\x00:OP_MSG.MsgHeader.messageLength
\x51\xdc\xb0\x74:OP_MSG.MsgHeader.requestID
\x00\x00\x00\x00:OP_MSG.MsgHeader.responseTo
\xdd\x07\x00\x00:OP_MSG.MsgHeader.opCode
\x00\x00\x00\x00:OP_MSG.flagBits
\x00:OP_MSG.sections[0].kind
\x4a\x00\x00\x00\x10\x73\x65\x72\x76\x65\x72\x53\x74\x61\x74\x75\x73\x00\x01\x00\x00\x00\x03\x6c\x73\x69\x64\x00\x1e\x00\x00\x00\x05\x69\x64\x00\x10\x00\x00\x00\x04\x7c\xc1\xc2\x6c\xd7\x11\x40\x21\xb6\xf7\x5a\x52\x08\xaf\xca\x5e\x00\x02\x24\x64\x62\x00\x06\x00\x00\x00\x61\x64\x6d\x69\x6e\x00\x00:OP_MSG.sections[0].payload

核心部分是OP_MSG中sections的payload,使用Python中的bson模块对payload解析:(见评论区)

其中的lsid是客户端请求服务端的会话ID,是bson类型的UUID:7cc1c26cd7114021b6f75a5208afca5e。

因此,可以使用自定义生成uuid来创建能够查询MongoDB版本信息的OP_MSG消息头:

import socket
import bson
import binascii
import uuiddef send_op_msg_request(request):host = '192.168.168.133'port = 27017client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)client.connect((host, port))client.sendall(request)response = client.recv(4096)client.close()return responsedef build_op_msg_request():msg_header = b'\x5f\x00\x00\x00'  # total message sizemsg_header += b'\x00\x00\x00\x00'  # identifier for messagemsg_header += b'\x00\x00\x00\x00'  # request idmsg_header += b'\xdd\x07\x00\x00'  # message typeop_msg = msg_header + b'\x00\x00\x00\x00'  # message flagssection = {'serverStatus': 1,'lsid': {'id': bson.binary.Binary(uuid.uuid4().bytes, bson.binary.UUID_SUBTYPE)},'$db': 'admin'}request = op_msg + b'\x00' + bson.encode(section)return requestop_msg_request = build_op_msg_request()
response = send_op_msg_request(op_msg_request)print(response)

上面代码中的request值就是发送至服务端的OP_MSG消息,可以用于替换nmap-service-probe文件的指纹信息。

以下是更换指纹前后的对比效果:

更改指纹文件前

更改指纹文件后

参考材料

https://www.mongodb.com/docs/v6.0/reference/mongodb-wire-protocol/

https://www.mongodb.com/docs/v6.0/reference/bson-types/#std-label-bson-types

https://nmap.org/book/vscan-fileformat.html

洞源实验室
安全工程师:裴伟伟
2024 年 11 月 19 日 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/20169.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

向量搜索工具之 Milvus vs. Elastic

在当今数据驱动的世界中&#xff0c;向量数据库因其在处理大规模非结构化数据方面的卓越能力而变得越来越重要。随着数据量的爆炸性增长&#xff0c;如何确保这些数据库在存储和检索数十亿数据点时仍能保持高性能&#xff0c;成为了一个关键挑战。 Milvus和Elasticsearch都是管…

Java中日志采集框架-JUL、Slf4j、Log4j、Logstash

1. 日志采集 日志采集是指在软件系统、网络设备、服务器或其他IT基础设施中自动收集日志文件和事件信息的过程。这些日志通常包含了时间戳、事件类型、源和目标信息、错误代码、用户操作记录等关键数据。日志采集的目的是为了监控系统运行状态、分析系统性能、审计用户行为、故…

每日学习记录003:(C++)unique_ptr和shared_ptr

每日学习记录003&#xff1a;&#xff08;C&#xff09;unique_ptr和shared_ptr 在C中&#xff0c;unique_ptr和shared_ptr都是智能指针&#xff0c;它们为动态内存管理提供了更安全、更方便的方式。 一、unique_ptr的特点 &#xff08;一&#xff09;独占所有权 unique_pt…

免费实用的图片加水印工具

高度自定义的图片加水印工具 因工作需要和朋友的需求&#xff0c;我基于canvas开发了这款图片加水印工具。 地址&#xff1a;https://potatotools.top/toolsEntrance/pic/ImageWatermark.vue.html 功能亮点 尺寸定制 &#xff0c;轻松调整水印宽高&#xff0c;精准适配每张图…

数字化工厂 MES 成功之艰:深度剖析与探究

系统集成的复杂性 多源异构系统对接难题 在数字化工厂的建设进程中&#xff0c;MES&#xff08;制造执行系统&#xff09;处于核心枢纽地位&#xff0c;需与众多不同来源、不同架构的系统进行集成。企业内部往往早已部署了诸如企业资源计划&#xff08;ERP&#xff09;系统、…

kimi 大模型 API 接口实现大模型对话 - python 实现

kimi API接口实现大模型对话 - python 实现&#xff0c;具体代码如下&#xff1a; 注意&#xff1a;api_key 需要kimi官网注册后创建。 from openai import OpenAI if __name__ __main__:client OpenAI(api_key "sk-***********", # $MOONSHOT_API_KEY 官网注册…

服务器被隔离导致无法登录

现象描述 云服务器可能会因安全违规&#xff08;内容或行为违规&#xff09;或因 DDoS 攻击被封堵隔离&#xff0c;被隔离的云服务器在控制台显示为 “BANNING” 状态。 云服务器被隔离可能由于该台服务器违反了当前法律法规的要求。您可以通过以下方式查看该台服务器是否处于…

PaddleNLP的环境配置:

PaddleNLP的环境配置&#xff1a; conda create -n paddle—test python3.9conda activate paddle—testpython -m pip install paddlepaddle-gpu2.6.1.post112 -f https://www.paddlepaddle.org.cn/whl/windows/mkl/avx/stable.html(paddle—test) (venv) PS D:\work\论文写…

物联网研究实训室建设方案

一、引言 随着物联网技术的快速发展&#xff0c;其在各个行业的应用越来越广泛&#xff0c;对物联网专业人才的需求也日益增加。为满足这一需求&#xff0c;建设一个符合现代化教学需求的物联网研究实训室&#xff0c;对于提高学生的实践能力和创新能力具有重要意义。本方案旨…

javaweb学习——Day2

JS对象 1、array 定义&#xff1a; var namenew Array(元素列表); var name[元素列表] 访问&#xff1a; name[索引]值 array的属性和方法 length属性&#xff0c;获取数组长度 foreach():遍历数组元素 x.forEach(element > { console.log(element); }); push():…

实战精选|如何使用 OpenVINO™ 在 ElectronJS 中创建桌面应用程序

点击蓝字 关注我们,让开发变得更有趣 作者 | Mikołaj Roszczyk 华沙理工大学物联网工程师 翻译 | 武卓 英特尔 AI 软件布道师 排版 | 吴紫琴 OpenVINO™ 最近&#xff0c;我完成了一个 demo 演示&#xff0c;展示了 OpenVINO™ 在 Node.js 框架中的强大功能。得益于与 Electr…

PyCharm的类型警告: Expected type ‘SupportsWrite[bytes]‘, got ‘BinaryIO‘ instead

记录时使用的PyCharm版本: PyCharm 2024.3 (Professional Edition) Build #PY-243.21565.199, built on November 13, 2024 问题描述 当在PyCharm里使用pickle保存文件, 比如以下代码这样: with open(meta_save_path, wb) as f:pickle.dump(meta, f)会发现PyCharm对此发出类型…

【Docker】快速部署 Pikachu:一个包含常见 Web 安全漏洞的渗透测试练习靶场

系统介绍 Pikachu是一个带有漏洞的Web应用系统&#xff0c;在这里包含了常见的web安全漏洞。 如果你是一个Web渗透测试学习人员且正发愁没有合适的靶场进行练习&#xff0c;那么Pikachu可能正合你意。 Pikachu上的漏洞类型列表如下&#xff1a; Burt Force(暴力破解漏洞) XSS…

vscode 执行 vue 命令无效/禁止运行

在cmd使用命令可以创建vue项目但是在vscode上面使用命令却不行 一、问题描述 在 cmd 中已确认vue、node、npm命令可以识别运行&#xff0c;但是在 vscode 编辑器中 vue 命令被禁止&#xff0c;详细报错为&#xff1a;vue : 无法加载文件 D:\Software\nodejs\node_global\vue.…

【电路笔记 通信】:数字式时分制指令响应型多路传输数据总线 1553协议 289A-97协议

系统及组成 MIL-STD-1553是一种用于航空、航天和军用系统中的多路传输数据总线标准。最初由美国国防部在1973年制定&#xff0c;该标准旨在为军用飞机、导弹和其他嵌入式系统提供可靠的数据通信&#xff0c;现已被广泛应用于航空航天、卫星、舰船、地面车辆以及其他关键任务系统…

npm/cnpm的使用

npm 1、安装npm 前往nodejs官网下载安装node 验证是否安装成功node node -v node安装npm也会安装 npm -v 2、使用npm 1. 初始化项目 在一个项目文件夹中运行&#xff1a; npm init 根据提示输入项目信息&#xff08;如项目名称、版本号等&#xff09;。 如果你希望快速初…

红外相机和RGB相机外参标定 - 无需标定板方案

1. 动机 在之前的文章中红外相机和RGB相机标定&#xff1a;实现两种模态数据融合_红外相机标定-CSDN博客 &#xff0c;介绍了如何利用标定板实现外参标定&#xff1b;但实测下来发现2个问题&#xff1a; &#xff08;1&#xff09;红外标定板尺寸问题&#xff0c;由于标定板小…

web小:在html页面实现多边形按钮

效果如下图所示 主要是使用了clip-path&#xff0c;代码如下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">&l…

【蓝桥杯C/C++】翻转游戏:多种实现与解法解析

文章目录 &#x1f4af;题目&#x1f4af;问题分析解法一&#xff1a;减法法解法二&#xff1a;位运算解法解法三&#xff1a;逻辑非解法解法四&#xff1a;条件运算符解法解法五&#xff1a;数组映射法不同解法的比较 &#x1f4af;小结 &#x1f4af;题目 在蓝桥镇&#xff0…

V-rep机器人仿真软件学习笔记

常用的机器人仿真软件有哪些&#xff1f;为什么选择V-rep&#xff1f; 目前常用的机器人物理仿真软件有Gazebo、V-rep、Webots等&#xff0c;这三款都是开源软件&#xff0c;自己使用过前两种&#xff0c;Gazebo配合ROS使用功能十分强大&#xff0c;但是要在Linux系统下使用&am…