拿到了一个虚拟机程序镜像,安装起来分析一下某设备。
为了保护隐私,这边厚码一下,把一些敏感的信息都给替换掉了。
在审计之前,你得先保证程序能够正常跑起来,那么就要把程序的授权给干掉。
找到web端口对应进程
yum install net-tools -y
netstat -lnpt
得到系统开放的端口和进程,例如
[root@testName ~]# netstat -ntlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:27017 0.0.0.0:* LISTEN 28708/mongod
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1417/master
tcp 0 0 0.0.0.0:60000 0.0.0.0:* LISTEN 2039/sshd: /usr/sbi
tcp6 0 0 :::7687 :::* LISTEN 45857/java
tcp6 0 0 :::9200 :::* LISTEN 2554/java
tcp6 0 0 :::7473 :::* LISTEN 45857/java
tcp6 0 0 :::7474 :::* LISTEN 45857/java
tcp6 0 0 :::9300 :::* LISTEN 2554/java
tcp6 0 0 ::1:25 :::* LISTEN 1417/master
tcp6 0 0 :::443 :::* LISTEN 2642/node /usr/loca
tcp6 0 0 127.0.0.1:9600 :::* LISTEN 2824/java
tcp6 0 0 :::60000 :::* LISTEN 2039/sshd: /usr/sbi
tcp6 0 0 :::50051 :::* LISTEN 1772/netmgrd
tcp6 0 0 :::6789 :::* LISTEN 2794/java
优先看允许所有人访问的,例如这里的
:::443
0.0.0.0:60000
一个个访问过去
这里确认443是web端口,并且知道对应的pid是2642,去找到端口对应的文件路径
[root@testName ~]# ps -aux | grep 2642
test 2642 0.4 3.5 1181852 290420 ? Ssl Jan16 1:00 node /usr/local/testName/program/jd_analysis/bin/www
root 108152 0.0 0.0 112832 2340 pts/2 S+ 01:03 0:00 grep --color=auto 2642
或者直接看/proc/2642 下面的信息。这里是一个二进制文件,如果是apache或者nginx这种中间件,就要去看指定的配置文件的信息。
[root@testName ~]# ls -alh /proc/2642
total 0
dr-xr-xr-x 9 test test 0 Jan 16 20:54 .
dr-xr-xr-x 246 root root 0 Jan 16 20:54 ..
-r--r--r-- 1 test test 0 Jan 17 01:04 arch_status
dr-xr-xr-x 2 test test 0 Jan 16 20:55 attr
-rw-r--r-- 1 test test 0 Jan 17 01:04 autogroup
-r-------- 1 test test 0 Jan 17 01:04 auxv
-r--r--r-- 1 test test 0 Jan 17 01:04 cgroup
--w------- 1 test test 0 Jan 17 01:04 clear_refs
-r--r--r-- 1 test test 0 Jan 16 20:55 cmdline
-rw-r--r-- 1 test test 0 Jan 17 01:04 comm
-rw-r--r-- 1 test test 0 Jan 17 01:04 coredump_filter
-r--r--r-- 1 test test 0 Jan 17 01:04 cpuset
lrwxrwxrwx 1 test test 0 Jan 17 01:04 cwd -> /
-r-------- 1 test test 0 Jan 17 01:04 environ
lrwxrwxrwx 1 test test 0 Jan 17 01:04 exe -> /usr/local/testName/program/node/bin/node
dr-x------ 2 test test 0 Jan 16 20:55 fd
dr-x------ 2 test test 0 Jan 17 01:04 fdinfo
-rw-r--r-- 1 test test 0 Jan 17 01:04 gid_map
-r-------- 1 test test 0 Jan 17 01:04 io
-r--r--r-- 1 test test 0 Jan 17 01:04 limits
-rw-r--r-- 1 test test 0 Jan 17 01:04 loginuid
dr-x------ 2 test test 0 Jan 17 01:04 map_files
-r--r--r-- 1 test test 0 Jan 17 01:04 maps
-rw------- 1 test test 0 Jan 17 01:04 mem
-r--r--r-- 1 test test 0 Jan 17 01:04 mountinfo
-r--r--r-- 1 test test 0 Jan 17 01:04 mounts
-r-------- 1 test test 0 Jan 17 01:04 mountstats
dr-xr-xr-x 51 test test 0 Jan 17 01:04 net
dr-x--x--x 2 test test 0 Jan 17 01:04 ns
-r--r--r-- 1 test test 0 Jan 17 01:04 numa_maps
-rw-r--r-- 1 test test 0 Jan 17 01:04 oom_adj
-r--r--r-- 1 test test 0 Jan 17 01:04 oom_score
-rw-r--r-- 1 test test 0 Jan 17 01:04 oom_score_adj
-r-------- 1 test test 0 Jan 17 01:04 pagemap
-r-------- 1 test test 0 Jan 17 01:04 personality
-rw-r--r-- 1 test test 0 Jan 17 01:04 projid_map
lrwxrwxrwx 1 test test 0 Jan 17 01:04 root -> /
-rw-r--r-- 1 test test 0 Jan 17 01:04 sched
-r--r--r-- 1 test test 0 Jan 17 01:04 schedstat
-r--r--r-- 1 test test 0 Jan 17 01:04 sessionid
-rw-r--r-- 1 test test 0 Jan 17 01:04 setgroups
-r--r--r-- 1 test test 0 Jan 17 01:04 smaps
-r--r--r-- 1 test test 0 Jan 17 01:04 smaps_rollup
-r-------- 1 test test 0 Jan 17 01:04 stack
-r--r--r-- 1 test test 0 Jan 16 20:54 stat
-r--r--r-- 1 test test 0 Jan 17 01:04 statm
-r--r--r-- 1 test test 0 Jan 16 20:55 status
-r-------- 1 test test 0 Jan 17 01:04 syscall
dr-xr-xr-x 12 test test 0 Jan 17 01:04 task
-rw-r--r-- 1 test test 0 Jan 17 01:04 timens_offsets
-r--r--r-- 1 test test 0 Jan 17 01:04 timers
-rw-rw-rw- 1 test test 0 Jan 17 01:04 timerslack_ns
-rw-r--r-- 1 test test 0 Jan 17 01:04 uid_map
-r--r--r-- 1 test test 0 Jan 17 01:04 wchan
从cmdline文件中可以看到启动命令是
node /usr/local/testName/program/jd_analysis/bin/www
那么就可以定位到 /usr/local/testName/program/jd_analysis/bin/www 但是这里是一个二进制文件
vi看一下发现是一个nodejs文件,包含了../app
#!/usr/bin/nodejs
var debug = require('debug')('my-application');
var app = require('../app');
var slowloris = require('node-slowloris');
app.set('port', process.env.PORT || 80);
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
//server.setTimeout(0);
slowloris(server, {
headerTimeout: 250000, // in ms, default 2500
minRate: 500, // bytes per second, default 500
rateOverhead: 50 // in ms this will be subtracted from the time when calculating the rate, default 50
});
到这里就可以定位到源码在 /usr/local/testName/program/jd_analysis/
[root@testName ~]# ls /usr/local/testName/program/jd_analysis/
app.js bin byteExchangeUtil.js db log4j.js logs npm-debug.log package.json public routes views winston.js
是node.js写的程序
代码分析
再往上一级的目录比较大,应该是用到的组件。我们先拉下来jd_analysis的代码看看
[root@testName ~]# ls /usr/local/testName/program/
conf c_program download elasticsearch java jd_analysis las.json laswatchdog logstash mongodb neo4j net-snmp node node_modules phantomjs upgrade
这里sftp一开始用不了,改一下sshd_config的配置就可以用了,把sftp的注释给去掉了
# override default of no subsystems
Subsystem sftp /usr/libexec/openssh/sftp-server
看了一下大致理解路由走向,app.use可以注册成一个路由,貌似nodejs也支持使用event绑定直接定义成路径,但是这里没看见
app.use()是Express中的一个中间件函数,用于将中间件函数绑定到应用程序的路径上。它可以接收一个或多个回调函数作为参数,每个回调函数都会在请求被路由匹配之前执行。假设我们有一个Express应用程序,并且需要对所有请求进行身份验证。我们可以使用app.use()来绑定一个身份验证中间件函数
/*app.use('/asset',asset);
app.use('/account',account);*/
app.use('/', routes);
app.use('/systemSetting', systemSetting);
app.use("/state", state);
app.use('/statistics', statistics);
app.use('/logSearch', logSearch);
app.use('/posiSearch', posiSearch);
app.use("/historySearch", historySearch);
app.use("/associationRules", associationRules);
app.use("/log", log);
app.use("/operationHistory", operationHistory);
app.use("/reverseHistory", reverseHistory);
app.use("/relationRule", relationRule);
app.use("/graph", graph);
app.use("/relationRuleFil", relationRuleFil);
app.use("/portrait", portrait);
app.use("/assetList", assetList);
app.use("/assetType", assetType);
app.use('/monitor', monitor);
app.use('/analysisRules', analysisRules);
app.use("/alarm", alarm);
app.use('/filterRules', filterRules);
app.use('/associationAnalysis', associationAnalysis);
app.use("/authorization", authorization);
app.use("/role", role);
app.use("/loginManager", loginManager);
app.use("/report", report);
app.use("/alarmOverview", alarmOverview);
app.use("/alarmUserRanking", alarmUserRanking);
app.use("/userOperation", userOperation);
app.use("/systemAlarmStatistics", systemAlarmStatistics);
app.use("/systemAlert", systemAlert);
app.use('/alert', alert);
app.use('/alertNotice', alertNotice);
app.use('/componentShape', componentShape);
app.use('/netWorkSetup', netWorkSetup);
app.use('/communicationSetup', communicationSetup);
app.use('/doubleMdisk', doubleMdisk);
app.use("/cascade", cascade);
app.use("/verControl", verControl);
app.use("/serverMailSetting", serverMailSetting);
app.use("/cipherStrategy", cipherStrategy);
app.use("/regular", regular);
app.use("/indexInformation", indexInformation);
app.use("/policeInformation", policeInformation);
app.use("/collector", collector);
app.use("/knowledge", knowledge);
app.use("/files", files);
app.use("/logSummary", logSummary);
app.use("/logImport", logImport);
app.use("/logMonitoring", logMonitoring);
app.use("/record", record);
app.use("/licenseInformation", licenseInformation);
app.use("/systemUpgrade", systemUpgrade);
app.use("/ping", ping);
app.use("/traceroute", traceroute);
app.use("/shutdownOrrestart", shutdownOrrestart);
app.use("/alertSing", alertSing);
app.use("/whiteList", whiteList);
app.use("/blockConfig", blockConfig);
app.use("/dbConfig", dbConfig);
app.use("/searchConditon", searchConditon);
app.use("/homeState", homeState);
app.use("/oem", oem);
app.use("/collectorManager", collectorManager);
app.use("/api", api);
// app.use("/supOS", supOS);
app.use("/sysinfo", sysinfo);
app.use("/theme", theme);
app.use("/netconf", netconf);
app.use("/system", System);
app.use("/auth", authJs);
app.use("/ifarm", ifarm);
app.use("/upgrade", ftpUpgrade);
app.use("/serviceSetting", serviceSetting);
app.use("/onlineParser", onlineParser);
app.use("/lexicon",lexicon)
app.use("/topology", topology);
app.use("/Filter", Filter);
app.use('/users', users);
app.use('/acquisition', acquisition);
app.use('/SafetyLibrary', SafetyLibrary); //安全库路由
app.use("/mergerRules", mergerRules);
还有一些路由如/ueditor/ueditor
等,直接搜索app.use("
就可以得到了。
授权破解
看描述授权是过期的,去看看相关代码
function execCheckLicenceStatus() {
var task = cron.schedule("*/1 * * * *", function () {
checkLicenceStatus();
});
}
授权状态检测
function checkAuthAssetNum(cal) {
var countquery = asset.count({"licenceStatus": 1});
countquery.exec(function (err, count) {
if (err) {
} else {
getLiceceAssetNum(function (sum, id) {
var result = sum - count;
var number = 0;
var noLicenResult = result;
if (result > 0) {
var query = asset.find({"licenceStatus": 0});
query.exec(function (err, noLicenceResult) {
if (noLicenceResult != null) {
noLicenceResult.forEach(function (element, index) {
if (index <= noLicenResult - 1) {
asset.update({_id: element._id}, {
$set: {
licenceStatus: 1
}
}, function (err) {
console.log("licence 更换")
});
result = result - 1;
} else {
result = 0;
}
});
}
});
number = result
} else {
var query = asset.find({"licenceStatus": 1}).sort({assetUpdateTime:-1});
query.exec(function (err, result) {
if (result != null) {
result.forEach(function (element, index) {
if (index > sum - 1) {
asset.update({_id: element._id}, {
$set: {
licenceStatus: 0,
assetEventCount: 0
}
}, function (err) {
console.log("licence 更换")
});
}
});
}
});
number = 0;
}
licenceModel.update({_id: id}, {
$set: {
surplusNum: number
}
}, function (err) {
});
cal(result);
})
}
});
}
感觉是uuid这些授权信息是从mongodb数据库拿的,需要连上数据库看看。
注释里的测试数据感觉也是有参考价值的
/*license.update({uuid: "eff3467a-e80e-11ea-a5c2-52540082e7d4"}, {
$set: {
sequenceStatus: 1,
timeStatus: 1,
volume: 1601557932000,
resourceNum: 100,
volumePercent: 1,
surplusNum: 99,
volumeStatus: 100,
time: 34,
changeStatus:1
}
},{upsert:true},function (err, result) {
if (err) {
console.log("active deviceLicence save license-updated failed,the error is:["+err+"]");
cb(0)
} else {
cb(1)
}
})*/
/*license.update({uuid: "eff3467a-e80e-11ea-a5c2-52540082e7d4"}, {
$set: {
sequenceStatus: 1,
timeStatus: 1,
volume: 1601557932000,
resourceNum: 100,
volumePercent: 1,
surplusNum: 99,
volumeStatus: 60,
time: 30,
changeStatus:1
}
},{upsert:true},function (err, result) {
if (err) {
console.log("active deviceLicence save license-updated failed,the error is:["+err+"]");
cb(0)
} else {
cb(1)
}
});*/
/*var aesResult = aseUtil.aes_encrypt_containAll("aa0e6fce-802b-440e-8ceb-1842f086c00dv112020-08-27T16:37:29+08:002020-09-27T23:59:59+08:00100","OFB").toString();
var mkSummary = StringUtil.getSha256(aesResult);
console.log(mkSummary)*/
/*aesResult = aseUtil.aes_encrypt("aa0e6fce-802b-440e-8ceb-1842f086c00dv132020-08-17T13:42:22+08:002021-02-17T23:59:59+08:00100","148fc14fa50b7f52","9e3612f18c520c6b","OFB");
console.log(aesResult.toString())
console.log(StringUtil.getSha256(aesResult.toString()));*/
用账号密码连接一下数据库。
192.168.121.143
admin
root
[email protected]
数据表信息一开始是隐藏的,但是可以这样打开
_id | resourceNum | sequenceStatus | timeStatus | time | volumeStatus | volume | volumePercent | changeStatus | uuid | surplusNum |
5fe308c93c863febac7g021b | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | e360a26e-28a9-11eb-a97f-5254003827cb | 0 |
结合这里的代码注释就可以修改成合格的license了
var licenceInfoModel = new Schema({
sequenceStatus:Number, //默认1
timeStatus:Number, //默认1
time:Number, //剩余时间
volumeStatus:Number, //授权天数
volume:Number, //授权时间
volumePercent:Number, //已用资源
resourceNum:Number, //授权资源数
uuid:String, //UUID信息
surplusNum:Number, //剩余资源数
changeStatus:Number
});
代码里的授权判断
var availableDay = parseInt((result.volume - new Date().getTime()) / (24 * 60 * 60 * 1000));
console.log("licence avaliableDay is:" + availableDay);
那么把这个字段改成合适的时间戳就可以了。
例如 1715479245312
就有115天了。(这里有一个坑点,忘记了字段原来的属性是啥了,我改了这个字段的属性为string,否则默认的属性无法保存)
接口也可以访问了
如果是授权未更新登录则是下图这样
漏洞审计……等后续得空更新1下
原文始发于微信公众号(安全光圈):记一次某设备的授权p解
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论