固定MongoDB数据库中的证据

kuyjf3vea2hg34taa-horizontal_default_slate_blue

最近做了很多爬虫案件,大多数都喜欢用阿里云或者自建的MongoDB数据库来存一些配置和爬取的数据,因此写文章记录固定方法,MongoDB数据库固定后的重构方法将在下一篇文章中讨论。

根据目标MongoDB数据库的版本号,把固定方法分为两类,一类是基于mongodump工具的固定方法,一类是基于阿里云控制台的固定方法。

MongoDB基础介绍

MongoDB的数据结构

MongoDB是面向文档的NoSQL(非关系型)数据库,它的数据结构由字段(Field)和值(Value)组成,类似于JSON对象,示例如下:

1
2
3
4
5
{
name:"张三",
sex:"男性",
age:30
}

MongoDB的存储结构

MongoDB的存储结构区别于传统的关系型数据库,由如下三个单元组成:

  • 文档(Document):MongoDB中最基本的单元,由BSON键值对(key-value)组成。相当于关系型数据库中的行(Row)。
  • 集合(Collection):一个集合可以包含多个文档,相当于关系型数据库中的表格(Table)。
  • 数据库(Database):等同于关系型数据库中的数据库概念,一个数据库中可以包含多个集合。可以在MongoDB中创建多个数据库。

放一张Navicat连接上的MongoDB数据库截图便于理解:

image-20230328012550049

JSON视图如下:

image-20230328012649124

生成这两个测试数据库的查询语句放在文章最后。

使用阿里云控制台的固定方法

适用场景:目标阿里云MongoDB版本小于等于4.2

查看版本方法

首先阿里云官网登上涉案的阿里云账号,打开下面的控制台地址。

1
2
##阿里云数据库MongoDB控制台地址
https://mongodb.console.aliyun.com/dashboard/

左边可以看到副本集实例列表或分片集群实例列表,点进去选择开通服务的地域后,就可以看到每个MongoDB实例的版本号,如下图:

image-20230327234107461

可以看到这个账号有三台4.2版本符合要求。

固定步骤

点击上图中的实例ID,就能进入实例的详情页,如下图:

image-20230327235616874

点击“备份与恢复”,再点击“备份实例”,会让选择物理还是逻辑备份,如下图:

image-20230328002500355

逻辑备份和物理备份的区别

逻辑备份的意思是,通过mongodump工具将对数据库的操作记录存储到逻辑备份文件中,恢复时通过mongorerstore命令的形式还原数据,简单的说就是阿里云帮你自动打mongodump命令备份,你只管下载备份文件就行,重构数据库时也比较方便。

物理备份指的是备份云数据库MongoDB实例中数据库相关的物理文件,备份速度比逻辑备份更快,且恢复速度也更快,但是重构时步骤相对麻烦。

因此当取证时间充足,数据量较小时,推荐选择逻辑备份;如果数据量超大,追求速度,选择物理备份。

以物理备份为例,点击确定,进入备份过程。

image-20230328002030917

但是阿里云不显示备份进度,这个很蛋疼,这样就不知道刚刚操作是否有效了,那就再点一边物理备份,报错提示备份正在进行,这样就没问题,剩下的等就行了。大小为108GB的备份大概花费了半小时,咱们就是说疯狂的按F5刷新页面,等下图的“√完成备份”字样出来就可以开始往本地下载了。

image-20230328004305483

如果选的是逻辑备份,效果是如下图,逻辑备份花费了两个半小时,备份大小51GB。

image-20230328093548770

点击你刚备份上的那个的“下载按钮”,会告诉你下载地址。

image-20230328003609570

点击复制公网下载地址,粘贴到迅雷里直接下载就行,速度超快,实测我家100Mbps带宽可以跑满,记得开迅雷会员。

image-20230328003817270

可以看到物理备份下载的是经典xbstream格式的_qp.xb后缀(2019年03月26日之前创建的实例,物理备份文件格式为tar),如果是逻辑备份,下载的则是“ar”格式,如下图。

image-20230328094016194

下载完记得算哈希,看下北京时间,结束录屏,阿里云控制台备份的方法就结束了。

直连数据库的固定方法

适用场景:自建的MongoDB数据库、阿里云MongoDB版本大于4.2

如果阿里云MongoDB版本大于4.2,去控制台发现只有快照备份,如下图。

image-20230328014925008

快照备份只能在阿里云上回滚或者新建实例,没法下载到本地,这样咱就没法拿到证据了。

image-20230328015143616

因此要通过连接到数据库来导出数据,可以使用MongoDB官方提供的备份工具mongodump进行这个操作。mongodump咱们上面讲逻辑备份提到过,是阿里云帮咱们打命令固定,等着下载就行了,所以直连的方法相当于是手动打mongodump命令进行逻辑备份了。

安装mongodump

mongodump是MongoDB Database Tools工具之一,先去MongoDB官网下载Database Tools工具包。

1
2
##MongoDB Database Tools工具包官方下载地址
https://www.mongodb.com/try/download/database-tools?tck=docs_databasetools

image-20230328113740144

然后把下载的zip包解压到任意路径,如下图:

image-20230328113949069

然后复制这个位置的路径,添加到环境变量里面。

image-20230328114154027

然后打开PowerShell终端,输入命令看看效果。

1
2
##mongodump帮助命令
mongodump --help

image-20230328114352267

有回显,没问题的。

获取MongoDB的连接信息

自建数据库

连接信息主要包括host地址、端口号、账户、密码、验证数据库等,最好是通过现场问到,问不到可以在他的Navicat、DBeaver工具、代码或者笔记中尝试找。

阿里云数据库

仍然是登录控制台,找到目标MongoDB,点击数据库连接,如下图:

image-20230328115808226

可以看到host为“dds-xxxxxxxxxxxxxxx-pub.mongodb.rds.aliyuncs.com”,端口号为3717,连接账号可以在账号管理页面找到,也可以对它重置密码,这样连接信息就齐全了。

image-20230328120105878

也可以创建一个只读账号来取证,防止误操作,这里我跳过了。

添加IP白名单

一般MongoDB会在白名单上设置允许访问的IP,所以直接连接我们可能会无法访问,因此要把我们自己的IP添加到白名单,我们先在PowerShell写一行命令来查询本机公网IP。

1
2
##查询公网IP
curl ipinfo.io

image-20230328130928274

随后我们打开MongoDB控制台,找到白名单设置,添加刚查到的IP地址。

image-20230328131811131

Dump数据

mongodump的常用参数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
-h,--host :代表远程连接的数据库地址,默认连接本地Mongo数据库;
--port:代表远程连接的数据库的端口,默认连接的远程端口27017;
-u,--username:代表连接远程数据库的账号,如果设置数据库的认证,需要指定用户账号;
-p,--password:代表连接数据库的账号对应的密码;
-d,--db:代表连接的数据库;
-c,--collection:代表连接数据库中的集合;
-o, --out:代表导出的文件输出目录;
-q, --query:代表查询条件;
-j,--numParallelCollections =要并行转储的集合数(默认为4)
--archive,输出为单个文件
--gzip,使用Gzip压缩存档;
--oplog,使用oplog进行时间点快照;
--authenticationDatabase,指定用户鉴定库

我们用上述参数去全量备份一个连接里的所有数据库,并导出为单个文件名为“forensax”,如下图所示。

1
2
3
##全量备份
##mongodump -h 连接地址:端口 --authenticationDatabase admin -u 账户 -p 密码 --archive=导出文件位置\导出文件名
mongodump -h 10.91.217.119:27017 --authenticationDatabase admin -u admin -p 123456 --archive=F:\mongo\forensax

image-20230328143436641

如果想让导出的文件小一点,可以加–gzip参数,命令如下:

1
2
##全量备份,压缩导出
mongodump -h 10.91.217.119:27017 --authenticationDatabase admin -u admin -p 123456 --gzip --archive=F:\mongo\forensax.gz

image-20230328143748707

如果要指定一个数据库,用-d参数,如果要指定一个集合,用-c参数。

1
2
##指定集合或者数据库
mongodump -h 10.91.217.119:27017 --authenticationDatabase admin -u admin -p 123456 -d fruitdb1 -c bananas --archive=F:\mongo\forensax

固定到本地后,就可以计算哈希值了,看下北京时间,结束录屏,取证工作就结束了。

附查询语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//以下查询语句由ChatGPT生成(帮我生成查询语句,在MongoDB中创建两个数据库,每个库三个集合,每个集合3个文档,每个文档3个字段,内容与水果有关)
// 创建fruitdb1数据库并插入文档
use fruitdb1
db.createCollection("apples")
db.createCollection("oranges")
db.createCollection("bananas")
db.apples.insertMany([
{ name: "Granny Smith", price: 0.99, description: "Green and tart" },
{ name: "Honeycrisp", price: 1.29, description: "Sweet and juicy" },
{ name: "Golden Delicious", price: 0.89, description: "Mild and sweet" }
])
db.oranges.insertMany([
{ name: "Navel", price: 0.79, description: "Sweet and seedless" },
{ name: "Cara Cara", price: 0.99, description: "Pink flesh and low acid" },
{ name: "Blood Orange", price: 1.09, description: "Deep red flesh and tangy" }
])
db.bananas.insertMany([
{ name: "Cavendish", price: 0.49, description: "Most common variety" },
{ name: "Manzano", price: 0.69, description: "Short and plump with sweet flesh" },
{ name: "Red", price: 0.89, description: "Sweet with a hint of raspberry flavor" }
])

// 创建fruitdb2数据库并插入文档
use fruitdb2
db.createCollection("kiwis")
db.createCollection("grapes")
db.createCollection("strawberries")
db.kiwis.insertMany([
{ name: "Hayward", price: 1.99, description: "Fuzzy brown skin and bright green flesh" },
{ name: "Zespri Green", price: 2.29, description: "Sweeter and more aromatic than other green kiwis" },
{ name: "Zespri SunGold", price: 2.99, description: "Yellow flesh and tropical flavor" }
])
db.grapes.insertMany([
{ name: "Thompson Seedless", price: 1.49, description: "Small, sweet and seedless" },
{ name: "Red Globe", price: 2.49, description: "Large and juicy with thick skin" },
{ name: "Concord", price: 1.99, description: "Dark purple with sweet and tangy flavor" }
])
db.strawberries.insertMany([
{ name: "Albion", price: 3.49, description: "Large and sweet with a conical shape" },
{ name: "Camarosa", price: 2.99, description: "Firm and bright red with a pointed tip" },
{ name: "Chandler", price: 3.99, description: "Very large and sweet with a heart shape" }
])

References
[1] 阿里云文档中心: https://help.aliyun.com/product/26556.html
[2] mongodump官方文档: https://www.mongodb.com/docs/database-tools/mongodump/
[3] ChatGPT: https://chat.openai.com/chat