这里只对2022长安杯的网站重构过程进行记录
首先看检材一里的历史命令
这里只截取部分
从历史命令可以看出,他执行了很多次start_web.sh
和npm run dev
且这个网站的服务就是用那几个jar包起的
java -jar /web/app/market.jar
java -jar /web/app/exchange.jar
java -jar /web/app/admin-api.jar
java -jar /web/app/ucenter-api.jar
但是start_web.sh后面被删了
先去看看npm run dev是什么意思
npm run dev是用来搭建脚手架环境的。
在npm run dev的时候,首先会去项目的package.json文件里找scripts 里找对应的 dev ,然后执行 dev 的命令。
例如启动vue项目 npm run serve的时候,实际上就是执行了vite这条命令,在这条命令中,包含了vue-cli-service serve,也就是说。
然后去/web/app/web里看看package.json
...
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"unit": "jest --config test/unit/jest.conf.js --coverage",
"e2e": "node test/e2e/runner.js",
"test": "npm run unit && npm run e2e",
"lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs",
"build": "node build/build.js"
}
...
在看看这条命命令是干嘛的
webpack-dev-server就是可以用来快速搭建一个服务
–inline选项会为入口页面添加“热加载”功能,即代码改变后重新加载页面
–progress 查看 webpack 的编译进度
–config 配置文件的路径
所以就是用来起服务,以build/webpack.dev.conf.js
作为配置文件
这个配置文件没什么看头
总的来说就是用来起vue前端服务的
查看数据库
有网站肯定就有数据库,解压admin-api.jar包
在admin-api\BOOT-INF\classes\application.properties
可以看数据库的配置
#datasource
spring.datasource.url=jdbc:mysql://172.16.80.128:33050/b1?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=shhl7001
是使用的mysql数据库,且地址为172.16.80.128 所以应该在其他检材上
同时在检材二中发现了建站笔记和被删除的start_web.sh以及b1数据库文件
在检材3中的历史命令里可以看见存在对docker的操作
且是用docker-compose.yml进行操作
查看这个文件
version: '3'
services:
mysql:
image: "mysql:5.7.32"
restart: always
container_name: mysql57
environment:
MYSQL_ROOT_PASSWORD: shhl7001
TZ: Asia/Shanghai
command:
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
--max_allowed_packet=128M
ports:
- 33050:3306
volumes:
- /data/mysql/db:/var/lib/mysql
- /data/mysql/conf/my.cnf:/etc/mysql/my.cnf
可以知道一下信息,
本机暴露33050端口来映射容器内的3306端口
本机的/data/mysql/db文件夹 映射容器里的/var/lib/mysql文件夹
本机的/data/mysql/conf/my.cnf文件 映射容器里的/etc/mysql/my.cnf文件
我们进入/data/mysql/db可以发现没有之前看到的b1数据库
只有这三个数据库,所以我们把检材二里的b1文件夹使用xftp拖进来即可,这样docker容器里的文件也会变
我之前还想着用frm和ibd恢复数据库(麻了
然后启动docker服务进入容器查看数据库是否正常被导入
systemctl start docker
docker exec -it 8eda /bin/bash
mysql -u root -p
在上面我们可以知道这个数据库的账户密码
#datasource
spring.datasource.url=jdbc:mysql://172.16.80.128:33050/b1?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=shhl7001
在docker-compose.yml里也可以看到密码
environment:
MYSQL_ROOT_PASSWORD: shhl7001
这样网站就可以正常连接这个数据库了
跑服务
我们按照建站笔记里的说,先开后端再开前端,将start_web.sh复制进检材一的/web/app目录,顺便看看他内容是什么
#!/bin/bash
echo "Starting App: Cloud "
nohup java -jar /web/app/cloud.jar &
sleep 20s
echo "Starting App: market "
nohup java -jar /web/app/market.jar &
sleep 60s
echo "Starting App:exchange "
nohup java -jar /web/app/exchange.jar &
sleep 20s
echo "Starting App:admin"
nohup java -jar /web/app/admin-api.jar &
sleep 20s
echo "Starting App:ucenter"
nohup java -jar /web/app/ucenter-api.jar &
sleep 20s
echo "Starting WEB:WEB"
cd /web/app/web/
nohup npm run dev &
cd /web/app
echo "Starting WEB:admin"
cd /web/app/admin/
nohup npm run dev &
cd /web/app
echo "Finish"kil
然后要赋予执行权限在执行
cd /web/app
chmod 777 start_web.sh
./start_web.sh
可以占用7000端口的进程为2461
然后再查看进程就可以知道是哪个文件在使用7000端口
开启前端
cd /web/app/web
npm run dev
访问3001端口
开启后台服务
cd /web/app/admin
npm run dev
关于服务器取证的几道题
3.检材1中,操作系统发行版本号为
7.5.1804
这个可以使用命令,也可以在火眼仿真里面看到
查看发行版本命令
cat /etc/redhat-release
查看系统内核命令
cat /proc/version
4.检材1系统中,网卡绑定的静态IP地址为
172.16.80.133
先ifconfig查看网卡信息,然后再使用下面命令查看
cat /etc/sysconfig/network-scripts/ifcfg-ens33
可以发现是使用的静态ip
5.检材1中,网站jar包所存放的目录是
/web/app
存在一些jar包,且开启网站服务就是用的这些(从日志里可以知道)
6.检材1中,监听7000端口的进程对应文件名为
cloud.jar
在上面重构网站跑jar包之后可以知道,也可以把一个个jar包解压缩查看application.properties
文件
7.检材1中,网站管理后台页面对应的网络端口为
9090
这里不是看admin-api的服务端口,因为这个只是个api,用来身份验证的
在日志里也可以看到,嫌疑人在/web/app/admin/文件里执行了npm run dev
所以去看看他的package.json
"scripts": {
"init": "webpack --progress --config build/webpack.dev.config.js",
"dev": "webpack-dev-server --content-base ./ --open --inline --hot --compress --config build/webpack.dev.config.js",
"build": "webpack --progress --hide-modules --config build/webpack.prod.config.js"
},
这里使用build/webpack.dev.config.js
作为配置文件,再看看这个文件
module.exports = merge(webpackBaseConfig, {
devtool: '#source-map',
devServer: {
port: 9090,
host: "0.0.0.0"
},
...
可以看出是使用了9090端口
同样,在/web/app/admin使用npm run dev
访问后也能验证这个就是后台
还有就是在检材二的历史记录也能看到
8.检材1中,网站前台页面里给出的APK的下载地址是
https://pan.forensix.cn/f/c45ca511c7f2469090ad/?dl=1
搭起网站后在首页可以看到两个下载app的二维码,保存下来用CyberChef3里解析二维码的工具来解析出url地址
同样也可以直接看源码,在/web/app/web/src/app.vue里可以看到相关信息,直接搜索‘二维码’关键字也可以搜到
9.检材1中,网站管理后台页面调用的用户表(admin)里的密码字段加密方式为?
md5
使用jd-gui反编译admin-api.jar
查看回显的内容来定位
在这里可以看到相关的信息
@RequestMapping({"googleAuth/sign/in"})
@ResponseBody
@AccessLog(module=AdminModule.SYSTEM, operation="提交登录信息Admin")
public MessageResult dogoogleAuthLogin(String username, String password, HttpServletRequest request)
{
if ((StringUtils.isBlank(username)) || (StringUtils.isBlank(password))) {
return error("用户名或密码不能为空");
}
password = Encrypt.MD5(password + this.md5Key);
Admin admin = this.adminService.login(username, password);
if (admin == null) {
return error("用户名或密码不存在");
}
try
{
log.info("md5Key {}", this.md5Key);
UsernamePasswordToken token = new UsernamePasswordToken(username, password, true);
token.setHost(getRemoteIp(request));
SecurityUtils.getSubject().login(token);
List<Menu> list;
List<Menu> list;
if (admin.getUsername().equalsIgnoreCase("root")) {
list = this.sysRoleService.toMenus(this.sysPermissionService.findAll(), Long.valueOf(0L));
} else {
list = this.sysRoleService.toMenus(this.sysRoleService.getPermissions(admin.getRoleId()), Long.valueOf(0L));
}
Map<String, Object> map = new HashMap();
map.put("permissions", list);
map.put("admin", admin);
return success("登录成功", map);
}
catch (AuthenticationException e)
{
e.printStackTrace();
return error(e.getMessage());
}
}
从这里可以知道是对输入的密码加盐后再md5计算,然后再去数据库里找
password = Encrypt.MD5(password + this.md5Key);
Admin admin = this.adminService.login(username, password);
所以为md5加密
然后这个md5key的定义为
@Value("${bdtop.system.md5.key}")
private String md5Key;
@Value(“${xxxx}”)注解从配置文件读取值
所以在admin-api.jar的BOOT-INF/classes/application.properties
里可以知道这个盐值
# system
bdtop.system.md5.key=XehGyeyrVgOV4P8Uf70REVpIw3iVNwNs
coin.not.sync=ETH
google.auth.url=ztuo.fcoincn.com
bdtop.system.work-id=1
bdtop.system.data-center-id=1
10.分析检材1,网站管理后台登录密码加密算法中所使用的盐值是
XehGyeyrVgOV4P8Uf70REVpIw3iVNwNs
见上
14.检材2中,下载的涉案网站源代码文件名为
ZTuoExchange_framework-master.zip
查看下载记录,可以看到,然后解压发现了和服务器上差不多的源码
15.检材2中,网站管理后台root账号的密码为
root
火眼可以直接分析出来
google保存的密码在C:\Users\xxxx\AppData\Local\Google\Chrome\User Data\Default\Login Data
里
是sqlit3文件,但是密码被加密了
火眼有解密的脚本
16.检材2中,技术员使用的WSL子系统发行版本是
20.04
这里是问子系统的发行版本,不是wsl的版本
powershell执行命令
wsl -l -v
得到
NAME STATE VERSION
* Ubuntu-20.04 Running 1
为20.04
17.检材2中,运行的数据库服务版本号是
8.0.30
可以火眼上看到,但可以看到两个版本
要注意b1是检材一里的数据库的版本,所以应该看其他的数据库的版本来确定
18.上述数据库debian-sys-maint用户的初始密码是
ZdQfi7vaXjHZs75M
因为知道检材二使用了wsl,所以数据库应该就在这里面,且在历史命令里也可以看到相关信息
而且知道了mysql目录在/etc/mysql
进去可以看到有debian.cnf文件,这里存储了debian-sys-maint的密码
如果直接访问,因为权限问题是访问不了的。这里存在弱密码123456,可以变成root权限。
也可以直接搜索文件读取,wsl是会在主机里有直接可以看到的文件夹的
得到
# Automatically generated for Debian scripts. DO NOT TOUCH!
[client]
host = localhost
user = debian-sys-maint
password = ZdQfi7vaXjHZs75M
socket = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
host = localhost
user = debian-sys-maint
password = ZdQfi7vaXjHZs75M
socket = /var/run/mysqld/mysqld.sock
19.检材3服务器root账号的密码是
hl123456
在检材二里的系统ssh历史命令里可以看到相关信息,且检材3的ip为172.16.80.128
所以可以确定密码
20.检材3中,监听33050端口的程序名(program name)为
docker-proxy
netstat -anop | grep 33050
21.除MySQL外,该网站还依赖以下哪种数据库
monogdb
redis
在admin-api.jar的application.properties里可以看到相关信息
22.检材3中,MySQL数据库root账号的密码是
shhl7001
在admin-api.jar的application.properties里可以看到相关信息
#datasource
spring.datasource.url=jdbc:mysql://172.16.80.128:33050/b1?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=shhl7001
23.检材3中,MySQL数据库在容器内部的数据目录为
/var/lib/mysql
在检材三的/data/mysql的docker-compose.yml文件可以看到相关信息
volumes:
- /data/mysql/db:/var/lib/mysql
- /data/mysql/conf/my.cnf:/etc/mysql/my.cnf
就是内部的文件夹映射到容器内部的文件夹,且在db文件夹可以看到多个数据库文件,所以可以确定/var/lib/mysql为数据目录
同时也可以使用sql语句查询,使用show VARIABLES like "datadir"
来查看数据目录
24.涉案网站调用的MySQL数据库名为
b1
在admin-api.jar的application.properties里可以看到相关信息
#datasource
spring.datasource.url=jdbc:mysql://172.16.80.128:33050/b1?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=shhl7001
25.勒索者在数据库中修改了多少个用户的手机号?
3
这里要看mysql的日志,在检材3主机的/data/mysql/db文件夹里可以看到日志文件8eda4cb0b452.log
对其进行检索信息
修改数据,就找update
发现了相关数据
Query UPDATE `b1`.`member` SET `mobile_phone` = '13638991111' WHERE `id` = 9
计数,总共有3次
26.勒索者在数据库中删除的用户数量为
28
同样还是查日志,删除就是delete
(比赛的时候实际上是随便翻到的)
发现一堆数据
计数,总共有28次
27.还原被破坏的数据库,通过查看数据库或登录管理后台的方式分析除技术员以外,还有哪个IP地址登录过网站管理后台?用该地址解压检材4
172.16.80.197
在上面重构网站的时候已经还原,直接看b1数据库(比赛的时候还以为要用frm和ibd文件来手工还原,结果搞了半天,麻)
在admin_access_log
表中可以看到3个ip地址(其实一个个试能不能解压就行)
首先可以知道172.16.80.100是检材2的ip地址,火眼搜索可以看到
emmmmm,还是一个个试吧,最后试出为172.16.80.197
28.还原全部被删改数据,用户id为500的注册会员的HT币钱包地址为
cee631121c2ec9232f3a2f028ad5c89b
进入后台可见
关于后台密码:
在15题里可以看到账户密码为root
也可以自己安装网站的加密方式设置密码,替换数据库中的数据
29.还原全部被删改数据,共有多少名用户的会员等级为’LV3’
164
可以看日志,因为在日志里有insert into语句向member表导入数据,且时间在delete之前,所以这个的数据是完整的
直接复制导出,修改后缀,转成csv文件
然后和后台数据对比每个字段的意思来判断哪个是等级,最后发现member_grade_id
为等级
然后进行计数就行,为164
也可以使用数据库语句来计数,然后再加上被删除的用户数据中等级为3的
sql语句
SELECT count(*) from member where member_grade_id=3
在日志里找被删除的数据的insert into记录,id为973开始 1000结束
然后被删除数据里的用户里有6个等级为3的(直接用筛选的话会少一个,因为他不计第一行的数据)
所以总共164个
30.还原全部被删改数据,哪些用户ID没有充值记录
989,318
就是找不在member_transaction表中的id
delimiter $$
CREATE PROCEDURE p234()
BEGIN
declare i int default 1;
while i<1001 DO
insert into `result` VALUES((select if((select LENGTH(create_time) from `member_transaction` where member_id=i limit 1)>1,1,i)));
set i=i+1;
END WHILE;
END;
$$
delimiter ;
call p234();
就是自己建一个表,然后如果查不出数据(即数据长度小于1)那么就往新表里插数据,就可以看到有哪些id不在交易表里。
建的表要去除主键
然后可以发现是989和318
31.还原全部被删改数据,2022年10月17日总计产生多少笔交易记录?
1000
sql语句
SELECT count(*) from member_transaction where create_time BETWEEN "2022-10-17 0:0:0" and "2022-10-18 0:0:0"
32.还原全部被删改数据,该网站中充值的USDT总额为
408228